Queue positions for the token allocation program, ranked from on-chain pool deposits with a time-in-queue multiplier and an optional trading-volume bonus. Read-only except for wallet linking; ranking runs on its own interval.
Responses carry queue position and deposited amounts. Multipliers, volume and scores are never served: a public score reads as an allocation promise.
/healthService health plus latest-snapshot metadata.
ok stays true while the volume source is degraded — the queue is still served; check volumeDegraded instead.relayer is null when no relayer key is configured: gasless deposits and withdrawals are unavailable and their routes 503.{ "ok": true, "latestSnapshotId": 42, "asOf": 1756677600, "users": 1337,
"volumeFetchedAt": 1756677000, "volumeDegraded": false,
"relayer": { "wallets": 2, "redisHealthy": true } }
/leaderboard?limit=50&offset=0The current queue, paginated.
limit defaults to 50, max 500. offset defaults to 0.totalDepositsUsd is the pool-wide sum in whole USD — an aggregate, not anyone's balance.{ "snapshotId": 42, "asOf": 1756677600, "users": 1337,
"totalDepositsUsd": 523000, "limit": 50, "offset": 0,
"rows": [ { "rank": 1, "user": "0xabc…", "depositUsd": 12000 }, … ] }
/leaderboard/:addressOne user's queue position.
{ "snapshotId": 42, "asOf": 1756677600, "users": 1337, "user": "0xabc…", "rank": 17 }
/snapshots?limit=20Ids of retained past rankings, newest first (limit max 100).
{ "snapshotIds": [42, 41, 40, …] }
/snapshots/:id?limit=50&offset=0A past ranking, same shape as /leaderboard.
Static presentation data for the IPO page — name, ticker, funding history, links — from a catalog committed with the service. Dollar figures are display strings. Nothing here changes at runtime.
/poolsEvery indexed pool with metadata, as { pools: [ { pool, …metadata } ] }.
/pools/:addressOne pool's metadata.
{ "pool": "0x033d…0973", "name": "Anthropic", "ticker": "ANTH", "logoUrl": null,
"description": "Anthropic is an AI safety and research company…",
"marketCapEstimate": { "low": "$1.5T", "high": "$2.5T" }, "closeTime": null,
"links": { "website": "https://www.anthropic.com", "x": "https://x.com/anthropicai" },
"details": { "sector": "Artificial Intelligence / Enterprise Software", "founded": 2021,
"founder": "Dario Amodei", "headquarters": "San Francisco, CA",
"type": "Public Benefit Corporation" },
"fundingRounds": [ { "label": "Series F", "year": 2025, "amountUsd": "$183B" }, … ],
"totalRaise": "$44B+", "lastValuation": "$1.3T" }
The user signs; the service submits and pays the gas. Present only when a relayer key is configured — check relayer on /health first, and fall back to the user calling the pool directly. Every consequential field is inside the signature, so the relayer cannot redirect a deposit or withdrawal; it is only ever msg.sender. Amounts, nonces and deadlines are decimal STRINGS in every body: they exceed Number.MAX_SAFE_INTEGER, and a JSON number would round the signed value into one that no longer matches the signature (400).
/relayDepositRelay a Permit2-signed deposit. Body: { pool, owner, beneficiary, amount, permitNonce, deadline, signature }.
additionalAllowances — one signed ERC-2612 permit — and the relayer lands permit() and the deposit back-to-back, both on our gas.additionalAllowances is [{ token, value, deadline, signature }]: at most one entry, token must be the pool's quote token, value must cover amount, signature exactly 65 bytes. The permit's spender is always Permit2 — it is not a field. Signed over the TOKEN's own EIP-712 domain with the TOKEN's sequential nonces(owner); see the second typed payload below. Silently dropped when the allowance already suffices, so it is safe to always include for a first-time depositor.permitNonce is a Permit2 *unordered* nonce — any unused 256-bit value, no sequence required. Reusing a spent one is a 400.spender in the signature is the ADAPTER, not the pool: it receives the pulled tokens before forwarding them.token is the pool's quoteToken(); read it from the pool, since the adapter signs over that value.txHash is real but pending (permitTxHash too, when a permit was folded). 400 is a bad request (error says which); 503 means retry.// domain — Permit2's, and it has NO version field
{ "name": "Permit2", "chainId": <CHAIN_ID>,
"verifyingContract": "0x000000000022d473030f116ddee9f6b43ac78ba3" }
// types
PermitWitnessTransferFrom(TokenPermissions permitted, address spender, uint256 nonce, uint256 deadline, TokenAllocationDeposit witness)
TokenPermissions(address token, uint256 amount)
TokenAllocationDeposit(address owner, address beneficiary, address pool)
// message
{ "permitted": { "token": <quoteToken>, "amount": <amount> },
"spender": <DEPOSIT_ADAPTER>, "nonce": <permitNonce>, "deadline": <unix seconds>,
"witness": { "owner": <owner>, "beneficiary": <owner>, "pool": <pool> } }
// primaryType: PermitWitnessTransferFrom
// additionalAllowances[0].signature signs the TOKEN's domain (read it
// via eip712Domain(); the nonce is the token's nonces(owner)):
Permit(address owner, address spender, uint256 value, uint256 nonce, uint256 deadline)
// message: { "owner": <owner>, "spender": "0x000000000022d473030f116ddee9f6b43ac78ba3",
// "value": <value>, "nonce": <token.nonces(owner)>, "deadline": <unix seconds> }
// → { "txHash": "0x…", "relayer": "0x…", "pool": "0x…", "owner": "0x…",
// "beneficiary": "0x…", "amount": "25000000000", "permitTxHash": "0x…"? }
/relayerWalletsWallets that may be named as a withdrawal's executor.
executor against msg.sender, so a signature naming an address we do not hold is unusable.{ "wallets": ["0x99…", "0x88…"] }
/poolNonce/:pool/:ownerThe nonce a withdrawal or allocation-request signature must carry.
{ "pool": "0x033d…0973", "owner": "0xabc…", "nonce": "3" }
/relayWithdrawRelay a signed withdrawal. Body: { pool, owner, recipient, executor, amount, nonce, deadline, signature }.
version.executor we do not hold, more than the owner's unallocated deposit, or an expired deadline.// domain — the POOL is the verifying contract
{ "name": "TokenAllocationPool", "version": "1",
"chainId": <CHAIN_ID>, "verifyingContract": <pool> }
// types
Withdraw(address owner, address recipient, address executor, uint256 amount, uint256 nonce, uint256 deadline)
// message
{ "owner": <owner>, "recipient": <owner>, "executor": <from /relayerWallets>,
"amount": <amount>, "nonce": <from /poolNonce>, "deadline": <unix seconds> }
// primaryType: Withdraw
// → { "txHash": "0x…", "relayer": "0x…", "pool": "0x…", "owner": "0x…",
// "recipient": "0x…", "amount": "12500000000" }
/relayAllocationRequestRelay a signed allocation request. Body: { pool, user, quoteAmount, maxPriceUsd, slippageBps, waiveCancellationRights, nonce, deadline, signature }.
executor field: the pool does not bind this signature to a sender.quoteAmount cannot exceed their deposit.maxPriceUsd is USD per whole offered token in 1e18 fixed point; slippageBps caps the discount from the oracle-implied amount (max 10000).waiveCancellationRights is part of the signed struct. false: relayable only before an allocation lock is scheduled. true: relayable any time and fillable while locked — but the request cannot be cancelled once locked.cancelAllocationRequest()/claimOfferedTokens() remain for a user sending their own transaction.// domain — the POOL is the verifying contract
{ "name": "TokenAllocationPool", "version": "1",
"chainId": <CHAIN_ID>, "verifyingContract": <pool> }
// types
AllocationRequest(address user, uint256 quoteAmount, uint256 maxPriceUsd, uint256 slippageBps, bool waiveCancellationRights, uint256 nonce, uint256 deadline)
// message
{ "user": <user>, "quoteAmount": <quoteAmount>, "maxPriceUsd": <1e18 USD>,
"slippageBps": <bps>, "waiveCancellationRights": <bool>,
"nonce": <from /poolNonce>, "deadline": <unix seconds> }
// primaryType: AllocationRequest
// → { "txHash": "0x…", "relayer": "0x…", "pool": "0x…", "user": "0x…",
// "quoteAmount": "5000000", "maxPriceUsd": "25000000000000000000",
// "slippageBps": "50", "waiveCancellationRights": false }
/relayCancelAllocationRequestRelay a signed cancellation. Body: { pool, user, nonce, deadline, signature }.
waiveCancellationRights: true cannot be cancelled once locked.// domain — the POOL is the verifying contract
{ "name": "TokenAllocationPool", "version": "1",
"chainId": <CHAIN_ID>, "verifyingContract": <pool> }
// types
CancelAllocationRequest(address user, uint256 nonce, uint256 deadline)
// message
{ "user": <user>, "nonce": <from /poolNonce>, "deadline": <unix seconds> }
// primaryType: CancelAllocationRequest
// → { "txHash": "0x…", "relayer": "0x…", "pool": "0x…", "user": "0x…" }
/relayClaimOfferedTokensRelay a signed claim of filled offered tokens. Body: { pool, user, nonce, deadline, signature }.
user — the signature carries no recipient, so the relayer cannot redirect the tokens.// domain — the POOL is the verifying contract
{ "name": "TokenAllocationPool", "version": "1",
"chainId": <CHAIN_ID>, "verifyingContract": <pool> }
// types
ClaimOfferedTokens(address user, uint256 nonce, uint256 deadline)
// message
{ "user": <user>, "nonce": <from /poolNonce>, "deadline": <unix seconds> }
// primaryType: ClaimOfferedTokens
// → { "txHash": "0x…", "relayer": "0x…", "pool": "0x…", "user": "0x…" }
Credits a trading wallet's volume to a depositing account. The wallet (not the account) signs an EIP-712 message; a per-(account, wallet) nonce makes each signature single-use. An account may link at most 20 wallets, and a wallet linked to one account must be unlinked before it can move to another (409 otherwise).
/linkedWallets/:addressWallets currently linked to an account.
{ "account": "0xabc…", "wallets": ["0xdef…"] }
/linkNonce/:account/:walletThe nonce the next link/unlink signature must carry.
{ "account": "0xabc…", "wallet": "0xdef…", "nonce": 3 }
/linkWalletLink a wallet. Body: { account, wallet, nonce, signature }.
signature is the wallet's EIP-712 signature over the typed data below. ERC-1271 contract wallets verify too.// domain
{ "name": "IPO Leaderboard", "version": "1", "chainId": <CHAIN_ID> }
// types
LinkWallet(address account, address wallet, uint256 nonce)
// message: the lowercased account + wallet and the nonce from /linkNonce
/unlinkWalletUnlink a wallet. Same body and signature scheme as /linkWallet.