drift

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Drift Protocol SDK Development Guide

Drift Protocol SDK 开发指南

A comprehensive guide for building Solana applications with the Drift Protocol SDK - the leading perpetual futures and spot trading protocol on Solana.
这是一份使用Drift Protocol SDK构建Solana应用的综合指南——Drift Protocol是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
Drift Protocol是Solana上的去中心化交易所,提供以下功能:
  • 永续期货(Perpetual Futures):加密资产最高20倍杠杆
  • 现货交易(Spot Trading):借贷与保证金交易
  • 跨抵押(Cross-Collateral):支持多资产作为抵押品
  • 金库(Vaults):委托交易池
  • Jupiter集成:直接现货兑换

Quick Start

快速开始

Installation

安装

bash
npm install @drift-labs/sdk @solana/web3.js @coral-xyz/anchor
For Python:
bash
pip install driftpy
bash
npm install @drift-labs/sdk @solana/web3.js @coral-xyz/anchor
Python版本安装:
bash
pip install driftpy

Basic Setup (TypeScript)

基础配置(TypeScript)

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();
}
typescript
import { Connection, Keypair } from '@solana/web3.js';
import { Wallet } from '@coral-xyz/anchor';
import {
  DriftClient,
  initialize,
  DriftEnv,
  BulkAccountLoader
} from '@drift-labs/sdk';

// 1. 配置连接与钱包
const connection = new Connection('https://api.mainnet-beta.solana.com');
const keypair = Keypair.fromSecretKey(/* 你的密钥 */);
const wallet = new Wallet(keypair);

// 2. 初始化SDK
const sdkConfig = initialize({ env: 'mainnet-beta' as DriftEnv });

// 3. 创建DriftClient实例
const driftClient = new DriftClient({
  connection,
  wallet,
  env: 'mainnet-beta',
  accountSubscription: {
    type: 'polling',
    accountLoader: new BulkAccountLoader(connection, 'confirmed', 1000),
  },
});

// 4. 订阅更新
await driftClient.subscribe();

// 5. 检查用户账户是否存在
const user = driftClient.getUser();
const userExists = await user.exists();

if (!userExists) {
  // 初始化用户账户(约需0.035 SOL租金)
  await driftClient.initializeUserAccount();
}

Basic Setup (Python)

基础配置(Python)

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())
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)

1. 精度与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:
ConstantValueUse Case
QUOTE_PRECISION
10^6USDC amounts
BASE_PRECISION
10^9Perp base asset amounts
PRICE_PRECISION
10^6Prices
SPOT_MARKET_BALANCE_PRECISION
10^9Spot token balances
FUNDING_RATE_PRECISION
10^9Funding rates
MARGIN_PRECISION
10,000Margin ratios
PEG_PRECISION
10^6AMM peg
AMM_RESERVE_PRECISION
10^9AMM reserves
Conversion Helper:
typescript
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
由于代币精度超出JavaScript浮点数限制,Drift使用BN.js处理所有数值。所有金额均为带指定精度级别的整数。
关键精度常量:
常量数值适用场景
QUOTE_PRECISION
10^6USDC金额
BASE_PRECISION
10^9永续合约基础资产金额
PRICE_PRECISION
10^6价格
SPOT_MARKET_BALANCE_PRECISION
10^9现货代币余额
FUNDING_RATE_PRECISION
10^9资金费率
MARGIN_PRECISION
10,000保证金比率
PEG_PRECISION
10^6AMM挂钩价
AMM_RESERVE_PRECISION
10^9AMM储备金
转换工具函数:
typescript
import { convertToNumber } from '@drift-labs/sdk';

// BN除法返回向下取整结果 - 使用工具函数实现精确除法
const result = convertToNumber(new BN(10500), new BN(1000)); // = 10.5

// 金额转换
const perpAmount = driftClient.convertToPerpPrecision(100);  // 100个基础单位
const spotAmount = driftClient.convertToSpotPrecision(0, 100); // 100 USDC
const price = driftClient.convertToPricePrecision(21.23);    // $21.23

2. Market Types

