Venues & custody
A venue is where a trade happens. Every venue sits behind the same adapter interface with one activation handshake β your integration code does not branch per venue β but each venue keeps its own custody model, because that is what makes the system non-custodial rather than non-custodial-in-name.
The venue model
The rule across all venues: the execution service can submit trades, it can never withdraw. What enforces that differs per venue and is listed below β it is always the venue's own credential mechanism, never a policy promise.
Venue reference
- Name
spot- Type
- live
- Description
Spot copying on EVM. Custody: an ERC-7579 smart session scoped to swap routers with an explicit spend cap and hard expiry β it cannot transfer tokens out and dies at
validUntil. Activation: one on-chain transaction (enable session); gas paid by the user or a paymaster. Requires an ERC-7579 smart-account wallet.
- Name
hyperliquid-perps- Type
- live
- Description
Perps copying on Hyperliquid. Custody: an agent key the user approves in their own wallet and can revoke at any time; agent approvals do not expire. Activation: 1β2 signatures, no gas, works from any EOA.
- Name
polymarket-predictions- Type
- sandbox
- Description
Prediction-market copying on the Polymarket CLOB. Custody: an ERC-7579 smart session scoped to order signing β the exchange asks the user's own account to validate every order signature (ERC-1271), and the account's on-chain session validator decides what it will honour. A fully compromised backend could sign bad orders; it cannot move a cent. Activation: a one-time transaction deploying the user's account on Polygon (Polymarket requires a deployed maker; gas paid by the user or sponsored by you) plus the session install. Prediction risk config adds
maxSlippagePointsandminHoursToResolution. Regional note: Polymarket rejects new orders from a number of regions (US, UK, DE and others) β the restriction follows the end user, and the venue'savailabilityblock lists the codes.
Predictions currently executes in sandbox: activation and leader
grading are real, every mirror decision is recorded with its reasoning, and
nothing is submitted while order signing finishes review. listVenues()
returns what your key is actually entitled to β ask rather than assume.
An earlier polymarket-perps venue was removed before launch: its proxy
credential was unscoped β capable of transferring arbitrary amounts β which
fails the rule at the top of this page. Venues here are non-custodial by
enforcement, not by promise, and a venue that cannot meet that bar does not
ship.
Which wallets land where
The deciding question per venue is what the end user's account can do β not which wallet brand they use. Three facts save integrators the most debugging:
- "Smart account" is not enough β spot and predictions need ERC-7579.
MetaMask's smart-account mode (EIP-7702) delegates to MetaMask's own
delegation framework, which has no ERC-7579 module surface β MetaMask users
are perps-only today, even after upgrading. A MetaMask lane built on that
framework's own scoped delegations is in development; its activation step
(
client_delegation_grant) already ships explained in the SDK, so an integration written today renders it correctly when it arrives. The same applies to other non-7579 smart accounts (e.g. Coinbase Smart Wallet). - Privy / Dynamic default embedded wallets are plain EOAs. They qualify for perps immediately. Your users are in the spot column only if your provider's smart-wallets feature is enabled on an ERC-7579 implementation (e.g. Kernel).
- A plain EOA can never do non-custodial spot copy β for anyone. One key, unlimited authority, no mechanism to scope it. Any product offering spot copy to plain EOAs holds either the user's key or their funds. This matrix is the honest boundary, not a missing feature.
Expiring credentials
Hyperliquid agent approvals do not expire. Smart sessions do β spot and Polymarket credentials both end at the session's validUntil. Handle the session.expiring signal and re-run activate() to renew.
An agent whose credentials lapse moves to status expired. This is deliberately distinct from paused: an expired agent needs the user to re-authorise in their wallet, not just a resume call from your app.
Agent status
- Name
active- Type
- status
- Description
Credentials valid, mirroring the leader.
- Name
paused- Type
- status
- Description
Stopped by the user or your app; resumable without re-authorisation.
- Name
expired- Type
- status
- Description
Credentials lapsed; the user must re-authorise via
activate(). Not resumable silently β surface it in your UI.