Skip to main content
Drift supports multiple order types including market, limit, trigger, and oracle orders. This guide covers how to place each type using the SDK.

Order Types

Market Orders

Execute immediately at the best available price

Limit Orders

Execute at a specified price or better

Trigger Orders

Activate when a condition is met

Oracle Orders

Reference oracle price with offset

Placing a Market Order

Market orders execute immediately at the best available price:
import { BN } from '@coral-xyz/anchor';
import {
  DriftClient,
  getMarketOrderParams,
  PositionDirection,
  BASE_PRECISION,
  MarketType,
} from '@drift-labs/sdk';

// Buy 1 SOL-PERP at market price
const marketIndex = 0; // SOL-PERP
const baseAssetAmount = new BN(1).mul(BASE_PRECISION); // 1 SOL

const orderParams = getMarketOrderParams({
  marketIndex,
  direction: PositionDirection.LONG,
  baseAssetAmount,
  marketType: MarketType.PERP,
});

const txSig = await driftClient.placePerpOrder(orderParams);
console.log('Market order placed:', txSig);

Market Order with Price Limits

Set a maximum acceptable price to prevent slippage:
import { PRICE_PRECISION } from '@drift-labs/sdk';

// Buy SOL-PERP but not above $150
const maxPrice = new BN(150).mul(PRICE_PRECISION);

const orderParams = getMarketOrderParams({
  marketIndex: 0,
  direction: PositionDirection.LONG,
  baseAssetAmount: new BN(1).mul(BASE_PRECISION),
  price: maxPrice,
  marketType: MarketType.PERP,
});

await driftClient.placePerpOrder(orderParams);

Placing a Limit Order

Limit orders execute only at your specified price or better:
import {
  getLimitOrderParams,
  PositionDirection,
  PostOnlyParams,
  BASE_PRECISION,
  PRICE_PRECISION,
} from '@drift-labs/sdk';

// Buy 1 SOL-PERP at $145 or better
const limitPrice = new BN(145).mul(PRICE_PRECISION);
const baseAmount = new BN(1).mul(BASE_PRECISION);

const orderParams = getLimitOrderParams({
  marketIndex: 0,
  direction: PositionDirection.LONG,
  baseAssetAmount: baseAmount,
  price: limitPrice,
  marketType: MarketType.PERP,
});

const txSig = await driftClient.placePerpOrder(orderParams);
console.log('Limit order placed:', txSig);

Post-Only Orders

Ensure your order only adds liquidity (maker fee):
const orderParams = getLimitOrderParams({
  marketIndex: 0,
  direction: PositionDirection.LONG,
  baseAssetAmount: baseAmount,
  price: limitPrice,
  postOnly: PostOnlyParams.MUST_POST_ONLY,
  marketType: MarketType.PERP,
});

await driftClient.placePerpOrder(orderParams);
Post-only orders are rejected if they would match immediately. Use PostOnlyParams.TRY_POST_ONLY to allow fallback to taker.

Reduce-Only Orders

Limit orders to only reduce existing positions:
const orderParams = getLimitOrderParams({
  marketIndex: 0,
  direction: PositionDirection.SHORT, // Close a long position
  baseAssetAmount: baseAmount,
  price: limitPrice,
  reduceOnly: true,
  marketType: MarketType.PERP,
});

await driftClient.placePerpOrder(orderParams);

Placing a Trigger Order

Trigger orders (stop-loss/take-profit) activate when a price condition is met:

Stop-Loss Order

import {
  getTriggerMarketOrderParams,
  OrderTriggerCondition,
  PositionDirection,
} from '@drift-labs/sdk';

// Close long position if SOL drops below $140
const triggerPrice = new BN(140).mul(PRICE_PRECISION);

const orderParams = getTriggerMarketOrderParams({
  marketIndex: 0,
  direction: PositionDirection.SHORT,
  baseAssetAmount: new BN(1).mul(BASE_PRECISION),
  triggerPrice,
  triggerCondition: OrderTriggerCondition.BELOW,
  marketType: MarketType.PERP,
});

await driftClient.placePerpOrder(orderParams);

Take-Profit Order

// Take profit if SOL rises above $160
const takeProfitPrice = new BN(160).mul(PRICE_PRECISION);

const orderParams = getTriggerMarketOrderParams({
  marketIndex: 0,
  direction: PositionDirection.SHORT, // Close long
  baseAssetAmount: new BN(1).mul(BASE_PRECISION),
  triggerPrice: takeProfitPrice,
  triggerCondition: OrderTriggerCondition.ABOVE,
  marketType: MarketType.PERP,
});

await driftClient.placePerpOrder(orderParams);

Trigger Limit Orders

Combine trigger activation with limit execution:
import { getTriggerLimitOrderParams } from '@drift-labs/sdk';

// Trigger at $140, execute as limit at $139
const orderParams = getTriggerLimitOrderParams({
  marketIndex: 0,
  direction: PositionDirection.SHORT,
  baseAssetAmount: new BN(1).mul(BASE_PRECISION),
  price: new BN(139).mul(PRICE_PRECISION), // Limit price
  triggerPrice: new BN(140).mul(PRICE_PRECISION), // Trigger price
  triggerCondition: OrderTriggerCondition.BELOW,
  marketType: MarketType.PERP,
});

await driftClient.placePerpOrder(orderParams);

Placing an Oracle Order

