TakerConfig

createTakerClient(config) takes one object and binds everything to it. Config is injected; nothing in the SDK reads globals or environment variables.
relayerUrl
string
required
parlays.live relayer base URL. The relayer prices from Hyperliquid, signs the maker side, and pays gas on submit. Trailing slashes are stripped.
escrow
Address
required
ParlayEscrow contract address on the host chain. Holds both sides’ funds, verifies both EIP-712 signatures, and pays out on settlement. Also the EIP-712 verifyingContract for taker signatures.
collateralToken
Address
required
The USDC (6 decimals) ERC-20 the escrow pulls stakes in. Used for the allowance and approve call builders.
chainId
number
required
HyperEVM chain id the contracts live on: 998 testnet, 999 mainnet. Used in the EIP-712 domain and every writeContract call.
import {createTakerClient} from "@parlays-live/taker";

export const taker = createTakerClient({
  relayerUrl: "https://sparrow-relayer.dennis-furrer.workers.dev",
  escrow: "0x77DeFc3E3B66bE01B8468Eb696Ec9F330D24332a",
  collateralToken: "0x75b69d0E8fA3CdB644b0f069E4e876B85A76E137",
  chainId: 998,
});

Network matrix

Two axes are independent: where the contracts live (HyperEVM chain id) and which Hyperliquid environment prices the legs (a relayer deployment flag, HL_TESTNET).
StackContractsPricing sourceWho runs it
parlays.live testnet (shared)HyperEVM testnet, chain 998HL mainnet HIP-4 (HL_TESTNET="false")Public shared stack
Dev env, HL testnet pricingHyperEVM testnet, chain 998HL testnet HIP-4 (HL_TESTNET="true")Your own relayer + contracts
MainnetHyperEVM mainnet, chain 999HL mainnet HIP-4Configured when contracts deploy
HIP-4 outcome markets live on HL mainnet, so the shared testnet stack prices real HL mainnet markets while settling test USDC on HyperEVM testnet. The pricing source is never a client-side option: the TakerConfig only decides which relayer you talk to.

Shared testnet addresses

WhatValue
Chain id998 (HyperEVM testnet)
Relayerhttps://sparrow-relayer.dennis-furrer.workers.dev
ParlayEscrow0x77DeFc3E3B66bE01B8468Eb696Ec9F330D24332a
MakerVault0x807c7cb41573b8B7d3E52E3F37410A0a8eDA4fc0
USDC (test, 6 dp)0x75b69d0E8fA3CdB644b0f069E4e876B85A76E137
Explorerhttps://explore-testnet.hyperpc.app

Multi-network hosts

If your app has a network toggle, resolve it before module load and export a single module-level client (this is what parlays.live does):
src/lib/taker.ts
import {createTakerClient} from "@parlays-live/taker";
import {config} from "../config"; // resolves testnet/mainnet from localStorage, then reloads on switch

export const taker = createTakerClient({
  relayerUrl: config.relayerUrl,
  escrow: config.escrow,
  collateralToken: config.collateralToken,
  chainId: config.chainId,
});
Hosts with their own network guard should also pass ensureChain to the write hooks (useSubmitParlay, useCashOut) so the wallet is switched by your logic instead of the default wagmi switchChain. See Analytics and callbacks.

Money convention: raw bigint USDC, 6 decimals

Every amount that crosses the SDK boundary is a raw bigint with 6 decimals: stakes, payouts, collateral, cash-out values, pots. Relayer JSON carries them as decimal strings; convert with BigInt(...) at the boundary and only ever format for display.
import {parseUsdc, formatUsdc, formatUsdcCompact, USDC, BPS} from "@parlays-live/taker";

const stake = parseUsdc("25");        // 25000000n
formatUsdc(25000000n);                // "25.00"
formatUsdcCompact(1234567890n);       // compact display for big pots
USDC;                                 // 1000000n  (1 USDC in raw units)
BPS;                                  // 10000n    (basis-point denominator)
Never Number() a raw amount for arithmetic. Number is fine only at the display or analytics edge, after formatUsdc. Odds fields (combinedOddsBps etc.) are bps strings; Number(oddsBps) / 10000 gives the decimal multiple for display.

Where addresses come from

  • Shared testnet: the table above (also the defaults baked into the parlays.live app config).
  • Your own deployment: the escrow, vault, and USDC addresses come out of your Foundry deploy scripts; the relayer’s wrangler.toml must be configured with the same ESCROW and VAULT, plus HL_TESTNET for the pricing source. The client’s escrow and chainId must match the relayer’s, since both sides derive the same EIP-712 domain (name: "Sparrow", version: "1"); a mismatch makes signature verification fail on-chain.
  • Mainnet: contracts are configured via environment at build time and read as “not deployed” (zero address) until they exist. Gate your UI on a configured escrow the way the reference app does: const isConfigured = !/^0x0+$/.test(escrow).