Drift¶
Connector for Drift protocol.
almanak.connectors.drift
¶
Drift Protocol Connector.
Provides perpetual futures trading on Drift (Solana's #1 perps DEX). Supports market orders for opening and closing perp positions.
Key classes: - DriftAdapter: Compiles PerpOpen/PerpClose intents to ActionBundles - DriftSDK: Low-level instruction building (PDA derivation, Borsh encoding) - DriftDataClient: REST client for Drift Data API (market info, funding rates) - DriftReceiptParser: Parses transaction receipts for fill data - DriftConfig: Adapter configuration
Lazy attribute access (VIB-4835): the strategy-side public surface is
exposed via PEP 562 __getattr__ so importing
almanak.connectors.drift.gateway.provider at gateway boot does not
eagerly pull adapter / SDK / client modules. The pre-existing
DRIFT_DATA_API_BASE_URL shim is preserved in the same __getattr__.
DriftAdapter
¶
Adapter for Drift protocol integration with the Intent system.
Converts PerpOpenIntent and PerpCloseIntent into ActionBundles containing serialized Solana VersionedTransactions.
Key features: - Market orders only (MVP scope) - Automatic account initialization if needed - Oracle and remaining accounts resolution via RPC - Sub-account 0 only (default)
compile_perp_open_intent
¶
Compile a PerpOpenIntent to an ActionBundle.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
intent
|
PerpOpenIntent
|
Perp open intent with market, size, direction, etc. |
必需 |
price_oracle
|
Any
|
Optional price oracle for USD conversions |
None
|
返回:
| 类型 | 描述 |
|---|---|
ActionBundle
|
ActionBundle with serialized VersionedTransaction |
compile_perp_close_intent
¶
Compile a PerpCloseIntent to an ActionBundle.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
intent
|
PerpCloseIntent
|
Perp close intent with market, direction, optional size |
必需 |
price_oracle
|
Any
|
Optional price oracle |
None
|
返回:
| 类型 | 描述 |
|---|---|
ActionBundle
|
ActionBundle with serialized VersionedTransaction |
DriftDataClient
¶
Client for the Drift public data API.
Provides read-only access to market data, funding rates, and oracle prices. No authentication required.
Example
client = DriftDataClient() markets = client.get_perp_markets() oracle_prices = client.get_oracle_prices()
get_perp_markets
¶
Get all perpetual futures markets.
返回:
| 类型 | 描述 |
|---|---|
list[DriftMarket]
|
List of DriftMarket with market info and stats |
get_oracle_prices
¶
Get current oracle prices for all perp markets.
返回:
| 类型 | 描述 |
|---|---|
dict[int, Decimal]
|
Dict of market_index → oracle price in USD |
get_oracle_price
¶
Get oracle price for a specific market.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market_index
|
int
|
Perp market index |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Decimal | None
|
Oracle price in USD, or None if not available |
get_funding_rates
¶
Get historical funding rates for a market.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market_index
|
int
|
Perp market index |
必需 |
返回:
| 类型 | 描述 |
|---|---|
list[FundingRate]
|
List of FundingRate data points |
get_market_info
¶
Get detailed info for a specific perp market.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market_index
|
int
|
Perp market index |
必需 |
返回:
| 类型 | 描述 |
|---|---|
DriftMarket | None
|
DriftMarket or None if not found |
DriftAccountNotFoundError
¶
Bases: DriftError
Exception raised when a Drift account is not found on-chain.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
message |
Error message |
|
account_type |
Type of account (e.g., "User", "PerpMarket") |
|
address |
The address that was looked up |
DriftAPIError
¶
DriftAPIError(
message: str,
status_code: int,
endpoint: str | None = None,
error_code: str | None = None,
)
Bases: DriftError
Exception raised for errors in the Drift Data API response.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
message |
Error message |
|
status_code |
HTTP status code of the response |
|
endpoint |
The API endpoint that was called |
|
error_code |
Drift-specific error code |
DriftConfigError
¶
Bases: DriftError
Exception raised for configuration errors.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
message |
Error message |
|
parameter |
Name of the configuration parameter that caused the error |
DriftError
¶
Bases: Exception
Base exception class for all Drift connector errors.
DriftMarketError
¶
Bases: DriftError
Exception raised for market-related errors.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
message |
Error message |
|
market |
Market identifier |
DriftValidationError
¶
Bases: DriftError
Exception raised for validation errors.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
message |
Error message |
|
field |
Name of the field that failed validation |
|
value |
The invalid value |
DriftConfig
dataclass
¶
DriftConfig(
wallet_address: str,
rpc_url: str = "",
sub_account_id: int = 0,
data_api_base_url: str = "https://data.api.drift.trade",
timeout: int = 30,
gateway_client: GatewayClient | None = None,
)
Configuration for Drift adapter.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
wallet_address |
str
|
Solana public key (Base58) |
rpc_url |
str
|
Solana RPC endpoint URL |
sub_account_id |
int
|
Drift sub-account ID (default 0) |
data_api_base_url |
str
|
Drift Data API base URL |
timeout |
int
|
Request timeout in seconds |
DriftMarket
dataclass
¶
DriftMarket(
market_index: int,
symbol: str = "",
base_asset_symbol: str = "",
oracle_price: Decimal = Decimal("0"),
funding_rate: Decimal = Decimal("0"),
funding_rate_24h: Decimal = Decimal("0"),
open_interest: Decimal = Decimal("0"),
volume_24h: Decimal = Decimal("0"),
mark_price: Decimal = Decimal("0"),
)
A Drift perpetual futures market.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
market_index |
int
|
On-chain market index |
symbol |
str
|
Market symbol (e.g., "SOL-PERP") |
base_asset_symbol |
str
|
Base asset symbol (e.g., "SOL") |
oracle_price |
Decimal
|
Current oracle price in USD |
funding_rate |
Decimal
|
Current funding rate (hourly) |
funding_rate_24h |
Decimal
|
24-hour average funding rate |
open_interest |
Decimal
|
Total open interest in base units |
volume_24h |
Decimal
|
24-hour volume in USD |
mark_price |
Decimal
|
Current mark price |
from_api_response
classmethod
¶
Create from Drift Data API market response.
DriftPerpPosition
dataclass
¶
DriftPerpPosition(
market_index: int = 0,
base_asset_amount: int = 0,
quote_asset_amount: int = 0,
last_cumulative_funding_rate: int = 0,
open_orders: int = 0,
)
A user's perpetual position on Drift.
Parsed from on-chain User account data.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
market_index |
int
|
Perp market index |
base_asset_amount |
int
|
Signed base amount (positive=long, negative=short) |
quote_asset_amount |
int
|
Quote amount (accumulated PnL) |
last_cumulative_funding_rate |
int
|
Last seen funding rate |
open_orders |
int
|
Number of open orders for this market |
DriftSpotPosition
dataclass
¶
DriftSpotPosition(
market_index: int = 0,
scaled_balance: int = 0,
balance_type: int = 0,
open_orders: int = 0,
)
A user's spot position on Drift.
Parsed from on-chain User account data.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
market_index |
int
|
Spot market index |
scaled_balance |
int
|
Scaled balance (deposit or borrow) |
balance_type |
int
|
0=Deposit, 1=Borrow |
open_orders |
int
|
Number of open orders |
DriftUserAccount
dataclass
¶
DriftUserAccount(
authority: str = "",
sub_account_id: int = 0,
perp_positions: list[DriftPerpPosition] = list(),
spot_positions: list[DriftSpotPosition] = list(),
exists: bool = True,
)
Parsed Drift User account state.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
authority |
str
|
Wallet public key that owns this account |
sub_account_id |
int
|
Sub-account identifier |
perp_positions |
list[DriftPerpPosition]
|
List of perp position slots |
spot_positions |
list[DriftSpotPosition]
|
List of spot position slots |
exists |
bool
|
Whether the account exists on-chain |
FundingRate
dataclass
¶
Funding rate data point.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
timestamp |
int
|
Unix timestamp |
funding_rate |
Decimal
|
Hourly funding rate as decimal |
market_index |
int
|
Market index |
from_api_response
classmethod
¶
Create from Drift Data API response.
OrderParams
dataclass
¶
OrderParams(
order_type: int = ORDER_TYPE_MARKET,
market_type: int = MARKET_TYPE_PERP,
direction: int = DIRECTION_LONG,
user_order_id: int = 0,
base_asset_amount: int = 0,
price: int = 0,
market_index: int = 0,
reduce_only: bool = False,
post_only: int = POST_ONLY_NONE,
bit_flags: int = 0,
max_ts: int | None = None,
trigger_price: int | None = None,
trigger_condition: int = TRIGGER_CONDITION_ABOVE,
oracle_price_offset: int | None = None,
auction_duration: int | None = None,
auction_start_price: int | None = None,
auction_end_price: int | None = None,
)
Parameters for a Drift perpetual order.
Maps to the on-chain OrderParams struct that gets Borsh-encoded into instruction data.
属性:
| 名称 | 类型 | 描述 |
|---|---|---|
order_type |
int
|
0=Market, 1=Limit, 2=TriggerMarket, 3=TriggerLimit, 4=Oracle |
market_type |
int
|
0=Perp, 1=Spot |
direction |
int
|
0=Long, 1=Short |
user_order_id |
int
|
User-assigned order ID (u8, 0-255) |
base_asset_amount |
int
|
Position size in base precision (1e9) |
price |
int
|
Limit price in price precision (1e6), 0 for market orders |
market_index |
int
|
Market index (u16) |
reduce_only |
bool
|
Whether order can only reduce position |
post_only |
int
|
PostOnlyParam enum (0=None, 1=MustPostOnly, 2=TryPostOnly, 3=Slide) |
bit_flags |
int
|
u8 bit field — bit 0: ImmediateOrCancel, bit 1: UpdateHighLeverageMode |
max_ts |
int | None
|
Optional max timestamp (unix seconds) |
trigger_price |
int | None
|
Optional trigger price for stop/take-profit orders |
trigger_condition |
int
|
0=Above, 1=Below |
oracle_price_offset |
int | None
|
Optional offset from oracle price (i32, in 1e6) |
auction_duration |
int | None
|
Optional auction duration in slots |
auction_start_price |
int | None
|
Optional auction start price |
auction_end_price |
int | None
|
Optional auction end price |
DriftReceiptParser
¶
Receipt parser for Drift Protocol transactions.
Uses balance-delta approach to extract execution information from Solana transaction receipts.
parse_receipt
¶
Parse a Drift transaction receipt.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Solana transaction receipt dict with 'meta' containing preTokenBalances, postTokenBalances, and logMessages |
必需 |
返回:
| 类型 | 描述 |
|---|---|
dict[str, Any]
|
Parsed result with extracted data |
extract_perp_fill
¶
Extract perpetual fill data from a receipt.
Parses Drift program logs for fill events that contain order execution details.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
receipt
|
dict[str, Any]
|
Transaction receipt |
必需 |
返回:
| 类型 | 描述 |
|---|---|
dict[str, Any] | None
|
Fill data dict or None |
extract_position_id
¶
No-op stub — Drift position IDs require account-state queries.
extract_size_delta
¶
No-op stub — Drift size delta requires account-state diff.
extract_collateral
¶
No-op stub — Drift collateral requires account-state diff.
extract_entry_price
¶
No-op stub — Drift entry price is not surfaced in receipt logs.
extract_leverage
¶
No-op stub — Drift leverage is not surfaced in receipt logs.
extract_exit_price
¶
No-op stub — Drift exit price requires log parsing (deferred).
extract_realized_pnl
¶
No-op stub — Drift PnL requires account-state diff (deferred).
extract_fees_paid
¶
No-op stub — Drift fees require log/account-state parsing (deferred).
extract_collateral_returned
¶
No-op stub — Drift collateral returned requires account-state diff.
extract_protocol_fees
¶
Placeholder for Drift protocol-fee extraction (VIB-3204).
Drift fees (taker fee, filler reward) are embedded in program log messages and account-state deltas that are non-trivial to parse. Full extraction is deferred to a follow-up ticket.
extract_funding_fee_usd
¶
No-op stub for funding fee USD extraction (VIB-3520).
Drift accrues funding payments through vAMM account-state changes rather than discrete receipt events. Extracting the USD-denominated funding cost at close time requires querying the user's PerpPosition account before and after settlement, which is out of scope for a receipt parser. This stub suppresses the extraction warning that ResultEnricher emits when processing PERP_CLOSE intents.
DriftSDK
¶
DriftSDK(
wallet_address: str,
rpc_url: str = "",
timeout: int = 30,
gateway_client: GatewayClient | None = None,
)
SDK for building Drift protocol instructions.
Provides methods to: - Derive PDAs for Drift accounts (state, user, markets) - Build Solana instructions for perp trading - Fetch and parse on-chain account data via RPC - Build remaining accounts lists for order placement
Example
sdk = DriftSDK(wallet_address="your-pubkey", rpc_url="https://...") ix = sdk.build_place_perp_order_ix( order_params=OrderParams(direction=DIRECTION_LONG, ...), remaining_accounts=[...], )
get_user_pda
¶
Derive a Drift User account PDA.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
authority
|
Pubkey | None
|
Wallet pubkey (defaults to SDK's wallet) |
None
|
sub_account_id
|
int
|
Sub-account ID (default 0) |
0
|
get_user_stats_pda
¶
Derive the User Stats account PDA.
get_perp_market_pda
¶
Derive a Perp Market account PDA.
get_spot_market_pda
¶
Derive a Spot Market account PDA.
fetch_user_account
¶
Fetch and parse a Drift User account from on-chain data.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
sub_account_id
|
int
|
Sub-account ID to fetch |
0
|
返回:
| 类型 | 描述 |
|---|---|
DriftUserAccount
|
DriftUserAccount with parsed positions, or exists=False if not found |
fetch_market_oracle
¶
Fetch the oracle pubkey from a perp market account.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market_index
|
int
|
Perp market index |
必需 |
返回:
| 类型 | 描述 |
|---|---|
Pubkey | None
|
Oracle Pubkey or None if not found |
fetch_spot_market_oracle
¶
Fetch the oracle pubkey from a spot market account.
build_remaining_accounts
¶
Build the remaining accounts list for a place_perp_order instruction.
Drift requires remaining accounts to include all markets the user has positions in, plus their oracles. The order is: 1. Oracle accounts (readable) 2. Spot market accounts (readable) 3. Perp market accounts (readable)
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
market_index
|
int
|
The perp market being traded |
必需 |
sub_account_id
|
int
|
Sub-account ID |
0
|
返回:
| 类型 | 描述 |
|---|---|
list[AccountMeta]
|
List of AccountMeta for remaining accounts |
build_place_perp_order_ix
¶
build_place_perp_order_ix(
order_params: OrderParams,
remaining_accounts: list[AccountMeta],
sub_account_id: int = 0,
) -> Instruction
Build a place_perp_order instruction.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
order_params
|
OrderParams
|
Order parameters to encode |
必需 |
remaining_accounts
|
list[AccountMeta]
|
Pre-built remaining accounts (oracles, markets) |
必需 |
sub_account_id
|
int
|
Sub-account ID |
0
|
返回:
| 类型 | 描述 |
|---|---|
Instruction
|
Solana Instruction ready for transaction |
build_initialize_user_ix
¶
Build an initialize_user instruction.
Creates a new Drift User account for the wallet. Must be called before the first order if no account exists.
build_initialize_user_stats_ix
¶
Build an initialize_user_stats instruction.
Must be called before initialize_user if no user stats exist.
build_deposit_ix
¶
Build a deposit instruction.
Deposits collateral (typically USDC) into a Drift spot market.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
amount
|
int
|
Amount in smallest units (e.g., USDC with 6 decimals) |
必需 |
market_index
|
int
|
Spot market index (0 = USDC) |
0
|
sub_account_id
|
int
|
Sub-account ID |
0
|
get_init_instructions
¶
Get instructions to initialize user accounts if they don't exist.
Returns an empty list if accounts already exist.
get_drift_data_api_base_url
¶
Return the Drift data API base URL.
Phase 5b of the config-service migration: the legacy module-level
constant DRIFT_DATA_API_BASE_URL = os.environ.get(...) froze the
env value at import time, which was a real bug (a test that
monkeypatched the env var after the constants module was first loaded
saw no effect). This helper reads the typed config at call time
instead, so monkeypatching DRIFT_DATA_API_BASE_URL between calls
works as expected.
is_supported_collateral
¶
Return True if collateral_token is a Drift spot-market symbol.
The check is case-insensitive. Raw 0x/base58 addresses are NOT recognised by this predicate — address-based collaterals are considered non-validatable here and should be treated as permissive by callers (the compiler's address-resolution path handles that).
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
collateral_token
|
str
|
Collateral token symbol (e.g. |
必需 |
返回:
| 类型 | 描述 |
|---|---|
bool
|
|
bool
|
|
validate_drift_collateral
¶
Validate that collateral_token is a legal Drift collateral symbol.
Compile-path validation. This is the entry point called by the intent compiler's PERP_OPEN path for Drift intents. It must be invoked BEFORE the Drift adapter is instantiated so that invalid configurations fail before any transaction is built.
Behaviour
- Empty / whitespace-only strings raise
:class:
InvalidCollateralForMarketError. - 0x-prefixed or base58-looking raw addresses (anything that does not look like a short ticker symbol) are skipped with a debug log — the compiler's downstream resolution path handles address collateral.
- A recognised symbol returns normally.
- An unrecognised symbol raises :class:
InvalidCollateralForMarketErrorwhoseallowed_collateralslists every Drift spot-market symbol.
参数:
| 名称 | 类型 | 描述 | 默认 |
|---|---|---|---|
collateral_token
|
str
|
Collateral token symbol (e.g. |
必需 |
引发:
| 类型 | 描述 |
|---|---|
InvalidCollateralForMarketError
|
When the supplied symbol is not one of Drift's registered spot-market collaterals. |
__getattr__
¶
PEP 562 lazy attribute access.
Resolves DRIFT_DATA_API_BASE_URL to the runtime accessor (legacy
shim from constants.py) and everything else via _LAZY.