surfpool_core/surfnet/
remote.rs1use solana_client::{
2 nonblocking::rpc_client::RpcClient, rpc_request::TokenAccountsFilter,
3 rpc_response::RpcKeyedAccount,
4};
5use solana_commitment_config::CommitmentConfig;
6use solana_epoch_info::EpochInfo;
7use solana_pubkey::Pubkey;
8use solana_sdk::bpf_loader_upgradeable::get_program_data_address;
9use solana_signature::Signature;
10use solana_transaction_status::UiTransactionEncoding;
11
12use super::GetTransactionResult;
13use crate::{
14 error::{SurfpoolError, SurfpoolResult},
15 surfnet::GetAccountResult,
16};
17
18pub struct SurfnetRemoteClient {
19 pub client: RpcClient,
20}
21impl Clone for SurfnetRemoteClient {
22 fn clone(&self) -> Self {
23 let remote_rpc_url = self.client.url();
24 SurfnetRemoteClient {
25 client: RpcClient::new(remote_rpc_url),
26 }
27 }
28}
29
30pub trait SomeRemoteCtx {
31 fn get_remote_ctx<T>(&self, input: T) -> Option<(SurfnetRemoteClient, T)>;
32}
33
34impl SomeRemoteCtx for Option<SurfnetRemoteClient> {
35 fn get_remote_ctx<T>(&self, input: T) -> Option<(SurfnetRemoteClient, T)> {
36 self.as_ref()
37 .map(|remote_rpc_client| (remote_rpc_client.clone(), input))
38 }
39}
40
41impl SurfnetRemoteClient {
42 pub fn new(remote_rpc_url: &str) -> Self {
43 SurfnetRemoteClient {
44 client: RpcClient::new(remote_rpc_url.to_string()),
45 }
46 }
47
48 pub async fn get_epoch_info(&self) -> SurfpoolResult<EpochInfo> {
49 self.client.get_epoch_info().await.map_err(Into::into)
50 }
51
52 pub async fn get_account(
53 &self,
54 pubkey: &Pubkey,
55 commitment_config: CommitmentConfig,
56 ) -> SurfpoolResult<GetAccountResult> {
57 let res = self
58 .client
59 .get_account_with_commitment(pubkey, commitment_config)
60 .await
61 .map_err(|e| SurfpoolError::get_account(*pubkey, e))?;
62
63 let result = match res.value {
64 Some(account) => {
65 if !account.executable {
66 GetAccountResult::FoundAccount(
67 *pubkey, account,
68 true,
70 )
71 } else {
72 let program_data_address = get_program_data_address(pubkey);
73
74 let program_data = self
75 .client
76 .get_account_with_commitment(&program_data_address, commitment_config)
77 .await
78 .map_err(|e| SurfpoolError::get_account(*pubkey, e))?;
79
80 GetAccountResult::FoundProgramAccount(
81 (*pubkey, account),
82 (program_data_address, program_data.value),
83 )
84 }
85 }
86 None => GetAccountResult::None(*pubkey),
87 };
88 Ok(result)
89 }
90
91 pub async fn get_multiple_accounts(
92 &self,
93 pubkeys: &[Pubkey],
94 commitment_config: CommitmentConfig,
95 ) -> SurfpoolResult<Vec<GetAccountResult>> {
96 let remote_accounts = self
97 .client
98 .get_multiple_accounts(pubkeys)
99 .await
100 .map_err(SurfpoolError::get_multiple_accounts)?;
101
102 let mut accounts_result = vec![];
103 for (pubkey, remote_account) in pubkeys.iter().zip(remote_accounts) {
104 if let Some(remote_account) = remote_account {
105 if !remote_account.executable {
106 accounts_result.push(GetAccountResult::FoundAccount(
107 *pubkey,
108 remote_account,
109 true,
111 ));
112 } else {
113 let program_data_address = get_program_data_address(pubkey);
114
115 let program_data = self
116 .client
117 .get_account_with_commitment(&program_data_address, commitment_config)
118 .await
119 .map_err(|e| SurfpoolError::get_account(*pubkey, e))?;
120
121 accounts_result.push(GetAccountResult::FoundProgramAccount(
122 (*pubkey, remote_account),
123 (program_data_address, program_data.value),
124 ));
125 }
126 }
127 }
128 Ok(accounts_result)
129 }
130
131 pub async fn get_transaction(
132 &self,
133 signature: Signature,
134 encoding: Option<UiTransactionEncoding>,
135 latest_absolute_slot: u64,
136 ) -> GetTransactionResult {
137 match self
138 .client
139 .get_transaction(
140 &signature,
141 encoding.unwrap_or(UiTransactionEncoding::Base64),
142 )
143 .await
144 {
145 Ok(tx) => GetTransactionResult::found_transaction(signature, tx, latest_absolute_slot),
146 Err(_) => GetTransactionResult::None(signature),
147 }
148 }
149
150 pub async fn get_token_accounts_by_owner(
151 &self,
152
153 owner: Pubkey,
154 token_program: Pubkey,
155 ) -> SurfpoolResult<Vec<RpcKeyedAccount>> {
156 self.client
157 .get_token_accounts_by_owner(&owner, TokenAccountsFilter::ProgramId(token_program))
158 .await
159 .map_err(|e| SurfpoolError::get_token_accounts(owner, token_program, e))
160 }
161}