solana_client_helpers/
client.rs1use std::ops::{Deref, DerefMut};
2
3pub use solana_client::{client_error, rpc_client::RpcClient};
4use solana_sdk::{
5 hash::Hash,
6 program_error::ProgramError,
7 pubkey::Pubkey,
8 signature::{Keypair, Signature, Signer},
9 system_instruction,
10 transaction::Transaction,
11};
12use thiserror::Error;
13
14#[derive(Debug, Error)]
15pub enum ClientError {
16 #[error(transparent)]
17 Client(#[from] client_error::ClientError),
18
19 #[error(transparent)]
20 Program(#[from] ProgramError),
21}
22
23pub type ClientResult<T> = Result<T, ClientError>;
24
25pub struct Client {
26 pub client: RpcClient,
27 pub payer: Keypair,
28}
29
30impl Client {
31 pub fn payer(&self) -> &Keypair {
32 &self.payer
33 }
34
35 pub fn payer_pubkey(&self) -> Pubkey {
36 self.payer.pubkey()
37 }
38
39 pub fn latest_blockhash(&self) -> ClientResult<Hash> {
40 Ok(self.client.get_latest_blockhash()?)
41 }
42
43 pub fn process_transaction(&self, transaction: &Transaction) -> ClientResult<()> {
44 self.send_and_confirm_transaction(transaction)?;
45 Ok(())
46 }
47
48 pub fn create_account(
49 &self,
50 owner: &Pubkey,
51 account_data_len: usize,
52 lamports: Option<u64>,
53 ) -> ClientResult<Keypair> {
54 let account = Keypair::new();
55 let lamports = if let Some(lamports) = lamports {
56 lamports
57 } else {
58 self.get_minimum_balance_for_rent_exemption(account_data_len)?
59 };
60
61 let mut transaction = Transaction::new_with_payer(
62 &[system_instruction::create_account(
63 &self.payer_pubkey(),
64 &account.pubkey(),
65 lamports,
66 account_data_len as u64,
67 owner,
68 )],
69 Some(&self.payer_pubkey()),
70 );
71 transaction.sign(&[self.payer(), &account], self.latest_blockhash()?);
72 self.process_transaction(&transaction)?;
73
74 Ok(account)
75 }
76
77 pub fn airdrop(&self, to_pubkey: &Pubkey, lamports: u64) -> ClientResult<Signature> {
78 let blockhash = self.client.get_latest_blockhash()?;
79 let signature = self.request_airdrop_with_blockhash(to_pubkey, lamports, &blockhash)?;
80 self.confirm_transaction_with_spinner(&signature, &blockhash, self.commitment())?;
81
82 Ok(signature)
83 }
84}
85
86impl Deref for Client {
87 type Target = RpcClient;
88
89 fn deref(&self) -> &Self::Target {
90 &self.client
91 }
92}
93
94impl DerefMut for Client {
95 fn deref_mut(&mut self) -> &mut Self::Target {
96 &mut self.client
97 }
98}