Take-profit / stop-loss
TP/SL is a deferred close. You sign a typed-data message now, the conditional-orders handler (COH) holds it, and when the trigger price is hit the COH submits a real close to the solver on your behalf. That's why the bot delegation exists.
A different domain and message shape
Unlike opens and closes, TP/SL doesn't use the SymmioInstantLayer domain. It uses:
domain = {
name: "ConditionalOrder",
version: "1",
chainId: <chain id>,
verifyingContract: <InstantLayer address> // same address
}The message has a top level with seven scalar fields and three nested "leg" structs:
virtualAccount: the VA holding the positionsubAccount: the parent sub-accountsalt: randomuint256quoteId:int256(yes,intfor some reason; the value is positive)symbolId,positionType,affiliatetakeProfit: leg struct (see below)stopLoss: leg struct (see below)sendQuote: leg struct with an extraleveragefield (see below)
All three legs must be present even if you're only setting one. The COH rejects messages with missing legs. Zero-fill the unused legs:
For an active leg, the fields mean:
quantity: total quantity to close (decimal string, must match symbol'squantity_precision)price: current mark price as a reference (decimal string, must matchprice_precision)orderType:1for MARKETconditionalPrice: the trigger price (decimal string, must matchprice_precision)conditionalPriceType: typically"last_close"
Decimal precision matters here. The COH rejects unbounded decimals with error_code: 407 "provided values do not meet the required precision standards". If price_precision = 6, send "0.013242", not "0.013241567893". Same for quantity and conditionalPrice.
You can sanity-check your typed-data encoder: hit GET <conditional-orders endpoint>/signing-spec (with the deployment's App-Name header) and you'll get back the live, authoritative type schema plus an expectedMessageHash for the included example. Encode that example with your library and confirm you produce the same hash.
POST it
200 { "successful": true } means the order is registered. The COH will fire it on trigger, you'll see TriggeredTPSL on the notifications feed, and a normal close fill will follow.
Failure modes worth recognizing on sight:
401 "parent subaccount has not delegated required access to COH for selectors=REQUEST_TO_CLOSE_POSITION"withrecovered_signer = 0x2471...: the bot delegation is missing. Re-run it.401 "recovered signer is neither owner nor active session key": the session-key delegation for0x00000001is gone (expired or never granted). Re-run it.401 "virtualAccount X does not match predicted VA Y": your sub-account doesn't havesingleVAMode = true. This can't be fixed on the existing sub-account; create a new one.400 error_code 407: precision. Quantize before sending.404on a quote that already has a TP/SL: one-shot per quote. Cancel the existing order or open a new position.
Last updated

