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:
Standard transaction signing with the authority keypair
Transactions signed by a delegate on behalf of the authority
Read-only mode - transaction signing is disabled
Constructor Methods
new()
Create a wallet from a keypair.
pub fn new(authority: Keypair) -> Self
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
The delegate’s keypair for signing transactions
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
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>
The transaction message to sign
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