2. 市场类型

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()
永续合约市场 (
MarketType.PERP
):
  • 无到期日的衍生品
  • 仓位通过
    baseAssetAmount
    追踪
  • 正数=多头,负数=空头
现货市场 (
MarketType.SPOT
):
  • 真实代币存入/借出
  • 仓位通过
    scaledBalance
    追踪
  • 类型为
    SpotBalanceType.DEPOSIT
    (存入)或
    SpotBalanceType.BORROW
    (借出)
常见市场索引:
  • 0
    - USDC(计价资产)
  • 1
    - SOL
  • 市场索引可能变动 - 调用
    getPerpMarketAccounts()
    /
    getSpotMarketAccounts()
    查询

3. Order Types

3. 订单类型

typescript
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
typescript
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

4. 只做市商参数

typescript
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
typescript
import { PostOnlyParams } from '@drift-labs/sdk';

PostOnlyParams.NONE           // 无限制(可作为吃单者)
PostOnlyParams.MUST_POST_ONLY // 若订单会穿透买卖价差则失败
PostOnlyParams.TRY_POST_ONLY  // 若订单会穿透买卖价差则跳过
PostOnlyParams.SLIDE          // 调整价格以满足只做市商要求

Trading Operations

交易操作

Placing Perpetual Orders

下单永续合约

typescript
// 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
});
typescript
// 市价单
await driftClient.placePerpOrder({
  orderType: OrderType.MARKET,
  marketIndex: 0,  // SOL永续合约
  direction: PositionDirection.LONG,
  baseAssetAmount: driftClient.convertToPerpPrecision(1), // 1 SOL
});

// 限价单
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,
});

// 止损单
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, // 比预言机价格低$0.10(以PRICE_PRECISION为单位)
  auctionDuration: 10,
  auctionStartPrice: new BN(-200000), // 起始价低于预言机$0.20
  auctionEndPrice: new BN(-50000),    // 结束价低于预言机$0.05
});

Placing Spot Orders

下单现货

typescript
// 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),
});
typescript
// 现货市价单
await driftClient.placeSpotOrder({
  orderType: OrderType.MARKET,
  marketIndex: 1, // SOL
  direction: PositionDirection.LONG, // 买入
  baseAssetAmount: driftClient.convertToSpotPrecision(1, 1), // 1 SOL
});

// 现货限价单
await driftClient.placeSpotOrder({
  orderType: OrderType.LIMIT,
  marketIndex: 1,
  direction: PositionDirection.LONG,
  baseAssetAmount: driftClient.convertToSpotPrecision(1, 1),
  price: driftClient.convertToPricePrecision(100),
});

Multiple Orders

批量下单

typescript
// 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),
  },
]);
typescript
// 原子化批量下单
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

订单管理

typescript
// 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),
  }],
});
typescript
// 按订单ID取消
await driftClient.cancelOrder(orderId);

// 按用户订单ID取消
await driftClient.cancelOrderByUserOrderId(userOrderId);

// 取消某市场的所有订单
await driftClient.cancelOrders(MarketType.PERP, 0); // 所有SOL永续合约订单

// 取消所有订单
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

查询订单

typescript
// 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();
typescript
// 查询指定订单
const order = driftClient.getOrder(orderId);

// 按用户ID查询订单
const order = driftClient.getOrderByUserId(userOrderId);

// 查询所有未成交订单
const user = driftClient.getUser();
const openOrders = user.getOpenOrders();

Deposits and Withdrawals

存入与提取

Deposits

存入资产

typescript
// 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
);
typescript
// 获取关联代币账户
const associatedTokenAccount = await driftClient.getAssociatedTokenAccount(0); // USDC

// 存入USDC
const amount = driftClient.convertToSpotPrecision(0, 100); // 100 USDC
await driftClient.deposit(amount, 0, associatedTokenAccount);

// 存入SOL
const solAccount = await driftClient.getAssociatedTokenAccount(1);
const solAmount = driftClient.convertToSpotPrecision(1, 1); // 1 SOL
await driftClient.deposit(solAmount, 1, solAccount);

