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>
Network context - use Context::MainNet or Context::DevNet
Solana RPC client instance for network communication
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>
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<()>
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<()>
Authentication token for gRPC
opts
GrpcSubscribeOpts
required
Subscription configuration options
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>
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<'_>>
User account address (subaccount)
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