Skip to Content

Orders

How it works

Orders on Drift go through a multi-stage matching process. When you place an order, it enters a JIT auction (Just-In-Time) where market makers can compete to fill it at better prices. If no one fills during the auction, the order either executes against the DLOB (Decentralized Limit Order Book) or the AMM as a fallback. This design ensures you get the best price from multiple liquidity sources.

Drift supports several order types: market (immediate execution), limit (rests on the orderbook at a specific price), oracle (price pegged to oracle with an offset), and trigger orders (conditional execution when a price threshold is hit). Each order has parameters like size, price, post-only flags, and reduce-only settings that control how it behaves.

Orders are stored in your user account and have both an onchain order ID and an optional user-assigned ID for tracking. When an order fills, your position updates automatically, and you can query fill events to see execution details.

SDK Usage

This page focuses on placing and canceling orders via DriftClient. For concise examples we use helper builders like getMarketOrderParams(...).

Build Market Order Params

import { BN, BASE_PRECISION, MarketType, PositionDirection, getMarketOrderParams } from "@drift-labs/sdk"; const orderParams = getMarketOrderParams({ marketIndex: 0, marketType: MarketType.PERP, direction: PositionDirection.LONG, baseAssetAmount: new BN(1).mul(BASE_PRECISION), // 1 SOL (in 1e9 precision) });
Function getMarketOrderParamsReference ↗
ParameterTypeRequired
params
Omit<OptionalOrderParams, "orderType">
Yes
Returns
OptionalOrderParams

Build Order Params (Generic Helper)

If you want a single helper that works for limit/market/oracle/trigger, use getOrderParams(...).

import { getOrderParams, OrderType, PositionDirection } from "@drift-labs/sdk"; const orderParams = getOrderParams({ orderType: OrderType.LIMIT, marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), // 1 base unit → BN(1e9) price: driftClient.convertToPricePrecision(21.23), // $21.23 → BN(21_230_000) });
Function getOrderParamsReference ↗

Creates an OrderParams object with the given OptionalOrderParams and any params to override.

example: ``` const orderParams = getOrderParams(optionalOrderParams, &#123; marketType: MarketType.PERP &#125;); ```

ParameterTypeRequired
optionalOrderParams
OptionalOrderParams
Yes
overridingParams
Record<string, any>
No
Returns
OrderParams

Place a Perp Order

// Assumes `driftClient` is subscribed. const txSig = await driftClient.placePerpOrder( getMarketOrderParams({ marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: new BN(1).mul(BASE_PRECISION), }) ); console.log(txSig);
Method DriftClient.placePerpOrderReference ↗
ParameterTypeRequired
orderParams
OptionalOrderParams
Yes
txParams
TxParams
No
subAccountId
number
No
isolatedPositionDepositAmount
any
No
Returns
Promise<string>

Oracle / Auction-Style Orders

Oracle orders have prices that track the oracle feed with an offset. They go through a JIT auction before execution, with auction prices that gradually converge from the start offset to the end offset relative to oracle.

Important: For OrderType.ORACLE, auctionStartPrice, auctionEndPrice, and oraclePriceOffset are all offsets from the oracle price (in PRICE_PRECISION, 1e6), not absolute prices.

import { BN, OrderType, PositionDirection, PRICE_PRECISION } from "@drift-labs/sdk"; const marketIndex = 18; // Offsets are relative to oracle price (in PRICE_PRECISION) // For a long: auction starts at a better (lower) price and ends at a worse (higher) price const auctionStartPrice = PRICE_PRECISION.muln(-5).divn(10); // -$0.50 below oracle const auctionEndPrice = PRICE_PRECISION.muln(5).divn(10); // +$0.50 above oracle const orderParams = { orderType: OrderType.ORACLE, baseAssetAmount: driftClient.convertToPerpPrecision(10), direction: PositionDirection.LONG, marketIndex, auctionStartPrice, auctionEndPrice, oraclePriceOffset: driftClient.convertToPricePrecision(0.30).toNumber(), // +$0.30 from oracle auctionDuration: 30, // slots }; await driftClient.placePerpOrder(orderParams);
Example Oracle orderReference ↗
TypeScript docs unavailable for Oracle order.

Instruction Builders (Advanced)

Higher-level methods like placePerpOrder() build, sign, and send a transaction in one call. Instruction (IX) builders give you the raw TransactionInstruction objects so you can:

  • Set a custom compute budget with priority fees for faster inclusion
  • Batch multiple instructions into a single transaction (e.g., cancel + place atomically)
  • Use Address Lookup Tables (ALTs) to fit more accounts into a transaction
  • Compose with other programs (e.g., add a memo or call another protocol in the same tx)

Complete Example: Batching IXs with Compute Budget

import { ComputeBudgetProgram } from "@solana/web3.js"; import { MarketType, PositionDirection, OrderType, getOrderParams, } from "@drift-labs/sdk"; // 1. Build individual instructions const cancelIx = await driftClient.getCancelOrdersIx( MarketType.PERP, // marketType (null to cancel all types) 0, // marketIndex (null to cancel across all markets) null // direction (null to cancel both sides) ); const placeIx = await driftClient.getPlacePerpOrderIx( getOrderParams({ orderType: OrderType.LIMIT, marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), price: driftClient.convertToPricePrecision(21.0), }) ); // 2. Add compute budget instructions for priority fees const computeUnitPrice = ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50_000, // priority fee in micro-lamports per CU }); const computeUnitLimit = ComputeBudgetProgram.setComputeUnitLimit({ units: 400_000, // max compute units for the transaction }); // 3. Build a versioned transaction with all instructions const tx = await driftClient.txSender.getVersionedTransaction( [computeUnitLimit, computeUnitPrice, cancelIx, placeIx], [], // lookup table accounts (AddressLookupTableAccount[]) driftClient.wallet.publicKey ); // 4. Send the transaction const { txSig } = await driftClient.txSender.sendVersionedTransaction( tx, [], driftClient.opts ); console.log("Batch tx:", txSig);
Example IX batching exampleReference ↗
TypeScript docs unavailable for IX batching example.

Individual IX Builders

getPlacePerpOrderIx builds an instruction to place a perp order.

// Params: // orderParams: OptionalOrderParams - same params as placePerpOrder() // subAccountId?: number - defaults to active subaccount const ix = await driftClient.getPlacePerpOrderIx( getOrderParams({ orderType: OrderType.LIMIT, marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), price: driftClient.convertToPricePrecision(21.0), }) );
Method DriftClient.getPlacePerpOrderIxReference ↗
ParameterTypeRequired
orderParams
OptionalOrderParams
Yes
subAccountId
number
No
depositToTradeArgs
{ isMakingNewAccount: boolean; depositMarketIndex: number; }
No
Returns
Promise<TransactionInstruction>

getPlaceSpotOrderIx builds an instruction to place a spot order.

// Params: // orderParams: OptionalOrderParams - same params as placeSpotOrder() // subAccountId?: number - defaults to active subaccount const ix = await driftClient.getPlaceSpotOrderIx({ orderType: OrderType.LIMIT, marketIndex: 1, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToSpotPrecision(1, 1), price: driftClient.convertToPricePrecision(150), });
Method DriftClient.getPlaceSpotOrderIxReference ↗
ParameterTypeRequired
orderParams
OptionalOrderParams
Yes
subAccountId
number
No
Returns
Promise<TransactionInstruction>

getCancelOrdersIx builds an instruction to cancel orders matching the given filters. Pass null for any filter to match all.

import { MarketType, PositionDirection } from "@drift-labs/sdk"; // Params: // marketType: MarketType | null - filter by PERP or SPOT (null = all) // marketIndex: number | null - filter by market index (null = all) // direction: PositionDirection | null - filter by LONG or SHORT (null = both) // subAccountId?: number - defaults to active subaccount // Cancel all perp orders on market 0 const ix = await driftClient.getCancelOrdersIx(MarketType.PERP, 0, null); // Cancel ALL orders across all markets const ixAll = await driftClient.getCancelOrdersIx(null, null, null);
Method DriftClient.getCancelOrdersIxReference ↗
ParameterTypeRequired
marketType
MarketType
Yes
marketIndex
number
Yes
direction
PositionDirection
Yes
subAccountId
number
No
Returns
Promise<TransactionInstruction>

getFillPerpOrderIx builds an instruction to fill another user’s perp order (used by filler/keeper bots).

// Params: // userAccountPublicKey: PublicKey - the taker's user account address // userAccount: UserAccount - the taker's deserialized user account // order: { marketIndex, orderId } - the order to fill // makerInfo?: MakerInfo | MakerInfo[] - optional maker(s) to match against // referrerInfo?: ReferrerInfo - optional referrer for fee sharing // fillerSubAccountId?: number - filler's subaccount const takerPubkey = takerUser.userAccountPublicKey; const takerAccount = takerUser.getUserAccount(); const order = takerAccount.orders[0]; // the order to fill const ix = await driftClient.getFillPerpOrderIx( takerPubkey, takerAccount, { marketIndex: order.marketIndex, orderId: order.orderId } );
Method DriftClient.getFillPerpOrderIxReference ↗
ParameterTypeRequired
userAccountPublicKey
PublicKey
Yes
userAccount
UserAccount
Yes
order
Pick<Order, "marketIndex" | "orderId">
Yes
makerInfo
MakerInfo | MakerInfo[]
No
referrerInfo
ReferrerInfo
No
fillerSubAccountId
number
No
isSignedMsg
boolean
No
fillerAuthority
PublicKey
No
hasBuilderFee
boolean
No
Returns
Promise<TransactionInstruction>

getFillSpotOrderIx builds an instruction to fill another user’s spot order.

// Same pattern as getFillPerpOrderIx but for spot markets. const ix = await driftClient.getFillSpotOrderIx( takerPubkey, takerAccount, { marketIndex: order.marketIndex, orderId: order.orderId } );
Method DriftClient.getFillSpotOrderIxReference ↗
ParameterTypeRequired
userAccountPublicKey
PublicKey
Yes
userAccount
UserAccount
Yes
order
Pick<Order, "marketIndex" | "orderId">
No
fulfillmentConfig
SerumV3FulfillmentConfigAccount | PhoenixV1FulfillmentConfigAccount | OpenbookV2FulfillmentConfigAccount
No
makerInfo
MakerInfo | MakerInfo[]
No
referrerInfo
ReferrerInfo
No
fillerPublicKey
PublicKey
No
Returns
Promise<TransactionInstruction>

getTriggerOrderIx builds an instruction to trigger a conditional order (stop-loss or take-profit) that has met its trigger condition.

// Params: // userAccountPublicKey: PublicKey - the user whose order to trigger // userAccount: UserAccount - the deserialized user account // order: Order - the full order object (must have trigger condition met) // fillerPublicKey?: PublicKey - optional, defaults to your user account const userPubkey = targetUser.userAccountPublicKey; const userAccount = targetUser.getUserAccount(); const triggerOrder = userAccount.orders.find( (o) => o.orderType.triggerMarket !== undefined || o.orderType.triggerLimit !== undefined ); const ix = await driftClient.getTriggerOrderIx( userPubkey, userAccount, triggerOrder );
Method DriftClient.getTriggerOrderIxReference ↗
ParameterTypeRequired
userAccountPublicKey
PublicKey
Yes
userAccount
UserAccount
Yes
order
Order
Yes
fillerPublicKey
PublicKey
No
Returns
Promise<TransactionInstruction>

getRevertFillIx builds an instruction to revert a fill (used by filler bots when a fill was invalid).

// Params: // fillerPublicKey?: PublicKey - defaults to your user account const ix = await driftClient.getRevertFillIx();
Method DriftClient.getRevertFillIxReference ↗
ParameterTypeRequired
fillerPublicKey
PublicKey
No
Returns
Promise<TransactionInstruction>

getSettlePNLsIxs builds instructions to settle PnL for one or more users across multiple markets. Returns an array of instructions (one per user per market).

// Params: // users: Array of { settleeUserAccountPublicKey, settleeUserAccount } // marketIndexes: number[] - perp market indexes to settle const user = driftClient.getUser(); const ixs = await driftClient.getSettlePNLsIxs( [ { settleeUserAccountPublicKey: user.userAccountPublicKey, settleeUserAccount: user.getUserAccount(), }, ], [0, 1] // settle PnL on perp markets 0 and 1 ); // ixs is an array of TransactionInstruction, one per user per market
Method DriftClient.getSettlePNLsIxsReference ↗
ParameterTypeRequired
users
{ settleeUserAccountPublicKey: PublicKey; settleeUserAccount: UserAccount; }[]
Yes
marketIndexes
number[]
Yes
revenueShareEscrowMap
RevenueShareEscrowMap
No
Returns
Promise<TransactionInstruction[]>

getJupiterSwapIxV6 builds a Jupiter swap instruction routed through Drift.

// Params: // inMarketIndex: number - spot market index of the input token // outMarketIndex: number - spot market index of the output token // amount: BN - amount of input token (in spot precision) // slippageBps: number - max slippage in basis points const ix = await driftClient.getJupiterSwapIxV6({ inMarketIndex: 0, // e.g. USDC outMarketIndex: 1, // e.g. SOL amount: driftClient.convertToSpotPrecision(0, 10), // 10 USDC slippageBps: 50, // 0.5% max slippage });
Method DriftClient.getJupiterSwapIxV6Reference ↗
ParameterTypeRequired
__0
{ jupiterClient: JupiterClient; outMarketIndex: number; inMarketIndex: number; outAssociatedTokenAccount?: PublicKey; inAssociatedTokenAccount?: PublicKey; ... 6 more ...; userAccountPublicKey?: PublicKey; }
Yes
Returns
Promise<{ ixs: TransactionInstruction[]; lookupTables: AddressLookupTableAccount[]; }>

Place a Spot Order

import { OrderType, PositionDirection } from "@drift-labs/sdk"; await driftClient.placeSpotOrder({ orderType: OrderType.LIMIT, marketIndex: 1, // e.g. SOL spot direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToSpotPrecision(1, 1), // 1 SOL price: driftClient.convertToPricePrecision(150), });
Method DriftClient.placeSpotOrderReference ↗
ParameterTypeRequired
orderParams
OptionalOrderParams
Yes
txParams
TxParams
No
subAccountId
number
No
Returns
Promise<string>

Place Multiple Orders

await driftClient.placeOrders([ { orderType: OrderType.LIMIT, marketType: MarketType.PERP, marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), price: driftClient.convertToPricePrecision(21.23), }, { orderType: OrderType.LIMIT, marketType: MarketType.PERP, marketIndex: 0, direction: PositionDirection.SHORT, baseAssetAmount: driftClient.convertToPerpPrecision(1), oraclePriceOffset: driftClient.convertToPricePrecision(0.05).toNumber(), }, ]);
Method DriftClient.placeOrdersReference ↗
ParameterTypeRequired
params
OrderParams[]
Yes
txParams
TxParams
No
subAccountId
number
No
optionalIxs
TransactionInstruction[]
No
isolatedPositionDepositAmount
any
No
Returns
Promise<string>

Cancel Orders

await driftClient.cancelOrder(1);
Method DriftClient.cancelOrderReference ↗
ParameterTypeRequired
orderId
number
No
txParams
TxParams
No
subAccountId
number
No
overrides
{ withdrawIsolatedDepositAmount?: any; }
No
Returns
Promise<string>
await driftClient.cancelOrdersByIds([1]);
Method DriftClient.cancelOrdersByIdsReference ↗
ParameterTypeRequired
orderIds
number[]
The order ids to cancel.
No
txParams
TxParams
The transaction parameters.
No
subAccountId
number
The sub account id to cancel the orders for.
No
user
User
The user to cancel the orders for. If provided, it will be prioritized over the subAccountId.
No
overrides
{ authority?: PublicKey; }
No
Returns
Promise<string>
import { MarketType, PositionDirection } from "@drift-labs/sdk"; // Cancels orders matching the filters. To cancel all orders, omit parameters. await driftClient.cancelOrders(MarketType.PERP, 0, PositionDirection.LONG);
Method DriftClient.cancelOrdersReference ↗
ParameterTypeRequired
marketType
MarketType
No
marketIndex
number
No
direction
PositionDirection
No
txParams
TxParams
No
subAccountId
number
No
Returns
Promise<string>

Cancel and Place (Atomic)

await driftClient.cancelAndPlaceOrders( { marketType: MarketType.PERP, marketIndex: 0 }, [ { orderType: OrderType.LIMIT, marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), price: driftClient.convertToPricePrecision(21.23), }, ] );
Method DriftClient.cancelAndPlaceOrdersReference ↗
ParameterTypeRequired
cancelOrderParams
{ marketType?: MarketType; marketIndex?: number; direction?: PositionDirection; }
Yes
placeOrderParams
OrderParams[]
Yes
txParams
TxParams
No
subAccountId
number
No
Returns
Promise<string>

Modify Orders

await driftClient.modifyOrder({ orderId: 1, newBaseAmount: driftClient.convertToPerpPrecision(2), });
Method DriftClient.modifyOrderReference ↗
ParameterTypeRequired
orderParams
{ orderId: number; newDirection?: PositionDirection; newBaseAmount?: any; newLimitPrice?: any; newOraclePriceOffset?: number; newTriggerPrice?: any; newTriggerCondition?: OrderTriggerCondition; ... 7 more ...; policy?: number; }
Yes
txParams
TxParams
No
subAccountId
number
No
Returns
Promise<string>
await driftClient.modifyOrderByUserOrderId({ userOrderId: 1, newBaseAmount: driftClient.convertToPerpPrecision(2), });
Method DriftClient.modifyOrderByUserOrderIdReference ↗
ParameterTypeRequired
orderParams
{ userOrderId: number; newDirection?: PositionDirection; newBaseAmount?: any; newLimitPrice?: any; newOraclePriceOffset?: number; newTriggerPrice?: any; newTriggerCondition?: OrderTriggerCondition; ... 7 more ...; maxTs?: any; }
Yes
txParams
TxParams
No
subAccountId
number
No
Returns
Promise<string>

Trigger Orders (Stop / Take-Profit)

import { OrderTriggerCondition, OrderType, PositionDirection } from "@drift-labs/sdk"; const orderParams = { orderType: OrderType.TRIGGER_MARKET, marketIndex: 0, direction: PositionDirection.SHORT, baseAssetAmount: driftClient.convertToPerpPrecision(1), triggerPrice: driftClient.convertToPricePrecision(95), triggerCondition: OrderTriggerCondition.BELOW, }; await driftClient.placePerpOrder(orderParams);
Example Trigger orderReference ↗
TypeScript docs unavailable for Trigger order.
Last updated on