Design: Flutter Polymarket Deposit Wallet
Status: Designed; plan written; paused on Flutter WIP. Source: docs/superpowers/specs/2026-05-07-flutter-polymarket-deposit-wallet-design.md. User-facing reference: Polymarket Deposit Wallet.
Summary
Section titled “Summary”Polymarket announced (May 2026) that new API users must trade through a relayer-deployed deposit wallet (CREATE2 contract) instead of a raw EOA. Existing Magic / proxy / Safe users are unaffected. The Polymarket flow has six steps; this slice covers the first four — derive address, deploy via WALLET-CREATE, hand off pUSD funding to the user, and submit the standard six-call approval batch via WALLET. Trading itself (CLOB orders with signature_type=3 / POLY_1271 / ERC-7739) is the next slice.
The Flutter app implements the flow standalone: no server-arenaton involvement, direct calls to relayer-v2.polymarket.com. polygolem serves as the canonical Go reference; the Dart code mirrors its internal/wallet/derive.go and internal/relayer/{client.go,signing.go,approvals.go} shapes file-for-file. Cross-language correctness is verified by golden tests against polygolem’s known-good outputs.
Architecture
Section titled “Architecture”The Dart code is organized to mirror polygolem layer-for-layer so cross-language parity is auditable.
arenaton-flutter/lib/├── config/│ └── polymarket_environment.dart # relayer URL, factory, addresses, chainId├── models/polymarket/│ ├── deposit_wallet_state.dart # state enum + persistence record│ └── relayer_transaction.dart # mirror of polygolem/internal/relayer/types.go├── services/polymarket/│ ├── polymarket_wallet_derivation.dart # mirror of internal/wallet/derive.go + auth/signer.go│ ├── polymarket_calldata.dart # mirror of internal/relayer/approvals.go│ ├── polymarket_typed_data.dart # mirror of internal/relayer/signing.go│ └── polymarket_relayer_service.dart # mirror of internal/relayer/client.go├── controllers/│ └── polymarket_setup_controller.dart # state machine, Reown bridge, persistence└── widgets/settings/ └── polymarket_setup_card.dart # the only UI surfaceState machine
Section titled “State machine”notStarted → addressReady → deploying → deployed → approving → ready ↓ error ← any failure (retryable | not)Each per-EOA record is persisted in flutter_secure_storage at key arenaton.polymarket.setup.<eoaLowercase>. Switching the active EOA in the wallet UI rehydrates the new EOA’s record without mutating the previous one.
Cross-language parity
Section titled “Cross-language parity”Three golden tests lock the Dart implementation byte-for-byte to polygolem:
| Test | Asserts |
|---|---|
polymarket_wallet_derivation_test | EOA 0x2c75…65c23 derives to 0xfd5041…fa3cf9c (matches polygolem auth_test.go:113). |
polymarket_calldata_test | The 6-call approval batch has the exact ordering and bytes polygolem’s BuildApprovalCalls() produces. |
polymarket_typed_data_test | The EIP-712 envelope (domain, types, primaryType) matches polygolem’s depositBatchTypes() and depositBatchDomain(). |
If polygolem ever changes its derivation or typed-data builder, the Dart goldens will break — that’s the intended failure mode.
Reference constants (Polygon 137)
Section titled “Reference constants (Polygon 137)”Mirrors polygolem internal/auth/signer.go and internal/relayer/approvals.go:
factory = 0x00000000000Fb5C9ADea0298D729A0CB3823Cc07impl = 0x58CA52ebe0DadfdF531Cde7062e76746de4Db1eBdepositCloneC2 = 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076depositCloneC1 = 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3prefix = 0x61 0x00 (0x3d + len(args)) 0x3d 0x81 0x60 0x23 0x3d 0x39 0x73pUSD = 0xC011a7E12a19f7B1f670d46F03B03f3342E82DFBCTF = 0x4D97DCd97eC945f40cF65F87097ACe5EA0476045ctfExchangeV2 = 0xE111180000d2663C0091e4f400237545B87B996BnegRiskV2 = 0xe2222d279d744050d28e00520010520000310F59negRiskAdptV2 = 0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296relayerProd = https://relayer-v2.polymarket.comrelayerPreprod = https://relayer-v2-preprod-int.polymarket.comNon-goals
Section titled “Non-goals”- No CLOB order placement (signature_type=3 / POLY_1271 / ERC-7739) — separate slice.
- No
server-arenatonchanges — Flutter standalone. - No
polygolemchanges — read-only reference. - No in-app pUSD funding — funding is fully external.
- No multi-chain — Polygon mainnet only.
- No support for Magic / browser / Safe accounts — existing users unaffected.
- Cross-language drift. Mitigated by golden tests on the Dart side; polygolem has its own Go tests.
- Polymarket API change. Addresses live in a single config file; no mid-flow auto-failover.
- Reown popup latency. Relayer rejects expired deadlines; user retries with a fresh nonce.
- User funds the wrong address. Funding panel emphasizes the deposit-wallet hex and labels it as different from the owner EOA.