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
65pub const STORE_ADDRESS: &str = "0xffffffffffffffffffffffffffffffffff010000";
67pub const ABI_ADDRESS: &str = "0xffffffffffffffffffffffffffffffffff010001";
69pub const AMEND_ADDRESS: &str = "0xffffffffffffffffffffffffffffffffff010002";
71
72pub const AMEND_ABI: &str = "0x01";
74pub const AMEND_CODE: &str = "0x02";
76pub const AMEND_KV_H256: &str = "0x03";
78pub const AMEND_BALANCE: &str = "0x05";
80
81pub enum CensorAction {
83 Add = 1,
85 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>>;
92pub 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 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 pub fn set_uri(mut self, url: &str) -> Self {
130 self.url = url.parse().unwrap();
131 self
132 }
133
134 pub fn uri(&self) -> &Uri {
136 &self.url
137 }
138
139 pub fn set_chain_id(&mut self, chain_id: U256) -> &mut Self {
141 self.chain_id = Some(chain_id);
142 self
143 }
144
145 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 pub fn private_key(&self) -> Option<&PrivateKey> {
156 self.private_key.as_ref()
157 }
158
159 pub fn debug(&self) -> bool {
161 self.debug
162 }
163
164 pub fn set_debug(mut self, mode: bool) -> Self {
166 self.debug = mode;
167 self
168 }
169
170 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 pub fn send_request(&self, param: JsonRpcParams) -> Result<JsonRpcResponse, ToolError> {
184 self.single_run(self.make_request(param))
185 }
186
187 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![¶ms].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(¶ms).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![¶m].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![¶m].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(¶m).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 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 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 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 #[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 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 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 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 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 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 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 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
537pub trait ClientExt<T, E>
569where
570 T: serde::Serialize + serde::Deserialize<'static> + ::std::fmt::Display,
571 E: Fail,
572{
573 fn get_peer_count(&self) -> Result<T, E>;
575 fn get_peers_info(&self, extra: bool) -> Result<T, E>;
577 fn get_license_info(&self) -> Result<T, E>;
579 fn get_block_number(&self) -> Result<T, E>;
581 fn send_raw_transaction(&mut self, transaction_option: TransactionOptions) -> Result<T, E>;
583 fn get_block_by_hash(&self, hash: &str, transaction_info: bool) -> Result<T, E>;
585 fn get_block_by_number(&self, height: &str, transaction_info: bool) -> Result<T, E>;
587 fn get_transaction_receipt(&self, hash: &str) -> Result<T, E>;
589 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 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 fn get_transaction(&self, hash: &str, in_pool: bool) -> Result<T, E>;
608 fn get_transaction_count(&self, address: &str, height: &str) -> Result<T, E>;
610 fn get_code(&self, address: &str, height: &str) -> Result<T, E>;
612 fn get_abi(&self, address: &str, height: &str) -> Result<T, E>;
614 fn get_balance(&self, address: &str, height: &str) -> Result<T, E>;
616 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 fn new_block_filter(&self) -> Result<T, E>;
626 fn uninstall_filter(&self, filter_id: &str) -> Result<T, E>;
628 fn get_filter_changes(&self, filter_id: &str) -> Result<T, E>;
630 fn get_filter_logs(&self, filter_id: &str) -> Result<T, E>;
632 fn get_transaction_proof(&self, hash: &str) -> Result<T, E>;
634 fn get_metadata(&self, height: &str) -> Result<T, E>;
636 fn get_block_header(&self, height: &str) -> Result<T, E>;
638 fn get_state_proof(&self, address: &str, key: &str, height: &str) -> Result<T, E>;
640 fn get_storage_at(&self, address: &str, key: &str, height: &str) -> Result<T, E>;
642 fn get_version(&self) -> Result<T, E>;
644 fn estimate_quota(
646 &self,
647 from: Option<&str>,
648 to: &str,
649 data: Option<&str>,
650 height: &str,
651 ) -> Result<T, E>;
652 fn get_pool_tx_num(&self) -> Result<T, E>;
654 fn operate_censored_address(&self, action: CensorAction, censor_addr: &str) -> Result<T, E>;
656 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
1137pub 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 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 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
1167pub 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 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 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 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 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
1226pub trait Transfer<T, E>: ClientExt<T, E>
1228where
1229 T: serde::Serialize + serde::Deserialize<'static> + ::std::fmt::Display,
1230 E: Fail,
1231{
1232 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}