Skip to main content
The Wallet struct provides key management, transaction signing, and account derivation for Drift Protocol.

Overview

pub struct Wallet {
    signer: Arc<Keypair>,
    authority: Pubkey,
    stats: Pubkey,
    mode: Mode,
}
The Wallet can operate in three modes:
Mode::Normal
enum
Standard transaction signing with the authority keypair
Mode::Delegated
enum
Transactions signed by a delegate on behalf of the authority
Mode::ReadOnly
enum
Read-only mode - transaction signing is disabled

Constructor Methods

new()

Create a wallet from a keypair.
pub fn new(authority: Keypair) -> Self
authority
Keypair
required
The keypair for transaction signing
Example:
use drift_rs::Wallet;
use solana_sdk::signature::Keypair;

let keypair = Keypair::new();
let wallet = Wallet::new(keypair);

from_seed_bs58()

Create a wallet from a base58-encoded private key.
pub fn from_seed_bs58(seed: &str) -> Self
Example:
let wallet = Wallet::from_seed_bs58("YOUR_BASE58_PRIVATE_KEY");

from_seed()

Create a wallet from seed bytes.
pub fn from_seed(seed: &[u8]) -> SdkResult<Self>

try_from_str()

Load a wallet from either a file path or base58 private key string.
pub fn try_from_str(path_or_key: &str) -> SdkResult<Self>
Example:
// From private key
let wallet = Wallet::try_from_str("YOUR_PRIVATE_KEY")?;

// From file path
let wallet = Wallet::try_from_str("/path/to/wallet.json")?;

delegated()

Create a delegated wallet.
pub fn delegated(signer: Keypair, authority: Pubkey) -> Self
signer
Keypair
required
The delegate’s keypair for signing transactions
authority
Pubkey
required
The authority account that the delegate is signing for
Example:
let delegate_keypair = Keypair::new();
let authority_pubkey = /* authority address */;
let wallet = Wallet::delegated(delegate_keypair, authority_pubkey);

read_only()

Create a read-only wallet for querying without signing.
pub fn read_only(authority: Pubkey) -> Self
Example:
let authority = /* some public key */;
let wallet = Wallet::read_only(authority);

// Can query accounts but cannot sign transactions

Account Derivation Methods

derive_user_account()

Derive a user subaccount address.
pub fn derive_user_account(authority: &Pubkey, sub_account_id: u16) -> Pubkey
authority
&Pubkey
required
The authority public key
sub_account_id
u16
required
Subaccount ID (0-65535)
Users can have up to 65,536 subaccounts. Subaccount 0 is the default. Example:
let authority = wallet.authority();
let subaccount_0 = Wallet::derive_user_account(authority, 0);
let subaccount_1 = Wallet::derive_user_account(authority, 1);

derive_stats_account()

Derive the user stats account address.
pub fn derive_stats_account(account: &Pubkey) -> Pubkey
The stats account stores aggregate statistics for an authority across all subaccounts. Example:
let stats_account = Wallet::derive_stats_account(wallet.authority());

derive_swift_order_account()

Derive the swift order account address.
pub fn derive_swift_order_account(authority: &Pubkey) -> Pubkey
Swift orders are pre-signed orders stored on-chain.

derive_associated_token_address()

Derive the associated token account (ATA) for a spot market.
pub fn derive_associated_token_address(
    authority: &Pubkey,
    market: &SpotMarket
) -> Pubkey
Example:
let spot_market = client.get_spot_market_account(1).await?;
let token_account = Wallet::derive_associated_token_address(
    wallet.authority(),
    &spot_market,
);

Instance Methods

authority()

Get the wallet’s authority public key.
pub fn authority(&self) -> &Pubkey

sub_account()

Derive a subaccount for this wallet.
pub fn sub_account(&self, sub_account_id: u16) -> Pubkey
Shorthand for derive_user_account(self.authority(), sub_account_id). Example:
let subaccount_0 = wallet.sub_account(0);
let subaccount_5 = wallet.sub_account(5);

default_sub_account()

Get the default subaccount (subaccount 0).
pub fn default_sub_account(&self) -> Pubkey

sign_tx()

Sign a transaction message.
pub fn sign_tx(
    &self,
    message: VersionedMessage,
    recent_block_hash: Hash,
) -> SdkResult<VersionedTransaction>
message
VersionedMessage
required
The transaction message to sign
recent_block_hash
Hash
required
Recent blockhash for transaction validity
Returns a signed VersionedTransaction ready to send.

sign_message()

Sign an arbitrary message.
pub fn sign_message(&self, message: &[u8]) -> SdkResult<Signature>

is_delegated()

Check if the wallet is in delegated mode.
pub fn is_delegated(&self) -> bool

is_read_only()

Check if the wallet is in read-only mode.
pub fn is_read_only(&self) -> bool

From Trait Implementation

You can create a Wallet directly from a Keypair:
use solana_sdk::signature::Keypair;

let keypair = Keypair::new();
let wallet: Wallet = keypair.into();

Complete Example

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

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create wallet from keypair
    let keypair = Keypair::new();
    let wallet = Wallet::new(keypair);
    
    println!("Authority: {}", wallet.authority());
    println!("Default subaccount: {}", wallet.default_sub_account());
    println!("Subaccount 1: {}", wallet.sub_account(1));
    println!("Stats account: {}", Wallet::derive_stats_account(wallet.authority()));
    
    // Create client
    let client = DriftClient::new(
        Context::MainNet,
        RpcClient::new("https://api.mainnet-beta.solana.com".to_string()),
        wallet.clone(),
    ).await?;
    
    // Query user account
    let user = client.get_user_account(&wallet.default_sub_account()).await?;
    println!("User authority: {}", user.authority);
    
    // Create a delegated wallet
    let delegate_keypair = Keypair::new();
    let delegated_wallet = Wallet::delegated(
        delegate_keypair,
        *wallet.authority(),
    );
    
    println!("Delegated: {}", delegated_wallet.is_delegated());
    
    Ok(())
}

Subaccount Management

Subaccounts allow you to isolate risk and organize positions:
// Trading account
let trading_account = wallet.sub_account(0);

// Hedging account
let hedge_account = wallet.sub_account(1);

// LP account
let lp_account = wallet.sub_account(2);

// Each subaccount has independent positions and margin
let trading_positions = client.all_positions(&trading_account).await?;
let hedge_positions = client.all_positions(&hedge_account).await?;

See Also

Build docs developers (and LLMs) love