Skip to main content
One script takes you through a full trade on Devnet. It registers your wallet (with an alpha test invitation code), waits for the automatic test-fund airdrop, locks collateral as margin, then places and cancels a limit order. Every POST /exchange call is signed with EIP-712; read queries to POST /info need no signature. The script resolves its contract from configs rather than assuming one. Filter to status: "Active" first — the response also returns delisted contracts, with a full parameter set and nothing else to mark them — then match on name. contractId 1/2/3 do not map to any fixed pair.

Prerequisites

Get an alpha test invitation code first. Devnet registration requires a valid single-use inviteCode — request one from the UpsideMAX team and set it as INVITE_CODE below. After you register, Devnet airdrops 10,000 USDC of Devnet-only funds (USDC only) to your account within ~10 seconds.

The script

Set INVITE_CODE, then run. Only registerAccount and lockCollateral use the EIP-712 typed path here — the full typed set is in Authentication.

Expected output

Configuration

The script hardcodes only two things, and neither is an ID: Everything else — the contract ID, the quote coin ID, priceScale, qtyScale, tickSize, stepSize — is read from configs at runtime, and the limit price is derived from the live mark price. Do not replace any of that with a literal. Contract IDs are server-assigned, scales differ per contract and are frequently 0, and a price that is not derived from the current mark will be rejected by the contract’s price band. Prices and sizes (p, s) are raw integer strings, scaled by that contract’s priceScale / qtyScale.
  • inviteCode requiredINVITE_CODE is missing or invalid. Set a valid single-use code from the UpsideMAX team.
  • Loop keeps waiting for margin — the airdrop hasn’t landed yet (it can take ~10s after registration). The loop exits automatically once marginAvailableForOrder turns positive.
  • Order rejected for margin — funds aren’t usable as margin yet. Wait for marginAvailableForOrder > 0, then retry.
  • No oid in the order response — submission is asynchronous. A 202 with "status": "accepted" means the batch was taken for processing, not that the order rested. The script confirms by polling userOrders for its own clientOrderId.
  • the order never rested — the order was rejected after acceptance. The rejection is only delivered on the orderUpdates channel, never in the HTTP response. Subscribe to it and read reason. The most common cause is price exceeds priceBandBps: a limit price further from the mark price than the contract’s priceBandBps allows.