TP/SL
Take-profit and stop-loss orders for open positions. Trigger prices are held off-chain by a conditional-order handler (“handler” from here on) — a solver-adjacent service. @symmio/trading-core speaks to the handler over signed HTTP for mutations and a defilytics-protocol WebSocket for state updates. The on-chain contract is only involved when a trigger actually fires and closes the position.
Each method, helper, and type below has its own page with the full signature, parameters, return shape, examples, and (for reads) query options.
The flow — POST + WebSocket
Every TP/SL mutation (new, edit, delete) follows the same two-step handshake:
- POST the signed EIP-712 message to the handler. A
200response means the handler accepted the request — the order is now processing, not yet live. - Wait for the WebSocket
reportframe withdata.successful: true. That frame is the final approval — the state transitions tonew(create / edit) orcanceled(delete).
The SDK does not poll after a mutation. The WebSocket report is authoritative, and the framework layer (@symmio/trading-react) reconciles confirming → new / canceled off it. If you’re building a UI, subscribe via watchTpSlNotifications and reflect the state change when the matching frame lands.
Same handshake for new / edit / delete — POST accepts, WS confirms. Even a 200 without a WS report means the order is still processing, and the UI should render it as such.
Attaching TP/SL to a new position (instant open)
For a brand-new order that should ship with a TP and/or SL attached, the flow is:
- Call
instantOpen(orinstantOpenAuto). The solver responds with atempQuoteId(negative integer) that identifies the pending trade before it anchors on-chain. - Immediately POST
setQuoteTpSlusing thattempQuoteIdas thequoteIdargument. The handler creates the conditional order against the pre-chain identity. - When the position anchors on-chain and gets its real positive
quoteId, the handler transparently mapstempQuoteId ↔ quoteId. The TP/SL row survives the transition — you can read it back with either id.
The React layer wraps this in useInstantOpenWithTpSl, which orchestrates both POSTs and stitches the state into one mutation. Directly in core, it’s two sequential calls: instantOpenAuto → setQuoteTpSl with the returned tempQuoteId.
Concepts
Conditional order — one leg of a TP/SL, addressed by a handler-issued cohQuoteId (e.g. "coh4213"). A quote has at most one active TP and one active SL at a time.
Quote id vs temp quote id — a pre-chain instant-open exists at the handler under a hedger-issued tempQuoteId (negative integer). Once it anchors on-chain, the same order gains a positive quoteId. TP/SL orders are addressable by either id — the handler maps them, so reads and writes can use whichever id the caller has. getQuoteTpSl accepts a negative tempQuoteId so a pre-chain quote’s TP/SL can be read the moment the hedger accepts an instant open.
Notification frame — a report on the WebSocket, normalized into a TpSlNotification. Carries primaryIdentifier (on-chain id or 0), secondaryIdentifier (temp id or 0), conditionalOrderType (take_profit | stop_loss), state, successful, and — on some frames — details.trigger_price. This is the source of truth for state transitions; the SDK does not poll after mutations.
States — the handler emits a small state machine over the WebSocket (the wire values of RawTpSlNotificationState):
| State | Meaning |
|---|---|
pending | POST accepted; awaiting handler processing. |
new | Handler confirmed the order is live (create path). |
edit | Handler confirmed an edit to an existing order. |
triggered / trigger | The price condition fired; the close is in flight. |
cancel / canceled / cancelled | Delete confirmed, or handler dropped the order. |
close | Terminal — position closed via this order. |
The React layer overlays a confirming synthetic state locally (part of TpSlInfoState) between the POST and the WS report so the UI can show “processing…” without extra plumbing.
Reads
Raw conditional-order rows for one quote from the handler.
getTpSlConfigHandler-side rules a TP/SL request must satisfy (min distance, min spread).
getTpSlSigningSpecEIP-712 typed-data domain + schema for POST (create / edit).
getTpSlDeleteSigningSpecEIP-712 typed-data domain + schema for the DELETE endpoint.
Writes
Sign and POST a TP and/or SL order for a quote.
deleteQuoteTpSlCancel a live TP or SL by its handler-issued cohQuoteId.
WebSocket
Subscribe to live conditional-order state transitions for a SubAccount.
parseTpSlFrameParse one raw defilytics frame into a TpSlNotification, or null.
Signing & validation
Pure pre-submit check of a TP/SL pair against the handler’s rules.
generateTpSlSaltRandom uint256 salt (decimal string) for replay protection.
signTpSlRequestSign a message with the session-key wallet into the handler’s request body.
toSignableTpSlMessagePad null legs with ZERO_LEG so EIP-712 can hash the message.
Build a delete-conditional-order EIP-712 message body.
buildConditionalOrderMessageBuild a create/edit conditional-order EIP-712 message body.
buildConditionalOrderLegBuild one leg (TP or SL) of a conditional-order message.
priceSlippageCalculationShift a trigger price by a slippage percent to derive a leg’s fill price.
Two constants ship alongside these helpers: DEFAULT_TPSL_SLIPPAGE_LOWCAPS (the default slippage percent — see priceSlippageCalculation) and ZERO_LEG (the empty-leg sentinel — see toSignableTpSlMessage).
Types
Normalized WebSocket report the SDK delivers to consumers.
RawTpSlNotificationThe raw defilytics wire frame retained on TpSlNotification.raw.
One conditional-order row as returned by getQuoteTpSl.
Folded per-quote snapshot with both sides merged.
TpSlConfigHandler /configs/ payload — the rules a request must satisfy.
Handler /signing-spec payload — EIP-712 domain + schema.
One side (TP or SL) of a setQuoteTpSl call.
Outcome of validateTpSl — ok plus per-side errors.
Inputs to validateTpSl.
Create/edit conditional-order message body (pre-signature).
TpSlConditionalOrderLegOne leg of a conditional-order message body.
TpSlDeleteMessageDelete-order message body (pre-signature).
TpSlSignedRequestFinal POST/DELETE body — typed data + signature.
TpSlPriceTypeWhether a trigger trips on the mark price or the last-close price.
TpSlInfoStateLifecycle stage of a TP or SL order, including the synthetic confirming.
Query options
Each read ships a matching …QueryOptions factory and a …QueryKey builder for TanStack Query; each write ships a …MutationOptions factory. See each method’s page for the exact call. These are the primitives @symmio/trading-react’s hooks build on.
Related
- React bindings —
useQuoteTpSl,useSetQuoteTpSl,useDeleteQuoteTpSl, anduseWatchTpSlNotifications. - WebSocket concept — pool, reconnect, and the
SocketStatuslifecycle the TP/SL stream reuses. - Solvers — instant open/close, the source of the
tempQuoteIda pre-chain TP/SL binds to. - Quotes — unified quote reconciliation the TP/SL state folds into.