Skip to main content
The DriftClient is the main interface for interacting with the Drift Protocol. It provides methods for querying accounts, subscribing to updates, and building transactions.

Overview

DriftClient is designed to be cheaply cloneable - it uses internal reference counting so you can clone it freely without duplicating network connections or memory allocations.
pub struct DriftClient {
    pub context: Context,
    backend: &'static DriftClientBackend,
    pub wallet: Wallet,
}

Constructor Methods

new()

Create a new DriftClient instance.
pub async fn new(
    context: Context,
    rpc_client: RpcClient,
    wallet: Wallet
) -> SdkResult<Self>
context
Context
required
Network context - use Context::MainNet or Context::DevNet
rpc_client
RpcClient
required
Solana RPC client instance for network communication
wallet
Wallet
required
Wallet for transaction signing
Example:
use drift_rs::{DriftClient, Context, Wallet};
use solana_sdk::signature::Keypair;
use solana_rpc_client::nonblocking::rpc_client::RpcClient;

let wallet = Wallet::from(Keypair::new());
let rpc = RpcClient::new("https://api.mainnet-beta.solana.com".to_string());

let client = DriftClient::new(
    Context::MainNet,
    rpc,
    wallet,
).await?;

new_with_ws_url()

Create a DriftClient with an explicit WebSocket URL.
pub async fn new_with_ws_url(
    context: Context,
    rpc_client: RpcClient,
    wallet: Wallet,
    ws_pubsub_url: &str
) -> SdkResult<Self>
ws_pubsub_url
&str
required
Custom WebSocket PubSub URL for subscriptions

Subscription Methods

subscribe_markets()

Subscribe to market account updates via WebSocket.
pub async fn subscribe_markets(&self, markets: &[MarketId]) -> SdkResult<()>
markets
&[MarketId]
required
Array of market IDs to subscribe to
Example:
let markets = vec![MarketId::perp(0), MarketId::spot(1)];
client.subscribe_markets(&markets).await?;

// Now market data is cached locally
let sol_perp = client.get_perp_market_account(0).await?;

subscribe_oracles()

Subscribe to oracle price feed updates.
pub async fn subscribe_oracles(&self, markets: &[MarketId]) -> SdkResult<()>

subscribe_account()

Subscribe to a specific account for live updates.
pub async fn subscribe_account(&self, account: &Pubkey) -> SdkResult<()>

grpc_subscribe()

Subscribe to all updates via high-performance gRPC (Yellowstone).
pub async fn grpc_subscribe(
    &self,
    endpoint: String,
    x_token: String,
    opts: GrpcSubscribeOpts,
    sync: bool
) -> SdkResult<()>
endpoint
String
required
gRPC endpoint URL
x_token
String
required
Authentication token for gRPC
opts
GrpcSubscribeOpts
required
Subscription configuration options
sync
bool
required
Whether to sync all accounts on startup
Learn more about gRPC subscriptions →

Market Query Methods

get_spot_market_account()

Get spot market account data.
pub async fn get_spot_market_account(&self, market_index: u16) -> SdkResult<SpotMarket>
market_index
u16
required
Spot market index (e.g., 0 for USDC, 1 for SOL)

get_perp_market_account()

Get perpetual market account data.
pub async fn get_perp_market_account(&self, market_index: u16) -> SdkResult<PerpMarket>

oracle_price()

Get the current oracle price for a market.
pub async fn oracle_price(&self, market: MarketId) -> SdkResult<i64>
Returns the price with PRICE_PRECISION (1e6) decimals. Example:
let sol_price = client.oracle_price(MarketId::perp(0)).await?;
println!("SOL price: ${}", sol_price as f64 / 1e6);

User Account Methods

get_user_account()

Get a user’s drift account.
pub async fn get_user_account(&self, account: &Pubkey) -> SdkResult<User>

all_orders()

Get all open orders for an account.
pub async fn all_orders(&self, account: &Pubkey) -> SdkResult<Vec<Order>>