Oracle orders reference the oracle price with an offset:
import { OrderType } from '@drift-labs/sdk';

// Buy 5% below oracle price
const orderParams = {
  orderType: OrderType.ORACLE,
  marketIndex: 0,
  direction: PositionDirection.LONG,
  baseAssetAmount: new BN(1).mul(BASE_PRECISION),
  oraclePrice Offset: new BN(-5).mul(PRICE_PRECISION).div(new BN(100)), // -5%
  marketType: MarketType.PERP,
};

await driftClient.placePerpOrder(orderParams);

Spot Market Orders

Place orders on spot markets (lending/borrowing):
import { getMarketOrderParams, MarketType } from '@drift-labs/sdk';

// Swap USDC for SOL (borrow if needed)
const orderParams = getMarketOrderParams({
  marketIndex: 1, // SOL spot market
  direction: PositionDirection.LONG,
  baseAssetAmount: new BN(10).mul(BASE_PRECISION), // 10 SOL
  marketType: MarketType.SPOT,
});

await driftClient.placeSpotOrder(orderParams);

Scale Orders

Place multiple orders across a price range:
import { ScaleOrderParams, SizeDistribution } from '@drift-labs/sdk';

// Place 10 orders from $140 to $150
const scaleOrderParams: ScaleOrderParams = {
  orderCount: 10,
  marketIndex: 0,
  direction: PositionDirection.LONG,
  baseAssetAmount: new BN(10).mul(BASE_PRECISION), // Total 10 SOL
  minPrice: new BN(140).mul(PRICE_PRECISION),
  maxPrice: new BN(150).mul(PRICE_PRECISION),
  sizeDistribution: SizeDistribution.UNIFORM,
};

const txSig = await driftClient.placeScaleOrder(scaleOrderParams);
console.log('Scale orders placed:', txSig);

Order Parameters

marketIndex
number
required
Market index (0 = SOL-PERP, 1 = BTC-PERP, etc.)
direction
PositionDirection
required
PositionDirection.LONG or PositionDirection.SHORT
baseAssetAmount
BN
required
Amount in base asset (use BASE_PRECISION for standard precision)
price
BN
Limit price (use PRICE_PRECISION for $1 = 1,000,000)
marketType
MarketType
MarketType.PERP or MarketType.SPOT (default: PERP)
reduceOnly
boolean
If true, order can only reduce existing positions
postOnly
PostOnlyParams
MUST_POST_ONLY, TRY_POST_ONLY, or NONE
immediateOrCancel
boolean
If true, cancel unfilled portion immediately
triggerPrice
BN
Price at which trigger order activates
triggerCondition
OrderTriggerCondition
ABOVE or BELOW for trigger orders
oraclePriceOffset
BN
Price offset from oracle for oracle orders
maxTs
BN
Unix timestamp for order expiration
userOrderId
number
Custom order ID for tracking (1-255)

Best Practices

  • Market orders: When you need immediate execution
  • Limit orders: When you want price control and maker fees
  • Trigger orders: For risk management (stop-loss/take-profit)
  • Oracle orders: For fair pricing relative to oracle
// Protect against extreme slippage
const currentPrice = calculateBidAskPrice(
  perpMarket.amm,
  oracleData
)[1]; // Ask price

const maxPrice = currentPrice.mul(new BN(105)).div(new BN(100)); // +5%

const orderParams = getMarketOrderParams({
  // ... other params
  price: maxPrice,
});
// Track your orders with custom IDs
const orderParams = getMarketOrderParams({
  // ... other params
  userOrderId: 42,
});

await driftClient.placePerpOrder(orderParams);

// Later, find your order
const order = user.getOrderByUserOrderId(42);
if (order) {
  console.log('Order status:', order.status);
}
try {
  await driftClient.placePerpOrder(orderParams);
} catch (error) {
  if (error.message.includes('Insufficient collateral')) {
    console.error('Need to deposit more collateral');
  } else if (error.message.includes('Market orders paused')) {
    console.error('Market is currently paused');
  } else {
    console.error('Order failed:', error);
  }
}

Examples

Opening a Leveraged Long Position

// Open 10x leveraged SOL long with $1000 collateral
const collateral = new BN(1000).mul(QUOTE_PRECISION);
const leverage = 10;
const notionalValue = collateral.mul(new BN(leverage));

// Get current SOL price
const solPrice = driftClient.getOracleDataForPerpMarket(0).price;
const baseAmount = notionalValue.mul(PRICE_PRECISION).div(solPrice);

const orderParams = getMarketOrderParams({
  marketIndex: 0,
  direction: PositionDirection.LONG,
  baseAssetAmount: baseAmount,
});

await driftClient.placePerpOrder(orderParams);

Closing a Position

// Get your current position
const position = user.getPerpPosition(0);

if (position && position.baseAssetAmount.gt(ZERO)) {
  // Close the entire position
  const orderParams = getMarketOrderParams({
    marketIndex: 0,
    direction: findDirectionToClose(position),
    baseAssetAmount: position.baseAssetAmount.abs(),
    reduceOnly: true,
  });
  
  await driftClient.placePerpOrder(orderParams);
}

Next Steps

Modify Orders

Learn to modify existing orders

Cancel Orders

Cancel individual or all orders

Manage Positions

Monitor and manage open positions

Order Params API

Complete order parameters reference

Build docs developers (and LLMs) love