Skip to main content

Take Profit Stop Loss SDK

The TPSL (Take Profit Stop Loss) SDK provides functions for managing conditional orders that execute when certain price conditions are met. A conditional order pairs a trigger condition with a pending order. Once the oracle price crosses the trigger price, anyone can execute the pending order on the manager's behalf.

SDK setup​

TPSL functions live on the DeepBook client extension. Create a SuiGrpcClient and extend it with deepbook(), passing the margin managers you want to address by key.

import { deepbook } from '@mysten/deepbook-v3';
import { SuiGrpcClient } from '@mysten/sui/grpc';

const client = new SuiGrpcClient({
network: 'testnet',
baseUrl: 'https://fullnode.testnet.sui.io:443',
}).$extend(
deepbook({
address: '<YOUR_ADDRESS>',
marginManagers: {
MARGIN_MANAGER_1: { address: '0x…', poolKey: 'SUI_DBUSDC' },
},
}),
);

All TPSL functions live on client.deepbook.marginTPSL and return a callback that accepts a Transaction object. Pass the returned function to tx.add(...) or call it with an existing Transaction instance. For the full client setup, including keypairs and margin manager keys, see DeepBook Margin SDK.

TPSL functions​

The DeepBook Margin SDK provides the following functions for managing conditional orders.

addConditionalOrder​

Use addConditionalOrder to add a conditional order that executes when a price condition is met. The call returns a function that takes a Transaction object.

Parameters

  • marginManagerKey: String that identifies the margin manager.
  • conditionalOrderId: String representing the unique ID for this conditional order.
  • triggerBelowPrice: Boolean indicating whether to trigger once the oracle price falls below the trigger price. Set it to false to trigger once the price rises above the trigger price.
  • triggerPrice: Number representing the oracle price at which to trigger the order. The trigger must not already have been crossed, otherwise the call aborts with EInvalidCondition.
  • pendingOrder: Object containing the order details (either PendingLimitOrderParams, which includes a price field for the limit price, or PendingMarketOrderParams, which has no price field).

cancelConditionalOrder​

Use cancelConditionalOrder to cancel a specific conditional order. The call returns a function that takes a Transaction object.

Parameters

  • marginManagerKey: String that identifies the margin manager.
  • conditionalOrderId: String representing the ID of the conditional order to cancel.

cancelAllConditionalOrders​

Use cancelAllConditionalOrders to cancel all conditional orders for a margin manager. The call returns a function that takes a Transaction object.

Parameters

  • marginManagerKey: String that identifies the margin manager.

executeConditionalOrders​

Use executeConditionalOrders to execute conditional orders that have been triggered. This is a permissionless function that anyone can call. The call returns a function that takes a Transaction object.

Parameters

  • managerAddress: String representing the address of the margin manager whose orders to execute. Unlike the other functions, this one takes the manager address rather than marginManagerKey, the string that identifies the margin manager.
  • poolKey: String that identifies the DeepBook pool.
  • maxOrdersToExecute: Number representing the maximum number of orders to execute in this call.

Helper functions​

These helper functions create conditions and pending orders for conditional orders.

newCondition​

Use newCondition to create a trigger condition for a conditional order. The call returns a function that takes a Transaction object.

Parameters

  • poolKey: String that identifies the pool.
  • triggerBelowPrice: Boolean indicating whether to trigger when price falls below the trigger price.
  • triggerPrice: Number representing the price at which to trigger.

newPendingLimitOrder​

Use newPendingLimitOrder to create a pending limit order for use in conditional orders. The call returns a function that takes a Transaction object.

Parameters

  • poolKey: String that identifies the pool.
  • params: PendingLimitOrderParams object containing:
    • clientOrderId: Number for client tracking.
    • orderType: Optional order type (default: NO_RESTRICTION).
    • selfMatchingOption: Optional self-matching option (default: SELF_MATCHING_ALLOWED).
    • price: Number representing the limit price.
    • quantity: Number representing the order quantity.
    • isBid: Boolean indicating if this is a buy order.
    • payWithDeep: Optional boolean for fee payment (default: true).
    • expireTimestamp: Optional expiration timestamp.

newPendingMarketOrder​

Use newPendingMarketOrder to create a pending market order for use in conditional orders. The call returns a function that takes a Transaction object.

Parameters

  • poolKey: String that identifies the pool.
  • params: PendingMarketOrderParams object containing:
    • clientOrderId: Number for client tracking.
    • selfMatchingOption: Optional self-matching option (default: SELF_MATCHING_ALLOWED).
    • quantity: Number representing the order quantity.
    • isBid: Boolean indicating if this is a buy order.
    • payWithDeep: Optional boolean for fee payment (default: true).

