Skip to main content

Orders

The struct, domain name and version are the same for both generations, binary and neg-risk:
Two values depend on the market’s generation (how to detect it):
  • maker, in the struct and in the request body: your vault of that generation;
  • domain.verifyingContract: the market’s exchange.
Everything else is as in Placing orders and EIP-712 signing. Cancels (POST /api/orders/cancel, cancel-batch, cancel-all) are keyed by your wallet: they cover orders of both vaults, before and after the upgrade. GET /api/orders/open lists the orders of both vaults; each order’s maker shows which vault it rests on.

The vault field

Withdraw, redeem and split / merge / convert take an optional vault: one of your vaults[].vaultAddress.

Withdraw

POST /api/withdrawals/request (withdraw:write or vault:write), the usual request plus vault. userSig is WithdrawERC20 signed in the domain of that vault:
  • Any other destination from a generation-2 vault: 400 withdrawal_destination_not_allowed (details: { destination, vaultAddress, generation }). It is checked before the 2FA code, so the code is not spent. Withdraw to your wallet and transfer from there.
  • A listed destination can be removed at any time. A refused destination is final for that request.
  • 2FA and whitelist rules are unchanged. A TOTP code is single-use per 30-second step: a second withdrawal in the same step needs the next code or a backup code.
  • 503 withdrawal_unknown: the withdrawal may have been created. Do not sign a new one; a new salt is a second withdrawal. Re-send the same body (same salt, expiry, userSig, totpCode) for up to about 60 seconds, then check GET /api/me/withdrawals. A stored request answers with its withdrawal (details.withdrawalId).
  • 503 withdrawal_temporarily_unavailable: nothing was created. Retry later, with a new 2FA code if 2FA is on.
  • Cancel (POST /api/me/withdrawals/{id}/cancel) now also accepts withdraw:write.

Redeem

POST /api/me/positions/redeem (positions:write or vault:write), then poll GET /api/me/positions/redeem/{jobId} until confirmed. Redeem a legacy market on the generation-1 vault and a generation-2 market on the generation-2 vault; the payout lands in that vault. API-key callers sign a RedeemAuthorization (the relay is gasless):
Refusals: 400 redeem_signature_required, 400 redeem_expired, 403 redeem_signer_mismatch. Sign a fresh authorization.

Split / merge / convert

The existing flow with vault added at each step:
  1. POST /api/vault/split-signature (or merge-signature, convert-signature) with { marketId, amount, vault } and an Idempotency-Key header. For neg-risk markets, supply outcomeIndex (uint8, 0..254) to specify the sub-question. The answer carries vaultAddress, the payload and backendSig.
  2. Sign the typed data in the domain of vaultAddress (PredictStreetVault / 1). Check it hashes to digest.
  3. POST /api/me/positions/op-submit with { signedOpId, ownerSig, backendSig, vault }, then poll GET /api/me/positions/op-submit/{jobId} until confirmed.

Balances and positions

Legacy markets after the upgrade

  • Quote and trade them as before, with the generation-1 vault as maker and the generation-1 exchange as verifyingContract.
  • Resting generation-1 orders stay live and cancel as usual.
  • When a legacy market resolves, redeem with vault = the generation-1 vault, then withdraw or move what is left.