waffles_solana_sdk/
client.rs

1//! Defines traits for blocking (synchronous) and non-blocking (asynchronous)
2//! communication with a Solana server as well a a trait that encompasses both.
3//!
4//! //! Synchronous implementations are expected to create transactions, sign them, and send
5//! them with multiple retries, updating blockhashes and resigning as-needed.
6//!
7//! Asynchronous implementations are expected to create transactions, sign them, and send
8//! them but without waiting to see if the server accepted it.
9
10#![cfg(feature = "full")]
11
12use crate::{
13    account::Account,
14    clock::Slot,
15    commitment_config::CommitmentConfig,
16    epoch_info::EpochInfo,
17    fee_calculator::{FeeCalculator, FeeRateGovernor},
18    hash::Hash,
19    instruction::Instruction,
20    message::Message,
21    pubkey::Pubkey,
22    signature::{Keypair, Signature},
23    signer::Signer,
24    signers::Signers,
25    system_instruction,
26    transaction::{self, Transaction, VersionedTransaction},
27    transport::Result,
28};
29
30pub trait Client: SyncClient + AsyncClient {
31    fn tpu_addr(&self) -> String;
32}
33
34pub trait SyncClient {
35    /// Create a transaction from the given message, and send it to the
36    /// server, retrying as-needed.
37    fn send_and_confirm_message<T: Signers>(
38        &self,
39        keypairs: &T,
40        message: Message,
41    ) -> Result<Signature>;
42
43    /// Create a transaction from a single instruction that only requires
44    /// a single signer. Then send it to the server, retrying as-needed.
45    fn send_and_confirm_instruction(
46        &self,
47        keypair: &Keypair,
48        instruction: Instruction,
49    ) -> Result<Signature>;
50
51    /// Transfer lamports from `keypair` to `pubkey`, retrying until the
52    /// transfer completes or produces and error.
53    fn transfer_and_confirm(
54        &self,
55        lamports: u64,
56        keypair: &Keypair,
57        pubkey: &Pubkey,
58    ) -> Result<Signature>;
59
60    /// Get an account or None if not found.
61    fn get_account_data(&self, pubkey: &Pubkey) -> Result<Option<Vec<u8>>>;
62
63    /// Get an account or None if not found.
64    fn get_account(&self, pubkey: &Pubkey) -> Result<Option<Account>>;
65
66    /// Get an account or None if not found. Uses explicit commitment configuration.
67    fn get_account_with_commitment(
68        &self,
69        pubkey: &Pubkey,
70        commitment_config: CommitmentConfig,
71    ) -> Result<Option<Account>>;
72
73    /// Get account balance or 0 if not found.
74    fn get_balance(&self, pubkey: &Pubkey) -> Result<u64>;
75
76    /// Get account balance or 0 if not found. Uses explicit commitment configuration.
77    fn get_balance_with_commitment(
78        &self,
79        pubkey: &Pubkey,
80        commitment_config: CommitmentConfig,
81    ) -> Result<u64>;
82
83    fn get_minimum_balance_for_rent_exemption(&self, data_len: usize) -> Result<u64>;
84
85    /// Get recent blockhash
86    #[deprecated(since = "1.9.0", note = "Please use `get_latest_blockhash` instead")]
87    fn get_recent_blockhash(&self) -> Result<(Hash, FeeCalculator)>;
88
89    /// Get recent blockhash. Uses explicit commitment configuration.
90    #[deprecated(
91        since = "1.9.0",
92        note = "Please use `get_latest_blockhash_with_commitment` and `get_latest_blockhash_with_commitment` instead"
93    )]
94    fn get_recent_blockhash_with_commitment(
95        &self,
96        commitment_config: CommitmentConfig,
97    ) -> Result<(Hash, FeeCalculator, Slot)>;
98
99    /// Get `Some(FeeCalculator)` associated with `blockhash` if it is still in
100    /// the BlockhashQueue`, otherwise `None`
101    #[deprecated(
102        since = "1.9.0",
103        note = "Please use `get_fee_for_message` or `is_blockhash_valid` instead"
104    )]
105    fn get_fee_calculator_for_blockhash(&self, blockhash: &Hash) -> Result<Option<FeeCalculator>>;
106
107    /// Get recent fee rate governor
108    #[deprecated(
109        since = "1.9.0",
110        note = "Please do not use, will no longer be available in the future"
111    )]
112    fn get_fee_rate_governor(&self) -> Result<FeeRateGovernor>;
113
114    /// Get signature status.
115    fn get_signature_status(
116        &self,
117        signature: &Signature,
118    ) -> Result<Option<transaction::Result<()>>>;
119
120    /// Get signature status. Uses explicit commitment configuration.
121    fn get_signature_status_with_commitment(
122        &self,
123        signature: &Signature,
124        commitment_config: CommitmentConfig,
125    ) -> Result<Option<transaction::Result<()>>>;
126
127    /// Get last known slot
128    fn get_slot(&self) -> Result<Slot>;
129
130    /// Get last known slot. Uses explicit commitment configuration.
131    fn get_slot_with_commitment(&self, commitment_config: CommitmentConfig) -> Result<u64>;
132
133    /// Get transaction count
134    fn get_transaction_count(&self) -> Result<u64>;
135
136    /// Get transaction count. Uses explicit commitment configuration.
137    fn get_transaction_count_with_commitment(
138        &self,
139        commitment_config: CommitmentConfig,
140    ) -> Result<u64>;
141
142    fn get_epoch_info(&self) -> Result<EpochInfo>;
143
144    /// Poll until the signature has been confirmed by at least `min_confirmed_blocks`
145    fn poll_for_signature_confirmation(
146        &self,
147        signature: &Signature,
148        min_confirmed_blocks: usize,
149    ) -> Result<usize>;
150
151    /// Poll to confirm a transaction.
152    fn poll_for_signature(&self, signature: &Signature) -> Result<()>;
153
154    #[deprecated(
155        since = "1.9.0",
156        note = "Please do not use, will no longer be available in the future"
157    )]
158    fn get_new_blockhash(&self, blockhash: &Hash) -> Result<(Hash, FeeCalculator)>;
159
160    /// Get last known blockhash
161    fn get_latest_blockhash(&self) -> Result<Hash>;
162
163    /// Get latest blockhash with last valid block height. Uses explicit commitment configuration.
164    fn get_latest_blockhash_with_commitment(
165        &self,
166        commitment_config: CommitmentConfig,
167    ) -> Result<(Hash, u64)>;
168
169    /// Check if the blockhash is valid
170    fn is_blockhash_valid(&self, blockhash: &Hash, commitment: CommitmentConfig) -> Result<bool>;
171
172    /// Calculate the fee for a `Message`
173    fn get_fee_for_message(&self, message: &Message) -> Result<u64>;
174}
175
176pub trait AsyncClient {
177    /// Send a signed transaction, but don't wait to see if the server accepted it.
178    fn async_send_transaction(&self, transaction: Transaction) -> Result<Signature> {
179        self.async_send_versioned_transaction(transaction.into())
180    }
181
182    /// Send a batch of signed transactions without confirmation.
183    fn async_send_batch(&self, transactions: Vec<Transaction>) -> Result<()> {
184        let transactions = transactions.into_iter().map(Into::into).collect();
185        self.async_send_versioned_transaction_batch(transactions)
186    }
187
188    /// Send a signed versioned transaction, but don't wait to see if the server accepted it.
189    fn async_send_versioned_transaction(
190        &self,
191        transaction: VersionedTransaction,
192    ) -> Result<Signature>;
193
194    /// Send a batch of signed versioned transactions without confirmation.
195    fn async_send_versioned_transaction_batch(
196        &self,
197        transactions: Vec<VersionedTransaction>,
198    ) -> Result<()> {
199        for t in transactions {
200            self.async_send_versioned_transaction(t)?;
201        }
202        Ok(())
203    }
204
205    /// Create a transaction from the given message, and send it to the
206    /// server, but don't wait for to see if the server accepted it.
207    fn async_send_message<T: Signers>(
208        &self,
209        keypairs: &T,
210        message: Message,
211        recent_blockhash: Hash,
212    ) -> Result<Signature> {
213        let transaction = Transaction::new(keypairs, message, recent_blockhash);
214        self.async_send_transaction(transaction)
215    }
216
217    /// Create a transaction from a single instruction that only requires
218    /// a single signer. Then send it to the server, but don't wait for a reply.
219    fn async_send_instruction(
220        &self,
221        keypair: &Keypair,
222        instruction: Instruction,
223        recent_blockhash: Hash,
224    ) -> Result<Signature> {
225        let message = Message::new(&[instruction], Some(&keypair.pubkey()));
226        self.async_send_message(&[keypair], message, recent_blockhash)
227    }
228
229    /// Attempt to transfer lamports from `keypair` to `pubkey`, but don't wait to confirm.
230    fn async_transfer(
231        &self,
232        lamports: u64,
233        keypair: &Keypair,
234        pubkey: &Pubkey,
235        recent_blockhash: Hash,
236    ) -> Result<Signature> {
237        let transfer_instruction =
238            system_instruction::transfer(&keypair.pubkey(), pubkey, lamports);
239        self.async_send_instruction(keypair, transfer_instruction, recent_blockhash)
240    }
241}