anchor_client/
nonblocking.rs1use crate::{
2 AsSigner, ClientError, Config, EventContext, EventUnsubscriber, Program,
3 ProgramAccountsIterator, RequestBuilder,
4};
5use anchor_lang::{prelude::Pubkey, AccountDeserialize, Discriminator};
6use solana_client::nonblocking::rpc_client::RpcClient as AsyncRpcClient;
7use solana_client::{rpc_config::RpcSendTransactionConfig, rpc_filter::RpcFilterType};
8use solana_sdk::{
9 commitment_config::CommitmentConfig, signature::Signature, signer::Signer,
10 transaction::Transaction,
11};
12use std::{marker::PhantomData, ops::Deref, sync::Arc};
13use tokio::sync::RwLock;
14
15impl<'a> EventUnsubscriber<'a> {
16 pub async fn unsubscribe(self) {
18 self.unsubscribe_internal().await
19 }
20}
21
22pub trait ThreadSafeSigner: Signer + Send + Sync + 'static {
23 fn to_signer(&self) -> &dyn Signer;
24}
25
26impl<T: Signer + Send + Sync + 'static> ThreadSafeSigner for T {
27 fn to_signer(&self) -> &dyn Signer {
28 self
29 }
30}
31
32impl AsSigner for Arc<dyn ThreadSafeSigner> {
33 fn as_signer(&self) -> &dyn Signer {
34 self.to_signer()
35 }
36}
37
38impl<C: Deref<Target = impl Signer> + Clone> Program<C> {
39 pub fn new(
40 program_id: Pubkey,
41 cfg: Config<C>,
42 #[cfg(feature = "mock")] rpc_client: AsyncRpcClient,
43 ) -> Result<Self, ClientError> {
44 #[cfg(not(feature = "mock"))]
45 let rpc_client = {
46 let comm_config = cfg.options.unwrap_or_default();
47 let cluster_url = cfg.cluster.url().to_string();
48 AsyncRpcClient::new_with_commitment(cluster_url.clone(), comm_config)
49 };
50
51 Ok(Self {
52 program_id,
53 cfg,
54 sub_client: Arc::new(RwLock::new(None)),
55 internal_rpc_client: rpc_client,
56 })
57 }
58
59 #[cfg(not(feature = "mock"))]
65 pub fn rpc(&self) -> AsyncRpcClient {
66 AsyncRpcClient::new_with_commitment(
67 self.cfg.cluster.url().to_string(),
68 self.cfg.options.unwrap_or_default(),
69 )
70 }
71
72 pub fn request(&self) -> RequestBuilder<'_, C, Arc<dyn ThreadSafeSigner>> {
74 RequestBuilder::from(
75 self.program_id,
76 self.cfg.cluster.url(),
77 self.cfg.payer.clone(),
78 self.cfg.options,
79 &self.internal_rpc_client,
80 )
81 }
82
83 pub async fn account<T: AccountDeserialize>(&self, address: Pubkey) -> Result<T, ClientError> {
85 self.account_internal(address).await
86 }
87
88 pub async fn accounts<T: AccountDeserialize + Discriminator>(
90 &self,
91 filters: Vec<RpcFilterType>,
92 ) -> Result<Vec<(Pubkey, T)>, ClientError> {
93 self.accounts_lazy(filters).await?.collect()
94 }
95
96 pub async fn accounts_lazy<T: AccountDeserialize + Discriminator>(
99 &self,
100 filters: Vec<RpcFilterType>,
101 ) -> Result<ProgramAccountsIterator<T>, ClientError> {
102 self.accounts_lazy_internal(filters).await
103 }
104
105 pub async fn on<T: anchor_lang::Event + anchor_lang::AnchorDeserialize>(
109 &self,
110 f: impl Fn(&EventContext, T) + Send + 'static,
111 ) -> Result<EventUnsubscriber, ClientError> {
112 let (handle, rx) = self.on_internal(f).await?;
113
114 Ok(EventUnsubscriber {
115 handle,
116 rx,
117 _lifetime_marker: PhantomData,
118 })
119 }
120}
121
122impl<'a, C: Deref<Target = impl Signer> + Clone> RequestBuilder<'a, C, Arc<dyn ThreadSafeSigner>> {
123 pub fn from(
124 program_id: Pubkey,
125 cluster: &str,
126 payer: C,
127 options: Option<CommitmentConfig>,
128 rpc_client: &'a AsyncRpcClient,
129 ) -> Self {
130 Self {
131 program_id,
132 payer,
133 cluster: cluster.to_string(),
134 accounts: Vec::new(),
135 options: options.unwrap_or_default(),
136 instructions: Vec::new(),
137 instruction_data: None,
138 signers: Vec::new(),
139 internal_rpc_client: rpc_client,
140 _phantom: PhantomData,
141 }
142 }
143
144 #[must_use]
145 pub fn signer<T: ThreadSafeSigner>(mut self, signer: T) -> Self {
146 self.signers.push(Arc::new(signer));
147 self
148 }
149
150 pub async fn signed_transaction(&self) -> Result<Transaction, ClientError> {
151 self.signed_transaction_internal().await
152 }
153
154 pub async fn send(self) -> Result<Signature, ClientError> {
155 self.send_internal().await
156 }
157
158 pub async fn send_with_spinner_and_config(
159 self,
160 config: RpcSendTransactionConfig,
161 ) -> Result<Signature, ClientError> {
162 self.send_with_spinner_and_config_internal(config).await
163 }
164}