mcpField
D
drift

drift

github.com/sendaifun開発13179 回インストール14 週間前に更新
リポジトリ

drift について

driftは、Drift Protocol SDKを使ってSolanaアプリを開発するためのガイドです。取引操作や市場データを組み込む開発者向けに、プロトコルの概念とTypeScript、Pythonの例を紹介します。

主な機能

  1. 01TypeScriptとPythonのセットアップ例
  2. 02無期限先物と現物の注文操作
  3. 03入金、出金、サブアカウント管理
  4. 04ポジション、証拠金、損益の照会
  5. 05市場データとオラクルデータへのアクセス
  6. 06JupiterスワップとSwift注文署名

活用シーン

  1. 01Solanaアプリへの無期限先物・現物取引の実装
  2. 02ポジション、担保、清算価格の参照
  3. 03市場アカウントとオラクル価格の照会
  4. 04サブアカウントやJupiterスワップを使う連携の構築

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/sendaifun/skills --skill drift

インストール後、Claude Code で/driftを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

docs/
market-making.md
troubleshooting.md
vaults.md
examples/basic-setup/
README.md
examples/deposits-withdrawals/
README.md
examples/events/
README.md
examples/jupiter-swaps/
README.md
examples/orders/
README.md
examples/positions/
README.md
examples/vaults/
README.md
resources/
drift-client-api.md
precision-constants.md
types-reference.md
user-api.md
templates/
trading-bot-template.ts

詳細

Drift Protocol SDK 開発ガイド

Drift Protocol SDK を使って Solana アプリケーションを構築するための包括的なガイドです。Drift Protocol は、Solana を代表する無期限先物および現物取引プロトコルです。

概要

Drift Protocol は Solana 上の分散型取引所で、以下を提供します。

  • 無期限先物:暗号資産を最大 20 倍のレバレッジで取引できます
  • 現物取引:借入・貸付および証拠金取引
  • クロス担保:複数の資産を担保として利用できます
  • ボールト:取引を委任するプール
  • Jupiter との統合:現物の直接スワップ

クイックスタート

インストール
npm install @drift-labs/sdk @solana/web3.js @coral-xyz/anchor

Python の場合:

pip install driftpy
基本的なセットアップ(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();
}
基本的なセットアップ(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())

コアコンセプト

1. 精度と BN(BigNumber)

Drift では、トークンの精度が JavaScript の浮動小数点数の限界を超えるため、すべての数値に BN.js を使用します。すべての金額は、指定された精度レベルを持つ整数です。

主な精度定数:

定数値用途
QUOTE_PRECISION10^6USDC の金額
BASE_PRECISION10^9無期限先物のベース資産の金額
PRICE_PRECISION10^6価格
SPOT_MARKET_BALANCE_PRECISION10^9現物トークン残高
FUNDING_RATE_PRECISION10^9資金調達率
MARGIN_PRECISION10,000証拠金比率
PEG_PRECISION10^6AMM ペグ
AMM_RESERVE_PRECISION10^9AMM の準備金

変換ヘルパー:

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. マーケットの種類

無期限先物マーケット(MarketType.PERP):

  • 有効期限のないデリバティブ
  • ポジションは baseAssetAmount で追跡されます
  • 正の値 = ロング、負の値 = ショート

現物マーケット(MarketType.SPOT):

  • 実際のトークンの預け入れ・借入
  • ポジションは scaledBalance で追跡されます
  • SpotBalanceType.DEPOSIT または SpotBalanceType.BORROW

一般的なマーケットインデックス:

  • 0 - USDC(クォート資産)
  • 1 - SOL
  • マーケットインデックスは異なる場合があります。getPerpMarketAccounts() / getSpotMarketAccounts() で取得してください。
3. 注文の種類
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 パラメーター
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);
AMM からの価格計算
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();

Jupiter スワップ

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 Protocol(注文不要の取引)

Swift では、Solana トランザクションを使わずにオフチェーンで注文に署名できます。

// 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(),
});

上級者向け:ビルダーコード(DBC)

Drift を経由して取引をルーティングし、手数料を獲得するプラットフォーム向け:

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

コメント