1use async_trait::async_trait;
2use futures_util::lock::Mutex;
3use getset::{Getters, Setters};
4use primitive_types::{H160, H256};
5use serde::{de::DeserializeOwned, Deserialize, Serialize};
6use serde_json::{json, value::Value};
7use std::{
8 collections::HashMap,
9 convert::TryFrom,
10 fmt::{Debug, Display},
11 future::Future,
12 net::Ipv4Addr,
13 pin::Pin,
14 str::FromStr,
15 sync::Arc,
16 time::Duration,
17};
18use tracing::{debug, trace};
19use tracing_futures::Instrument;
20use url::{Host, ParseError, Url};
21
22use crate::{
24 neo_builder::{
25 CallFlags, InteropService, ScriptBuilder, TransactionBuilder, TransactionSigner,
26 },
27 neo_clients::{
28 APITrait, Http, HttpProvider, HttpRateLimitRetryPolicy, JsonRpcProvider, ProviderError,
29 RetryClient, RwClient,
30 },
31};
32
33use crate::{
34 builder::{Signer, Transaction, TransactionSendToken},
35 codec::NeoSerializable,
36 config::NEOCONFIG,
37 neo_crypto::utils::{FromBase64String, FromHexString, ToHexString},
38 neo_protocol::*,
39 neo_types::ScriptHashExtension,
40 prelude::Base64Encode,
41 Address, ContractManifest, ContractParameter, ContractState, InvocationResult,
42 NativeContractState, NefFile, StackItem, ValueExtension,
43};
44
45#[derive(Copy, Clone)]
47pub enum NeoClient {
48 NEO,
50}
51
52impl FromStr for NeoClient {
53 type Err = ProviderError;
54
55 fn from_str(s: &str) -> Result<Self, Self::Err> {
56 let first_segment = s
57 .split('/')
58 .next()
59 .ok_or(ProviderError::ParseError("Invalid client string format".to_string()))?;
60 match first_segment.to_lowercase().as_str() {
61 "neo" => Ok(NeoClient::NEO),
62 _ => Err(ProviderError::UnsupportedNodeClient),
63 }
64 }
65}
66
67#[derive(Clone, Debug, Getters)]
88pub struct RpcClient<P> {
89 provider: P,
90 nns: Option<Address>,
91 interval: Option<Duration>,
92 from: Option<Address>,
93 _node_client: Arc<Mutex<Option<NeoVersion>>>,
94 }
97
98impl<P> AsRef<P> for RpcClient<P> {
99 fn as_ref(&self) -> &P {
100 &self.provider
101 }
102}
103
104impl<P: JsonRpcProvider> RpcClient<P> {
106 pub fn new(provider: P) -> Self {
108 Self {
109 provider,
110 nns: None,
111 interval: None,
112 from: None,
113 _node_client: Arc::new(Mutex::new(None)),
114 }
116 }
117
118 pub async fn node_client(&self) -> Result<NeoVersion, ProviderError> {
121 let mut node_client = self._node_client.lock().await;
122
123 if let Some(ref node_client) = *node_client {
124 Ok(node_client.clone())
125 } else {
126 let client_version = self.get_version().await?;
127 *node_client = Some(client_version.clone());
128 Ok(client_version)
129 }
130 }
131
132 #[must_use]
133 pub fn with_sender(mut self, address: impl Into<Address>) -> Self {
135 self.from = Some(address.into());
136 self
137 }
138
139 pub async fn request<T, R>(&self, method: &str, params: T) -> Result<R, ProviderError>
141 where
142 T: Debug + Serialize + Send + Sync,
143 R: Serialize + DeserializeOwned + Debug + Send,
144 {
145 let span = tracing::trace_span!("rpc: ", method = method, params = ?serde_json::to_string(¶ms)?);
146 let res = async move {
148 let fetched = self.provider.fetch(method, params).await;
150 let res: R = fetched.map_err(Into::into)?;
151 trace!(rx = ?serde_json::to_string(&res)?);
153 Ok::<_, ProviderError>(res)
154 }
155 .instrument(span)
156 .await?;
157 Ok(res)
158 }
159}
160
161#[cfg_attr(target_arch = "wasm32", async_trait(? Send))]
162#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
163impl<P: JsonRpcProvider> APITrait for RpcClient<P> {
164 type Error = ProviderError;
165 type Provider = P;
166
167 fn rpc_client(&self) -> &RpcClient<Self::Provider> {
168 self
169 }
170
171 async fn network(&self) -> Result<u32, ProviderError> {
172 if NEOCONFIG.lock().map_err(|_| ProviderError::LockError)?.network.is_none() {
174 let version = self.get_version().await?;
175 let protocol = version.protocol.ok_or(ProviderError::ProtocolNotFound)?;
176 return Ok(protocol.network);
177 }
178 NEOCONFIG
179 .lock()
180 .map_err(|_| ProviderError::LockError)?
181 .network
182 .ok_or(ProviderError::NetworkNotFound)
183 }
184
185 async fn get_best_block_hash(&self) -> Result<H256, ProviderError> {
191 self.request("getbestblockhash", Vec::<H256>::new()).await
192 }
193
194 async fn get_block_hash(&self, block_index: u32) -> Result<H256, ProviderError> {
198 self.request("getblockhash", [block_index.to_value()].to_vec()).await
199 }
200
201 async fn get_block(&self, block_hash: H256, full_tx: bool) -> Result<NeoBlock, ProviderError> {
207 Ok(if full_tx {
208 self.request("getblock", [block_hash.to_value(), 1.to_value()]).await?
209 } else {
210 self.get_block_header(block_hash).await?
211 })
212 }
213
214 async fn get_block_by_hash(
220 &self,
221 hash: &str,
222 full_tx: bool,
223 ) -> Result<NeoBlock, ProviderError> {
224 let block_hash = H256::from_str(hash)
225 .map_err(|e| ProviderError::ParseError(format!("Invalid block hash: {}", e)))?;
226 self.get_block(block_hash, full_tx).await
227 }
228
229 async fn get_raw_block(&self, block_hash: H256) -> Result<String, ProviderError> {
233 self.request("getblock", [block_hash.to_value(), 0.to_value()]).await
234 }
235
236 async fn get_block_header_count(&self) -> Result<u32, ProviderError> {
240 self.request("getblockheadercount", Vec::<u32>::new()).await
241 }
242
243 async fn get_block_count(&self) -> Result<u32, ProviderError> {
246 self.request("getblockcount", Vec::<u32>::new()).await
247 }
248
249 async fn get_block_header(&self, block_hash: H256) -> Result<NeoBlock, ProviderError> {
253 self.request("getblockheader", vec![block_hash.to_value(), 1.to_value()]).await
254 }
255
256 async fn get_block_header_by_index(&self, index: u32) -> Result<NeoBlock, ProviderError> {
260 self.request("getblockheader", vec![index.to_value(), 1.to_value()]).await
261 }
262
263 async fn get_raw_block_header(&self, block_hash: H256) -> Result<String, ProviderError> {
267 self.request("getblockheader", vec![block_hash.to_value(), 0.to_value()]).await
268 }
269
270 async fn get_raw_block_header_by_index(&self, index: u32) -> Result<String, ProviderError> {
274 self.request("getblockheader", vec![index.to_value(), 0.to_value()]).await
275 }
276
277 async fn get_native_contracts(&self) -> Result<Vec<NativeContractState>, ProviderError> {
280 self.request("getnativecontracts", Vec::<NativeContractState>::new()).await
281 }
282
283 async fn get_contract_state(&self, hash: H160) -> Result<ContractState, ProviderError> {
287 self.request("getcontractstate", vec![hash.to_hex()]).await
288 }
289
290 async fn get_contract_state_by_id(&self, id: i64) -> Result<ContractState, ProviderError> {
294 self.request("getcontractstate", vec![id.to_value()]).await
295 }
296
297 async fn get_native_contract_state(&self, name: &str) -> Result<ContractState, ProviderError> {
303 self.request("getcontractstate", vec![name.to_value()]).await
304 }
305
306 async fn get_mem_pool(&self) -> Result<MemPoolDetails, ProviderError> {
309 self.request("getrawmempool", vec![1.to_value()]).await
310 }
311
312 async fn get_raw_mem_pool(&self) -> Result<Vec<H256>, ProviderError> {
315 self.request("getrawmempool", Vec::<H256>::new()).await
316 }
317
318 async fn get_transaction(&self, hash: H256) -> Result<RTransaction, ProviderError> {
322 self.request("getrawtransaction", vec![hash.to_value(), 1.to_value()]).await
323 }
324
325 async fn get_raw_transaction(&self, tx_hash: H256) -> Result<String, ProviderError> {
329 self.request("getrawtransaction", vec![tx_hash.to_value(), 0.to_value()]).await
330 }
331
332 async fn get_storage(&self, contract_hash: H160, key: &str) -> Result<String, ProviderError> {
338 let params: [String; 2] =
339 [contract_hash.to_hex(), Base64Encode::to_base64(&key.to_string())];
340 self.request("getstorage", params.to_vec()).await
341 }
342
343 async fn find_storage(
350 &self,
351 contract_hash: H160,
352 prefix_hex_string: &str,
353 start_index: u64,
354 ) -> Result<String, ProviderError> {
355 let params = json!([
357 contract_hash.to_hex(),
358 Base64Encode::to_base64(&prefix_hex_string.to_string()),
359 start_index
360 ]);
361 self.request("findstorage", params).await
362 }
363
364 async fn find_storage_with_id(
371 &self,
372 contract_id: i64,
373 prefix_hex_string: &str,
374 start_index: u64,
375 ) -> Result<String, ProviderError> {
376 let params = json!([
378 contract_id,
379 Base64Encode::to_base64(&prefix_hex_string.to_string()),
380 start_index
381 ]);
382 self.request("findstorage", params).await
383 }
384
385 async fn get_transaction_height(&self, tx_hash: H256) -> Result<u32, ProviderError> {
389 let params = [tx_hash.to_value()];
390 self.request("gettransactionheight", params.to_vec()).await
391 }
392
393 async fn get_next_block_validators(&self) -> Result<Vec<Validator>, ProviderError> {
396 self.request("getnextblockvalidators", Vec::<Validator>::new()).await
397 }
398
399 async fn get_committee(&self) -> Result<Vec<String>, ProviderError> {
402 self.request("getcommittee", Vec::<String>::new()).await
403 }
404
405 async fn get_connection_count(&self) -> Result<u32, ProviderError> {
408 self.request("getconnectioncount", Vec::<u32>::new()).await
409 }
410
411 async fn get_peers(&self) -> Result<Peers, ProviderError> {
414 self.request("getpeers", Vec::<Peers>::new()).await
415 }
416
417 async fn get_version(&self) -> Result<NeoVersion, ProviderError> {
420 self.request("getversion", Vec::<NeoVersion>::new()).await
421 }
422
423 async fn send_raw_transaction(&self, hex: String) -> Result<RawTransaction, ProviderError> {
427 self.request("sendrawtransaction", vec![Base64Encode::to_base64(&hex)]).await
428 }
429
430 async fn send_transaction<'a>(&self, tx: Transaction<'a, P>) -> Result<H256, ProviderError> {
440 let tx_hex = hex::encode(tx.to_array());
441 let result = self.send_raw_transaction(tx_hex).await?;
442
443 let tx_hash = H256::from_str(&result.hash.to_string()).map_err(|e| {
445 ProviderError::ParseError(format!("Failed to parse transaction hash: {}", e))
446 })?;
447
448 Ok(tx_hash)
449 }
450
451 async fn submit_block(&self, hex: String) -> Result<SubmitBlock, ProviderError> {
455 self.request("submitblock", vec![hex.to_value()]).await
456 }
457
458 async fn broadcast_address(&self) -> Result<bool, ProviderError> {
460 self.request("broadcastaddr", Vec::<String>::new()).await
461 }
462
463 async fn broadcast_block(&self, block: NeoBlock) -> Result<bool, ProviderError> {
465 let block_json = serde_json::to_string(&block)
466 .map_err(|e| ProviderError::ParseError(format!("Failed to serialize block: {}", e)))?;
467
468 self.request("broadcastblock", vec![block_json.to_value()]).await
469 }
470
471 async fn broadcast_get_blocks(&self, hash: &str, count: u32) -> Result<bool, ProviderError> {
482 let hash_obj = H256::from_str(hash)
483 .map_err(|e| ProviderError::ParseError(format!("Invalid block hash: {}", e)))?;
484
485 self.request("broadcastgetblocks", vec![hash_obj.to_value(), count.to_value()])
486 .await
487 }
488
489 async fn broadcast_transaction(&self, tx: RTransaction) -> Result<bool, ProviderError> {
499 let tx_json = serde_json::to_string(&tx).map_err(|e| {
500 ProviderError::ParseError(format!("Failed to serialize transaction: {}", e))
501 })?;
502
503 self.request("broadcasttransaction", vec![tx_json.to_value()]).await
504 }
505
506 async fn create_contract_deployment_transaction(
508 &self,
509 nef: NefFile,
510 manifest: ContractManifest,
511 signers: Vec<Signer>,
512 ) -> Result<TransactionBuilder<P>, ProviderError> {
513 let nef_bytes = nef.to_array();
514 let manifest_json = serde_json::to_string(&manifest).map_err(|e| {
515 ProviderError::ParseError(format!("Failed to serialize manifest: {}", e))
516 })?;
517
518 let mut script_builder = ScriptBuilder::new();
519 script_builder
520 .push_data(manifest_json.as_bytes().to_vec())
521 .push_data(nef_bytes)
522 .sys_call(InteropService::SystemContractCall);
523
524 let mut builder = TransactionBuilder::new();
525 builder.extend_script(script_builder.to_bytes());
526
527 Ok(builder)
531 }
532
533 async fn create_contract_update_transaction(
535 &self,
536 contract_hash: H160,
537 nef: NefFile,
538 manifest: ContractManifest,
539 signers: Vec<Signer>,
540 ) -> Result<TransactionBuilder<P>, ProviderError> {
541 let nef_bytes = nef.to_array();
542 let manifest_json = serde_json::to_string(&manifest).map_err(|e| {
543 ProviderError::ParseError(format!("Failed to serialize manifest: {}", e))
544 })?;
545
546 let mut script_builder = ScriptBuilder::new();
547 script_builder
548 .push_data(manifest_json.as_bytes().to_vec())
549 .push_data(nef_bytes)
550 .push_data(contract_hash.to_vec())
551 .sys_call(InteropService::SystemContractCall);
552
553 let mut builder = TransactionBuilder::new();
554 builder.extend_script(script_builder.to_bytes());
555
556 Ok(builder)
560 }
561
562 async fn create_invocation_transaction(
564 &self,
565 contract_hash: H160,
566 method: &str,
567 parameters: Vec<ContractParameter>,
568 signers: Vec<Signer>,
569 ) -> Result<TransactionBuilder<P>, ProviderError> {
570 let mut script_builder = ScriptBuilder::new();
571 script_builder
572 .contract_call(&contract_hash, method, ¶meters, None)
573 .map_err(|e| {
574 ProviderError::ParseError(format!("Failed to create contract call: {}", e))
575 })?;
576
577 let mut builder = TransactionBuilder::new();
578 builder.extend_script(script_builder.to_bytes());
579
580 Ok(builder)
584 }
585
586 async fn invoke_function(
596 &self,
597 contract_hash: &H160,
598 method: String,
599 params: Vec<ContractParameter>,
600 signers: Option<Vec<Signer>>,
601 ) -> Result<InvocationResult, ProviderError> {
602 match signers {
603 Some(signers) => {
604 let signers: Vec<TransactionSigner> = signers.iter().map(|f| f.into()).collect();
605 self.request(
606 "invokefunction",
607 json!([contract_hash.to_hex(), method, params, signers,]),
608 )
609 .await
610 },
611 None => {
612 let signers: Vec<TransactionSigner> = vec![];
613 self.request(
614 "invokefunction",
615 json!([
616 contract_hash.to_hex(),
618 method,
619 params,
620 signers
621 ]), )
627 .await
628 },
629 }
630 }
631
632 async fn invoke_script(
638 &self,
639 hex: String,
640 signers: Vec<Signer>,
641 ) -> Result<InvocationResult, ProviderError> {
642 let signers: Vec<TransactionSigner> =
643 signers.into_iter().map(|signer| signer.into()).collect::<Vec<_>>();
644 let hex_bytes = hex::decode(&hex)
645 .map_err(|e| ProviderError::ParseError(format!("Failed to parse hex: {}", e)))?;
646 let script_base64 = serde_json::to_value(hex_bytes.to_base64())?;
647 let signers_json = serde_json::to_value(&signers)?;
648 self.request("invokescript", [script_base64, signers_json]).await
649 }
650
651 async fn get_unclaimed_gas(&self, hash: H160) -> Result<UnclaimedGas, ProviderError> {
655 self.request("getunclaimedgas", [hash.to_address()]).await
656 }
657
658 async fn list_plugins(&self) -> Result<Vec<Plugin>, ProviderError> {
661 self.request("listplugins", Vec::<u32>::new()).await
662 }
663
664 async fn validate_address(&self, address: &str) -> Result<ValidateAddress, ProviderError> {
668 self.request("validateaddress", vec![address.to_value()]).await
669 }
670
671 async fn close_wallet(&self) -> Result<bool, ProviderError> {
674 self.request("closewallet", Vec::<u32>::new()).await
675 }
676
677 async fn dump_priv_key(&self, script_hash: H160) -> Result<String, ProviderError> {
681 let params = [script_hash.to_address()].to_vec();
682 self.request("dumpprivkey", params).await
683 }
684
685 async fn get_wallet_balance(&self, token_hash: H160) -> Result<Balance, ProviderError> {
689 self.request("getwalletbalance", vec![token_hash.to_value()]).await
690 }
691
692 async fn get_new_address(&self) -> Result<String, ProviderError> {
695 self.request("getnewaddress", Vec::<u32>::new()).await
696 }
697
698 async fn get_wallet_unclaimed_gas(&self) -> Result<String, ProviderError> {
701 self.request("getwalletunclaimedgas", Vec::<String>::new()).await
702 }
703
704 async fn import_priv_key(&self, priv_key: String) -> Result<NeoAddress, ProviderError> {
708 let params = [priv_key.to_value()].to_vec();
709 self.request("importprivkey", params).await
710 }
711
712 async fn calculate_network_fee(
716 &self,
717 txBase64: String,
718 ) -> Result<NeoNetworkFee, ProviderError> {
719 self.request("calculatenetworkfee", vec![Base64Encode::to_base64(&txBase64)])
720 .await
721 }
722
723 async fn list_address(&self) -> Result<Vec<NeoAddress>, ProviderError> {
726 self.request("listaddress", Vec::<NeoAddress>::new()).await
727 }
728
729 async fn open_wallet(&self, path: String, password: String) -> Result<bool, ProviderError> {
735 self.request("openwallet", vec![path.to_value(), password.to_value()]).await
736 }
737
738 async fn send_from(
746 &self,
747 token_hash: H160,
748 from: H160,
749 to: H160,
750 amount: u32,
751 ) -> Result<RTransaction, ProviderError> {
752 let params = json!([token_hash.to_hex(), from.to_address(), to.to_address(), amount,]);
755 self.request("sendfrom", params).await
756 }
757
758 async fn send_many(
764 &self,
765 from: Option<H160>,
766 send_tokens: Vec<TransactionSendToken>,
767 ) -> Result<RTransaction, ProviderError> {
768 let params = match from {
769 Some(f) => json!([f.to_address(), send_tokens]),
770 None => json!([send_tokens]),
771 };
772 self.request("sendmany", params).await
774 }
775
776 async fn send_to_address(
783 &self,
784 token_hash: H160,
785 to: H160,
786 amount: u32,
787 ) -> Result<RTransaction, ProviderError> {
788 let params = json!([token_hash.to_hex(), to.to_address(), amount]);
789 self.request("sendtoaddress", params).await
790 }
791
792 async fn cancel_transaction(
793 &self,
794 txHash: H256,
795 signers: Vec<H160>,
796 extra_fee: Option<u64>,
797 ) -> Result<RTransaction, ProviderError> {
798 if signers.is_empty() {
800 return Err(ProviderError::CustomError("signers must not be empty".into()));
801 }
802 let signer_addresses: Vec<String> =
803 signers.into_iter().map(|signer| signer.to_address()).collect();
804 let params = json!([
805 hex::encode(txHash.0),
806 signer_addresses,
807 extra_fee.map_or("".to_string(), |fee| fee.to_string())
808 ]);
809 self.request("canceltransaction", params).await
811 }
812
813 async fn get_application_log(&self, tx_hash: H256) -> Result<ApplicationLog, ProviderError> {
817 self.request("getapplicationlog", vec![hex::encode(tx_hash.0).to_value()]).await
818 }
819
820 async fn get_nep17_balances(&self, script_hash: H160) -> Result<Nep17Balances, ProviderError> {
824 self.request("getnep17balances", [script_hash.to_address().to_value()].to_vec())
825 .await
826 }
827
828 async fn get_nep17_transfers(
832 &self,
833 script_hash: H160,
834 ) -> Result<Nep17Transfers, ProviderError> {
835 let params = json!([script_hash.to_address()]);
836 self.request("getnep17transfers", params).await
837 }
838
839 async fn get_nep17_transfers_from(
845 &self,
846 script_hash: H160,
847 from: u64,
848 ) -> Result<Nep17Transfers, ProviderError> {
849 self.request("getnep17transfers", json!([script_hash.to_address(), from])).await
851 }
852
853 async fn get_nep17_transfers_range(
860 &self,
861 script_hash: H160,
862 from: u64,
863 to: u64,
864 ) -> Result<Nep17Transfers, ProviderError> {
865 let params = json!([script_hash.to_address(), from, to]);
866 self.request("getnep17transfers", params).await
867 }
868
869 async fn get_nep11_balances(&self, script_hash: H160) -> Result<Nep11Balances, ProviderError> {
873 let params = json!([script_hash.to_address()]);
874 self.request("getnep11balances", params).await
875 }
876
877 async fn get_nep11_transfers(
881 &self,
882 script_hash: H160,
883 ) -> Result<Nep11Transfers, ProviderError> {
884 let params = json!([script_hash.to_address()]);
885 self.request("getnep11transfers", params).await
886 }
887
888 async fn get_nep11_transfers_from(
894 &self,
895 script_hash: H160,
896 from: u64,
897 ) -> Result<Nep11Transfers, ProviderError> {
898 let params = json!([script_hash.to_address(), from]);
899 self.request("getnep11transfers", params).await
900 }
901
902 async fn get_nep11_transfers_range(
909 &self,
910 script_hash: H160,
911 from: u64,
912 to: u64,
913 ) -> Result<Nep11Transfers, ProviderError> {
914 let params = json!([script_hash.to_address(), from, to]);
915 self.request("getnep11transfers", params).await
916 }
917
918 async fn get_nep11_properties(
930 &self,
931 script_hash: H160,
932 token_id: &str,
933 ) -> Result<HashMap<String, String>, ProviderError> {
934 let params = json!([script_hash.to_address(), token_id]);
935 self.request("getnep11properties", params).await
936 }
937
938 async fn get_state_root(&self, block_index: u32) -> Result<StateRoot, ProviderError> {
942 let params = json!([block_index]);
943 self.request("getstateroot", params).await
944 }
945
946 async fn get_proof(
953 &self,
954 root_hash: H256,
955 contract_hash: H160,
956 key: &str,
957 ) -> Result<String, ProviderError> {
958 self.request(
959 "getproof",
960 json!([
961 hex::encode(root_hash.0),
962 contract_hash.to_hex(),
963 Base64Encode::to_base64(&key.to_string())
964 ]),
965 )
966 .await
967 }
968
969 async fn verify_proof(&self, root_hash: H256, proof: &str) -> Result<String, ProviderError> {
975 let params = json!([hex::encode(root_hash.0), Base64Encode::to_base64(&proof.to_string())]);
976 self.request("verifyproof", params).await
977 }
978
979 async fn get_state_height(&self) -> Result<StateHeight, ProviderError> {
982 self.request("getstateheight", Vec::<StateHeight>::new()).await
983 }
984
985 async fn get_state(
992 &self,
993 root_hash: H256,
994 contract_hash: H160,
995 key: &str,
996 ) -> Result<String, ProviderError> {
997 self.request(
998 "getstate",
999 json!([
1000 hex::encode(root_hash.0),
1001 contract_hash.to_hex(),
1002 Base64Encode::to_base64(&key.to_string())
1003 ]), )
1005 .await
1006 }
1007
1008 async fn find_states(
1019 &self,
1020 root_hash: H256,
1021 contract_hash: H160,
1022 key_prefix: &str,
1023 start_key: Option<&str>,
1024 count: Option<u32>,
1025 ) -> Result<States, ProviderError> {
1026 let mut params = json!([
1027 hex::encode(root_hash.0),
1028 contract_hash.to_hex(),
1029 Base64Encode::to_base64(&key_prefix.to_string())
1030 ]);
1031 if let (Some(start_key), Some(count)) = (start_key, count) {
1032 params = json!([
1033 hex::encode(root_hash.0),
1034 contract_hash.to_hex(),
1035 Base64Encode::to_base64(&key_prefix.to_string()),
1036 Base64Encode::to_base64(&start_key.to_string()),
1037 count,
1038 ]);
1039 } else if let Some(count) = count {
1040 params = json!([
1041 hex::encode(root_hash.0),
1042 contract_hash.to_hex(),
1043 Base64Encode::to_base64(&key_prefix.to_string()),
1044 "".to_string(),
1045 count,
1046 ]);
1047 } else if let Some(start_key) = start_key {
1048 params = json!([
1049 hex::encode(root_hash.0),
1050 contract_hash.to_hex(),
1051 Base64Encode::to_base64(&key_prefix.to_string()),
1052 Base64Encode::to_base64(&start_key.to_string()),
1053 ]);
1054 }
1055
1056 self.request("findstates", params).await
1057 }
1058
1059 async fn get_block_by_index(
1060 &self,
1061 index: u32,
1062 full_tx: bool,
1063 ) -> Result<NeoBlock, ProviderError> {
1064 return Ok(if full_tx {
1067 self.request("getblock", vec![index.to_value(), 1.to_value()]).await?
1068 } else {
1069 self.get_block_header_by_index(index).await?
1070 });
1071 }
1072
1073 async fn get_raw_block_by_index(&self, index: u32) -> Result<String, ProviderError> {
1074 self.request("getblock", vec![index.to_value(), 0.to_value()]).await
1075 }
1076
1077 async fn invoke_function_diagnostics(
1087 &self,
1088 contract_hash: H160,
1089 function_name: String,
1090 params: Vec<ContractParameter>,
1091 signers: Vec<Signer>,
1092 ) -> Result<InvocationResult, ProviderError> {
1093 let signers: Vec<TransactionSigner> = signers.iter().map(|f| f.into()).collect();
1094 let params = json!([contract_hash.to_hex(), function_name, params, signers, true]);
1095 self.request("invokefunction", params).await
1096 }
1097
1098 async fn invoke_script_diagnostics(
1106 &self,
1107 hex: String,
1108 signers: Vec<Signer>,
1109 ) -> Result<InvocationResult, ProviderError> {
1110 let signers: Vec<TransactionSigner> =
1111 signers.into_iter().map(|signer| signer.into()).collect::<Vec<_>>();
1112 let hex_bytes = hex::decode(&hex)
1113 .map_err(|e| ProviderError::ParseError(format!("Failed to parse hex: {}", e)))?;
1114 let script_base64 = serde_json::to_value(hex_bytes.to_base64())?;
1115 let signers_json = serde_json::to_value(&signers)?;
1116 let params = vec![script_base64, signers_json, true.to_value()];
1117 self.request("invokescript", params).await
1118 }
1119
1120 async fn traverse_iterator(
1129 &self,
1130 session_id: String,
1131 iterator_id: String,
1132 count: u32,
1133 ) -> Result<Vec<StackItem>, ProviderError> {
1134 let params = vec![session_id.to_value(), iterator_id.to_value(), count.to_value()];
1135 self.request("traverseiterator", params).await
1136 }
1137
1138 async fn terminate_session(&self, session_id: &str) -> Result<bool, ProviderError> {
1139 self.request("terminatesession", vec![session_id.to_value()]).await
1140 }
1141
1142 async fn invoke_contract_verify(
1143 &self,
1144 hash: H160,
1145 params: Vec<ContractParameter>,
1146 signers: Vec<Signer>,
1147 ) -> Result<InvocationResult, ProviderError> {
1148 let signers: Vec<TransactionSigner> =
1149 signers.into_iter().map(|signer| signer.into()).collect::<Vec<_>>();
1150 let params = json!([hash.to_hex(), params, signers]);
1151 self.request("invokecontractverify", params).await
1152 }
1153
1154 fn get_raw_mempool<'life0, 'async_trait>(
1155 &'life0 self,
1156 ) -> Pin<Box<dyn Future<Output = Result<MemPoolDetails, Self::Error>> + Send + 'async_trait>>
1157 where
1158 'life0: 'async_trait,
1159 Self: 'async_trait,
1160 {
1161 Box::pin(async move { self.get_mem_pool().await })
1162 }
1163
1164 fn import_private_key<'life0, 'async_trait>(
1165 &'life0 self,
1166 wif: String,
1167 ) -> Pin<Box<dyn Future<Output = Result<NeoAddress, Self::Error>> + Send + 'async_trait>>
1168 where
1169 'life0: 'async_trait,
1170 Self: 'async_trait,
1171 {
1172 Box::pin(async move { self.import_priv_key(wif).await })
1173 }
1174
1175 fn get_block_header_hash<'life0, 'async_trait>(
1176 &'life0 self,
1177 hash: H256,
1178 ) -> Pin<Box<dyn Future<Output = Result<NeoBlock, Self::Error>> + Send + 'async_trait>>
1179 where
1180 'life0: 'async_trait,
1181 Self: 'async_trait,
1182 {
1183 Box::pin(async move { self.get_block_header(hash).await })
1184 }
1185
1186 async fn send_to_address_send_token(
1187 &self,
1188 send_token: &TransactionSendToken,
1189 ) -> Result<RTransaction, ProviderError> {
1190 let params = json!([send_token.token.to_hex(), send_token.address, send_token.value,]);
1192 self.request("sendtoaddress", params).await
1193 }
1194
1195 async fn send_from_send_token(
1196 &self,
1197 send_token: &TransactionSendToken,
1198 from: H160,
1199 ) -> Result<RTransaction, ProviderError> {
1200 let params = json!([
1201 send_token.token.to_hex(),
1202 from.to_address(),
1203 send_token.address,
1204 send_token.value,
1205 ]);
1206 self.request("sendfrom", params).await
1208 }
1209}
1210
1211impl<P: JsonRpcProvider> RpcClient<P> {
1212 pub fn set_interval<T: Into<Duration>>(&mut self, interval: T) -> &mut Self {
1215 self.interval = Some(interval.into());
1216 self
1217 }
1218
1219 #[must_use]
1222 pub fn interval<T: Into<Duration>>(mut self, interval: T) -> Self {
1223 self.set_interval(interval);
1224 self
1225 }
1226}
1227
1228#[cfg(all(feature = "ipc", any(unix, windows)))]
1229impl RpcClient<crate::Ipc> {
1230 #[cfg_attr(unix, doc = "Connects to the Unix socket at the provided path.")]
1231 #[cfg_attr(windows, doc = "Connects to the named pipe at the provided path.\n")]
1232 #[cfg_attr(
1233 windows,
1234 doc = r"Note: the path must be the fully qualified, like: `\\.\pipe\<name>`."
1235 )]
1236 pub async fn connect_ipc(path: impl AsRef<std::path::Path>) -> Result<Self, ProviderError> {
1237 let ipc = crate::Ipc::connect(path).await?;
1238 Ok(Self::new(ipc))
1239 }
1240}
1241
1242impl RpcClient<Http> {
1243 pub fn url(&self) -> &Url {
1245 self.provider.url()
1246 }
1247
1248 pub fn url_mut(&mut self) -> &mut Url {
1250 self.provider.url_mut()
1251 }
1252}
1253
1254impl<Read, Write> RpcClient<RwClient<Read, Write>>
1255where
1256 Read: JsonRpcProvider + 'static,
1257 <Read as JsonRpcProvider>::Error: Sync + Send + 'static + Display,
1258 Write: JsonRpcProvider + 'static,
1259 <Write as JsonRpcProvider>::Error: Sync + Send + 'static + Display,
1260{
1261 pub fn rw(r: Read, w: Write) -> Self {
1263 Self::new(RwClient::new(r, w))
1264 }
1265}