// 一次性完成用户初始化与资产存入
const [txSig, userPubkey] = await driftClient.initializeUserAccountAndDepositCollateral(
  driftClient.convertToSpotPrecision(0, 100),
  await driftClient.getAssociatedTokenAccount(0),
  0, // 市场索引
  0, // 子账户ID
  'MyAccount', // 账户名称
);

Withdrawals

提取资产

typescript
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);
typescript
const associatedTokenAccount = await driftClient.getAssociatedTokenAccount(0);
const amount = driftClient.convertToSpotPrecision(0, 50); // 50 USDC

// 提取资产(若存入不足可能产生借贷)
await driftClient.withdraw(amount, 0, associatedTokenAccount);

// 仅平仓提取(禁止产生借贷)
await driftClient.withdraw(amount, 0, associatedTokenAccount, undefined, true);

Transfers Between Sub-Accounts

子账户间转账

typescript
// 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),
});
typescript
// 转账存入资产
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

查询仓位

typescript
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();
typescript
const user = driftClient.getUser();

// 永续合约仓位
const perpPosition = user.getPerpPosition(0); // SOL永续合约
if (perpPosition) {
  const baseAmount = perpPosition.baseAssetAmount;
  const isLong = baseAmount.gt(new BN(0));
  const isShort = baseAmount.lt(new BN(0));
  console.log('仓位大小:', convertToNumber(baseAmount, BASE_PRECISION));
}

// 所有活跃永续合约仓位
const activePerpPositions = user.getActivePerpPositions();

// 现货仓位
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));

// 所有活跃现货仓位
const activeSpotPositions = user.getActiveSpotPositions();

Collateral and Margin

抵押品与保证金

typescript
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);
typescript
const user = driftClient.getUser();

// 总抵押品价值
const totalCollateral = user.getTotalCollateral();

// 可用抵押品(可用于开新仓)
const freeCollateral = user.getFreeCollateral();

// 保证金要求
const initialMargin = user.getInitialMarginRequirement();
const maintenanceMargin = user.getMaintenanceMarginRequirement();

// 当前杠杆
const leverage = user.getLeverage();

// 账户健康度(0-100,0时触发清算)
const health = user.getHealth();

// 某市场的最大杠杆
const maxLeverage = user.getMaxLeverageForPerp(0); // SOL永续合约

// 购买力
const buyingPower = user.getPerpBuyingPower(0);

PnL Calculations

盈亏计算

typescript
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
);
typescript
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

清算价格

typescript
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();
typescript
const user = driftClient.getUser();

// 获取永续合约仓位的清算价格
const liqPrice = user.liquidationPrice(0); // SOL永续合约

// 检查是否可被清算
const canBeLiquidated = user.canBeLiquidated();

Market Data

市场数据

Market Accounts

市场账户

typescript
// 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();
typescript
// 永续合约市场
const perpMarket = driftClient.getPerpMarketAccount(0);
console.log('市场索引:', perpMarket.marketIndex);
console.log('AMM基础资产储备:', perpMarket.amm.baseAssetReserve.toString());

// 所有永续合约市场
const allPerpMarkets = driftClient.getPerpMarketAccounts();

// 现货市场
const spotMarket = driftClient.getSpotMarketAccount(0);
console.log('小数位数:', spotMarket.decimals);

// 所有现货市场
const allSpotMarkets = driftClient.getSpotMarketAccounts();

Oracle Data

预言机数据

typescript
// 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);
typescript
// 获取永续合约市场的预言机价格
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const price = oracleData.price; // 以PRICE_PRECISION为单位的BN值

console.log('预言机价格:', convertToNumber(price, PRICE_PRECISION));

// 获取现货市场的预言机数据
const spotOracleData = driftClient.getOracleDataForSpotMarket(1);

Calculate Prices from AMM

通过AMM计算价格

typescript
import { calculateBidAskPrice } from '@drift-labs/sdk';

const perpMarket = driftClient.getPerpMarketAccount(0);
const oracleData = driftClient.getOracleDataForPerpMarket(0);