all_positions()

Get all open positions for an account.
pub async fn all_positions(
    &self,
    account: &Pubkey
) -> SdkResult<(Vec<SpotPosition>, Vec<PerpPosition>)>
Returns a tuple of (spot_positions, perp_positions).

get_order_by_id()

Get a specific order by its ID.
pub async fn get_order_by_id(
    &self,
    account: &Pubkey,
    order_id: u32
) -> SdkResult<Option<Order>>

Transaction Methods

init_tx()

Initialize a transaction builder.
pub async fn init_tx(
    &self,
    account: &Pubkey,
    delegated: bool
) -> SdkResult<TransactionBuilder<'_>>
account
&Pubkey
required
User account address (subaccount)
delegated
bool
required
Whether this is a delegated transaction
Example:
let subaccount = wallet.derive_user_account(0);

let tx = client
    .init_tx(&subaccount, false)
    .await?
    .place_orders(vec![order_params])
    .build();

let sig = client.sign_and_send(tx).await?;

sign_and_send()

Sign and send a transaction to the network.
pub async fn sign_and_send(&self, tx: VersionedMessage) -> SdkResult<Signature>

simulate_tx()

Simulate a transaction without sending it.
pub async fn simulate_tx(
    &self,
    tx: VersionedMessage
) -> SdkResult<RpcSimulateTransactionResult>

Utility Methods

get_all_market_ids()

Get all active market IDs (spot and perp).
pub fn get_all_market_ids(&self) -> Vec<MarketId>

get_all_spot_market_ids()

Get all active spot market IDs.
pub fn get_all_spot_market_ids(&self) -> Vec<MarketId>

get_all_perp_market_ids()

Get all active perpetual market IDs.
pub fn get_all_perp_market_ids(&self) -> Vec<MarketId>

market_lookup()

Lookup a market by its symbol.
pub fn market_lookup(&self, symbol: &str) -> Option<MarketId>
Example:
if let Some(market_id) = client.market_lookup("SOL-PERP") {
    let market = client.get_perp_market_account(market_id.index()).await?;
}

program_data()

Get on-chain program metadata and configuration.
pub fn program_data(&self) -> &ProgramData

wallet()

Get a reference to the client’s wallet.
pub fn wallet(&self) -> &Wallet

rpc()

Get a reference to the underlying RPC client.
pub fn rpc(&self) -> Arc<RpcClient>

unsubscribe()

Unsubscribe from all WebSocket/gRPC subscriptions.
pub async fn unsubscribe(&self) -> SdkResult<()>

Complete Example

use drift_rs::{DriftClient, Context, Wallet, MarketId};
use solana_sdk::signature::Keypair;
use solana_rpc_client::nonblocking::rpc_client::RpcClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize client
    let wallet = Wallet::from(Keypair::new());
    let rpc = RpcClient::new("https://api.mainnet-beta.solana.com".to_string());
    
    let client = DriftClient::new(
        Context::MainNet,
        rpc,
        wallet.clone(),
    ).await?;

    // Subscribe to markets and oracles
    let markets = vec![MarketId::perp(0), MarketId::spot(1)];
    client.subscribe_markets(&markets).await?;
    client.subscribe_oracles(&markets).await?;

    // Query market data
    let sol_perp = client.get_perp_market_account(0).await?;
    let sol_price = client.oracle_price(MarketId::perp(0)).await?;
    
    println!("SOL-PERP market: {:?}", sol_perp.market_index);
    println!("SOL price: ${}", sol_price as f64 / 1e6);

    // Query user account
    let subaccount = wallet.derive_user_account(0);
    let user = client.get_user_account(&subaccount).await?;
    let (spot_positions, perp_positions) = client.all_positions(&subaccount).await?;
    
    println!("Open positions: {} spot, {} perp", 
        spot_positions.len(), 
        perp_positions.len()
    );

    Ok(())
}

See Also

Build docs developers (and LLMs) love