重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
drift by sendaifun/skills
npx skills add https://github.com/sendaifun/skills --skill drift使用 Drift Protocol SDK 构建 Solana 应用程序的全面指南 - Solana 上领先的永续期货和现货交易协议。
Drift Protocol 是 Solana 上的一个去中心化交易所,提供:
npm install @drift-labs/sdk @solana/web3.js @coral-xyz/anchor
对于 Python:
pip install driftpy
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(/* your secret key */);
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();
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
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())
由于代币精度超过 JavaScript 浮点数限制,Drift 对所有数值使用 BN.js。所有金额都是具有指定精度级别的整数。
关键精度常量:
| 常量 | 值 | 用例 |
|---|---|---|
QUOTE_PRECISION | 10^6 | USDC 金额 |
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^6 | AMM 锚定 |
AMM_RESERVE_PRECISION | 10^9 | AMM 储备 |
转换辅助函数:
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
永续市场 (MarketType.PERP):
baseAssetAmount 跟踪仓位现货市场 (MarketType.SPOT):
scaledBalance 跟踪仓位SpotBalanceType.DEPOSIT 或 SpotBalanceType.BORROW常见市场索引:
0 - USDC (报价资产)1 - SOLgetPerpMarketAccounts() / getSpotMarketAccounts()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 // 当价格 < 阈值时触发
import { PostOnlyParams } from '@drift-labs/sdk';
PostOnlyParams.NONE // 不强制执行 (可以是吃单方)
PostOnlyParams.MUST_POST_ONLY // 如果订单会穿越价差则失败
PostOnlyParams.TRY_POST_ONLY // 如果订单会穿越价差则跳过
PostOnlyParams.SLIDE // 调整价格以成为仅挂单
// 市价单
await driftClient.placePerpOrder({
orderType: OrderType.MARKET,
marketIndex: 0, // SOL-PERP
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
});
// 现货市价单
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),
});
// 原子性地下达多笔订单
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),
},
]);
// 按订单 ID 取消
await driftClient.cancelOrder(orderId);
// 按用户订单 ID 取消
await driftClient.cancelOrderByUserOrderId(userOrderId);
// 取消某个市场的所有订单
await driftClient.cancelOrders(MarketType.PERP, 0); // 所有 SOL-PERP 订单
// 取消所有订单
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),
}],
});
// 获取特定订单
const order = driftClient.getOrder(orderId);
// 按用户 ID 获取订单
const order = driftClient.getOrderByUserId(userOrderId);
// 获取所有未成交订单
const user = driftClient.getUser();
const openOrders = user.getOpenOrders();
// 获取关联的代币账户
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', // 名称
);
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);
// 转移存款
await driftClient.transferDeposit(
driftClient.convertToSpotPrecision(0, 100),
0, // 市场索引
0, // 来源子账户
1, // 目标子账户
);
// 转移永续仓位
await driftClient.transferPerpPosition({
fromSubAccountId: 0,
toSubAccountId: 1,
marketIndex: 0,
amount: driftClient.convertToPerpPrecision(1),
});
const user = driftClient.getUser();
// 永续仓位
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('仓位大小:', 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();
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-PERP
// 购买力
const buyingPower = user.getPerpBuyingPower(0);
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 // 市场索引
);
const user = driftClient.getUser();
// 获取永续仓位的清算价格
const liqPrice = user.liquidationPrice(0); // SOL-PERP
// 检查是否可能被清算
const canBeLiquidated = user.canBeLiquidated();
// 永续市场
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();
// 获取永续市场的预言机价格
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const price = oracleData.price; // BN 类型,单位为 PRICE_PRECISION
console.log('预言机价格:', convertToNumber(price, PRICE_PRECISION));
// 获取现货市场的预言机数据
const spotOracleData = driftClient.getOracleDataForSpotMarket(1);
import { calculateBidAskPrice } from '@drift-labs/sdk';
const perpMarket = driftClient.getPerpMarketAccount(0);
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const [bidPrice, askPrice] = calculateBidAskPrice(
perpMarket.amm,
oracleData
);
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();
import { JupiterClient } from '@drift-labs/sdk';
// 初始化 Jupiter 客户端
const jupiterClient = new JupiterClient({ connection });
// 获取报价预览
const quote = await jupiterClient.getQuote({
inputMint: /* USDC mint */,
outputMint: /* SOL mint */,
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,
});
// 创建新的子账户
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);
Swift 允许无需 Solana 交易的链下订单签名:
// 签署订单消息
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(),
});
适用于通过 Drift 路由交易以赚取费用的平台:
// 初始化为构建者
await driftClient.initializeRevenueShare(builderAuthority);
// 初始化用户的托管账户
await driftClient.initializeRevenueShareEscrow(userAuthority, numOrders);
// 批准构建者
await driftClient.changeApprovedBuilder(
builderAuthority,
maxFeeTenthBps, // 最大费用,单位为十分之一个基点
true // 添加 (false 表示移除)
);
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;
}
}
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 # 复制粘贴入门模板
每周安装次数
48
仓库
GitHub 星标数
68
首次出现
2026年1月24日
安全审计
安装于
opencode44
codex44
gemini-cli44
github-copilot41
amp40
kimi-cli40
A comprehensive guide for building Solana applications with the Drift Protocol SDK - the leading perpetual futures and spot trading protocol on Solana.
Drift Protocol is a decentralized exchange on Solana offering:
npm install @drift-labs/sdk @solana/web3.js @coral-xyz/anchor
For Python:
pip install driftpy
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();
}
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())
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 |
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
Perpetual Markets (MarketType.PERP):
baseAssetAmountSpot Markets (MarketType.SPOT):
scaledBalanceSpotBalanceType.DEPOSIT or SpotBalanceType.BORROWCommon Market Indexes:
0 - USDC (quote asset)1 - SOLgetPerpMarketAccounts() / getSpotMarketAccounts()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
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
// 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
});
// 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),
});
// 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),
},
]);
// 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 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();
// 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
);
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);
// 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),
});
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();
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);
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
);
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();
// 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();
// 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);
import { calculateBidAskPrice } from '@drift-labs/sdk';
const perpMarket = driftClient.getPerpMarketAccount(0);
const oracleData = driftClient.getOracleDataForPerpMarket(0);
const [bidPrice, askPrice] = calculateBidAskPrice(
perpMarket.amm,
oracleData
);
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();
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,
});
// 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);
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(),
});
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)
);
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;
}
}
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
Weekly Installs
48
Repository
GitHub Stars
68
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode44
codex44
gemini-cli44
github-copilot41
amp40
kimi-cli40
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
127,000 周安装
微信自动化监控与消息处理指南:Windows wxauto 与 macOS Accessibility API 实战
275 周安装
Go gRPC生产环境配置指南:版本化Protobuf、TLS、健康检查与错误处理
267 周安装
mgrep 代码语义搜索工具 - 智能探索大型代码库,支持自然语言查询代码/文本/PDF/图像
271 周安装
Three.js游戏开发指南:架构、性能优化与核心模式
273 周安装
文献深度研究方法与工具:系统性文献综述、证据分级与结构化报告生成
273 周安装
单细胞RNA测序质量控制工具 - 遵循scverse最佳实践的自动化QC工作流
278 周安装
| Funding rates |
MARGIN_PRECISION | 10,000 | Margin ratios |
PEG_PRECISION | 10^6 | AMM peg |
AMM_RESERVE_PRECISION | 10^9 | AMM reserves |