Read-only functions​

conditionalOrderIds​

Query all conditional order IDs for a margin manager. Like the other TPSL functions, conditionalOrderIds lives on client.deepbook.marginTPSL. Like the other TPSL functions, conditionalOrderIds lives on client.deepbook.marginTPSL.

conditionalOrder​

Query a specific conditional order by ID.

lowestTriggerAbovePrice, highestTriggerBelowPrice​

Query trigger prices for conditional orders. lowestTriggerAbovePrice returns the lowest trigger price among trigger-above orders (or max_u64 if none exist). highestTriggerBelowPrice returns the highest trigger price among trigger-below orders (or 0 if none exist).

Examples​

Set up a stop loss order​

// Example: stop loss on a long position, selling once the oracle price drops below 2.0
const setStopLoss = (tx: Transaction) => {
const managerKey = 'MARGIN_MANAGER_1';
client.deepbook.marginTPSL.addConditionalOrder({
marginManagerKey: managerKey,
conditionalOrderId: '1',
triggerBelowPrice: true, // Fires once the oracle price falls below the trigger
triggerPrice: 2.0,
pendingOrder: {
clientOrderId: '100',
quantity: 50,
isBid: false, // Sell order
payWithDeep: true,
},
})(tx);
};

Set up a take profit order​

// Example: take profit on a long position, selling once the oracle price rises above 5.0
const setTakeProfit = (tx: Transaction) => {
const managerKey = 'MARGIN_MANAGER_1';
client.deepbook.marginTPSL.addConditionalOrder({
marginManagerKey: managerKey,
conditionalOrderId: '2',
triggerBelowPrice: false, // Fires once the oracle price rises above the trigger
triggerPrice: 5.0,
pendingOrder: {
clientOrderId: '101',
price: 5.0, // Limit order at 5.0
quantity: 50,
isBid: false, // Sell order
payWithDeep: true,
},
})(tx);
};

Execute triggered orders (keeper)​

// Example: Execute conditional orders as a keeper
const executeOrders = (tx: Transaction) => {
const managerAddress = '0x...'; // Address of margin manager
// Execute up to 10 triggered orders
client.deepbook.marginTPSL.executeConditionalOrders(managerAddress, 'SUI_DBUSDC', 10)(tx);
};

Query and cancel orders​

// Example: Query all conditional order IDs, then cancel a specific order
const manageOrders = async () => {
const tx = new Transaction();
const managerKey = 'MARGIN_MANAGER_1';

// Query existing conditional order IDs
const orderIds = await client.deepbook.getConditionalOrderIds(managerKey);

// Cancel a specific order by ID
if (orderIds.length > 0) {
tx.add(client.deepbook.marginTPSL.cancelConditionalOrder(managerKey, orderIds[0]));
}

// Or cancel all conditional orders at once
tx.add(client.deepbook.marginTPSL.cancelAllConditionalOrders(managerKey));
};

How conditional orders work​

A conditional order consists of two parts: a trigger condition and a pending order. addConditionalOrder stores both on the margin manager. Nothing onchain watches the price, so the order simply sits there until someone calls executeConditionalOrders.

Triggers compare against the margin registry's oracle (Pyth) price, not the order book price. A trigger that the oracle price has already crossed is rejected at registration with EInvalidCondition, so you can only register a condition that is still ahead of the market.

Execution is permissionless. Any caller can invoke executeConditionalOrders for a given margin manager address. Keeper bots typically monitor trigger prices using lowestTriggerAbovePrice and highestTriggerBelowPrice, then call executeConditionalOrders when the oracle price crosses those thresholds. For stop losses, prefer executeConditionalOrdersV3: it repays the loan with each market fill before checking the risk ratio, which lets a stop loss fire when the position is near liquidation, where executeConditionalOrders rejects the fill.

triggerBelowPrice sets the direction of the trigger, not the intent of the order:

  • triggerBelowPrice: true fires once the oracle price falls below triggerPrice. For a long position this is the stop loss; for a short it is the take profit.
  • triggerBelowPrice: false fires once the oracle price rises above triggerPrice. For a long position this is the take profit; for a short it is the stop loss.

Pair the trigger condition with either a limit order (newPendingLimitOrder) for price-controlled execution or a market order (newPendingMarketOrder) for immediate execution at the best available prices. A market order fills against whatever liquidity the book holds at that moment, so it controls timing rather than price.