const [bidPrice, askPrice] = calculateBidAskPrice(
  perpMarket.amm,
  oracleData
);
typescript
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

事件订阅器

typescript
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();
typescript
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.eventType);
  console.log('事件数据:', event);
});

// 按类型查询事件
const depositEvents = eventSubscriber.getEventsReceived()
  .filter(e => e.eventType === 'DepositRecord');

// 取消订阅
await eventSubscriber.unsubscribe();

Jupiter Swaps

Jupiter兑换

typescript
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,
});
typescript
import { JupiterClient } from '@drift-labs/sdk';

// 初始化Jupiter客户端
const jupiterClient = new JupiterClient({ connection });

// 获取报价预览
const quote = await jupiterClient.getQuote({
  inputMint: /* USDC铸币地址 */,
  outputMint: /* SOL铸币地址 */,
  amount: driftClient.convertToSpotPrecision(0, 100),
  slippageBps: 50,
});

// 通过Drift执行兑换
const txSig = await driftClient.swap({
  jupiterClient,
  inMarketIndex: 0,   // USDC
  outMarketIndex: 1,  // SOL
  amount: driftClient.convertToSpotPrecision(0, 100),
  slippageBps: 50,
  onlyDirectRoutes: false,
});

Sub-Accounts

子账户

typescript
// 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);
typescript
// 创建新子账户
const [txSig, userPubkey] = await driftClient.initializeUserAccount(
  1, // 子账户ID
  '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协议(无订单交易)

Swift allows off-chain order signing without Solana transactions:
typescript
// 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(),
});
Swift协议支持链下签名订单,无需Solana交易:
typescript
// 签名订单消息
const orderMessage = {
  marketIndex: 0,
  marketType: MarketType.PERP,
  direction: PositionDirection.LONG,
  baseAssetAmount: driftClient.convertToPerpPrecision(1),
  price: driftClient.convertToPricePrecision(100),
};

const signature = driftClient.signSignedMsgOrderParamsMessage(orderMessage);

// 提交至Swift服务器
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)

进阶:Builder Codes(DBC)

For platforms routing trades through Drift to earn fees:
typescript
// 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)
);
适用于通过Drift路由交易以赚取手续费的平台:
typescript
// 初始化为Builder
await driftClient.initializeRevenueShare(builderAuthority);

// 初始化用户托管账户
await driftClient.initializeRevenueShareEscrow(userAuthority, numOrders);

// 授权Builder
await driftClient.changeApprovedBuilder(
  builderAuthority,
  maxFeeTenthBps, // 最高手续费(万分之零点一)
  true // 添加(false为移除)
);

Error Handling

错误处理

typescript
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;
  }
}
typescript
try {
  await driftClient.placePerpOrder(orderParams);
} catch (error) {
  if (error.message.includes('InsufficientCollateral')) {
    console.error('抵押品不足,无法进行此交易');
  } else if (error.message.includes('MaxLeverageExceeded')) {
    console.error('超出最大杠杆限制');
  } else if (error.message.includes('OrderWouldCrossMaker')) {
    console.error('只做市商订单会穿透买卖价差');
  } 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
drift-protocol/
├── SKILL.md                          # 本文档
├── resources/
│   ├── precision-constants.md        # 所有精度常量
│   ├── types-reference.md            # TypeScript类型与枚举
│   ├── drift-client-api.md           # DriftClient方法参考
│   └── user-api.md                   # User类方法参考
├── examples/
│   ├── basic-setup/                  # 客户端初始化示例
│   ├── orders/                       # 下单示例
│   ├── deposits-withdrawals/         # 抵押品管理示例
│   ├── positions/                    # 仓位查询示例
│   ├── jupiter-swaps/                # 兑换集成示例
│   ├── vaults/                       # 金库管理示例
│   └── events/                       # 事件订阅示例
├── docs/
│   ├── vaults.md                     # 金库文档
│   ├── market-making.md              # 做市指南
│   └── troubleshooting.md            # 常见问题排查
└── templates/
    └── trading-bot-template.ts       # 可直接复用的交易机器人模板