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'
;
// 1. Setup connection and wallet
const
connection
=
new
Connection
(
'https://api.mainnet-beta.solana.com'
)
;
const
keypair
=
Keypair
.
fromSecretKey
(
/ your secret key /
)
;
const
wallet
=
new
Wallet
(
keypair
)
;
// 2. Initialize SDK
const
sdkConfig
=
initialize
(
{
env
:
'mainnet-beta'
as
DriftEnv
}
)
;
// 3. Create DriftClient
const
driftClient
=
new
DriftClient
(
{
connection
,
wallet
,
env
:
'mainnet-beta'
,
accountSubscription
:
{
type
:
'polling'
,
accountLoader
:
new
BulkAccountLoader
(
connection
,
'confirmed'
,
1000
)
,
}
,
}
)
;
// 4. Subscribe to updates
await
driftClient
.
subscribe
(
)
;
// 5. Check if user account exists
const
user
=
driftClient
.
getUser
(
)
;
const
userExists
=
await
user
.
exists
(
)
;
if
(
!
userExists
)
{
// Initialize user account (costs ~0.035 SOL rent)
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.mainnet-beta.solana.com"
)
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'
;
// BN division returns floor - use helper for precise division
const
result
=
convertToNumber
(
new
BN
(
10500
)
,
new
BN
(
1000
)
)
;
// = 10.5
// Converting amounts
const
perpAmount
=
driftClient
.
convertToPerpPrecision
(
100
)
;
// 100 base units
const
spotAmount
=
driftClient
.
convertToSpotPrecision
(
0
,
100
)
;
// 100 USDC
const
price
=
driftClient
.
convertToPricePrecision
(
21.23
)
;
// $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'
;
// Available order types
OrderType
.
MARKET
// Immediate execution
OrderType
.
LIMIT
// Price-specific orders
OrderType
.
TRIGGER_MARKET
// Stop-loss/take-profit market
OrderType
.
TRIGGER_LIMIT
// Stop-loss/take-profit limit
OrderType
.
ORACLE
// Oracle-based pricing
// Position directions
PositionDirection
.
LONG
// Buy/bid
PositionDirection
.
SHORT
// Sell/ask
// Trigger conditions (for stop orders)
OrderTriggerCondition
.
ABOVE
// Trigger when price > threshold
OrderTriggerCondition
.
BELOW
// Trigger when price < threshold
4. Post-Only Parameters
import
{
PostOnlyParams
}
from
'@drift-labs/sdk'
;
PostOnlyParams
.
NONE
// No enforcement (can be taker)
PostOnlyParams
.
MUST_POST_ONLY
// Fail if order would cross spread
PostOnlyParams
.
TRY_POST_ONLY
// Skip order if would cross spread
PostOnlyParams
.
SLIDE
// Adjust price to be post-only
Trading Operations
Placing Perpetual Orders
// Market Order
await
driftClient
.
placePerpOrder
(
{
orderType
:
OrderType
.
MARKET
,
marketIndex
:
0
,
// SOL-PERP
direction
:
PositionDirection
.
LONG
,
baseAssetAmount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
// 1 SOL
}
)
;
// Limit Order
await
driftClient
.
placePerpOrder
(
{
orderType
:
OrderType
.
LIMIT
,
marketIndex
:
0
,
direction
:
PositionDirection
.
LONG
,
baseAssetAmount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
price
:
driftClient
.
convertToPricePrecision
(
100
)
,
// $100
postOnly
:
PostOnlyParams
.
MUST_POST_ONLY
,
}
)
;
// Stop-Loss Order
await
driftClient
.
placePerpOrder
(
{
orderType
:
OrderType
.
TRIGGER_MARKET
,
marketIndex
:
0
,
direction
:
PositionDirection
.
SHORT
,
// Close long
baseAssetAmount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
triggerPrice
:
driftClient
.
convertToPricePrecision
(
90
)
,
triggerCondition
:
OrderTriggerCondition
.
BELOW
,
reduceOnly
:
true
,
}
)
;
// Take-Profit Order
await
driftClient
.
placePerpOrder
(
{
orderType
:
OrderType
.
TRIGGER_LIMIT
,
marketIndex
:
0
,
direction
:
PositionDirection
.
SHORT
,
// Close long
baseAssetAmount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
price
:
driftClient
.
convertToPricePrecision
(
120
)
,
triggerPrice
:
driftClient
.
convertToPricePrecision
(
120
)
,
triggerCondition
:
OrderTriggerCondition
.
ABOVE
,
reduceOnly
:
true
,
}
)
;
// Oracle Order (price relative to oracle)
await
driftClient
.
placePerpOrder
(
{
orderType
:
OrderType
.
ORACLE
,
marketIndex
:
0
,
direction
:
PositionDirection
.
LONG
,
baseAssetAmount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
oraclePriceOffset
:
-
100000
,
// $0.10 below oracle (PRICE_PRECISION)
auctionDuration
:
10
,
auctionStartPrice
:
new
BN
(
-
200000
)
,
// Start $0.20 below
auctionEndPrice
:
new
BN
(
-
50000
)
,
// End $0.05 below
}
)
;
Placing Spot Orders
// Spot Market Order
await
driftClient
.
placeSpotOrder
(
{
orderType
:
OrderType
.
MARKET
,
marketIndex
:
1
,
// SOL
direction
:
PositionDirection
.
LONG
,
// Buy
baseAssetAmount
:
driftClient
.
convertToSpotPrecision
(
1
,
1
)
,
// 1 SOL
}
)
;
// Spot Limit Order
await
driftClient
.
placeSpotOrder
(
{
orderType
:
OrderType
.
LIMIT
,
marketIndex
:
1
,
direction
:
PositionDirection
.
LONG
,
baseAssetAmount
:
driftClient
.
convertToSpotPrecision
(
1
,
1
)
,
price
:
driftClient
.
convertToPricePrecision
(
100
)
,
}
)
;
Multiple Orders
// Place multiple orders atomically
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
// Cancel by order ID
await
driftClient
.
cancelOrder
(
orderId
)
;
// Cancel by user order ID
await
driftClient
.
cancelOrderByUserOrderId
(
userOrderId
)
;
// Cancel all orders for a market
await
driftClient
.
cancelOrders
(
MarketType
.
PERP
,
0
)
;
// All SOL-PERP orders
// Cancel all orders
await
driftClient
.
cancelOrders
(
)
;
// Modify existing order
await
driftClient
.
modifyOrder
(
orderId
,
{
price
:
driftClient
.
convertToPricePrecision
(
102
)
,
}
)
;
// Cancel and place atomically
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
// Get specific order
const
order
=
driftClient
.
getOrder
(
orderId
)
;
// Get order by user ID
const
order
=
driftClient
.
getOrderByUserId
(
userOrderId
)
;
// Get all open orders
const
user
=
driftClient
.
getUser
(
)
;
const
openOrders
=
user
.
getOpenOrders
(
)
;
Deposits and Withdrawals
Deposits
// Get associated token account
const
associatedTokenAccount
=
await
driftClient
.
getAssociatedTokenAccount
(
0
)
;
// USDC
// Deposit USDC
const
amount
=
driftClient
.
convertToSpotPrecision
(
0
,
100
)
;
// 100 USDC
await
driftClient
.
deposit
(
amount
,
0
,
associatedTokenAccount
)
;
// Deposit SOL
const
solAccount
=
await
driftClient
.
getAssociatedTokenAccount
(
1
)
;
const
solAmount
=
driftClient
.
convertToSpotPrecision
(
1
,
1
)
;
// 1 SOL
await
driftClient
.
deposit
(
solAmount
,
1
,
solAccount
)
;
// Initialize user and deposit in one transaction
const
[
txSig
,
userPubkey
]
=
await
driftClient
.
initializeUserAccountAndDepositCollateral
(
driftClient
.
convertToSpotPrecision
(
0
,
100
)
,
await
driftClient
.
getAssociatedTokenAccount
(
0
)
,
0
,
// market index
0
,
// sub account ID
'MyAccount'
,
// name
)
;
Withdrawals
const
associatedTokenAccount
=
await
driftClient
.
getAssociatedTokenAccount
(
0
)
;
const
amount
=
driftClient
.
convertToSpotPrecision
(
0
,
50
)
;
// 50 USDC
// Withdraw (may create borrow if insufficient deposits)
await
driftClient
.
withdraw
(
amount
,
0
,
associatedTokenAccount
)
;
// Withdraw with reduce-only (prevents creating borrow)
await
driftClient
.
withdraw
(
amount
,
0
,
associatedTokenAccount
,
undefined
,
true
)
;
Transfers Between Sub-Accounts
// Transfer deposits
await
driftClient
.
transferDeposit
(
driftClient
.
convertToSpotPrecision
(
0
,
100
)
,
0
,
// market index
0
,
// from sub-account
1
,
// to sub-account
)
;
// Transfer perp positions
await
driftClient
.
transferPerpPosition
(
{
fromSubAccountId
:
0
,
toSubAccountId
:
1
,
marketIndex
:
0
,
amount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
}
)
;
Position Management
Reading Positions
const
user
=
driftClient
.
getUser
(
)
;
// Perpetual Position
const
perpPosition
=
user
.
getPerpPosition
(
0
)
;
// SOL-PERP
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
)
)
;
}
// All active perp positions
const
activePerpPositions
=
user
.
getActivePerpPositions
(
)
;
// Spot Position
const
spotPosition
=
user
.
getSpotPosition
(
0
)
;
// USDC
const
tokenAmount
=
user
.
getTokenAmount
(
0
)
;
const
isDeposit
=
tokenAmount
.
gt
(
new
BN
(
0
)
)
;
const
isBorrow
=
tokenAmount
.
lt
(
new
BN
(
0
)
)
;
// All active spot positions
const
activeSpotPositions
=
user
.
getActiveSpotPositions
(
)
;
Collateral and Margin
const
user
=
driftClient
.
getUser
(
)
;
// Total collateral value
const
totalCollateral
=
user
.
getTotalCollateral
(
)
;
// Free collateral (available for new positions)
const
freeCollateral
=
user
.
getFreeCollateral
(
)
;
// Margin requirements
const
initialMargin
=
user
.
getInitialMarginRequirement
(
)
;
const
maintenanceMargin
=
user
.
getMaintenanceMarginRequirement
(
)
;
// Current leverage
const
leverage
=
user
.
getLeverage
(
)
;
// Account health (0-100, liquidation at 0)
const
health
=
user
.
getHealth
(
)
;
// Max leverage for a market
const
maxLeverage
=
user
.
getMaxLeverageForPerp
(
0
)
;
// SOL-PERP
// Buying power
const
buyingPower
=
user
.
getPerpBuyingPower
(
0
)
;
PnL Calculations
const
user
=
driftClient
.
getUser
(
)
;
// Unrealized PnL (all positions)
const
unrealizedPnl
=
user
.
getUnrealizedPNL
(
)
;
// Unrealized PnL with funding
const
unrealizedPnlWithFunding
=
user
.
getUnrealizedPNL
(
true
)
;
// PnL for specific market
const
marketPnl
=
user
.
getUnrealizedPNL
(
false
,
0
)
;
// Unrealized funding PnL
const
fundingPnl
=
user
.
getUnrealizedFundingPNL
(
)
;
// Settle PnL
await
driftClient
.
settlePNL
(
user
.
getUserAccountPublicKey
(
)
,
user
.
getUserAccount
(
)
,
0
// market index
)
;
Liquidation Price
const
user
=
driftClient
.
getUser
(
)
;
// Get liquidation price for perp position
const
liqPrice
=
user
.
liquidationPrice
(
0
)
;
// SOL-PERP
// Check if can be liquidated
const
canBeLiquidated
=
user
.
canBeLiquidated
(
)
;
Market Data
Market Accounts
// Perpetual market
const
perpMarket
=
driftClient
.
getPerpMarketAccount
(
0
)
;
console
.
log
(
'Market index:'
,
perpMarket
.
marketIndex
)
;
console
.
log
(
'AMM base reserves:'
,
perpMarket
.
amm
.
baseAssetReserve
.
toString
(
)
)
;
// All perp markets
const
allPerpMarkets
=
driftClient
.
getPerpMarketAccounts
(
)
;
// Spot market
const
spotMarket
=
driftClient
.
getSpotMarketAccount
(
0
)
;
console
.
log
(
'Decimals:'
,
spotMarket
.
decimals
)
;
// All spot markets
const
allSpotMarkets
=
driftClient
.
getSpotMarketAccounts
(
)
;
Oracle Data
// Get oracle price for perp market
const
oracleData
=
driftClient
.
getOracleDataForPerpMarket
(
0
)
;
const
price
=
oracleData
.
price
;
// BN in PRICE_PRECISION
console
.
log
(
'Oracle price:'
,
convertToNumber
(
price
,
PRICE_PRECISION
)
)
;
// Get oracle for spot market
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
(
)
;
// Listen for events
eventSubscriber
.
eventEmitter
.
on
(
'newEvent'
,
(
event
)
=>
{
console
.
log
(
'Event type:'
,
event
.
eventType
)
;
console
.
log
(
'Event data:'
,
event
)
;
}
)
;
// Get events by type
const
depositEvents
=
eventSubscriber
.
getEventsReceived
(
)
.
filter
(
e
=>
e
.
eventType
===
'DepositRecord'
)
;
// Unsubscribe
await
eventSubscriber
.
unsubscribe
(
)
;
Jupiter Swaps
import
{
JupiterClient
}
from
'@drift-labs/sdk'
;
// Initialize Jupiter client
const
jupiterClient
=
new
JupiterClient
(
{
connection
}
)
;
// Get quote preview
const
quote
=
await
jupiterClient
.
getQuote
(
{
inputMint
:
/ USDC mint /
,
outputMint
:
/ SOL mint /
,
amount
:
driftClient
.
convertToSpotPrecision
(
0
,
100
)
,
slippageBps
:
50
,
}
)
;
// Execute swap through Drift
const
txSig
=
await
driftClient
.
swap
(
{
jupiterClient
,
inMarketIndex
:
0
,
// USDC
outMarketIndex
:
1
,
// SOL
amount
:
driftClient
.
convertToSpotPrecision
(
0
,
100
)
,
slippageBps
:
50
,
onlyDirectRoutes
:
false
,
}
)
;
Sub-Accounts
// Create new sub-account
const
[
txSig
,
userPubkey
]
=
await
driftClient
.
initializeUserAccount
(
1
,
// sub-account ID
'SubAccount1'
// name
)
;
// Switch active sub-account
await
driftClient
.
switchActiveUser
(
1
)
;
// Get user for specific sub-account
const
user
=
driftClient
.
getUser
(
1
)
;
// Delete sub-account (must have no positions)
await
driftClient
.
deleteUser
(
1
)
;
// Update delegate (allow another key to trade)
await
driftClient
.
updateUserDelegate
(
delegatePublicKey
,
0
)
;
Advanced: Swift Protocol (Orderless Trades)
Swift allows off-chain order signing without Solana transactions:
// Sign order message
const
orderMessage
=
{
marketIndex
:
0
,
marketType
:
MarketType
.
PERP
,
direction
:
PositionDirection
.
LONG
,
baseAssetAmount
:
driftClient
.
convertToPerpPrecision
(
1
)
,
price
:
driftClient
.
convertToPricePrecision
(
100
)
,
}
;
const
signature
=
driftClient
.
signSignedMsgOrderParamsMessage
(
orderMessage
)
;
// Submit to Swift server
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:
// Initialize as builder
await
driftClient
.
initializeRevenueShare
(
builderAuthority
)
;
// Initialize user's escrow
await
driftClient
.
initializeRevenueShareEscrow
(
userAuthority
,
numOrders
)
;
// Approve builder
await
driftClient
.
changeApprovedBuilder
(
builderAuthority
,
maxFeeTenthBps
,
// max fee in tenth basis points
true
// add (false to remove)
)
;
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
Drift Protocol Docs
SDK Documentation
TypeScript SDK
Python SDK (DriftPy)
Keeper Bots Examples
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