Skip to Content

Sending Actions

Once you have UI state, you can send actions using the Drift SDK. There are two approaches: high-level methods that handle transaction construction for you, and instruction builders that give you full control.

When to use which

ApproachUse when
High-level methods (placePerpOrder, cancelOrder)Simple flows , one action per transaction, default compute budget
Instruction builders (getPlacePerpOrderIx, getCancelOrderIx)You need multiple instructions in one transaction, custom compute budget, or atomic cancel-and-replace

Most ecosystem apps start with high-level methods and move to instruction builders when they need atomic multi-step transactions or fine-grained priority fee control.

Step 1: Initialize a Drift client

Follow SDK setup:

Step 2: Place and cancel orders

Use the SDK’s order helpers for common flows:

Step 3: Manage collateral and accounts

Deposits, withdrawals, and account lifecycle are covered in:

Step 4: Monitor risk and health

UI parity requires the same risk/health calculations:

Step 5: Build custom transactions

For advanced use cases, you can build transactions with multiple instructions. This is essential when you need atomicity , either all instructions succeed or none do.

import { ComputeBudgetProgram } from "@solana/web3.js"; import { getMarketOrderParams, PositionDirection } from "@drift-labs/sdk"; // Get instruction for placing order (doesn't send tx yet) const orderParams = getMarketOrderParams({ marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), }); const placeOrderIx = await driftClient.getPlacePerpOrderIx(orderParams); // Build transaction with compute budget + order instruction const tx = await driftClient.txSender.getVersionedTransaction( [ ComputeBudgetProgram.setComputeUnitLimit({ units: 400000 }), ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50000 }), placeOrderIx, ], [], // lookup tables (if any) driftClient.wallet.publicKey ); // Sign and send const signature = await driftClient.txSender.sendVersionedTransaction( tx, [], driftClient.opts ); console.log("Transaction:", signature);
Method DriftClient.getPlacePerpOrderIxReference ↗
ParameterTypeRequired
orderParams
OptionalOrderParams
Yes
subAccountId
number
No
depositToTradeArgs
{ isMakingNewAccount: boolean; depositMarketIndex: number; }
No
Returns
Promise<TransactionInstruction>

Step 6: Atomic cancel-and-place (order replacement)

A common pattern for trading UIs is atomically canceling existing orders and placing new ones in a single transaction. This prevents the window where you have no orders resting while updating prices.

import { ComputeBudgetProgram } from "@solana/web3.js"; import { getLimitOrderParams, PositionDirection } from "@drift-labs/sdk"; // Cancel all existing perp orders for this market, then place new ones const cancelIx = await driftClient.getCancelOrdersIx( null, // marketType (null = all) null, // marketIndex (null = all) null // direction (null = both) ); const bidParams = getLimitOrderParams({ marketIndex: 0, direction: PositionDirection.LONG, baseAssetAmount: driftClient.convertToPerpPrecision(1), price: driftClient.convertToPricePrecision(120), postOnly: true, }); const askParams = getLimitOrderParams({ marketIndex: 0, direction: PositionDirection.SHORT, baseAssetAmount: driftClient.convertToPerpPrecision(1), price: driftClient.convertToPricePrecision(125), postOnly: true, }); const bidIx = await driftClient.getPlacePerpOrderIx(bidParams); const askIx = await driftClient.getPlacePerpOrderIx(askParams); // All three instructions in one atomic transaction const tx = await driftClient.txSender.getVersionedTransaction( [ ComputeBudgetProgram.setComputeUnitLimit({ units: 600000 }), ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 50000 }), cancelIx, bidIx, askIx, ], [], driftClient.wallet.publicKey ); const signature = await driftClient.txSender.sendVersionedTransaction( tx, [], driftClient.opts ); console.log("Cancel + place transaction:", signature);
Method DriftClient.cancelAndPlaceOrdersReference ↗
ParameterTypeRequired
cancelOrderParams
{ marketType?: MarketType; marketIndex?: number; direction?: PositionDirection; }
Yes
placeOrderParams
OrderParams[]
Yes
txParams
TxParams
No
subAccountId
number
No
Returns
Promise<string>

Step 7: Keep transaction performance healthy

If you’re batching or sending frequent transactions, consider:

  • Priority fees , Set ComputeUnitPrice to land transactions faster during congestion
  • Compute budget , Use setComputeUnitLimit to allocate enough CU for multi-instruction transactions
  • Address Lookup Tables (ALTs) , Reduce transaction size when referencing many accounts. See SDK documentation for details.
  • Retry logic , Transactions can be dropped; implement retries with backoff for production systems
Last updated on