1use ethers_core::types::SyncingStatus;
2
3use crate::{
4 call_raw::CallBuilder,
5 errors::ProviderError,
6 ext::{ens, erc},
7 stream::{FilterWatcher, DEFAULT_LOCAL_POLL_INTERVAL, DEFAULT_POLL_INTERVAL},
8 utils::maybe,
9 Http as HttpProvider, JsonRpcClient, JsonRpcClientWrapper, LogQuery, MiddlewareError,
10 MockProvider, NodeInfo, PeerInfo, PendingTransaction, PubsubClient, QuorumProvider, RwClient,
11 SubscriptionStream,
12};
13
14#[cfg(not(target_arch = "wasm32"))]
15use crate::{HttpRateLimitRetryPolicy, RetryClient};
16use std::net::Ipv4Addr;
17
18pub use crate::Middleware;
19
20use async_trait::async_trait;
21
22use ethers_core::{
23 abi::{self, Detokenize, ParamType},
24 types::{
25 transaction::{eip2718::TypedTransaction, eip2930::AccessListWithGasUsed},
26 Address, Block, BlockId, BlockNumber, BlockTrace, Bytes, Chain, EIP1186ProofResponse,
27 FeeHistory, Filter, FilterBlockOption, GethDebugTracingCallOptions,
28 GethDebugTracingOptions, GethTrace, Log, NameOrAddress, Selector, Signature, Trace,
29 TraceFilter, TraceType, Transaction, TransactionReceipt, TransactionRequest, TxHash,
30 TxpoolContent, TxpoolInspect, TxpoolStatus, H256, U256, U64,
31 },
32 utils,
33};
34use futures_util::{lock::Mutex, try_join};
35use serde::{de::DeserializeOwned, Serialize};
36use std::{collections::VecDeque, fmt::Debug, str::FromStr, sync::Arc, time::Duration};
37use tracing::trace;
38use tracing_futures::Instrument;
39use url::{Host, ParseError, Url};
40
41#[derive(Copy, Clone)]
43pub enum NodeClient {
44 Geth,
46 Erigon,
48 OpenEthereum,
50 Nethermind,
52 Besu,
54}
55
56impl FromStr for NodeClient {
57 type Err = ProviderError;
58
59 fn from_str(s: &str) -> Result<Self, Self::Err> {
60 match s.split('/').next().unwrap().to_lowercase().as_str() {
61 "geth" => Ok(NodeClient::Geth),
62 "erigon" => Ok(NodeClient::Erigon),
63 "openethereum" => Ok(NodeClient::OpenEthereum),
64 "nethermind" => Ok(NodeClient::Nethermind),
65 "besu" => Ok(NodeClient::Besu),
66 _ => Err(ProviderError::UnsupportedNodeClient),
67 }
68 }
69}
70
71#[derive(Clone, Debug)]
93pub struct Provider<P> {
94 inner: P,
95 ens: Option<Address>,
96 interval: Option<Duration>,
97 from: Option<Address>,
98 _node_client: Arc<Mutex<Option<NodeClient>>>,
102}
103
104impl<P> AsRef<P> for Provider<P> {
105 fn as_ref(&self) -> &P {
106 &self.inner
107 }
108}
109
110#[derive(Clone, Debug)]
112pub enum FilterKind<'a> {
113 Logs(&'a Filter),
115
116 NewBlocks,
118
119 PendingTransactions,
121}
122
123impl<P: JsonRpcClient> Provider<P> {
125 pub fn new(provider: P) -> Self {
127 Self {
128 inner: provider,
129 ens: None,
130 interval: None,
131 from: None,
132 _node_client: Arc::new(Mutex::new(None)),
133 }
134 }
135
136 pub async fn node_client(&self) -> Result<NodeClient, ProviderError> {
139 let mut node_client = self._node_client.lock().await;
140
141 if let Some(node_client) = *node_client {
142 Ok(node_client)
143 } else {
144 let client_version = self.client_version().await?;
145 let client_version = match client_version.parse::<NodeClient>() {
146 Ok(res) => res,
147 Err(_) => return Err(ProviderError::UnsupportedNodeClient),
148 };
149 *node_client = Some(client_version);
150 Ok(client_version)
151 }
152 }
153
154 #[must_use]
155 pub fn with_sender(mut self, address: impl Into<Address>) -> Self {
157 self.from = Some(address.into());
158 self
159 }
160
161 pub async fn request<T, R>(&self, method: &str, params: T) -> Result<R, ProviderError>
163 where
164 T: Debug + Serialize + Send + Sync,
165 R: Serialize + DeserializeOwned + Debug + Send,
166 {
167 let span =
168 tracing::trace_span!("rpc", method = method, params = ?serde_json::to_string(¶ms)?);
169 let res = async move {
171 trace!("tx");
172 let res: R = self.inner.request(method, params).await.map_err(Into::into)?;
173 trace!(rx = ?serde_json::to_string(&res)?);
174 Ok::<_, ProviderError>(res)
175 }
176 .instrument(span)
177 .await?;
178 Ok(res)
179 }
180
181 async fn get_block_gen<Tx: Default + Serialize + DeserializeOwned + Debug + Send>(
182 &self,
183 id: BlockId,
184 include_txs: bool,
185 ) -> Result<Option<Block<Tx>>, ProviderError> {
186 let include_txs = utils::serialize(&include_txs);
187
188 Ok(match id {
189 BlockId::Hash(hash) => {
190 let hash = utils::serialize(&hash);
191 self.request("eth_getBlockByHash", [hash, include_txs]).await?
192 }
193 BlockId::Number(num) => {
194 let num = utils::serialize(&num);
195 self.request("eth_getBlockByNumber", [num, include_txs]).await?
196 }
197 })
198 }
199
200 pub fn call_raw<'a>(&'a self, tx: &'a TypedTransaction) -> CallBuilder<'a, P> {
235 CallBuilder::new(self, tx)
236 }
237}
238
239#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
240#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
241impl<P: JsonRpcClient> Middleware for Provider<P> {
242 type Error = ProviderError;
243 type Provider = P;
244 type Inner = Self;
245
246 fn inner(&self) -> &Self::Inner {
247 unreachable!("There is no inner provider here")
248 }
249
250 fn provider(&self) -> &Provider<Self::Provider> {
251 self
252 }
253
254 fn convert_err(p: ProviderError) -> Self::Error {
255 p
257 }
258
259 fn default_sender(&self) -> Option<Address> {
260 self.from
261 }
262
263 async fn client_version(&self) -> Result<String, Self::Error> {
264 self.request("web3_clientVersion", ()).await
265 }
266
267 async fn fill_transaction(
268 &self,
269 tx: &mut TypedTransaction,
270 block: Option<BlockId>,
271 ) -> Result<(), Self::Error> {
272 if let Some(default_sender) = self.default_sender() {
273 if tx.from().is_none() {
274 tx.set_from(default_sender);
275 }
276 }
277
278 if let Some(NameOrAddress::Name(ref ens_name)) = tx.to() {
282 let addr = self.resolve_name(ens_name).await?;
283 tx.set_to(addr);
284 }
285
286 match tx {
288 TypedTransaction::Eip2930(_) | TypedTransaction::Legacy(_) => {
289 let gas_price = maybe(tx.gas_price(), self.get_gas_price()).await?;
290 tx.set_gas_price(gas_price);
291 }
292 TypedTransaction::Eip1559(ref mut inner) => {
293 if inner.max_fee_per_gas.is_none() || inner.max_priority_fee_per_gas.is_none() {
294 let (max_fee_per_gas, max_priority_fee_per_gas) =
295 self.estimate_eip1559_fees(None).await?;
296 let mfpg = inner.max_fee_per_gas.get_or_insert(max_fee_per_gas);
305 inner.max_priority_fee_per_gas = inner
306 .max_priority_fee_per_gas
307 .map(|tip| std::cmp::min(tip, *mfpg))
308 .or(Some(max_priority_fee_per_gas));
309 };
310 }
311 #[cfg(feature = "optimism")]
312 TypedTransaction::DepositTransaction(_) => {
313 let gas_price = maybe(tx.gas_price(), self.get_gas_price()).await?;
314 tx.set_gas_price(gas_price);
315 }
316 }
317
318 if tx.gas().is_none() {
321 let gas_estimate = self.estimate_gas(tx, block).await?;
322 tx.set_gas(gas_estimate);
323 }
324
325 Ok(())
326 }
327
328 async fn get_block_number(&self) -> Result<U64, ProviderError> {
329 self.request("eth_blockNumber", ()).await
330 }
331
332 async fn get_block<T: Into<BlockId> + Send + Sync>(
333 &self,
334 block_hash_or_number: T,
335 ) -> Result<Option<Block<TxHash>>, Self::Error> {
336 self.get_block_gen(block_hash_or_number.into(), false).await
337 }
338
339 async fn get_header<T: Into<BlockId> + Send + Sync>(
340 &self,
341 block_hash_or_number: T,
342 ) -> Result<Option<Block<Transaction>>, Self::Error> {
343 let id = block_hash_or_number.into();
344 Ok(match id {
345 BlockId::Number(num) => {
346 let num = utils::serialize(&num);
347 self.request("eth_getHeaderByNumber", [num]).await?
348 }
349 BlockId::Hash(hash) => {
350 let hash = utils::serialize(&hash);
351 self.request("eth_getHeaderByHash", [hash]).await?
352 }
353 })
354 }
355
356 async fn get_block_with_txs<T: Into<BlockId> + Send + Sync>(
357 &self,
358 block_hash_or_number: T,
359 ) -> Result<Option<Block<Transaction>>, ProviderError> {
360 self.get_block_gen(block_hash_or_number.into(), true).await
361 }
362
363 async fn get_uncle_count<T: Into<BlockId> + Send + Sync>(
364 &self,
365 block_hash_or_number: T,
366 ) -> Result<U256, Self::Error> {
367 let id = block_hash_or_number.into();
368 Ok(match id {
369 BlockId::Hash(hash) => {
370 let hash = utils::serialize(&hash);
371 self.request("eth_getUncleCountByBlockHash", [hash]).await?
372 }
373 BlockId::Number(num) => {
374 let num = utils::serialize(&num);
375 self.request("eth_getUncleCountByBlockNumber", [num]).await?
376 }
377 })
378 }
379
380 async fn get_uncle<T: Into<BlockId> + Send + Sync>(
381 &self,
382 block_hash_or_number: T,
383 idx: U64,
384 ) -> Result<Option<Block<H256>>, ProviderError> {
385 let blk_id = block_hash_or_number.into();
386 let idx = utils::serialize(&idx);
387 Ok(match blk_id {
388 BlockId::Hash(hash) => {
389 let hash = utils::serialize(&hash);
390 self.request("eth_getUncleByBlockHashAndIndex", [hash, idx]).await?
391 }
392 BlockId::Number(num) => {
393 let num = utils::serialize(&num);
394 self.request("eth_getUncleByBlockNumberAndIndex", [num, idx]).await?
395 }
396 })
397 }
398
399 async fn get_transaction<T: Send + Sync + Into<TxHash>>(
400 &self,
401 transaction_hash: T,
402 ) -> Result<Option<Transaction>, ProviderError> {
403 let hash = transaction_hash.into();
404 self.request("eth_getTransactionByHash", [hash]).await
405 }
406
407 async fn get_transaction_by_block_and_index<T: Into<BlockId> + Send + Sync>(
408 &self,
409 block_hash_or_number: T,
410 idx: U64,
411 ) -> Result<Option<Transaction>, ProviderError> {
412 let blk_id = block_hash_or_number.into();
413 let idx = ethers_core::utils::serialize(&idx);
414 Ok(match blk_id {
415 BlockId::Hash(hash) => {
416 let hash = ethers_core::utils::serialize(&hash);
417 self.request("eth_getTransactionByBlockHashAndIndex", [hash, idx]).await?
418 }
419 BlockId::Number(num) => {
420 let num = ethers_core::utils::serialize(&num);
421 self.request("eth_getTransactionByBlockNumberAndIndex", [num, idx]).await?
422 }
423 })
424 }
425
426 async fn get_transaction_receipt<T: Send + Sync + Into<TxHash>>(
427 &self,
428 transaction_hash: T,
429 ) -> Result<Option<TransactionReceipt>, ProviderError> {
430 let hash = transaction_hash.into();
431 self.request("eth_getTransactionReceipt", [hash]).await
432 }
433
434 async fn get_block_receipts<T: Into<BlockNumber> + Send + Sync>(
435 &self,
436 block: T,
437 ) -> Result<Vec<TransactionReceipt>, Self::Error> {
438 self.request("eth_getBlockReceipts", [block.into()]).await
439 }
440
441 async fn parity_block_receipts<T: Into<BlockNumber> + Send + Sync>(
442 &self,
443 block: T,
444 ) -> Result<Vec<TransactionReceipt>, Self::Error> {
445 self.request("parity_getBlockReceipts", vec![block.into()]).await
446 }
447
448 async fn get_gas_price(&self) -> Result<U256, ProviderError> {
449 self.request("eth_gasPrice", ()).await
450 }
451
452 async fn estimate_eip1559_fees(
453 &self,
454 estimator: Option<fn(U256, Vec<Vec<U256>>) -> (U256, U256)>,
455 ) -> Result<(U256, U256), Self::Error> {
456 let base_fee_per_gas = self
457 .get_block(BlockNumber::Latest)
458 .await?
459 .ok_or_else(|| ProviderError::CustomError("Latest block not found".into()))?
460 .base_fee_per_gas
461 .ok_or_else(|| ProviderError::CustomError("EIP-1559 not activated".into()))?;
462
463 let fee_history = self
464 .fee_history(
465 utils::EIP1559_FEE_ESTIMATION_PAST_BLOCKS,
466 BlockNumber::Latest,
467 &[utils::EIP1559_FEE_ESTIMATION_REWARD_PERCENTILE],
468 )
469 .await?;
470
471 let (max_fee_per_gas, max_priority_fee_per_gas) = if let Some(es) = estimator {
473 es(base_fee_per_gas, fee_history.reward)
474 } else {
475 utils::eip1559_default_estimator(base_fee_per_gas, fee_history.reward)
476 };
477
478 Ok((max_fee_per_gas, max_priority_fee_per_gas))
479 }
480
481 async fn get_accounts(&self) -> Result<Vec<Address>, ProviderError> {
482 self.request("eth_accounts", ()).await
483 }
484
485 async fn get_transaction_count<T: Into<NameOrAddress> + Send + Sync>(
486 &self,
487 from: T,
488 block: Option<BlockId>,
489 ) -> Result<U256, ProviderError> {
490 let from = match from.into() {
491 NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
492 NameOrAddress::Address(addr) => addr,
493 };
494
495 let from = utils::serialize(&from);
496 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
497 self.request("eth_getTransactionCount", [from, block]).await
498 }
499
500 async fn get_balance<T: Into<NameOrAddress> + Send + Sync>(
501 &self,
502 from: T,
503 block: Option<BlockId>,
504 ) -> Result<U256, ProviderError> {
505 let from = match from.into() {
506 NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
507 NameOrAddress::Address(addr) => addr,
508 };
509
510 let from = utils::serialize(&from);
511 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
512 self.request("eth_getBalance", [from, block]).await
513 }
514
515 async fn get_chainid(&self) -> Result<U256, ProviderError> {
516 self.request("eth_chainId", ()).await
517 }
518
519 async fn syncing(&self) -> Result<SyncingStatus, Self::Error> {
520 self.request("eth_syncing", ()).await
521 }
522
523 async fn get_net_version(&self) -> Result<String, ProviderError> {
524 self.request("net_version", ()).await
525 }
526
527 async fn call(
528 &self,
529 tx: &TypedTransaction,
530 block: Option<BlockId>,
531 ) -> Result<Bytes, ProviderError> {
532 let tx = utils::serialize(tx);
533 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
534 self.request("eth_call", [tx, block]).await
535 }
536
537 async fn estimate_gas(
538 &self,
539 tx: &TypedTransaction,
540 block: Option<BlockId>,
541 ) -> Result<U256, ProviderError> {
542 let tx = utils::serialize(tx);
543 let params = if let Some(block_id) = block {
546 vec![tx, utils::serialize(&block_id)]
547 } else {
548 vec![tx]
549 };
550 self.request("eth_estimateGas", params).await
551 }
552
553 async fn create_access_list(
554 &self,
555 tx: &TypedTransaction,
556 block: Option<BlockId>,
557 ) -> Result<AccessListWithGasUsed, ProviderError> {
558 let tx = utils::serialize(tx);
559 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
560 self.request("eth_createAccessList", [tx, block]).await
561 }
562
563 async fn send_transaction<T: Into<TypedTransaction> + Send + Sync>(
564 &self,
565 tx: T,
566 block: Option<BlockId>,
567 ) -> Result<PendingTransaction<'_, P>, ProviderError> {
568 let mut tx = tx.into();
569 self.fill_transaction(&mut tx, block).await?;
570 let tx_hash = self.request("eth_sendTransaction", [tx]).await?;
571
572 Ok(PendingTransaction::new(tx_hash, self))
573 }
574
575 async fn send_raw_transaction<'a>(
576 &'a self,
577 tx: Bytes,
578 ) -> Result<PendingTransaction<'a, P>, ProviderError> {
579 let rlp = utils::serialize(&tx);
580 let tx_hash = self.request("eth_sendRawTransaction", [rlp]).await?;
581 Ok(PendingTransaction::new(tx_hash, self))
582 }
583
584 async fn is_signer(&self) -> bool {
585 match self.from {
586 Some(sender) => self.sign(vec![], &sender).await.is_ok(),
587 None => false,
588 }
589 }
590
591 async fn sign<T: Into<Bytes> + Send + Sync>(
592 &self,
593 data: T,
594 from: &Address,
595 ) -> Result<Signature, ProviderError> {
596 let data = utils::serialize(&data.into());
597 let from = utils::serialize(from);
598
599 let sig: String = self.request("eth_sign", [from, data]).await?;
601
602 let sig = hex::decode(sig)?;
604 Ok(Signature::try_from(sig.as_slice())
605 .map_err(|e| ProviderError::CustomError(e.to_string()))?)
606 }
607
608 async fn sign_transaction(
610 &self,
611 _tx: &TypedTransaction,
612 _from: Address,
613 ) -> Result<Signature, Self::Error> {
614 Err(MiddlewareError::from_err(ProviderError::SignerUnavailable))
615 }
616
617 async fn get_logs(&self, filter: &Filter) -> Result<Vec<Log>, ProviderError> {
620 self.request("eth_getLogs", [filter]).await
621 }
622
623 fn get_logs_paginated<'a>(&'a self, filter: &Filter, page_size: u64) -> LogQuery<'a, P> {
624 LogQuery::new(self, filter).with_page_size(page_size)
625 }
626
627 async fn watch<'a>(
628 &'a self,
629 filter: &Filter,
630 ) -> Result<FilterWatcher<'a, P, Log>, ProviderError> {
631 let id = self.new_filter(FilterKind::Logs(filter)).await?;
632 let filter = FilterWatcher::new(id, self).interval(self.get_interval());
633 Ok(filter)
634 }
635
636 async fn watch_blocks(&self) -> Result<FilterWatcher<'_, P, H256>, ProviderError> {
637 let id = self.new_filter(FilterKind::NewBlocks).await?;
638 let filter = FilterWatcher::new(id, self).interval(self.get_interval());
639 Ok(filter)
640 }
641
642 async fn watch_pending_transactions(
644 &self,
645 ) -> Result<FilterWatcher<'_, P, H256>, ProviderError> {
646 let id = self.new_filter(FilterKind::PendingTransactions).await?;
647 let filter = FilterWatcher::new(id, self).interval(self.get_interval());
648 Ok(filter)
649 }
650
651 async fn new_filter(&self, filter: FilterKind<'_>) -> Result<U256, ProviderError> {
652 let (method, args) = match filter {
653 FilterKind::NewBlocks => ("eth_newBlockFilter", vec![]),
654 FilterKind::PendingTransactions => ("eth_newPendingTransactionFilter", vec![]),
655 FilterKind::Logs(filter) => ("eth_newFilter", vec![utils::serialize(&filter)]),
656 };
657
658 self.request(method, args).await
659 }
660
661 async fn uninstall_filter<T: Into<U256> + Send + Sync>(
662 &self,
663 id: T,
664 ) -> Result<bool, ProviderError> {
665 let id = utils::serialize(&id.into());
666 self.request("eth_uninstallFilter", [id]).await
667 }
668
669 async fn get_filter_changes<T, R>(&self, id: T) -> Result<Vec<R>, ProviderError>
670 where
671 T: Into<U256> + Send + Sync,
672 R: Serialize + DeserializeOwned + Send + Sync + Debug,
673 {
674 let id = utils::serialize(&id.into());
675 self.request("eth_getFilterChanges", [id]).await
676 }
677
678 async fn get_storage_at<T: Into<NameOrAddress> + Send + Sync>(
679 &self,
680 from: T,
681 location: H256,
682 block: Option<BlockId>,
683 ) -> Result<H256, ProviderError> {
684 let from = match from.into() {
685 NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
686 NameOrAddress::Address(addr) => addr,
687 };
688
689 let position = U256::from_big_endian(location.as_bytes());
692 let position = utils::serialize(&position);
693 let from = utils::serialize(&from);
694 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
695
696 let value: String = self.request("eth_getStorageAt", [from, position, block]).await?;
698 let bytes = hex::decode(value)?;
700 if bytes.len() > 32 {
701 Err(hex::FromHexError::InvalidStringLength.into())
702 } else {
703 let mut buf = [0; 32];
704 buf[32 - bytes.len()..].copy_from_slice(&bytes);
705 Ok(H256(buf))
706 }
707 }
708
709 async fn get_code<T: Into<NameOrAddress> + Send + Sync>(
710 &self,
711 at: T,
712 block: Option<BlockId>,
713 ) -> Result<Bytes, ProviderError> {
714 let at = match at.into() {
715 NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
716 NameOrAddress::Address(addr) => addr,
717 };
718
719 let at = utils::serialize(&at);
720 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
721 self.request("eth_getCode", [at, block]).await
722 }
723
724 async fn get_proof<T: Into<NameOrAddress> + Send + Sync>(
725 &self,
726 from: T,
727 locations: Vec<H256>,
728 block: Option<BlockId>,
729 ) -> Result<EIP1186ProofResponse, ProviderError> {
730 let from = match from.into() {
731 NameOrAddress::Name(ens_name) => self.resolve_name(&ens_name).await?,
732 NameOrAddress::Address(addr) => addr,
733 };
734
735 let from = utils::serialize(&from);
736 let locations = locations.iter().map(|location| utils::serialize(&location)).collect();
737 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
738
739 self.request("eth_getProof", [from, locations, block]).await
740 }
741
742 async fn mining(&self) -> Result<bool, Self::Error> {
744 self.request("eth_mining", ()).await
745 }
746
747 async fn import_raw_key(
748 &self,
749 private_key: Bytes,
750 passphrase: String,
751 ) -> Result<Address, ProviderError> {
752 let private_key_hex = hex::encode(private_key);
757 let private_key = utils::serialize(&private_key_hex);
758 let passphrase = utils::serialize(&passphrase);
759 self.request("personal_importRawKey", [private_key, passphrase]).await
760 }
761
762 async fn unlock_account<T: Into<Address> + Send + Sync>(
763 &self,
764 account: T,
765 passphrase: String,
766 duration: Option<u64>,
767 ) -> Result<bool, ProviderError> {
768 let account = utils::serialize(&account.into());
769 let duration = utils::serialize(&duration.unwrap_or(0));
770 let passphrase = utils::serialize(&passphrase);
771 self.request("personal_unlockAccount", [account, passphrase, duration]).await
772 }
773
774 async fn add_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
775 let enode_url = utils::serialize(&enode_url);
776 self.request("admin_addPeer", [enode_url]).await
777 }
778
779 async fn add_trusted_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
780 let enode_url = utils::serialize(&enode_url);
781 self.request("admin_addTrustedPeer", [enode_url]).await
782 }
783
784 async fn node_info(&self) -> Result<NodeInfo, Self::Error> {
785 self.request("admin_nodeInfo", ()).await
786 }
787
788 async fn peers(&self) -> Result<Vec<PeerInfo>, Self::Error> {
789 self.request("admin_peers", ()).await
790 }
791
792 async fn remove_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
793 let enode_url = utils::serialize(&enode_url);
794 self.request("admin_removePeer", [enode_url]).await
795 }
796
797 async fn remove_trusted_peer(&self, enode_url: String) -> Result<bool, Self::Error> {
798 let enode_url = utils::serialize(&enode_url);
799 self.request("admin_removeTrustedPeer", [enode_url]).await
800 }
801
802 async fn start_mining(&self) -> Result<(), Self::Error> {
803 self.request("miner_start", ()).await
804 }
805
806 async fn stop_mining(&self) -> Result<(), Self::Error> {
807 self.request("miner_stop", ()).await
808 }
809
810 async fn resolve_name(&self, ens_name: &str) -> Result<Address, ProviderError> {
811 self.query_resolver(ParamType::Address, ens_name, ens::ADDR_SELECTOR).await
812 }
813
814 async fn lookup_address(&self, address: Address) -> Result<String, ProviderError> {
815 let ens_name = ens::reverse_address(address);
816 let domain: String =
817 self.query_resolver(ParamType::String, &ens_name, ens::NAME_SELECTOR).await?;
818 let reverse_address = self.resolve_name(&domain).await?;
819 if address != reverse_address {
820 Err(ProviderError::EnsNotOwned(domain))
821 } else {
822 Ok(domain)
823 }
824 }
825
826 async fn resolve_avatar(&self, ens_name: &str) -> Result<Url, ProviderError> {
827 let (field, owner) =
828 try_join!(self.resolve_field(ens_name, "avatar"), self.resolve_name(ens_name))?;
829 let url = Url::from_str(&field).map_err(|e| ProviderError::CustomError(e.to_string()))?;
830 match url.scheme() {
831 "https" | "data" => Ok(url),
832 "ipfs" => erc::http_link_ipfs(url).map_err(ProviderError::CustomError),
833 "eip155" => {
834 let token =
835 erc::ERCNFT::from_str(url.path()).map_err(ProviderError::CustomError)?;
836 match token.type_ {
837 erc::ERCNFTType::ERC721 => {
838 let tx = TransactionRequest {
839 data: Some(
840 [&erc::ERC721_OWNER_SELECTOR[..], &token.id].concat().into(),
841 ),
842 to: Some(NameOrAddress::Address(token.contract)),
843 ..Default::default()
844 };
845 let data = self.call(&tx.into(), None).await?;
846 if decode_bytes::<Address>(ParamType::Address, data) != owner {
847 return Err(ProviderError::CustomError("Incorrect owner.".to_string()))
848 }
849 }
850 erc::ERCNFTType::ERC1155 => {
851 let tx = TransactionRequest {
852 data: Some(
853 [
854 &erc::ERC1155_BALANCE_SELECTOR[..],
855 &[0x0; 12],
856 &owner.0,
857 &token.id,
858 ]
859 .concat()
860 .into(),
861 ),
862 to: Some(NameOrAddress::Address(token.contract)),
863 ..Default::default()
864 };
865 let data = self.call(&tx.into(), None).await?;
866 if decode_bytes::<u64>(ParamType::Uint(64), data) == 0 {
867 return Err(ProviderError::CustomError("Incorrect balance.".to_string()))
868 }
869 }
870 }
871
872 let image_url = self.resolve_nft(token).await?;
873 match image_url.scheme() {
874 "https" | "data" => Ok(image_url),
875 "ipfs" => erc::http_link_ipfs(image_url).map_err(ProviderError::CustomError),
876 _ => Err(ProviderError::CustomError(
877 "Unsupported scheme for the image".to_string(),
878 )),
879 }
880 }
881 _ => Err(ProviderError::CustomError("Unsupported scheme".to_string())),
882 }
883 }
884
885 async fn resolve_nft(&self, token: erc::ERCNFT) -> Result<Url, ProviderError> {
886 let selector = token.type_.resolution_selector();
887 let tx = TransactionRequest {
888 data: Some([&selector[..], &token.id].concat().into()),
889 to: Some(NameOrAddress::Address(token.contract)),
890 ..Default::default()
891 };
892 let data = self.call(&tx.into(), None).await?;
893 let mut metadata_url = Url::parse(&decode_bytes::<String>(ParamType::String, data))
894 .map_err(|e| ProviderError::CustomError(format!("Invalid metadata url: {e}")))?;
895
896 if token.type_ == erc::ERCNFTType::ERC1155 {
897 metadata_url.set_path(&metadata_url.path().replace("%7Bid%7D", &hex::encode(token.id)));
898 }
899 if metadata_url.scheme() == "ipfs" {
900 metadata_url = erc::http_link_ipfs(metadata_url).map_err(ProviderError::CustomError)?;
901 }
902 let metadata: erc::Metadata = reqwest::get(metadata_url).await?.json().await?;
903 Url::parse(&metadata.image).map_err(|e| ProviderError::CustomError(e.to_string()))
904 }
905
906 async fn resolve_field(&self, ens_name: &str, field: &str) -> Result<String, ProviderError> {
907 let field: String = self
908 .query_resolver_parameters(
909 ParamType::String,
910 ens_name,
911 ens::FIELD_SELECTOR,
912 Some(&ens::parameterhash(field)),
913 )
914 .await?;
915 Ok(field)
916 }
917
918 async fn txpool_content(&self) -> Result<TxpoolContent, ProviderError> {
919 self.request("txpool_content", ()).await
920 }
921
922 async fn txpool_inspect(&self) -> Result<TxpoolInspect, ProviderError> {
923 self.request("txpool_inspect", ()).await
924 }
925
926 async fn txpool_status(&self) -> Result<TxpoolStatus, ProviderError> {
927 self.request("txpool_status", ()).await
928 }
929
930 async fn debug_trace_transaction(
931 &self,
932 tx_hash: TxHash,
933 trace_options: GethDebugTracingOptions,
934 ) -> Result<GethTrace, ProviderError> {
935 let tx_hash = utils::serialize(&tx_hash);
936 let trace_options = utils::serialize(&trace_options);
937 self.request("debug_traceTransaction", [tx_hash, trace_options]).await
938 }
939
940 async fn debug_trace_call<T: Into<TypedTransaction> + Send + Sync>(
941 &self,
942 req: T,
943 block: Option<BlockId>,
944 trace_options: GethDebugTracingCallOptions,
945 ) -> Result<GethTrace, ProviderError> {
946 let req = req.into();
947 let req = utils::serialize(&req);
948 let block = utils::serialize(&block.unwrap_or_else(|| BlockNumber::Latest.into()));
949 let trace_options = utils::serialize(&trace_options);
950 self.request("debug_traceCall", [req, block, trace_options]).await
951 }
952
953 async fn debug_trace_block_by_number(
954 &self,
955 block: Option<BlockNumber>,
956 trace_options: GethDebugTracingOptions,
957 ) -> Result<Vec<GethTrace>, ProviderError> {
958 let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
959 let trace_options = utils::serialize(&trace_options);
960 self.request("debug_traceBlockByNumber", [block, trace_options]).await
961 }
962
963 async fn debug_trace_block_by_hash(
964 &self,
965 block: H256,
966 trace_options: GethDebugTracingOptions,
967 ) -> Result<Vec<GethTrace>, ProviderError> {
968 let block = utils::serialize(&block);
969 let trace_options = utils::serialize(&trace_options);
970 self.request("debug_traceBlockByHash", [block, trace_options]).await
971 }
972
973 async fn trace_call<T: Into<TypedTransaction> + Send + Sync>(
974 &self,
975 req: T,
976 trace_type: Vec<TraceType>,
977 block: Option<BlockNumber>,
978 ) -> Result<BlockTrace, ProviderError> {
979 let req = req.into();
980 let req = utils::serialize(&req);
981 let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
982 let trace_type = utils::serialize(&trace_type);
983 self.request("trace_call", [req, trace_type, block]).await
984 }
985
986 async fn trace_call_many<T: Into<TypedTransaction> + Send + Sync>(
987 &self,
988 req: Vec<(T, Vec<TraceType>)>,
989 block: Option<BlockNumber>,
990 ) -> Result<Vec<BlockTrace>, ProviderError> {
991 let req: Vec<(TypedTransaction, Vec<TraceType>)> =
992 req.into_iter().map(|(tx, trace_type)| (tx.into(), trace_type)).collect();
993 let req = utils::serialize(&req);
994 let block = utils::serialize(&block.unwrap_or(BlockNumber::Latest));
995 self.request("trace_callMany", [req, block]).await
996 }
997
998 async fn trace_raw_transaction(
999 &self,
1000 data: Bytes,
1001 trace_type: Vec<TraceType>,
1002 ) -> Result<BlockTrace, ProviderError> {
1003 let data = utils::serialize(&data);
1004 let trace_type = utils::serialize(&trace_type);
1005 self.request("trace_rawTransaction", [data, trace_type]).await
1006 }
1007
1008 async fn trace_replay_transaction(
1009 &self,
1010 hash: H256,
1011 trace_type: Vec<TraceType>,
1012 ) -> Result<BlockTrace, ProviderError> {
1013 let hash = utils::serialize(&hash);
1014 let trace_type = utils::serialize(&trace_type);
1015 self.request("trace_replayTransaction", [hash, trace_type]).await
1016 }
1017
1018 async fn trace_replay_block_transactions(
1019 &self,
1020 block: BlockNumber,
1021 trace_type: Vec<TraceType>,
1022 ) -> Result<Vec<BlockTrace>, ProviderError> {
1023 let block = utils::serialize(&block);
1024 let trace_type = utils::serialize(&trace_type);
1025 self.request("trace_replayBlockTransactions", [block, trace_type]).await
1026 }
1027
1028 async fn trace_block(&self, block: BlockNumber) -> Result<Vec<Trace>, ProviderError> {
1029 let block = utils::serialize(&block);
1030 self.request("trace_block", [block]).await
1031 }
1032
1033 async fn trace_filter(&self, filter: TraceFilter) -> Result<Vec<Trace>, ProviderError> {
1034 let filter = utils::serialize(&filter);
1035 self.request("trace_filter", vec![filter]).await
1036 }
1037
1038 async fn trace_get<T: Into<U64> + Send + Sync>(
1039 &self,
1040 hash: H256,
1041 index: Vec<T>,
1042 ) -> Result<Trace, ProviderError> {
1043 let hash = utils::serialize(&hash);
1044 let index: Vec<U64> = index.into_iter().map(|i| i.into()).collect();
1045 let index = utils::serialize(&index);
1046 self.request("trace_get", vec![hash, index]).await
1047 }
1048
1049 async fn trace_transaction(&self, hash: H256) -> Result<Vec<Trace>, ProviderError> {
1050 let hash = utils::serialize(&hash);
1051 self.request("trace_transaction", vec![hash]).await
1052 }
1053
1054 async fn subscribe<T, R>(
1055 &self,
1056 params: T,
1057 ) -> Result<SubscriptionStream<'_, P, R>, ProviderError>
1058 where
1059 T: Debug + Serialize + Send + Sync,
1060 R: DeserializeOwned + Send + Sync,
1061 P: PubsubClient,
1062 {
1063 let id: U256 = self.request("eth_subscribe", params).await?;
1064 SubscriptionStream::new(id, self).map_err(Into::into)
1065 }
1066
1067 async fn unsubscribe<T>(&self, id: T) -> Result<bool, ProviderError>
1068 where
1069 T: Into<U256> + Send + Sync,
1070 P: PubsubClient,
1071 {
1072 self.request("eth_unsubscribe", [id.into()]).await
1073 }
1074
1075 async fn subscribe_blocks(
1076 &self,
1077 ) -> Result<SubscriptionStream<'_, P, Block<TxHash>>, ProviderError>
1078 where
1079 P: PubsubClient,
1080 {
1081 self.subscribe(["newHeads"]).await
1082 }
1083
1084 async fn subscribe_pending_txs(
1085 &self,
1086 ) -> Result<SubscriptionStream<'_, P, TxHash>, ProviderError>
1087 where
1088 P: PubsubClient,
1089 {
1090 self.subscribe(["newPendingTransactions"]).await
1091 }
1092
1093 async fn subscribe_full_pending_txs(
1094 &self,
1095 ) -> Result<SubscriptionStream<'_, P, Transaction>, ProviderError>
1096 where
1097 P: PubsubClient,
1098 {
1099 self.subscribe([utils::serialize(&"newPendingTransactions"), utils::serialize(&true)]).await
1100 }
1101
1102 async fn subscribe_logs<'a>(
1103 &'a self,
1104 filter: &Filter,
1105 ) -> Result<SubscriptionStream<'a, P, Log>, ProviderError>
1106 where
1107 P: PubsubClient,
1108 {
1109 let loaded_logs = match filter.block_option {
1110 FilterBlockOption::Range { from_block, to_block: _ } => {
1111 if from_block.is_none() {
1112 vec![]
1113 } else {
1114 self.get_logs(filter).await?
1115 }
1116 }
1117 FilterBlockOption::AtBlockHash(_block_hash) => self.get_logs(filter).await?,
1118 };
1119 let loaded_logs = VecDeque::from(loaded_logs);
1120
1121 let logs = utils::serialize(&"logs"); let filter = utils::serialize(filter);
1123 self.subscribe([logs, filter]).await.map(|mut stream| {
1124 stream.set_loaded_elements(loaded_logs);
1125 stream
1126 })
1127 }
1128
1129 async fn fee_history<T: Into<U256> + Send + Sync>(
1130 &self,
1131 block_count: T,
1132 last_block: BlockNumber,
1133 reward_percentiles: &[f64],
1134 ) -> Result<FeeHistory, Self::Error> {
1135 let block_count = block_count.into();
1136 let last_block = utils::serialize(&last_block);
1137 let reward_percentiles = utils::serialize(&reward_percentiles);
1138
1139 match self
1143 .request::<_, FeeHistory>(
1144 "eth_feeHistory",
1145 [utils::serialize(&block_count), last_block.clone(), reward_percentiles.clone()],
1146 )
1147 .await
1148 {
1149 success @ Ok(_) => success,
1150 err @ Err(_) => {
1151 let fallback = self
1152 .request::<_, FeeHistory>(
1153 "eth_feeHistory",
1154 [utils::serialize(&block_count.as_u64()), last_block, reward_percentiles],
1155 )
1156 .await;
1157
1158 if fallback.is_err() {
1159 return err
1162 }
1163 fallback
1164 }
1165 }
1166 }
1167}
1168
1169impl<P: JsonRpcClient> Provider<P> {
1170 async fn query_resolver<T: Detokenize>(
1171 &self,
1172 param: ParamType,
1173 ens_name: &str,
1174 selector: Selector,
1175 ) -> Result<T, ProviderError> {
1176 self.query_resolver_parameters(param, ens_name, selector, None).await
1177 }
1178
1179 async fn query_resolver_parameters<T: Detokenize>(
1180 &self,
1181 param: ParamType,
1182 ens_name: &str,
1183 selector: Selector,
1184 parameters: Option<&[u8]>,
1185 ) -> Result<T, ProviderError> {
1186 let ens_addr = self.ens.unwrap_or(ens::ENS_ADDRESS);
1188
1189 let data = self.call(&ens::get_resolver(ens_addr, ens_name).into(), None).await?;
1192
1193 if data.0.is_empty() {
1195 return Err(ProviderError::EnsError(ens_name.to_string()))
1196 }
1197
1198 let resolver_address: Address = decode_bytes(ParamType::Address, data);
1199 if resolver_address == Address::zero() {
1200 return Err(ProviderError::EnsError(ens_name.to_string()))
1201 }
1202
1203 if let ParamType::Address = param {
1204 self.validate_resolver(resolver_address, selector, ens_name).await?;
1206 }
1207
1208 let data = self
1210 .call(&ens::resolve(resolver_address, selector, ens_name, parameters).into(), None)
1211 .await?;
1212
1213 Ok(decode_bytes(param, data))
1214 }
1215
1216 async fn validate_resolver(
1218 &self,
1219 resolver_address: Address,
1220 selector: Selector,
1221 ens_name: &str,
1222 ) -> Result<(), ProviderError> {
1223 let data =
1224 self.call(&ens::supports_interface(resolver_address, selector).into(), None).await?;
1225
1226 if data.is_empty() {
1227 return Err(ProviderError::EnsError(format!(
1228 "`{ens_name}` resolver ({resolver_address:?}) is invalid."
1229 )))
1230 }
1231
1232 let supports_selector = abi::decode(&[ParamType::Bool], data.as_ref())
1233 .map(|token| token[0].clone().into_bool().unwrap_or_default())
1234 .unwrap_or_default();
1235
1236 if !supports_selector {
1237 return Err(ProviderError::EnsError(format!(
1238 "`{}` resolver ({:?}) does not support selector {}.",
1239 ens_name,
1240 resolver_address,
1241 hex::encode(selector)
1242 )))
1243 }
1244
1245 Ok(())
1246 }
1247
1248 #[cfg(test)]
1249 pub async fn mine(&self, num_blocks: usize) -> Result<(), ProviderError> {
1251 for _ in 0..num_blocks {
1252 self.inner.request::<_, U256>("evm_mine", None::<()>).await.map_err(Into::into)?;
1253 }
1254 Ok(())
1255 }
1256
1257 #[must_use]
1259 pub fn ens<T: Into<Address>>(mut self, ens: T) -> Self {
1260 self.ens = Some(ens.into());
1261 self
1262 }
1263
1264 pub fn set_interval<T: Into<Duration>>(&mut self, interval: T) -> &mut Self {
1267 self.interval = Some(interval.into());
1268 self
1269 }
1270
1271 #[must_use]
1274 pub fn interval<T: Into<Duration>>(mut self, interval: T) -> Self {
1275 self.set_interval(interval);
1276 self
1277 }
1278
1279 pub fn get_interval(&self) -> Duration {
1282 self.interval.unwrap_or(DEFAULT_POLL_INTERVAL)
1283 }
1284}
1285
1286#[cfg(all(feature = "ipc", any(unix, windows)))]
1287impl Provider<crate::Ipc> {
1288 #[cfg_attr(unix, doc = "Connects to the Unix socket at the provided path.")]
1289 #[cfg_attr(windows, doc = "Connects to the named pipe at the provided path.\n")]
1290 #[cfg_attr(
1291 windows,
1292 doc = r"Note: the path must be the fully qualified, like: `\\.\pipe\<name>`."
1293 )]
1294 pub async fn connect_ipc(path: impl AsRef<std::path::Path>) -> Result<Self, ProviderError> {
1295 let ipc = crate::Ipc::connect(path).await?;
1296 Ok(Self::new(ipc))
1297 }
1298}
1299
1300impl Provider<HttpProvider> {
1301 pub fn url(&self) -> &Url {
1303 self.inner.url()
1304 }
1305
1306 pub fn url_mut(&mut self) -> &mut Url {
1308 self.inner.url_mut()
1309 }
1310}
1311
1312impl<Read, Write> Provider<RwClient<Read, Write>>
1313where
1314 Read: JsonRpcClient + 'static,
1315 <Read as JsonRpcClient>::Error: Sync + Send + 'static,
1316 Write: JsonRpcClient + 'static,
1317 <Write as JsonRpcClient>::Error: Sync + Send + 'static,
1318{
1319 pub fn rw(r: Read, w: Write) -> Self {
1321 Self::new(RwClient::new(r, w))
1322 }
1323}
1324
1325impl<T: JsonRpcClientWrapper> Provider<QuorumProvider<T>> {
1326 pub fn quorum(inner: QuorumProvider<T>) -> Self {
1328 Self::new(inner)
1329 }
1330}
1331
1332impl Provider<MockProvider> {
1333 pub fn mocked() -> (Self, MockProvider) {
1355 let mock = MockProvider::new();
1356 let mock_clone = mock.clone();
1357 (Self::new(mock), mock_clone)
1358 }
1359}
1360
1361fn decode_bytes<T: Detokenize>(param: ParamType, bytes: Bytes) -> T {
1367 let tokens = abi::decode(&[param], bytes.as_ref())
1368 .expect("could not abi-decode bytes to address tokens");
1369 T::from_tokens(tokens).expect("could not parse tokens as address")
1370}
1371
1372impl TryFrom<&str> for Provider<HttpProvider> {
1373 type Error = ParseError;
1374
1375 fn try_from(src: &str) -> Result<Self, Self::Error> {
1376 Ok(Provider::new(HttpProvider::new(Url::parse(src)?)))
1377 }
1378}
1379
1380impl TryFrom<String> for Provider<HttpProvider> {
1381 type Error = ParseError;
1382
1383 fn try_from(src: String) -> Result<Self, Self::Error> {
1384 Provider::try_from(src.as_str())
1385 }
1386}
1387
1388impl<'a> TryFrom<&'a String> for Provider<HttpProvider> {
1389 type Error = ParseError;
1390
1391 fn try_from(src: &'a String) -> Result<Self, Self::Error> {
1392 Provider::try_from(src.as_str())
1393 }
1394}
1395
1396#[cfg(not(target_arch = "wasm32"))]
1397impl Provider<RetryClient<HttpProvider>> {
1398 pub fn new_client(src: &str, max_retry: u32, initial_backoff: u64) -> Result<Self, ParseError> {
1401 Ok(Provider::new(RetryClient::new(
1402 HttpProvider::new(Url::parse(src)?),
1403 Box::new(HttpRateLimitRetryPolicy),
1404 max_retry,
1405 initial_backoff,
1406 )))
1407 }
1408}
1409
1410mod sealed {
1411 use crate::{Http, Provider};
1412 pub trait Sealed {}
1414 impl Sealed for Provider<Http> {}
1415}
1416
1417#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
1443#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
1444pub trait ProviderExt: sealed::Sealed {
1445 type Error: Debug;
1447
1448 async fn connect(url: &str) -> Self
1450 where
1451 Self: Sized,
1452 {
1453 Self::try_connect(url).await.unwrap()
1454 }
1455
1456 async fn try_connect(url: &str) -> Result<Self, Self::Error>
1458 where
1459 Self: Sized;
1460
1461 fn for_chain(mut self, chain: impl Into<Chain>) -> Self
1468 where
1469 Self: Sized,
1470 {
1471 self.set_chain(chain);
1472 self
1473 }
1474
1475 fn set_chain(&mut self, chain: impl Into<Chain>) -> &mut Self;
1477}
1478
1479#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
1480#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
1481impl ProviderExt for Provider<HttpProvider> {
1482 type Error = ParseError;
1483
1484 async fn try_connect(url: &str) -> Result<Self, Self::Error>
1485 where
1486 Self: Sized,
1487 {
1488 let mut provider = Provider::try_from(url)?;
1489 if is_local_endpoint(url) {
1490 provider.set_interval(DEFAULT_LOCAL_POLL_INTERVAL);
1491 } else if let Some(chain) =
1492 provider.get_chainid().await.ok().and_then(|id| Chain::try_from(id).ok())
1493 {
1494 provider.set_chain(chain);
1495 }
1496
1497 Ok(provider)
1498 }
1499
1500 fn set_chain(&mut self, chain: impl Into<Chain>) -> &mut Self {
1501 let chain = chain.into();
1502 if let Some(blocktime) = chain.average_blocktime_hint() {
1503 self.set_interval(blocktime / 2);
1505 }
1506 self
1507 }
1508}
1509
1510#[inline]
1526pub fn is_local_endpoint(endpoint: &str) -> bool {
1527 if let Ok(url) = Url::parse(endpoint) {
1528 if let Some(host) = url.host() {
1529 match host {
1530 Host::Domain(domain) => {
1531 return domain.contains("localhost") || domain.contains("localdev.me")
1532 }
1533 Host::Ipv4(ipv4) => {
1534 return ipv4 == Ipv4Addr::LOCALHOST ||
1535 ipv4.is_link_local() ||
1536 ipv4.is_loopback() ||
1537 ipv4.is_private()
1538 }
1539 Host::Ipv6(ipv6) => return ipv6.is_loopback(),
1540 }
1541 }
1542 }
1543 false
1544}
1545
1546#[cfg(test)]
1547mod tests {
1548 use super::*;
1549 use crate::Http;
1550 use ethers_core::{
1551 types::{
1552 transaction::eip2930::AccessList, Eip1559TransactionRequest,
1553 GethDebugBuiltInTracerConfig, GethDebugBuiltInTracerType, GethDebugTracerConfig,
1554 GethDebugTracerType, PreStateConfig,
1555 },
1556 utils::{Anvil, Genesis, Geth, GethInstance},
1557 };
1558 use futures_util::StreamExt;
1559 use std::path::PathBuf;
1560
1561 #[test]
1562 fn convert_h256_u256_quantity() {
1563 let hash: H256 = H256::zero();
1564 let quantity = U256::from_big_endian(hash.as_bytes());
1565 assert_eq!(format!("{quantity:#x}"), "0x0");
1566 assert_eq!(utils::serialize(&quantity).to_string(), "\"0x0\"");
1567
1568 let address: Address = "0x295a70b2de5e3953354a6a8344e616ed314d7251".parse().unwrap();
1569 let block = BlockNumber::Latest;
1570 let params =
1571 [utils::serialize(&address), utils::serialize(&quantity), utils::serialize(&block)];
1572
1573 let params = serde_json::to_string(¶ms).unwrap();
1574 assert_eq!(params, r#"["0x295a70b2de5e3953354a6a8344e616ed314d7251","0x0","latest"]"#);
1575 }
1576
1577 #[tokio::test]
1579 async fn mainnet_resolve_name() {
1580 let provider = crate::test_provider::MAINNET.provider();
1581
1582 let addr = provider.resolve_name("registrar.firefly.eth").await.unwrap();
1583 assert_eq!(addr, "6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap());
1584
1585 provider.resolve_name("asdfasdffads").await.unwrap_err();
1587
1588 provider.resolve_name("asdfasdf.registrar.firefly.eth").await.unwrap_err();
1590 }
1591
1592 #[tokio::test]
1594 async fn mainnet_lookup_address() {
1595 let provider = crate::MAINNET.provider();
1596
1597 let name = provider
1598 .lookup_address("6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap())
1599 .await
1600 .unwrap();
1601
1602 assert_eq!(name, "registrar.firefly.eth");
1603
1604 provider
1605 .lookup_address("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA".parse().unwrap())
1606 .await
1607 .unwrap_err();
1608 }
1609
1610 #[tokio::test]
1611 #[ignore]
1612 async fn mainnet_resolve_avatar() {
1613 let provider = crate::MAINNET.provider();
1614
1615 for (ens_name, res) in &[
1616 ("alisha.eth", "https://ipfs.io/ipfs/QmeQm91kAdPGnUKsE74WvkqYKUeHvc2oHd2FW11V3TrqkQ"),
1618 ("nick.eth", "https://img.seadn.io/files/3ae7be6c41ad4767bf3ecbc0493b4bfb.png"),
1620 ("parishilton.eth", "https://i.imgur.com/YW3Hzph.jpg"),
1622 ("ikehaya-nft.eth", "https://ipfs.io/ipfs/QmdKkwCE8uVhgYd7tWBfhtHdQZDnbNukWJ8bvQmR6nZKsk"),
1624 ("vitalik.eth", "https://ipfs.io/ipfs/QmSP4nq9fnN9dAiCj42ug9Wa79rqmQerZXZch82VqpiH7U/image.gif"),
1626 ("cdixon.eth", "https://ipfs.io/ipfs/QmYA6ZpEARgHvRHZQdFPynMMX8NtdL2JCadvyuyG2oA88u"),
1628 ("0age.eth", "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrIiB2aWV3Qm94PSIwIDAgNTAwIDUwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB4PSIxNTUiIHk9IjYwIiB3aWR0aD0iMTkwIiBoZWlnaHQ9IjM5MCIgZmlsbD0iIzY5ZmYzNyIvPjwvc3ZnPg==")
1629 ] {
1630 println!("Resolving: {ens_name}");
1631 assert_eq!(provider.resolve_avatar(ens_name).await.unwrap(), Url::parse(res).unwrap());
1632 }
1633 }
1634
1635 #[tokio::test]
1636 #[cfg_attr(feature = "celo", ignore)]
1637 async fn test_new_block_filter() {
1638 let num_blocks = 3;
1639 let geth = Anvil::new().block_time(2u64).spawn();
1640 let provider = Provider::<Http>::try_from(geth.endpoint())
1641 .unwrap()
1642 .interval(Duration::from_millis(1000));
1643
1644 let start_block = provider.get_block_number().await.unwrap();
1645
1646 let stream = provider.watch_blocks().await.unwrap().stream();
1647
1648 let hashes: Vec<H256> = stream.take(num_blocks).collect::<Vec<H256>>().await;
1649 for (i, hash) in hashes.iter().enumerate() {
1650 let block = provider.get_block(start_block + i as u64 + 1).await.unwrap().unwrap();
1651 assert_eq!(*hash, block.hash.unwrap());
1652 }
1653 }
1654
1655 #[tokio::test]
1656 async fn test_is_signer() {
1657 use ethers_core::utils::Anvil;
1658 use std::str::FromStr;
1659
1660 let anvil = Anvil::new().spawn();
1661 let provider =
1662 Provider::<Http>::try_from(anvil.endpoint()).unwrap().with_sender(anvil.addresses()[0]);
1663 assert!(provider.is_signer().await);
1664
1665 let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
1666 assert!(!provider.is_signer().await);
1667
1668 let sender = Address::from_str("635B4764D1939DfAcD3a8014726159abC277BecC")
1669 .expect("should be able to parse hex address");
1670 let provider = Provider::<Http>::try_from(
1671 "https://ropsten.infura.io/v3/fd8b88b56aa84f6da87b60f5441d6778",
1672 )
1673 .unwrap()
1674 .with_sender(sender);
1675 assert!(!provider.is_signer().await);
1676 }
1677
1678 #[tokio::test]
1679 async fn test_new_pending_txs_filter() {
1680 let num_txs = 5;
1681
1682 let geth = Anvil::new().block_time(2u64).spawn();
1683 let provider = Provider::<Http>::try_from(geth.endpoint())
1684 .unwrap()
1685 .interval(Duration::from_millis(1000));
1686 let accounts = provider.get_accounts().await.unwrap();
1687
1688 let stream = provider.watch_pending_transactions().await.unwrap().stream();
1689
1690 let mut tx_hashes = Vec::new();
1691 let tx = TransactionRequest::new().from(accounts[0]).to(accounts[0]).value(1e18 as u64);
1692
1693 for _ in 0..num_txs {
1694 tx_hashes.push(provider.send_transaction(tx.clone(), None).await.unwrap());
1695 }
1696
1697 let hashes: Vec<H256> = stream.take(num_txs).collect::<Vec<H256>>().await;
1698 assert_eq!(tx_hashes, hashes);
1699 }
1700
1701 #[tokio::test]
1702 async fn receipt_on_unmined_tx() {
1703 use ethers_core::{
1704 types::TransactionRequest,
1705 utils::{parse_ether, Anvil},
1706 };
1707 let anvil = Anvil::new().block_time(2u64).spawn();
1708 let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
1709
1710 let accounts = provider.get_accounts().await.unwrap();
1711 let tx = TransactionRequest::pay(accounts[0], parse_ether(1u64).unwrap()).from(accounts[0]);
1712 let pending_tx = provider.send_transaction(tx, None).await.unwrap();
1713
1714 assert!(provider.get_transaction_receipt(*pending_tx).await.unwrap().is_none());
1715
1716 let hash = *pending_tx;
1717 let receipt = pending_tx.await.unwrap().unwrap();
1718 assert_eq!(receipt.transaction_hash, hash);
1719 }
1720
1721 #[tokio::test]
1722 async fn parity_block_receipts() {
1723 let url = match std::env::var("PARITY") {
1724 Ok(inner) => inner,
1725 _ => return,
1726 };
1727 let provider = Provider::<Http>::try_from(url.as_str()).unwrap();
1728 let receipts = provider.parity_block_receipts(10657200).await.unwrap();
1729 assert!(!receipts.is_empty());
1730 }
1731
1732 #[tokio::test]
1733 #[ignore]
1734 async fn debug_trace_block() {
1735 let provider = Provider::<Http>::try_from("https://eth.llamarpc.com").unwrap();
1736
1737 let opts = GethDebugTracingOptions {
1738 disable_storage: Some(false),
1739 tracer: Some(GethDebugTracerType::BuiltInTracer(
1740 GethDebugBuiltInTracerType::PreStateTracer,
1741 )),
1742 tracer_config: Some(GethDebugTracerConfig::BuiltInTracer(
1743 GethDebugBuiltInTracerConfig::PreStateTracer(PreStateConfig {
1744 diff_mode: Some(true),
1745 }),
1746 )),
1747 ..Default::default()
1748 };
1749
1750 let latest_block = provider
1751 .get_block(BlockNumber::Latest)
1752 .await
1753 .expect("Failed to fetch latest block.")
1754 .expect("Latest block is none.");
1755
1756 let latest_block_num = BlockNumber::Number(latest_block.number.unwrap());
1758 let traces_by_num = provider
1759 .debug_trace_block_by_number(Some(latest_block_num), opts.clone())
1760 .await
1761 .unwrap();
1762 for trace in &traces_by_num {
1763 assert!(matches!(trace, GethTrace::Known(..)));
1764 }
1765
1766 let latest_block_hash = latest_block.hash.unwrap();
1768 let traces_by_hash =
1769 provider.debug_trace_block_by_hash(latest_block_hash, opts).await.unwrap();
1770 for trace in &traces_by_hash {
1771 assert!(matches!(trace, GethTrace::Known(..)));
1772 }
1773
1774 assert_eq!(traces_by_num, traces_by_hash);
1775 }
1776
1777 #[tokio::test]
1778 #[cfg_attr(feature = "celo", ignore)]
1779 async fn fee_history() {
1780 let provider = Provider::<Http>::try_from(
1781 "https://goerli.infura.io/v3/fd8b88b56aa84f6da87b60f5441d6778",
1782 )
1783 .unwrap();
1784
1785 provider.fee_history(10u64, BlockNumber::Latest, &[10.0, 40.0]).await.unwrap();
1786 }
1787
1788 #[tokio::test]
1789 #[ignore]
1790 #[cfg(feature = "ws")]
1791 async fn test_trace_call_many() {
1792 use ethers_core::types::H160;
1793
1794 let provider = Provider::new(crate::Ws::connect("ws://127.0.0.1:8545").await.unwrap());
1796 provider
1797 .trace_call_many(
1798 vec![
1799 (
1800 TransactionRequest::new()
1801 .from(Address::zero())
1802 .to("0x0000000000000000000000000000000000000001"
1803 .parse::<H160>()
1804 .unwrap())
1805 .value(U256::from(10000000000000000u128)),
1806 vec![TraceType::StateDiff],
1807 ),
1808 (
1809 TransactionRequest::new()
1810 .from(
1811 "0x0000000000000000000000000000000000000001"
1812 .parse::<H160>()
1813 .unwrap(),
1814 )
1815 .to("0x0000000000000000000000000000000000000002"
1816 .parse::<H160>()
1817 .unwrap())
1818 .value(U256::from(10000000000000000u128)),
1819 vec![TraceType::StateDiff],
1820 ),
1821 ],
1822 None,
1823 )
1824 .await
1825 .unwrap();
1826 }
1827
1828 #[tokio::test]
1829 async fn test_fill_transaction_1559() {
1830 let (mut provider, mock) = Provider::mocked();
1831 provider.from = Some("0x6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap());
1832
1833 let gas = U256::from(21000_usize);
1834 let max_fee = U256::from(25_usize);
1835 let prio_fee = U256::from(25_usize);
1836 let access_list: AccessList = vec![Default::default()].into();
1837
1838 let from: Address = "0x0000000000000000000000000000000000000001".parse().unwrap();
1840 let to: Address = "0x0000000000000000000000000000000000000002".parse().unwrap();
1841 let mut tx = Eip1559TransactionRequest::new()
1842 .from(from)
1843 .to(to)
1844 .gas(gas)
1845 .max_fee_per_gas(max_fee)
1846 .max_priority_fee_per_gas(prio_fee)
1847 .access_list(access_list.clone())
1848 .into();
1849 provider.fill_transaction(&mut tx, None).await.unwrap();
1850
1851 assert_eq!(tx.from(), Some(&from));
1852 assert_eq!(tx.to(), Some(&to.into()));
1853 assert_eq!(tx.gas(), Some(&gas));
1854 assert_eq!(tx.gas_price(), Some(max_fee));
1855 assert_eq!(tx.access_list(), Some(&access_list));
1856
1857 let mut tx = Eip1559TransactionRequest::new()
1860 .gas(gas)
1861 .max_fee_per_gas(max_fee)
1862 .max_priority_fee_per_gas(prio_fee)
1863 .into();
1864
1865 provider.fill_transaction(&mut tx, None).await.unwrap();
1866
1867 assert_eq!(tx.from(), provider.from.as_ref());
1868 assert!(tx.to().is_none());
1869 assert_eq!(tx.gas(), Some(&gas));
1870 assert_eq!(tx.access_list(), Some(&Default::default()));
1871
1872 let mut tx = Eip1559TransactionRequest::new()
1874 .max_fee_per_gas(max_fee)
1875 .max_priority_fee_per_gas(prio_fee)
1876 .into();
1877
1878 mock.push(gas).unwrap();
1879
1880 provider.fill_transaction(&mut tx, None).await.unwrap();
1881
1882 assert_eq!(tx.from(), provider.from.as_ref());
1883 assert!(tx.to().is_none());
1884 assert_eq!(tx.gas(), Some(&gas));
1885 assert_eq!(tx.access_list(), Some(&Default::default()));
1886
1887 let mut tx = Eip1559TransactionRequest::new()
1889 .max_fee_per_gas(max_fee)
1890 .max_priority_fee_per_gas(prio_fee)
1891 .into();
1892
1893 mock.push(b'b').unwrap();
1895
1896 let res = provider.fill_transaction(&mut tx, None).await;
1897
1898 assert!(matches!(res, Err(ProviderError::JsonRpcClientError(_))));
1899 }
1900
1901 #[tokio::test]
1902 async fn test_fill_transaction_legacy() {
1903 let (mut provider, mock) = Provider::mocked();
1904 provider.from = Some("0x6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap());
1905
1906 let gas = U256::from(21000_usize);
1907 let gas_price = U256::from(50_usize);
1908
1909 let from: Address = "0x0000000000000000000000000000000000000001".parse().unwrap();
1911 let to: Address = "0x0000000000000000000000000000000000000002".parse().unwrap();
1912 let mut tx =
1913 TransactionRequest::new().from(from).to(to).gas(gas).gas_price(gas_price).into();
1914 provider.fill_transaction(&mut tx, None).await.unwrap();
1915
1916 assert_eq!(tx.from(), Some(&from));
1917 assert_eq!(tx.to(), Some(&to.into()));
1918 assert_eq!(tx.gas(), Some(&gas));
1919 assert_eq!(tx.gas_price(), Some(gas_price));
1920 assert!(tx.access_list().is_none());
1921
1922 let mut tx = TransactionRequest::new().into();
1924 mock.push(gas).unwrap();
1925 mock.push(gas_price).unwrap();
1926 provider.fill_transaction(&mut tx, None).await.unwrap();
1927
1928 assert_eq!(tx.from(), provider.from.as_ref());
1929 assert!(tx.to().is_none());
1930 assert_eq!(tx.gas(), Some(&gas));
1931 assert_eq!(tx.gas_price(), Some(gas_price));
1932 assert!(tx.access_list().is_none());
1933 }
1934
1935 #[tokio::test]
1936 async fn mainnet_lookup_address_invalid_resolver() {
1937 let provider = crate::MAINNET.provider();
1938
1939 let err = provider
1940 .lookup_address("0x30c9223d9e3d23e0af1073a38e0834b055bf68ed".parse().unwrap())
1941 .await
1942 .unwrap_err();
1943
1944 assert_eq!(
1945 &err.to_string(),
1946 "ens name not found: `ox63616e.eth` resolver (0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) is invalid."
1947 );
1948 }
1949
1950 #[tokio::test]
1951 async fn geth_admin_nodeinfo() {
1952 let network = 1337u64;
1954 let dir = tempfile::tempdir().unwrap();
1955
1956 let (geth, provider) =
1957 spawn_geth_and_create_provider(network, Some(dir.path().into()), None);
1958
1959 let info = provider.node_info().await.unwrap();
1960 drop(geth);
1961
1962 assert!(info.protocols.eth.is_some());
1964
1965 assert_eq!(info.protocols.eth.unwrap().network, network);
1967
1968 #[cfg(not(windows))]
1969 dir.close().unwrap();
1970 }
1971
1972 fn spawn_geth_and_create_provider(
1976 chain_id: u64,
1977 datadir: Option<PathBuf>,
1978 genesis: Option<Genesis>,
1979 ) -> (GethInstance, Provider<HttpProvider>) {
1980 let geth = Geth::new().chain_id(chain_id).disable_discovery();
1981
1982 let geth = match genesis {
1983 Some(genesis) => geth.genesis(genesis),
1984 None => geth,
1985 };
1986
1987 let geth = match datadir {
1988 Some(dir) => geth.data_dir(dir),
1989 None => geth,
1990 }
1991 .spawn();
1992
1993 let provider = Provider::try_from(geth.endpoint()).unwrap();
1994 (geth, provider)
1995 }
1996
1997 fn spawn_geth_instances<const N: usize>(
2001 datadirs: [PathBuf; N],
2002 chain_id: u64,
2003 genesis: Option<Genesis>,
2004 ) -> [(GethInstance, Provider<HttpProvider>); N] {
2005 datadirs.map(|dir| spawn_geth_and_create_provider(chain_id, Some(dir), genesis.clone()))
2006 }
2007
2008 #[tokio::test]
2009 #[cfg_attr(windows, ignore = "cannot spawn multiple geth instances")]
2010 async fn add_second_geth_peer() {
2011 let dir1 = tempfile::tempdir().unwrap();
2013 let dir2 = tempfile::tempdir().unwrap();
2014
2015 let genesis = utils::Genesis::default();
2017
2018 let [(mut first_geth, first_peer), (second_geth, second_peer)] =
2020 spawn_geth_instances([dir1.path().into(), dir2.path().into()], 1337, Some(genesis));
2021
2022 let first_info = first_peer.node_info().await.unwrap();
2024 let second_info = second_peer.node_info().await.unwrap();
2025 let first_port = first_info.ports.listener;
2026
2027 let first_prefix = first_info.enode.split('@').collect::<Vec<&str>>();
2029
2030 let first_enode = format!("{}@localhost:{}", first_prefix.first().unwrap(), first_port);
2032
2033 let res = second_peer.add_peer(first_enode).await.unwrap();
2035 assert!(res);
2036
2037 first_geth.wait_to_add_peer(second_info.id).unwrap();
2039
2040 let peers = first_peer.peers().await.unwrap();
2042
2043 drop(first_geth);
2044 drop(second_geth);
2045
2046 assert_eq!(peers.len(), 1);
2048
2049 let peer = peers.first().unwrap();
2050 assert_eq!(H256::from_str(&peer.id).unwrap(), second_info.id);
2051
2052 #[cfg(not(windows))]
2054 {
2055 dir1.close().unwrap();
2056 dir2.close().unwrap();
2057 }
2058 }
2059}