| name | drift |
| creator | raunit-dev |
| description | Complete Drift Protocol SDK for building perpetual futures, spot trading, and DeFi applications on Solana. Use when building trading bots, integrating Drift markets, managing positions, or working with vaults. |
Drift Protocol SDK Development Guide
A comprehensive guide for building Solana applications with the Drift Protocol SDK - the leading perpetual futures and spot trading protocol on Solana.
Overview
Drift Protocol is a decentralized exchange on Solana offering:
- Perpetual Futures: Up to 20x leverage on crypto assets
- Spot Trading: Borrow/lend and margin trading
- Cross-Collateral: Use multiple assets as collateral
- Vaults: Delegated trading pools
- Jupiter Integration: Direct spot swaps
Quick Start
Installation
npm install @drift-labs/sdk @solana/web3.js @coral-xyz/anchor
For Python:
pip install driftpy
Basic Setup (TypeScript)
import { Connection, Keypair } from '@solana/web3.js';
import { Wallet } from '@coral-xyz/anchor';
import {
DriftClient,
initialize,
DriftEnv,
BulkAccountLoader
} from '@drift-labs/sdk';
const connection = new Connection('https://api.breeze.baby/agent/rpc-mainnet-beta');
const keypair = Keypair.fromSecretKey();
const wallet = new Wallet(keypair);
const sdkConfig = initialize({ env: 'mainnet-beta' as DriftEnv });
const driftClient = new DriftClient({
connection,
wallet,
env: 'mainnet-beta',
accountSubscription: {
type: 'polling',
accountLoader: new BulkAccountLoader(connection, 'confirmed', 1000),
},
});
await driftClient.subscribe();
const user = driftClient.getUser();
const userExists = await user.exists();
if (!userExists) {
await driftClient.initializeUserAccount();
}
Basic Setup (Python)
import asyncio
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from driftpy.drift_client import DriftClient
from driftpy.account_subscription_config import AccountSubscriptionConfig
from anchorpy import Wallet
async def main():
connection = AsyncClient("https://api.breeze.baby/agent/rpc-mainnet-beta")
keypair = Keypair.from_bytes(secret_key_bytes)
wallet = Wallet(keypair)
drift_client = DriftClient(
connection,
wallet,
"mainnet",
account_subscription=AccountSubscriptionConfig("polling"),
)
await drift_client.subscribe()
user = drift_client.get_user()
if not await user.exists():
await drift_client.initialize_user_account()
asyncio.run(main())
Core Concepts
1. Precision and BN (BigNumber)
Drift uses BN.js for all numerical values due to token precision exceeding JavaScript float limits. All amounts are integers with designated precision levels.
Key Precision Constants:
| Constant | Value | Use Case |
|---|
QUOTE_PRECISION | 10^6 | USDC amounts |
BASE_PRECISION | 10^9 | Perp base asset amounts |
PRICE_PRECISION | 10^6 | Prices |
SPOT_MARKET_BALANCE_PRECISION | 10^9 | Spot token balances |
FUNDING_RATE_PRECISION | 10^9 | Funding rates |
MARGIN_PRECISION | 10,000 | Margin ratios |
PEG_PRECISION | 10^6 | AMM peg |
AMM_RESERVE_PRECISION | 10^9 | AMM reserves |
Conversion Helper:
import { convertToNumber } from '@drift-labs/sdk';
const result = convertToNumber(new BN(10500), new BN(1000));
const perpAmount = driftClient.convertToPerpPrecision(100);
const spotAmount = driftClient.convertToSpotPrecision(0, 100);
const price = driftClient.convertToPricePrecision(21.23);
2. Market Types
Perpetual Markets (MarketType.PERP):
- Derivatives with no expiry
- Positions tracked via
baseAssetAmount
- Positive = Long, Negative = Short
Spot Markets (MarketType.SPOT):
- Real token deposits/borrows
- Positions tracked via
scaledBalance
SpotBalanceType.DEPOSIT or SpotBalanceType.BORROW
Common Market Indexes:
0 - USDC (quote asset)
1 - SOL
- Market indexes vary - query
getPerpMarketAccounts() / getSpotMarketAccounts()
3. Order Types
import { OrderType, PositionDirection, OrderTriggerCondition } from '@drift-labs/sdk';
OrderType.MARKET
OrderType.LIMIT
OrderType.TRIGGER_MARKET
OrderType.TRIGGER_LIMIT
OrderType.ORACLE
PositionDirection.LONG
PositionDirection.SHORT
OrderTriggerCondition.ABOVE
OrderTriggerCondition.BELOW
4. Post-Only Parameters
import { PostOnlyParams } from '@drift-labs/sdk';
PostOnlyParams.NONE
PostOnlyParams.MUST_POST_ONLY
PostOnlyParams.TRY_POST_ONLY
PostOnlyParams.SLIDE
Trading Operations
Placing Perpetual Orders
await driftClient.placePerpOrder({
orderType: OrderType.MARKET,
marketIndex: 0,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
});
await driftClient.placePerpOrder({
orderType: OrderType.LIMIT,
marketIndex: 0,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
price: driftClient.convertToPricePrecision(100),
postOnly: PostOnlyParams.MUST_POST_ONLY,
});
await driftClient.placePerpOrder({
orderType: OrderType.TRIGGER_MARKET,
marketIndex: 0,
direction: PositionDirection.SHORT,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
triggerPrice: driftClient.convertToPricePrecision(90),
triggerCondition: OrderTriggerCondition.BELOW,
reduceOnly: true,
});
await driftClient.placePerpOrder({
orderType: OrderType.TRIGGER_LIMIT,
marketIndex: 0,
direction: PositionDirection.SHORT,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
price: driftClient.convertToPricePrecision(120),
triggerPrice: driftClient.convertToPricePrecision(120),
triggerCondition: OrderTriggerCondition.ABOVE,
reduceOnly: true,
});
await driftClient.placePerpOrder({
orderType: OrderType.ORACLE,
marketIndex: 0,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
oraclePriceOffset: -100000,
auctionDuration: 10,
auctionStartPrice: new BN(-200000),
auctionEndPrice: new BN(-50000),
});
Placing Spot Orders
await driftClient.placeSpotOrder({
orderType: OrderType.MARKET,
marketIndex: 1,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToSpotPrecision(1, 1),
});
await driftClient.placeSpotOrder({
orderType: OrderType.LIMIT,
marketIndex: 1,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToSpotPrecision(1, 1),
price: driftClient.convertToPricePrecision(100),
});
Multiple Orders
await driftClient.placeOrders([
{
orderType: OrderType.LIMIT,
marketType: MarketType.PERP,
marketIndex: 0,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
price: driftClient.convertToPricePrecision(99),
},
{
orderType: OrderType.LIMIT,
marketType: MarketType.PERP,
marketIndex: 0,
direction: PositionDirection.SHORT,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
price: driftClient.convertToPricePrecision(101),
},
]);
Order Management
await driftClient.cancelOrder(orderId);
await driftClient.cancelOrderByUserOrderId(userOrderId);
await driftClient.cancelOrders(MarketType.PERP, 0);
await driftClient.cancelOrders();
await driftClient.modifyOrder(orderId, {
price: driftClient.convertToPricePrecision(102),
});
await driftClient.cancelAndPlaceOrders({
cancelOrderParams: { orderId: existingOrderId },
placeOrderParams: [{
orderType: OrderType.LIMIT,
marketType: MarketType.PERP,
marketIndex: 0,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
price: driftClient.convertToPricePrecision(100),
}],
});
Get Orders
const order = driftClient.getOrder(orderId);
const order = driftClient.getOrderByUserId(userOrderId);
const user = driftClient.getUser();
const openOrders = user.getOpenOrders();
Deposits and Withdrawals
Deposits
const associatedTokenAccount = await driftClient.getAssociatedTokenAccount(0);
const amount = driftClient.convertToSpotPrecision(0, 100);
await driftClient.deposit(amount, 0, associatedTokenAccount);
const solAccount = await driftClient.getAssociatedTokenAccount(1);
const solAmount = driftClient.convertToSpotPrecision(1, 1);
await driftClient.deposit(solAmount, 1, solAccount);
const [txSig, userPubkey] = await driftClient.initializeUserAccountAndDepositCollateral(
driftClient.convertToSpotPrecision(0, 100),
await driftClient.getAssociatedTokenAccount(0),
0,
0,
'MyAccount',
);
Withdrawals
const associatedTokenAccount = await driftClient.getAssociatedTokenAccount(0);
const amount = driftClient.convertToSpotPrecision(0, 50);
await driftClient.withdraw(amount, 0, associatedTokenAccount);
await driftClient.withdraw(amount, 0, associatedTokenAccount, undefined, true);
Transfers Between Sub-Accounts
await driftClient.transferDeposit(
driftClient.convertToSpotPrecision(0, 100),
0,
0,
1,
);
await driftClient.transferPerpPosition({
fromSubAccountId: 0,
toSubAccountId: 1,
marketIndex: 0,
amount: driftClient.convertToPerpPrecision(1),
});
Position Management
Reading Positions
const user = driftClient.getUser();
const perpPosition = user.getPerpPosition(0);
if (perpPosition) {
const baseAmount = perpPosition.baseAssetAmount;
const isLong = baseAmount.gt(new BN(0));
const isShort = baseAmount.lt(new BN(0));
console.log('Position size:', convertToNumber(baseAmount, BASE_PRECISION));
}
const activePerpPositions = user.getActivePerpPositions();
const spotPosition = user.getSpotPosition(0);
const tokenAmount = user.getTokenAmount(0);
const isDeposit = tokenAmount.gt(new BN(0));
const isBorrow = tokenAmount.lt(new BN(0));
const activeSpotPositions = user.getActiveSpotPositions();
Collateral and Margin
const user = driftClient.getUser();
const totalCollateral = user.getTotalCollateral();
const freeCollateral = user.getFreeCollateral();
const initialMargin = user.getInitialMarginRequirement();
const maintenanceMargin = user.getMaintenanceMarginRequirement();
const leverage = user.getLeverage();
const health = user.getHealth();
const maxLeverage = user.getMaxLeverageForPerp(0);
const buyingPower = user.getPerpBuyingPower(0);
PnL Calculations
const user = driftClient.getUser();
const unrealizedPnl = user.getUnrealizedPNL();
const unrealizedPnlWithFunding = user.getUnrealizedPNL(true);
const marketPnl = user.getUnrealizedPNL(false, 0);
const fundingPnl = user.getUnrealizedFundingPNL();
await driftClient.settlePNL(
user.getUserAccountPublicKey(),
user.getUserAccount(),
0
);
Liquidation Price
const user = driftClient.getUser();
const liqPrice = user.liquidationPrice(0);
const canBeLiquidated = user.canBeLiquidated();
Market Data
Market Accounts
const perpMarket = driftClient.getPerpMarketAccount(0);
console.log('Market index:', perpMarket.marketIndex);
console.log('AMM base reserves:', perpMarket.amm.baseAssetReserve.toString());
const allPerpMarkets = driftClient.getPerpMarketAccounts();
const spotMarket = driftClient.getSpotMarketAccount(0);
console.log('Decimals:', spotMarket.decimals);
const allSpotMarkets = driftClient.getSpotMarketAccounts();
Oracle Data
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const price = oracleData.price;
console.log('Oracle price:', convertToNumber(price, PRICE_PRECISION));
const spotOracleData = driftClient.getOracleDataForSpotMarket(1);
Calculate Prices from AMM
import { calculateBidAskPrice } from '@drift-labs/sdk';
const perpMarket = driftClient.getPerpMarketAccount(0);
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const [bidPrice, askPrice] = calculateBidAskPrice(
perpMarket.amm,
oracleData
);
Events
Event Subscriber
import { EventSubscriber } from '@drift-labs/sdk';
const eventSubscriber = new EventSubscriber(connection, driftClient.program, {
eventTypes: [
'DepositRecord',
'FundingPaymentRecord',
'LiquidationRecord',
'OrderRecord',
'OrderActionRecord',
'FundingRateRecord',
'SettlePnlRecord',
'LPRecord',
'InsuranceFundRecord',
'SpotInterestRecord',
],
maxTx: 4096,
maxEventsPerType: 4096,
commitment: 'confirmed',
logProviderConfig: { type: 'websocket' },
});
await eventSubscriber.subscribe();
eventSubscriber.eventEmitter.on('newEvent', (event) => {
console.log('Event type:', event.eventType);
console.log('Event data:', event);
});
const depositEvents = eventSubscriber.getEventsReceived()
.filter(e => e.eventType === 'DepositRecord');
await eventSubscriber.unsubscribe();
Jupiter Swaps
import { JupiterClient } from '@drift-labs/sdk';
const jupiterClient = new JupiterClient({ connection });
const quote = await jupiterClient.getQuote({
inputMint: ,
outputMint: ,
amount: driftClient.convertToSpotPrecision(0, 100),
slippageBps: 50,
});
const txSig = await driftClient.swap({
jupiterClient,
inMarketIndex: 0,
outMarketIndex: 1,
amount: driftClient.convertToSpotPrecision(0, 100),
slippageBps: 50,
onlyDirectRoutes: false,
});
Sub-Accounts
const [txSig, userPubkey] = await driftClient.initializeUserAccount(
1,
'SubAccount1'
);
await driftClient.switchActiveUser(1);
const user = driftClient.getUser(1);
await driftClient.deleteUser(1);
await driftClient.updateUserDelegate(delegatePublicKey, 0);
Advanced: Swift Protocol (Orderless Trades)
Swift allows off-chain order signing without Solana transactions:
const orderMessage = {
marketIndex: 0,
marketType: MarketType.PERP,
direction: PositionDirection.LONG,
baseAssetAmount: driftClient.convertToPerpPrecision(1),
price: driftClient.convertToPricePrecision(100),
};
const signature = driftClient.signSignedMsgOrderParamsMessage(orderMessage);
await axios.post('https://swift.drift.trade/orders', {
market_index: 0,
message: signature.message,
signature: signature.signature,
taker_authority: wallet.publicKey.toString(),
});
Advanced: Builder Codes (DBC)
For platforms routing trades through Drift to earn fees:
await driftClient.initializeRevenueShare(builderAuthority);
await driftClient.initializeRevenueShareEscrow(userAuthority, numOrders);
await driftClient.changeApprovedBuilder(
builderAuthority,
maxFeeTenthBps,
true
);
Error Handling
try {
await driftClient.placePerpOrder(orderParams);
} catch (error) {
if (error.message.includes('InsufficientCollateral')) {
console.error('Not enough collateral for this trade');
} else if (error.message.includes('MaxLeverageExceeded')) {
console.error('Would exceed maximum leverage');
} else if (error.message.includes('OrderWouldCrossMaker')) {
console.error('Post-only order would cross spread');
} else {
throw error;
}
}
Resources
Skill Structure
drift-protocol/
├── SKILL.md # This file
├── resources/
│ ├── precision-constants.md # All precision constants
│ ├── types-reference.md # TypeScript types and enums
│ ├── drift-client-api.md # DriftClient method reference
│ └── user-api.md # User class method reference
├── examples/
│ ├── basic-setup/ # Client initialization
│ ├── orders/ # Order placement examples
│ ├── deposits-withdrawals/ # Collateral management
│ ├── positions/ # Position queries
│ ├── jupiter-swaps/ # Swap integration
│ ├── vaults/ # Vault management
│ └── events/ # Event subscription
├── docs/
│ ├── vaults.md # Vault documentation
│ ├── market-making.md # Market making guide
│ └── troubleshooting.md # Common issues
└── templates/
└── trading-bot-template.ts # Copy-paste starter