associatedWallet
from nothing to fully trading in five steps. Every code block is
real ethers v6 against the live testnet — paste it in, swap your
API key + private key, run.
Don’t have an API key yet? Partner keys are issued by PredictStreet
ops — they are never self-service. Email your integration manager
(or partners@predictstreet.com)
with the items listed in
API keys → Getting a key and you’ll
receive a testnet
ps_live_… key plus the KYC prerequisites for
orders:write and vault:write scopes.Prerequisites
1. Mint testnet USDC to your EOA
MockCollateral exposes a public mint(address, uint256) on testnet —
mint as much as you want. Note: USDC needs to land in your EOA
first; the vault deposit moves it from EOA → vault in a later step.
2. Get your vault address
The platform deploys your vault automatically once your associated wallet has a platform account (its first sign-in to the web app) — you do not callVaultFactory.deployVault yourself, and you do not
pay the deploy gas. An orders:write / vault:write key is issued
only for a wallet that has signed in and cleared KYC tier 1, so by the
time you have a working API key, your vault is either deployed or
about to be.
Poll GET /api/me/vault until deployed: true:
Multi-wallet partner keys. If your key acts for many wallets, the
first authenticated request with a new
X-User-Wallet (for example
GET /api/me/balances or the GET /api/me/vault poll above) onboards
that wallet: the platform deploys its vault and opens its deposit
limits, typically within 30 seconds, with no per-wallet KYC. Public
endpoints such as GET /api/events do not trigger it. Do not sign in to
the web app with a wallet you intend to use through the partner key: that
makes it a regular retail account (KYC tier 0), and deposits into its
vault revert with KycRequired().Instead of polling, you can listen for
vault_created on the
user_activity channel of /ws/user. Auto-deploy normally
completes within a few seconds.3. Approve + deposit USDC into the vault
/api/me/balances will show available = 500 USDC. The on-chain approve
step stays on your side regardless of auto-deploy — ERC-20 transferability
is owner-only by design. See Deposits for
the full lifecycle and Deposit limits for
the per-deposit, 30-day and 12-month caps applied to your wallet.
The platform sets your deposit tier and caps from your KYC level,
independently of the vault deploy:
deployed: true on
GET /api/me/vault does not mean you can deposit yet. Before the
first deposit, poll GET /api/me/deposit-limits until tier is
non-zero and restrictions.depositBlocked is false. Stop polling
if tier reads 5: the wallet has been rejected by compliance and
every deposit reverts with UserIsRejected(). If tier is 1–4
but depositBlocked stays true, the cause is a deposit restriction
or a fully used cap, not timing — see
Deposit limits.4. Place orders
EIP-712 helper
Every order is signed against the on-chainCTFExchange Order
struct (11 fields). See EIP-712 signing
for the full type table. Helper:
Pull a real tokenId (and the per-market fee)
LIMIT BUY (rests in the book)
MARKET BUY (best-effort, IOC)
MARKET requires timeInForce: ioc or fok. The price field still
travels (it acts as a slippage cap — you only fill at price-or-better).
Cancelling
5. Split USDC → YES + NO so you can SELL
A SELL order must reference outcome ERC-1155 tokens that already sit in your vault. You get them by depositing USDC and then callingvault.splitPosition(...) with a backend co-signature. The backend
returns the co-sig from POST /api/vault/split-signature; you sign
the same struct yourself, then submit on-chain.
side: 'sell':
Order types — what you can ask for
The platform supports the following combinations end-to-end:price is always required, even for MARKET — it acts as the
slippage cap. The matcher will only consume liquidity at price or
better.
expiry (= EIP-712 expiration) defaults to 0 (no on-chain
expiry). A non-zero value is fine for off-chain matching but races
async on-chain settlement; if the deadline passes between match and
submit, the on-chain leg reverts with OrderExpired(). Recommend
keeping 0 unless you specifically need a hard TTL well above
worst-case settlement latency.
Verifying state after each step
Common pitfalls
Where to go next
EIP-712 signing reference
Full struct + TypeScript / Python signing examples.
Order lifecycle
PENDING → OPEN → PARTIAL → FILLED state machine + on-chain settlement.
Vault contract reference
Full ABI, dual-sig flow, emergency withdraw, digest invalidation.
Time-in-force semantics
GTC / IOC / FOK behaviour in detail.