Deposits and withdrawals
Deposits involve approval and confirmation. Approval alone does not increase your platform balance. Check the asset, amount and recipient before withdrawing.
Actions and states
How do I participate?
Connect your wallet, fund your platform balance, choose numbers and confirm your purchase.
When can I claim?
After results are confirmed and prizes settled, claim winnings in your account.
What happens during a dispute?
The round awaits UMA resolution. A countdown ending does not confirm the result.
What are public records?
The result sources, draw transactions and settlement records for a round.
Read full technical documentation
Choose the right boundary
A third-party client does not need to trust the WF frontend. Read the active manifest, connect a wallet to Polygon Mainnet, read state from the chain or indexer, and submit user transactions directly to the deployed contracts.
The backend is not a general transaction relay. Its public write surface is limited to issuing an EIP-712 deposit authorization after fixed-asset whitelist and AML checks. The new Reserve has no per-transaction or daily quantity cap; balance, reserve liquidity, authorization, signature, minOut and pause checks still apply.
| Boundary | Use it for | Trust model |
|---|---|---|
| Chain RPC | Contract reads, simulations, receipts | Authoritative state |
| User wallet | approve, deposit, buy, claim, withdraw | User signs every write |
| Indexer | Rounds, tickets, activity, history | Eventually consistent cache |
| Public backend | Deposit authorization and token list | Policy-gated service |
1. Read the deployment
Do not hard-code an address copied from a blog post or an old environment. The active manifest is the versioned source for chainId, deploymentId, start blocks, feature gates, and contract addresses.
import { deployment } from "@wf-protocol/contract-sdk";
if (deployment.chainId !== 137) throw new Error("wrong network");
if (deployment.status !== "active") throw new Error("deployment is not active");
console.log(deployment.deploymentId);
console.log(deployment.contracts.unifiedLedger);
console.log(deployment.features.btc15m);2. Fund USD through the authorized deposit flow
The user first requests a signed authorization from the public backend. The response is then consumed by the user's wallet in the StablecoinReserve.deposit call. The backend never receives the user's private key and never submits the deposit transaction.
The EIP-712 domain is WUSDStablecoinReserve v1 on chain 137. The signed message fields are user, token, authorizedAmount, deadline, and nonce. The contract also receives minWusdOut for slippage protection.
const auth = await fetch(`${PUBLIC_API}/api/v1/deposit-authorizations`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ userAddress, token, amount: amount.toString() }),
}).then((r) => r.json());
await wallet.writeContract({
address: stablecoinReserve,
functionName: "deposit",
args: [token, amount, BigInt(auth.amount), amount,
BigInt(auth.deadline), BigInt(auth.nonce), auth.signature],
});3. Authorize and enter a game
Standalone UnifiedLedgerV4 is an internal six-decimal ledger, not an ERC-20. Users call executePurchaseV4 themselves, or sign PurchaseRequestV4 for a broadcaster to call executePurchaseWithAuthorizationV4. Both paths bind the owner, game, amount, purchase data, nonce and deadline. No operator allowance is required.
await wallet.writeContract({
address: unifiedLedger,
abi: unifiedLedgerV4Abi,
functionName: "executePurchaseV4",
args: [request, purchaseData],
});4. Wait for finality, then reconcile
- Treat the transaction receipt and contract state as the source of truth for a write.
- Use the indexer after the receipt to render history and denormalized round state; indexing may lag the chain.
- Every integration should surface deploymentId and txHash so a user can audit the exact chain and transaction.
- Never infer a prize, refund, or final draw from an indexer row without checking the corresponding contract state when money is at stake.