Build a perp operation
The instructions of one perp operation, as ONE transaction for wallet to sign, and with
serialize: true the unsigned transaction itself. Nothing is signed, sent or reserved.
The same body works on both venues; only marketId changes. The operations:
op | What it does | Jupiter | GMTrade |
|---|---|---|---|
open | Open or increase a position at market | yes | yes |
limit | Open at a trigger price (long below the mark, short above) | 422 venue_form | yes |
close | Reduce or close at market (closeBps, default all) | yes, paid out in USDC | yes, paid out in the position’s collateral |
tpsl | Resting take profit (tp) or stop loss (sl) on a position | yes, paid out in USDC | yes, paid out in the position’s collateral |
update | Move the trigger or the size of a resting order | 422 venue_form (cancel, then tpsl) | yes |
cancel | Cancel a request or pending order (orderId) | yes, 45 s after it was created | yes, while pending |
deposit | Add collateral to a position (amountUsd) | yes | yes |
withdraw | Remove collateral from a position (amountUsd) | yes, paid out in USDC | yes, in the position’s collateral |
The transaction is, in order: a memo dad-perp:<op>:<clientOrderId> signed by the wallet, the
funding route (if any), then the venue’s instructions (token accounts created idempotently,
native SOL wrapped before and unwrapped after, GMTrade’s user and position accounts when
missing, the order). It is a v1 transaction
(4 096 bytes, 64 instructions, 64 accounts, no lookup tables): compute limits are in its
message, not in instructions.
Keeper execution. Landing this transaction queues the operation; the venue’s keeper executes
it later (venueForm says how). On Jupiter a market request lives seconds and can be cancelled
45 s after its creation; on GMTrade an order can be cancelled while it is pending, and each
order escrows a 300 000-lamport execution fee for the keeper, returned by cancel.
clientOrderId is not an idempotency key. It derives the address of the request/order,
so a retry of the same (op, clientOrderId) fails while the first one is still pending, but
acts a second time once the keeper has executed it. Check whether the first transaction landed
before retrying.
Wallet accounts (positions, the GMTrade user account, the order named by orderId) are read
from the chain at every call.
Authorizations
Body
One body for every operation and venue. Fields an operation does not use are ignored.
Always required: wallet, op, marketId, side, clientOrderId.
Fee payer, owner and only signer of the transaction (base58)
open, close, tpsl, cancel, deposit, withdraw, limit, update <venue>:<SYMBOL>-PERP
"jupiter:SOL-PERP"
The position's side (buy/sell accepted). For close, tpsl, deposit, withdraw, cancel and update, the side of the existing position or order
long, short Your id, 1 to 64 bytes. Goes in the memo and derives the request/order address: use a new one per operation
1 - 64open, limit (required): collateral in micro-USD
x >= 1open, limit (required): leverage in bps
x >= 10000Price band around the mark (around the trigger for limit; unused by tpsl) the keeper may execute at; the funding route's slippage; and how far the collateral may move from a routeTicket before 409
0 <= x <= 9999open, limit, deposit: what the wallet pays with; see /perp/quote
open, limit, deposit with a routed fundingMint: the funding.routeTicket of a /perp/quote. Without it the route is quoted again
close, tpsl: share of the position, 10000 = all
1 <= x <= 10000tpsl (required). TP of a long and SL of a short must be above the mark, the other two below
tp, sl limit, tpsl (required), update (optional): price × 10^6
x >= 1cancel, update (required): the request/order address, from /perp/account orders[].orderId or a build's detail.request
deposit, withdraw (required): micro-USD. update: the new size in micro-USD (how much a TP/SL closes, or a limit's notional)
x >= 1Also return the unsigned transaction (transaction, lastValidBlockHeight)
Priority fee for the whole transaction in lamports (set in the serialized transaction's message)
Transaction format. Only v1 is served; 0 is refused
1 Response
The operation, its accounts and its transaction
Id of the built transaction (32 hex), joined with the landed transaction through the memo
jupiter, gmtrade long, short What else this one transaction carries besides the order
The accounts this operation creates or acts on
Compute unit limit of the transaction (funding route + 300 000 on Jupiter, 400 000 on GMTrade)
Bytes of accounts the transaction loads, declared in a v1 message
v1 In execution order. No ComputeBudget instruction: in v1 the limits are computeUnits and loadedAccountsDataSize, which you must set yourself if you assemble the transaction
Always empty
How the venue executes the operation (by its keeper)
With serialize: the unsigned v1 transaction, base64. The wallet signs it
With serialize: the blockhash expires after this block height
open and limit only: the numbers the order was built with
Only with a routed fundingMint; routeTicket is not repeated here