cita_tool/client/
basic.rs

1use crate::client::{remove_0x, TransactionOptions};
2use crate::crypto::PrivateKey;
3use crate::error::ToolError;
4use crate::protos::{Transaction, UnverifiedTransaction};
5use crate::rpctypes::{JsonRpcParams, JsonRpcResponse, ParamsValue, ResponseValue};
6use crate::LowerHex;
7use failure::Fail;
8use futures::{
9    channel::{mpsc, oneshot},
10    future::join_all,
11    future::JoinAll,
12    Future, StreamExt,
13};
14use hex::{decode, encode};
15use http_body_util::{BodyExt, Full};
16use hyper::{body::Bytes, Request, Uri};
17use hyper_util::{
18    client::legacy::{connect::HttpConnector, Client as HyperClient},
19    rt::TokioExecutor,
20};
21use protobuf::{parse_from_bytes, Message};
22use std::collections::HashMap;
23use std::pin::Pin;
24use std::str::FromStr;
25use std::sync::atomic::{AtomicUsize, Ordering};
26use std::thread;
27use types::U256;
28use uuid::Uuid;
29
30const BLOCK_NUMBER: &str = "blockNumber";
31const GET_META_DATA: &str = "getMetaData";
32const SEND_RAW_TRANSACTION: &str = "sendRawTransaction";
33const PEER_COUNT: &str = "peerCount";
34const PEERS_INFO: &str = "peersInfo";
35const LICENSE_INFO: &str = "licenseInfo";
36const GET_BLOCK_BY_HASH: &str = "getBlockByHash";
37const GET_BLOCK_BY_NUMBER: &str = "getBlockByNumber";
38const GET_TRANSACTION: &str = "getTransaction";
39const GET_TRANSACTION_PROOF: &str = "getTransactionProof";
40
41const GET_TRANSACTION_RECEIPT: &str = "getTransactionReceipt";
42const GET_LOGS: &str = "getLogs";
43const CALL: &str = "call";
44const GET_TRANSACTION_COUNT: &str = "getTransactionCount";
45const GET_CODE: &str = "getCode";
46const GET_ABI: &str = "getAbi";
47const GET_BALANCE: &str = "getBalance";
48const GET_POOL_TX_NUM: &str = "getPoolTxNum";
49
50const NEW_FILTER: &str = "newFilter";
51const NEW_BLOCK_FILTER: &str = "newBlockFilter";
52const UNINSTALL_FILTER: &str = "uninstallFilter";
53const GET_FILTER_CHANGES: &str = "getFilterChanges";
54const GET_FILTER_LOGS: &str = "getFilterLogs";
55
56const GET_BLOCK_HEADER: &str = "getBlockHeader";
57const GET_STATE_PROOF: &str = "getStateProof";
58const GET_STORAGE_AT: &str = "getStorageAt";
59const GET_VERSION: &str = "getVersion";
60
61const ESTIMATE_QUOTA: &str = "estimateQuota";
62const OP_CENSORED_ADDR: &str = "opCensoredAddress";
63const GET_CENSORED_ADDR: &str = "getCensoredAddrs";
64
65/// Store action target address
66pub const STORE_ADDRESS: &str = "0xffffffffffffffffffffffffffffffffff010000";
67/// StoreAbi action target address
68pub const ABI_ADDRESS: &str = "0xffffffffffffffffffffffffffffffffff010001";
69/// Amend action target address
70pub const AMEND_ADDRESS: &str = "0xffffffffffffffffffffffffffffffffff010002";
71
72/// amend the abi data
73pub const AMEND_ABI: &str = "0x01";
74/// amend the account code
75pub const AMEND_CODE: &str = "0x02";
76/// amend the kv of db
77pub const AMEND_KV_H256: &str = "0x03";
78/// amend account balance
79pub const AMEND_BALANCE: &str = "0x05";
80
81/// define censorship action
82pub enum CensorAction {
83    /// Add a censored address
84    Add = 1,
85    /// Remove a censored address
86    Remove = 2,
87}
88
89pub(crate) type BoxedFutureTask = Pin<Box<dyn Future<Output = ()> + Send + 'static>>;
90type JsonFuture =
91    Pin<Box<dyn Future<Output = Result<JsonRpcResponse, ToolError>> + 'static + Send>>;
92/// Jsonrpc client, Only to one chain
93pub struct Client {
94    id: AtomicUsize,
95    url: Uri,
96    sender: mpsc::UnboundedSender<BoxedFutureTask>,
97    chain_id: Option<U256>,
98    private_key: Option<PrivateKey>,
99    debug: bool,
100}
101
102impl Client {
103    /// Create a client for CITA
104    pub fn new() -> Self {
105        let (sender, mut receiver) = mpsc::unbounded();
106
107        thread::spawn(move || {
108            let rt = tokio::runtime::Runtime::new().unwrap();
109            rt.block_on(async move {
110                while let Some(task) = receiver.next().await {
111                    tokio::spawn(task);
112                }
113            })
114        });
115
116        Client {
117            id: AtomicUsize::new(0),
118            url: "http://127.0.0.1:1337".parse().unwrap(),
119            sender,
120            chain_id: None,
121            private_key: None,
122            debug: false,
123        }
124    }
125
126    /// Set url
127    /// ---
128    /// When the url address is invalid, panic
129    pub fn set_uri(mut self, url: &str) -> Self {
130        self.url = url.parse().unwrap();
131        self
132    }
133
134    /// Get url
135    pub fn uri(&self) -> &Uri {
136        &self.url
137    }
138
139    /// Set chain id
140    pub fn set_chain_id(&mut self, chain_id: U256) -> &mut Self {
141        self.chain_id = Some(chain_id);
142        self
143    }
144
145    /// Set private key
146    pub fn set_private_key(&mut self, private_key: &PrivateKey) -> &mut Self {
147        match private_key {
148            PrivateKey::Null => {}
149            _ => self.private_key = Some(*private_key),
150        }
151        self
152    }
153
154    /// Get private key
155    pub fn private_key(&self) -> Option<&PrivateKey> {
156        self.private_key.as_ref()
157    }
158
159    /// Get debug
160    pub fn debug(&self) -> bool {
161        self.debug
162    }
163
164    /// Set debug mode
165    pub fn set_debug(mut self, mode: bool) -> Self {
166        self.debug = mode;
167        self
168    }
169
170    /// Send requests
171    pub fn send_requests<T: Iterator<Item = JsonRpcParams>>(
172        &self,
173        params: T,
174    ) -> Vec<Result<JsonRpcResponse, ToolError>> {
175        let params = params.collect::<Vec<JsonRpcParams>>();
176
177        let reqs = self.make_requests_with_params_list(params.into_iter());
178
179        self.run(reqs)
180    }
181
182    /// Send request
183    pub fn send_request(&self, param: JsonRpcParams) -> Result<JsonRpcResponse, ToolError> {
184        self.single_run(self.make_request(param))
185    }
186
187    /// Send multiple params to one node
188    pub fn send_request_with_multiple_url<T: Iterator<Item = Uri>>(
189        &self,
190        url: T,
191        params: JsonRpcParams,
192    ) -> Vec<Result<JsonRpcResponse, ToolError>> {
193        let reqs = self.make_requests_with_all_url(url, params);
194
195        self.run(reqs)
196    }
197
198    #[inline]
199    fn make_requests_with_all_url<T: Iterator<Item = Uri>>(
200        &self,
201        urls: T,
202        params: JsonRpcParams,
203    ) -> JoinAll<JsonFuture> {
204        self.id.fetch_add(1, Ordering::Relaxed);
205        let params = params.insert("id", ParamsValue::String(Uuid::new_v4().to_string()));
206
207        if self.debug {
208            Self::debug_request(vec![&params].into_iter())
209        }
210
211        let client = create_client();
212        let mut reqs = Vec::with_capacity(100);
213        urls.for_each(|url| {
214            let req = Request::builder()
215                .uri(url)
216                .method("POST")
217                .header("Content-Type", "application/json")
218                .body(Full::new(Bytes::from(
219                    serde_json::to_string(&params).unwrap(),
220                )))
221                .unwrap();
222            let client = client.clone();
223            let future: JsonFuture = Box::pin(async move {
224                match client.request(req).await {
225                    Ok(resp) => match resp.collect().await {
226                        Ok(bytes) => serde_json::from_slice::<JsonRpcResponse>(&bytes.to_bytes())
227                            .map_err(ToolError::SerdeJson),
228                        Err(e) => Err(ToolError::Hyper(e)),
229                    },
230                    Err(e) => Err(ToolError::HyperLegacy(e)),
231                }
232            });
233            reqs.push(future);
234        });
235        join_all(reqs)
236    }
237
238    #[inline]
239    fn make_requests_with_params_list<T: Iterator<Item = JsonRpcParams>>(
240        &self,
241        params: T,
242    ) -> JoinAll<JsonFuture> {
243        let client = create_client();
244        let mut reqs = Vec::with_capacity(100);
245        let mut json_params = Vec::new();
246        for param in params {
247            let param = param.insert("id", ParamsValue::String(Uuid::new_v4().to_string()));
248            if self.debug {
249                Self::debug_request(vec![&param].into_iter())
250            }
251            json_params.push(param);
252        }
253        let req = Request::builder()
254            .uri(self.url.clone())
255            .method("POST")
256            .header("Content-Type", "application/json")
257            .body(Full::new(Bytes::from(
258                serde_json::to_string(&json_params).unwrap(),
259            )))
260            .unwrap();
261        let future: JsonFuture = Box::pin(async move {
262            match client.request(req).await {
263                Ok(resp) => match resp.collect().await {
264                    Err(e) => Err(ToolError::Hyper(e)),
265                    _ => Ok(JsonRpcResponse::default()),
266                },
267                Err(e) => Err(ToolError::HyperLegacy(e)),
268            }
269        });
270        reqs.push(future);
271
272        join_all(reqs)
273    }
274
275    #[inline]
276    fn make_request(&self, param: JsonRpcParams) -> JsonFuture {
277        let client = create_client();
278        let param = param.insert("id", ParamsValue::String(Uuid::new_v4().to_string()));
279        if self.debug {
280            Self::debug_request(vec![&param].into_iter())
281        }
282        let req = Request::builder()
283            .uri(self.url.clone())
284            .method("POST")
285            .header("Content-Type", "application/json")
286            .body(Full::new(Bytes::from(
287                serde_json::to_string(&param).unwrap(),
288            )))
289            .unwrap();
290        Box::pin(async move {
291            match client.request(req).await {
292                Ok(resp) => match resp.collect().await {
293                    Ok(bytes) => serde_json::from_slice::<JsonRpcResponse>(&bytes.to_bytes())
294                        .map_err(ToolError::SerdeJson),
295                    Err(e) => Err(ToolError::Hyper(e)),
296                },
297                Err(e) => Err(ToolError::HyperLegacy(e)),
298            }
299        })
300    }
301
302    /// Constructing a Transaction
303    pub fn generate_transaction(
304        &mut self,
305        transaction_options: TransactionOptions,
306    ) -> Result<Transaction, ToolError> {
307        let data = decode(remove_0x(transaction_options.code())).map_err(ToolError::Decode)?;
308        let current_height = transaction_options
309            .current_height()
310            .ok_or_else(|| ToolError::Customize("No height input".to_string()))
311            .or_else(|_| self.get_current_height())?;
312
313        let mut tx = Transaction::new();
314        tx.set_data(data);
315
316        tx.set_nonce(encode(Uuid::new_v4().as_bytes()));
317        tx.set_valid_until_block(current_height + 88);
318        tx.set_quota(transaction_options.quota().unwrap_or(10_000_000));
319        let value = transaction_options
320            .value()
321            .map(|value| value.completed_lower_hex())
322            .unwrap_or_else(|| U256::zero().completed_lower_hex());
323        tx.set_value(decode(value).map_err(ToolError::Decode)?);
324
325        let version = transaction_options
326            .version()
327            .unwrap_or_else(|| self.get_version().unwrap());
328
329        if version == 0 {
330            // Create a contract if the target address is empty
331            tx.set_to(remove_0x(transaction_options.address()).to_string());
332            tx.set_chain_id(self.get_chain_id()?);
333        } else if version < 3 {
334            // Create a contract if the target address is empty
335            tx.set_to_v1(
336                decode(remove_0x(transaction_options.address())).map_err(ToolError::Decode)?,
337            );
338            tx.set_chain_id_v1(
339                decode(self.get_chain_id_v1()?.completed_lower_hex()).map_err(ToolError::Decode)?,
340            );
341        } else {
342            return Err(ToolError::Customize("Invalid version".to_string()));
343        }
344
345        tx.set_version(version);
346
347        Ok(tx)
348    }
349
350    /// Constructing a UnverifiedTransaction hex string
351    #[inline]
352    pub fn generate_sign_transaction(&self, tx: &Transaction) -> Result<String, ToolError> {
353        Ok(format!(
354            "0x{}",
355            encode(
356                tx.build_unverified(self.private_key().ok_or_else(|| ToolError::Customize(
357                    "The provided private key do not match the algorithm".to_string(),
358                ))?)
359                .write_to_bytes()
360                .map_err(ToolError::Proto)?
361            )
362        ))
363    }
364
365    /// Send a signed transaction
366    pub fn send_signed_transaction(&mut self, param: &str) -> Result<JsonRpcResponse, ToolError> {
367        let byte_code = format!(
368            "0x{}",
369            encode(
370                parse_from_bytes::<UnverifiedTransaction>(
371                    decode(remove_0x(param))
372                        .map_err(ToolError::Decode)?
373                        .as_slice()
374                )
375                .map_err(ToolError::Proto)?
376                .write_to_bytes()
377                .map_err(ToolError::Proto)?
378            )
379        );
380        let params = JsonRpcParams::new()
381            .insert(
382                "method",
383                ParamsValue::String(String::from(SEND_RAW_TRANSACTION)),
384            )
385            .insert(
386                "params",
387                ParamsValue::List(vec![ParamsValue::String(byte_code)]),
388            );
389        self.send_request(params)
390    }
391
392    /// Send unsigned transactions
393    pub fn send_transaction(&mut self, param: &str) -> Result<JsonRpcResponse, ToolError> {
394        let tx: Transaction = parse_from_bytes(
395            decode(remove_0x(param))
396                .map_err(ToolError::Decode)?
397                .as_slice(),
398        )
399        .map_err(ToolError::Proto)?;
400        let byte_code = self.generate_sign_transaction(&tx)?;
401        let params = JsonRpcParams::new()
402            .insert(
403                "method",
404                ParamsValue::String(String::from(SEND_RAW_TRANSACTION)),
405            )
406            .insert(
407                "params",
408                ParamsValue::List(vec![ParamsValue::String(byte_code)]),
409            );
410        self.send_request(params)
411    }
412
413    /// Get chain id
414    pub fn get_chain_id(&mut self) -> Result<u32, ToolError> {
415        if self.chain_id.is_some() && self.check_chain_id() {
416            Ok(self.chain_id.unwrap().low_u32())
417        } else if let Some(ResponseValue::Map(mut value)) = self.get_metadata("latest")?.result() {
418            match value.remove("chainId").unwrap() {
419                ParamsValue::Int(chain_id) => {
420                    self.chain_id = Some(U256::from(chain_id));
421                    Ok(chain_id as u32)
422                }
423                _ => Ok(0),
424            }
425        } else {
426            Ok(0)
427        }
428    }
429
430    #[inline]
431    fn check_chain_id(&self) -> bool {
432        self.chain_id
433            .map(|id| id > U256::from(u32::max_value()))
434            .unwrap_or(false)
435    }
436
437    /// Get chain id v1
438    pub fn get_chain_id_v1(&mut self) -> Result<U256, ToolError> {
439        if self.chain_id.is_some() {
440            Ok(self.chain_id.unwrap())
441        } else if let Some(ResponseValue::Map(mut value)) = self.get_metadata("latest")?.result() {
442            match value.remove("chainIdV1") {
443                Some(ParamsValue::String(chain_id)) => {
444                    let chain_id = U256::from_str(remove_0x(&chain_id))
445                        .map_err(|e| ToolError::Customize(e.to_string()))?;
446                    self.chain_id = Some(chain_id);
447                    Ok(chain_id)
448                }
449                _ => Ok(U256::zero()),
450            }
451        } else {
452            Ok(U256::zero())
453        }
454    }
455
456    /// Get block height
457    pub fn get_current_height(&self) -> Result<u64, ToolError> {
458        let params =
459            JsonRpcParams::new().insert("method", ParamsValue::String(String::from(BLOCK_NUMBER)));
460        let response = self.send_request(params)?;
461
462        if let Some(ResponseValue::Singe(ParamsValue::String(height))) = response.result() {
463            Ok(u64::from_str_radix(remove_0x(&height), 16).map_err(ToolError::Parse)?)
464        } else {
465            Err(ToolError::Customize(
466                "Corresponding address does not respond".to_string(),
467            ))
468        }
469    }
470
471    /// Get version
472    pub fn get_version(&self) -> Result<u32, ToolError> {
473        if let Some(ResponseValue::Singe(ParamsValue::String(version))) = self
474            .call(
475                None,
476                "0xffffffffffffffffffffffffffffffffff020011",
477                Some("0x0d8e6e2c"),
478                "latest",
479                false,
480            )?
481            .result()
482        {
483            Ok(u32::from_str_radix(remove_0x(&version), 16).map_err(ToolError::Parse)?)
484        } else {
485            Err(ToolError::Customize("not get version".to_string()))
486        }
487    }
488
489    /// Start run
490    fn run(&self, reqs: JoinAll<JsonFuture>) -> Vec<Result<JsonRpcResponse, ToolError>> {
491        let (tx, rx) = oneshot::channel::<Vec<Result<JsonRpcResponse, ToolError>>>();
492        self.sender
493            .unbounded_send(Box::pin(async move {
494                let _ = tx.send(reqs.await);
495            }))
496            .unwrap();
497        futures::executor::block_on(async { rx.await }).unwrap()
498    }
499
500    fn single_run(&self, req: JsonFuture) -> Result<JsonRpcResponse, ToolError> {
501        let (tx, rx) = oneshot::channel::<Result<JsonRpcResponse, ToolError>>();
502        self.sender
503            .unbounded_send(Box::pin(async move {
504                let _ = tx.send(req.await);
505            }))
506            .map_err(|e| ToolError::Customize(e.to_string()))?;
507        futures::executor::block_on(async { rx.await })
508            .map_err(|e| ToolError::Customize(e.to_string()))?
509    }
510
511    fn debug_request<'a, T: Iterator<Item = &'a JsonRpcParams>>(params: T) {
512        params.for_each(|param| {
513            println!("<--{param}");
514        });
515    }
516}
517
518impl Clone for Client {
519    fn clone(&self) -> Self {
520        Client {
521            id: AtomicUsize::new(self.id.load(Ordering::Relaxed)),
522            url: self.url.clone(),
523            sender: self.sender.clone(),
524            chain_id: None,
525            private_key: self.private_key,
526            debug: self.debug,
527        }
528    }
529}
530
531impl Default for Client {
532    fn default() -> Self {
533        Self::new()
534    }
535}
536
537/// High level jsonrpc call
538///
539/// [Documentation](https://cryptape.github.io/cita/zh/usage-guide/rpc/index.html)
540///
541/// JSONRPC methods:
542///   * peerCount
543///   * peersInfo
544///   * blockNumber
545///   * sendTransaction
546///   * getBlockByHash
547///   * getBlockByNumber
548///   * getTransactionReceipt
549///   * getLogs
550///   * call
551///   * getTransaction
552///   * getTransactionCount
553///   * getCode
554///   * getAbi
555///   * getBalance
556///   * newFilter
557///   * newBlockFilter
558///   * uninstallFilter
559///   * getFilterChanges
560///   * getFilterLogs
561///   * getTransactionProof
562///   * getMetaData
563///   * getBlockHeader
564///   * getStateProof
565///   * getStorageAt
566///   * getVersion
567///   * estimateQuota
568pub trait ClientExt<T, E>
569where
570    T: serde::Serialize + serde::Deserialize<'static> + ::std::fmt::Display,
571    E: Fail,
572{
573    /// peerCount: Get network peer count
574    fn get_peer_count(&self) -> Result<T, E>;
575    /// peersInfo: Get all peers information
576    fn get_peers_info(&self, extra: bool) -> Result<T, E>;
577    /// licenseInfo: Get CITA license information
578    fn get_license_info(&self) -> Result<T, E>;
579    /// blockNumber: Get current height
580    fn get_block_number(&self) -> Result<T, E>;
581    /// sendTransaction: Send a transaction and return transaction hash
582    fn send_raw_transaction(&mut self, transaction_option: TransactionOptions) -> Result<T, E>;
583    /// getBlockByHash: Get block by hash
584    fn get_block_by_hash(&self, hash: &str, transaction_info: bool) -> Result<T, E>;
585    /// getBlockByNumber: Get block by number
586    fn get_block_by_number(&self, height: &str, transaction_info: bool) -> Result<T, E>;
587    /// getTransactionReceipt: Get transaction receipt
588    fn get_transaction_receipt(&self, hash: &str) -> Result<T, E>;
589    /// getLogs: Get logs
590    fn get_logs(
591        &self,
592        topic: Option<Vec<&str>>,
593        address: Option<Vec<&str>>,
594        from: Option<&str>,
595        to: Option<&str>,
596    ) -> Result<T, E>;
597    /// call: (readonly, will not save state change)
598    fn call(
599        &self,
600        from: Option<&str>,
601        to: &str,
602        data: Option<&str>,
603        height: &str,
604        extra: bool,
605    ) -> Result<T, E>;
606    /// getTransaction: Get transaction by hash
607    fn get_transaction(&self, hash: &str, in_pool: bool) -> Result<T, E>;
608    /// getTransactionCount: Get transaction count of an account
609    fn get_transaction_count(&self, address: &str, height: &str) -> Result<T, E>;
610    /// getCode: Get the code of a contract
611    fn get_code(&self, address: &str, height: &str) -> Result<T, E>;
612    /// getAbi: Get the ABI of a contract
613    fn get_abi(&self, address: &str, height: &str) -> Result<T, E>;
614    /// getBalance: Get the balance of a contract (TODO: return U256)
615    fn get_balance(&self, address: &str, height: &str) -> Result<T, E>;
616    /// newFilter:
617    fn new_filter(
618        &self,
619        topic: Option<Vec<&str>>,
620        address: Option<Vec<&str>>,
621        from: Option<&str>,
622        to: Option<&str>,
623    ) -> Result<T, E>;
624    /// newBlockFilter:
625    fn new_block_filter(&self) -> Result<T, E>;
626    /// uninstallFilter: Uninstall a filter by its id
627    fn uninstall_filter(&self, filter_id: &str) -> Result<T, E>;
628    /// getFilterChanges: Get filter changes
629    fn get_filter_changes(&self, filter_id: &str) -> Result<T, E>;
630    /// getFilterLogs: Get filter logs
631    fn get_filter_logs(&self, filter_id: &str) -> Result<T, E>;
632    /// getTransactionProof: Get proof of a transaction
633    fn get_transaction_proof(&self, hash: &str) -> Result<T, E>;
634    /// getMetaData: Get metadata
635    fn get_metadata(&self, height: &str) -> Result<T, E>;
636    /// getBlockHeader: Get block headers based on block height
637    fn get_block_header(&self, height: &str) -> Result<T, E>;
638    /// getStateProof: Get the proof of the variable at the specified height
639    fn get_state_proof(&self, address: &str, key: &str, height: &str) -> Result<T, E>;
640    /// getStorageAt: Get the value of the key at the specified height
641    fn get_storage_at(&self, address: &str, key: &str, height: &str) -> Result<T, E>;
642    /// getVersion: Get release version info of all modules
643    fn get_version(&self) -> Result<T, E>;
644    /// estimateQuota: Estimate a transaction's quota used
645    fn estimate_quota(
646        &self,
647        from: Option<&str>,
648        to: &str,
649        data: Option<&str>,
650        height: &str,
651    ) -> Result<T, E>;
652    /// get tx number in pool
653    fn get_pool_tx_num(&self) -> Result<T, E>;
654    /// operate censorship address list
655    fn operate_censored_address(&self, action: CensorAction, censor_addr: &str) -> Result<T, E>;
656    /// get censorship address list
657    fn get_censored_addr(&self) -> Result<T, E>;
658}
659
660impl ClientExt<JsonRpcResponse, ToolError> for Client {
661    fn get_peer_count(&self) -> Result<JsonRpcResponse, ToolError> {
662        let params =
663            JsonRpcParams::new().insert("method", ParamsValue::String(String::from(PEER_COUNT)));
664        self.send_request(params)
665    }
666
667    fn get_peers_info(&self, extra: bool) -> Result<JsonRpcResponse, ToolError> {
668        let params = if extra {
669            JsonRpcParams::new()
670                .insert("method", ParamsValue::String(String::from(PEERS_INFO)))
671                .insert("params", ParamsValue::List(vec![ParamsValue::Bool(extra)]))
672        } else {
673            JsonRpcParams::new().insert("method", ParamsValue::String(String::from(PEERS_INFO)))
674        };
675        self.send_request(params)
676    }
677
678    fn get_license_info(&self) -> Result<JsonRpcResponse, ToolError> {
679        let params =
680            JsonRpcParams::new().insert("method", ParamsValue::String(String::from(LICENSE_INFO)));
681        self.send_request(params)
682    }
683
684    fn get_block_number(&self) -> Result<JsonRpcResponse, ToolError> {
685        let params =
686            JsonRpcParams::new().insert("method", ParamsValue::String(String::from(BLOCK_NUMBER)));
687        self.send_request(params)
688    }
689
690    fn send_raw_transaction(
691        &mut self,
692        transaction_option: TransactionOptions,
693    ) -> Result<JsonRpcResponse, ToolError> {
694        let tx = self.generate_transaction(transaction_option)?;
695        let byte_code = self.generate_sign_transaction(&tx)?;
696        self.send_signed_transaction(&byte_code)
697    }
698
699    fn get_block_by_hash(
700        &self,
701        hash: &str,
702        transaction_info: bool,
703    ) -> Result<JsonRpcResponse, ToolError> {
704        let params = JsonRpcParams::new()
705            .insert(
706                "method",
707                ParamsValue::String(String::from(GET_BLOCK_BY_HASH)),
708            )
709            .insert(
710                "params",
711                ParamsValue::List(vec![
712                    ParamsValue::String(String::from(hash)),
713                    ParamsValue::Bool(transaction_info),
714                ]),
715            );
716        self.send_request(params)
717    }
718
719    fn get_block_by_number(
720        &self,
721        height: &str,
722        transaction_info: bool,
723    ) -> Result<JsonRpcResponse, ToolError> {
724        let params = JsonRpcParams::new()
725            .insert(
726                "method",
727                ParamsValue::String(String::from(GET_BLOCK_BY_NUMBER)),
728            )
729            .insert(
730                "params",
731                ParamsValue::List(vec![
732                    ParamsValue::String(String::from(height)),
733                    ParamsValue::Bool(transaction_info),
734                ]),
735            );
736        self.send_request(params)
737    }
738
739    fn get_transaction_receipt(&self, hash: &str) -> Result<JsonRpcResponse, ToolError> {
740        let params = JsonRpcParams::new()
741            .insert(
742                "method",
743                ParamsValue::String(String::from(GET_TRANSACTION_RECEIPT)),
744            )
745            .insert(
746                "params",
747                ParamsValue::List(vec![ParamsValue::String(String::from(hash))]),
748            );
749        self.send_request(params)
750    }
751
752    fn get_logs(
753        &self,
754        topic: Option<Vec<&str>>,
755        address: Option<Vec<&str>>,
756        from: Option<&str>,
757        to: Option<&str>,
758    ) -> Result<JsonRpcResponse, ToolError> {
759        let mut object = HashMap::new();
760        object.insert(
761            String::from("fromBlock"),
762            ParamsValue::String(String::from(from.unwrap_or("latest"))),
763        );
764        object.insert(
765            String::from("toBlock"),
766            ParamsValue::String(String::from(to.unwrap_or("latest"))),
767        );
768
769        if topic.is_some() {
770            object.insert(
771                String::from("topics"),
772                serde_json::from_str::<ParamsValue>(&serde_json::to_string(&topic).unwrap())
773                    .unwrap(),
774            );
775        } else {
776            object.insert(String::from("topics"), ParamsValue::List(Vec::new()));
777        }
778
779        object.insert(
780            String::from("address"),
781            serde_json::from_str::<ParamsValue>(&serde_json::to_string(&address).unwrap()).unwrap(),
782        );
783
784        let params = JsonRpcParams::new()
785            .insert("method", ParamsValue::String(String::from(GET_LOGS)))
786            .insert("params", ParamsValue::List(vec![ParamsValue::Map(object)]));
787        self.send_request(params)
788    }
789
790    fn call(
791        &self,
792        from: Option<&str>,
793        to: &str,
794        data: Option<&str>,
795        height: &str,
796        extra: bool,
797    ) -> Result<JsonRpcResponse, ToolError> {
798        let mut object = HashMap::new();
799
800        object.insert(String::from("to"), ParamsValue::String(String::from(to)));
801        if let Some(from) = from {
802            object.insert(
803                String::from("from"),
804                ParamsValue::String(String::from(from)),
805            );
806        }
807        if let Some(data) = data {
808            object.insert(
809                String::from("data"),
810                ParamsValue::String(String::from(data)),
811            );
812        }
813
814        let param = if extra {
815            ParamsValue::List(vec![
816                ParamsValue::Map(object),
817                ParamsValue::String(String::from(height)),
818                ParamsValue::Bool(extra),
819            ])
820        } else {
821            ParamsValue::List(vec![
822                ParamsValue::Map(object),
823                ParamsValue::String(String::from(height)),
824            ])
825        };
826        let params = JsonRpcParams::new()
827            .insert("method", ParamsValue::String(String::from(CALL)))
828            .insert("params", param);
829
830        self.send_request(params)
831    }
832
833    fn get_transaction(&self, hash: &str, in_pool: bool) -> Result<JsonRpcResponse, ToolError> {
834        let pv = if in_pool {
835            ParamsValue::List(vec![
836                ParamsValue::String(String::from(hash)),
837                ParamsValue::Bool(in_pool),
838            ])
839        } else {
840            ParamsValue::List(vec![ParamsValue::String(String::from(hash))])
841        };
842        let params = JsonRpcParams::new()
843            .insert("method", ParamsValue::String(String::from(GET_TRANSACTION)))
844            .insert("params", pv);
845
846        self.send_request(params)
847    }
848
849    fn get_transaction_count(
850        &self,
851        address: &str,
852        height: &str,
853    ) -> Result<JsonRpcResponse, ToolError> {
854        let params = JsonRpcParams::new()
855            .insert(
856                "method",
857                ParamsValue::String(String::from(GET_TRANSACTION_COUNT)),
858            )
859            .insert(
860                "params",
861                ParamsValue::List(vec![
862                    ParamsValue::String(String::from(address)),
863                    ParamsValue::String(String::from(height)),
864                ]),
865            );
866
867        self.send_request(params)
868    }
869
870    fn get_code(&self, address: &str, height: &str) -> Result<JsonRpcResponse, ToolError> {
871        let params = JsonRpcParams::new()
872            .insert("method", ParamsValue::String(String::from(GET_CODE)))
873            .insert(
874                "params",
875                ParamsValue::List(vec![
876                    ParamsValue::String(String::from(address)),
877                    ParamsValue::String(String::from(height)),
878                ]),
879            );
880
881        self.send_request(params)
882    }
883
884    fn get_abi(&self, address: &str, height: &str) -> Result<JsonRpcResponse, ToolError> {
885        let params = JsonRpcParams::new()
886            .insert("method", ParamsValue::String(String::from(GET_ABI)))
887            .insert(
888                "params",
889                ParamsValue::List(vec![
890                    ParamsValue::String(String::from(address)),
891                    ParamsValue::String(String::from(height)),
892                ]),
893            );
894
895        self.send_request(params)
896    }
897
898    fn get_balance(&self, address: &str, height: &str) -> Result<JsonRpcResponse, ToolError> {
899        let params = JsonRpcParams::new()
900            .insert("method", ParamsValue::String(String::from(GET_BALANCE)))
901            .insert(
902                "params",
903                ParamsValue::List(vec![
904                    ParamsValue::String(String::from(address)),
905                    ParamsValue::String(String::from(height)),
906                ]),
907            );
908
909        self.send_request(params)
910    }
911
912    fn new_filter(
913        &self,
914        topic: Option<Vec<&str>>,
915        address: Option<Vec<&str>>,
916        from: Option<&str>,
917        to: Option<&str>,
918    ) -> Result<JsonRpcResponse, ToolError> {
919        let mut object = HashMap::new();
920        object.insert(
921            String::from("fromBlock"),
922            ParamsValue::String(String::from(from.unwrap_or("latest"))),
923        );
924        object.insert(
925            String::from("toBlock"),
926            ParamsValue::String(String::from(to.unwrap_or("latest"))),
927        );
928        object.insert(
929            String::from("topics"),
930            serde_json::from_str::<ParamsValue>(&serde_json::to_string(&topic).unwrap()).unwrap(),
931        );
932        object.insert(
933            String::from("address"),
934            serde_json::from_str::<ParamsValue>(&serde_json::to_string(&address).unwrap()).unwrap(),
935        );
936
937        let params = JsonRpcParams::new()
938            .insert("method", ParamsValue::String(String::from(NEW_FILTER)))
939            .insert("params", ParamsValue::List(vec![ParamsValue::Map(object)]));
940        self.send_request(params)
941    }
942
943    fn new_block_filter(&self) -> Result<JsonRpcResponse, ToolError> {
944        let params = JsonRpcParams::new().insert(
945            "method",
946            ParamsValue::String(String::from(NEW_BLOCK_FILTER)),
947        );
948        self.send_request(params)
949    }
950
951    fn uninstall_filter(&self, filter_id: &str) -> Result<JsonRpcResponse, ToolError> {
952        let params = JsonRpcParams::new()
953            .insert(
954                "method",
955                ParamsValue::String(String::from(UNINSTALL_FILTER)),
956            )
957            .insert(
958                "params",
959                ParamsValue::List(vec![ParamsValue::String(String::from(filter_id))]),
960            );
961
962        self.send_request(params)
963    }
964
965    fn get_filter_changes(&self, filter_id: &str) -> Result<JsonRpcResponse, ToolError> {
966        let params = JsonRpcParams::new()
967            .insert(
968                "method",
969                ParamsValue::String(String::from(GET_FILTER_CHANGES)),
970            )
971            .insert(
972                "params",
973                ParamsValue::List(vec![ParamsValue::String(String::from(filter_id))]),
974            );
975
976        self.send_request(params)
977    }
978
979    fn get_filter_logs(&self, filter_id: &str) -> Result<JsonRpcResponse, ToolError> {
980        let params = JsonRpcParams::new()
981            .insert("method", ParamsValue::String(String::from(GET_FILTER_LOGS)))
982            .insert(
983                "params",
984                ParamsValue::List(vec![ParamsValue::String(String::from(filter_id))]),
985            );
986        self.send_request(params)
987    }
988
989    fn get_transaction_proof(&self, hash: &str) -> Result<JsonRpcResponse, ToolError> {
990        let params = JsonRpcParams::new()
991            .insert(
992                "method",
993                ParamsValue::String(String::from(GET_TRANSACTION_PROOF)),
994            )
995            .insert(
996                "params",
997                ParamsValue::List(vec![ParamsValue::String(String::from(hash))]),
998            );
999        self.send_request(params)
1000    }
1001
1002    fn get_metadata(&self, height: &str) -> Result<JsonRpcResponse, ToolError> {
1003        let params = JsonRpcParams::new()
1004            .insert(
1005                "params",
1006                ParamsValue::List(vec![ParamsValue::String(String::from(height))]),
1007            )
1008            .insert("method", ParamsValue::String(String::from(GET_META_DATA)));
1009        self.send_request(params)
1010    }
1011
1012    fn get_block_header(&self, height: &str) -> Result<JsonRpcResponse, ToolError> {
1013        let params = JsonRpcParams::new()
1014            .insert(
1015                "params",
1016                ParamsValue::List(vec![ParamsValue::String(String::from(height))]),
1017            )
1018            .insert(
1019                "method",
1020                ParamsValue::String(String::from(GET_BLOCK_HEADER)),
1021            );
1022        self.send_request(params)
1023    }
1024
1025    fn get_state_proof(
1026        &self,
1027        address: &str,
1028        key: &str,
1029        height: &str,
1030    ) -> Result<JsonRpcResponse, ToolError> {
1031        let params = JsonRpcParams::new()
1032            .insert(
1033                "params",
1034                ParamsValue::List(vec![
1035                    ParamsValue::String(String::from(address)),
1036                    ParamsValue::String(String::from(key)),
1037                    ParamsValue::String(String::from(height)),
1038                ]),
1039            )
1040            .insert("method", ParamsValue::String(String::from(GET_STATE_PROOF)));
1041        self.send_request(params)
1042    }
1043
1044    fn get_storage_at(
1045        &self,
1046        address: &str,
1047        key: &str,
1048        height: &str,
1049    ) -> Result<JsonRpcResponse, ToolError> {
1050        let params = JsonRpcParams::new()
1051            .insert(
1052                "params",
1053                ParamsValue::List(vec![
1054                    ParamsValue::String(String::from(address)),
1055                    ParamsValue::String(String::from(key)),
1056                    ParamsValue::String(String::from(height)),
1057                ]),
1058            )
1059            .insert("method", ParamsValue::String(String::from(GET_STORAGE_AT)));
1060        self.send_request(params)
1061    }
1062
1063    fn get_version(&self) -> Result<JsonRpcResponse, ToolError> {
1064        let params =
1065            JsonRpcParams::new().insert("method", ParamsValue::String(String::from(GET_VERSION)));
1066        self.send_request(params)
1067    }
1068
1069    fn estimate_quota(
1070        &self,
1071        from: Option<&str>,
1072        to: &str,
1073        data: Option<&str>,
1074        height: &str,
1075    ) -> Result<JsonRpcResponse, ToolError> {
1076        let mut object = HashMap::new();
1077
1078        object.insert(String::from("to"), ParamsValue::String(String::from(to)));
1079        if let Some(from) = from {
1080            object.insert(
1081                String::from("from"),
1082                ParamsValue::String(String::from(from)),
1083            );
1084        }
1085        if let Some(data) = data {
1086            object.insert(
1087                String::from("data"),
1088                ParamsValue::String(String::from(data)),
1089            );
1090        }
1091
1092        let param = ParamsValue::List(vec![
1093            ParamsValue::Map(object),
1094            ParamsValue::String(String::from(height)),
1095        ]);
1096        let params = JsonRpcParams::new()
1097            .insert("method", ParamsValue::String(String::from(ESTIMATE_QUOTA)))
1098            .insert("params", param);
1099
1100        self.send_request(params)
1101    }
1102
1103    fn get_pool_tx_num(&self) -> Result<JsonRpcResponse, ToolError> {
1104        let params = JsonRpcParams::new()
1105            .insert("method", ParamsValue::String(String::from(GET_POOL_TX_NUM)));
1106        self.send_request(params)
1107    }
1108
1109    fn operate_censored_address(
1110        &self,
1111        action: CensorAction,
1112        censor_addr: &str,
1113    ) -> Result<JsonRpcResponse, ToolError> {
1114        let param = ParamsValue::List(vec![
1115            ParamsValue::Int(action as u64),
1116            ParamsValue::String(censor_addr.to_string()),
1117        ]);
1118        let params = JsonRpcParams::new()
1119            .insert(
1120                "method",
1121                ParamsValue::String(String::from(OP_CENSORED_ADDR)),
1122            )
1123            .insert("params", param);
1124
1125        self.send_request(params)
1126    }
1127
1128    fn get_censored_addr(&self) -> Result<JsonRpcResponse, ToolError> {
1129        let params = JsonRpcParams::new().insert(
1130            "method",
1131            ParamsValue::String(String::from(GET_CENSORED_ADDR)),
1132        );
1133        self.send_request(params)
1134    }
1135}
1136
1137/// Store data or contract ABI to chain
1138pub trait StoreExt<T, E>: ClientExt<T, E>
1139where
1140    T: serde::Serialize + serde::Deserialize<'static> + ::std::fmt::Display,
1141    E: Fail + From<ToolError>,
1142{
1143    /// Store data to chain, data can be get back by `getTransaction` rpc call
1144    fn store_data(&mut self, content: &str, quota: Option<u64>) -> Result<T, E> {
1145        let tx_options = TransactionOptions::new()
1146            .set_code(content)
1147            .set_address(STORE_ADDRESS)
1148            .set_quota(quota);
1149        self.send_raw_transaction(tx_options)
1150    }
1151
1152    /// Store contract ABI to chain, ABI can be get back by `getAbi` rpc call
1153    fn store_abi(&mut self, address: &str, content: String, quota: Option<u64>) -> Result<T, E> {
1154        let address = remove_0x(address);
1155        let content_abi = encode(content);
1156        let data = format!("0x{address}{content_abi}");
1157        let tx_options = TransactionOptions::new()
1158            .set_code(&data)
1159            .set_address(ABI_ADDRESS)
1160            .set_quota(quota);
1161        self.send_raw_transaction(tx_options)
1162    }
1163}
1164
1165impl StoreExt<JsonRpcResponse, ToolError> for Client {}
1166
1167/// Amend(Update) ABI/contract code/H256KV
1168pub trait AmendExt<T, E>: ClientExt<T, E>
1169where
1170    T: serde::Serialize + serde::Deserialize<'static> + ::std::fmt::Display,
1171    E: Fail + From<ToolError>,
1172{
1173    /// Amend contract code
1174    fn amend_code(&mut self, address: &str, content: &str, quota: Option<u64>) -> Result<T, E> {
1175        let address = remove_0x(address);
1176        let content = remove_0x(content);
1177        let data = format!("0x{address}{content}");
1178        let tx_options = TransactionOptions::new()
1179            .set_code(&data)
1180            .set_address(AMEND_ADDRESS)
1181            .set_quota(quota)
1182            .set_value(Some(U256::from_str(remove_0x(AMEND_CODE)).unwrap()));
1183        self.send_raw_transaction(tx_options)
1184    }
1185
1186    /// Amend contract ABI
1187    fn amend_abi(&mut self, address: &str, content: String, quota: Option<u64>) -> Result<T, E> {
1188        let address = remove_0x(address);
1189        let content_abi = encode(content);
1190        let data = format!("0x{address}{content_abi}");
1191        let tx_options = TransactionOptions::new()
1192            .set_code(&data)
1193            .set_address(AMEND_ADDRESS)
1194            .set_quota(quota)
1195            .set_value(Some(U256::from_str(remove_0x(AMEND_ABI)).unwrap()));
1196        self.send_raw_transaction(tx_options)
1197    }
1198
1199    /// Amend H256KV
1200    fn amend_h256kv(&mut self, address: &str, h256_kv: &str, quota: Option<u64>) -> Result<T, E> {
1201        let address = remove_0x(address);
1202        let data = format!("0x{address}{h256_kv}");
1203        let tx_options = TransactionOptions::new()
1204            .set_code(&data)
1205            .set_address(AMEND_ADDRESS)
1206            .set_quota(quota)
1207            .set_value(Some(U256::from_str(remove_0x(AMEND_KV_H256)).unwrap()));
1208        self.send_raw_transaction(tx_options)
1209    }
1210
1211    /// Amend account balance
1212    fn amend_balance(&mut self, address: &str, balance: U256, quota: Option<u64>) -> Result<T, E> {
1213        let address = remove_0x(address);
1214        let data = format!("0x{}{}", address, balance.completed_lower_hex());
1215        let tx_options = TransactionOptions::new()
1216            .set_code(&data)
1217            .set_address(AMEND_ADDRESS)
1218            .set_quota(quota)
1219            .set_value(Some(U256::from_str(remove_0x(AMEND_BALANCE)).unwrap()));
1220        self.send_raw_transaction(tx_options)
1221    }
1222}
1223
1224impl AmendExt<JsonRpcResponse, ToolError> for Client {}
1225
1226/// Account transfer, only applies to charge mode
1227pub trait Transfer<T, E>: ClientExt<T, E>
1228where
1229    T: serde::Serialize + serde::Deserialize<'static> + ::std::fmt::Display,
1230    E: Fail,
1231{
1232    /// Account transfer, only applies to charge mode
1233    fn transfer(&mut self, value: U256, address: &str, quota: Option<u64>) -> Result<T, E> {
1234        let tx_options = TransactionOptions::new()
1235            .set_address(address)
1236            .set_quota(quota)
1237            .set_value(Some(value));
1238        self.send_raw_transaction(tx_options)
1239    }
1240}
1241
1242impl Transfer<JsonRpcResponse, ToolError> for Client {}
1243
1244#[cfg(feature = "openssl")]
1245pub(crate) fn create_client() -> HyperClient<hyper_tls::HttpsConnector<HttpConnector>> {
1246    let https = hyper_tls::HttpsConnector::new();
1247    HyperClient::builder(TokioExecutor::new()).build(https)
1248}
1249
1250#[cfg(feature = "rustls")]
1251pub(crate) fn create_client(
1252) -> HyperClient<hyper_rustls::HttpsConnector<HttpConnector>, Full<Bytes>> {
1253    let https = hyper_rustls::HttpsConnectorBuilder::new()
1254        .with_native_roots()
1255        .unwrap()
1256        .https_or_http()
1257        .enable_http1()
1258        .build();
1259    HyperClient::builder(TokioExecutor::new()).build(https)
1260}