Skip to content
This repository has been archived by the owner on Oct 19, 2024. It is now read-only.

feat: rotating infura keys #1017

Merged
merged 3 commits into from
Mar 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions ethers-middleware/tests/nonce_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
async fn nonce_manager() {
use ethers_core::types::*;
use ethers_middleware::{nonce_manager::NonceManagerMiddleware, signer::SignerMiddleware};
use ethers_providers::{Http, Middleware, Provider};
use ethers_providers::Middleware;
use ethers_signers::{LocalWallet, Signer};
use std::{convert::TryFrom, time::Duration};
use std::time::Duration;

let provider =
Provider::<Http>::try_from("https://rinkeby.infura.io/v3/fd8b88b56aa84f6da87b60f5441d6778")
.unwrap()
.interval(Duration::from_millis(2000u64));
let provider = ethers_providers::RINKEBY.provider().interval(Duration::from_millis(2000u64));
let chain_id = provider.get_chainid().await.unwrap().as_u64();

let wallet = std::env::var("RINKEBY_PRIVATE_KEY")
Expand Down
13 changes: 4 additions & 9 deletions ethers-middleware/tests/signer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![allow(unused)]
use ethers_providers::{Http, JsonRpcClient, Middleware, Provider};
use ethers_providers::{Http, JsonRpcClient, Middleware, Provider, RINKEBY};

use ethers_core::{
types::{BlockNumber, TransactionRequest},
Expand All @@ -8,7 +8,7 @@ use ethers_core::{
use ethers_middleware::signer::SignerMiddleware;
use ethers_signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer};
use once_cell::sync::Lazy;
use std::{convert::TryFrom, sync::atomic::AtomicU8, time::Duration};
use std::{convert::TryFrom, iter::Cycle, sync::atomic::AtomicU8, time::Duration};

static WALLETS: Lazy<TestWallets> = Lazy::new(|| {
TestWallets {
Expand Down Expand Up @@ -54,10 +54,7 @@ async fn send_eth() {
#[tokio::test]
#[cfg(not(feature = "celo"))]
async fn pending_txs_with_confirmations_testnet() {
let provider =
Provider::<Http>::try_from("https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
.unwrap()
.interval(Duration::from_millis(3000));
let provider = RINKEBY.provider().interval(Duration::from_millis(3000));
let chain_id = provider.get_chainid().await.unwrap();
let wallet = WALLETS.next().with_chain_id(chain_id.as_u64());
let address = wallet.address();
Expand Down Expand Up @@ -97,9 +94,7 @@ async fn generic_pending_txs_test<M: Middleware>(provider: M, who: Address) {
#[tokio::test]
#[cfg(not(feature = "celo"))]
async fn typed_txs() {
let provider =
Provider::<Http>::try_from("https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
.unwrap();
let provider = RINKEBY.provider();

let chain_id = provider.get_chainid().await.unwrap();
let wallet = WALLETS.next().with_chain_id(chain_id.as_u64());
Expand Down
1 change: 1 addition & 0 deletions ethers-providers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ tracing = { version = "0.1.32", default-features = false }
tracing-futures = { version = "0.2.5", default-features = false, features = ["std-future"] }

bytes = { version = "1.1.0", default-features = false, optional = true }
once_cell = "1.10.0"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
# tokio
Expand Down
50 changes: 50 additions & 0 deletions ethers-providers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,3 +657,53 @@ pub trait CeloMiddleware: Middleware {
self.provider().get_validators_bls_public_keys(block_id).await.map_err(FromErr::from)
}
}

pub use test_provider::{GOERLI, MAINNET, RINKEBY, ROPSTEN};

/// Pre-instantiated Infura HTTP clients which rotate through multiple API keys
/// to prevent rate limits
pub mod test_provider {
use super::*;
use crate::Http;
use once_cell::sync::Lazy;
use std::{convert::TryFrom, iter::Cycle, slice::Iter, sync::Mutex};

// List of infura keys to rotate through so we don't get rate limited
const INFURA_KEYS: &[&str] = &[
"6770454bc6ea42c58aac12978531b93f",
"7a8769b798b642f6933f2ed52042bd70",
"631fd9a6539644088297dc605d35fff3",
"16a8be88795540b9b3903d8de0f7baa5",
"f4a0bdad42674adab5fc0ac077ffab2b",
"5c812e02193c4ba793f8c214317582bd",
];

pub static RINKEBY: Lazy<TestProvider> =
Lazy::new(|| TestProvider::new(INFURA_KEYS, "rinkeby"));
pub static MAINNET: Lazy<TestProvider> =
Lazy::new(|| TestProvider::new(INFURA_KEYS, "mainnet"));
pub static GOERLI: Lazy<TestProvider> = Lazy::new(|| TestProvider::new(INFURA_KEYS, "goerli"));
pub static ROPSTEN: Lazy<TestProvider> =
Lazy::new(|| TestProvider::new(INFURA_KEYS, "ropsten"));

#[derive(Debug)]
pub struct TestProvider {
network: String,
keys: Mutex<Cycle<Iter<'static, &'static str>>>,
}

impl TestProvider {
pub fn new(keys: &'static [&'static str], network: &str) -> Self {
Self { keys: Mutex::new(keys.iter().cycle()), network: network.to_owned() }
}

pub fn provider(&self) -> Provider<Http> {
let url = format!(
"https://{}.infura.io/v3/{}",
self.network,
self.keys.lock().unwrap().next().unwrap()
);
Provider::try_from(url.as_str()).unwrap()
}
}
}
8 changes: 3 additions & 5 deletions ethers-providers/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1488,12 +1488,10 @@ mod tests {
};
use futures_util::StreamExt;

const INFURA: &str = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27";

#[tokio::test]
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
async fn mainnet_resolve_name() {
let provider = Provider::<HttpProvider>::try_from(INFURA).unwrap();
let provider = crate::test_provider::MAINNET.provider();

let addr = provider.resolve_name("registrar.firefly.eth").await.unwrap();
assert_eq!(addr, "6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap());
Expand All @@ -1508,7 +1506,7 @@ mod tests {
#[tokio::test]
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
async fn mainnet_lookup_address() {
let provider = Provider::<HttpProvider>::try_from(INFURA).unwrap();
let provider = crate::MAINNET.provider();

let name = provider
.lookup_address("6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap())
Expand All @@ -1525,7 +1523,7 @@ mod tests {

#[tokio::test]
async fn mainnet_resolve_avatar() {
let provider = Provider::<HttpProvider>::try_from(INFURA).unwrap();
let provider = crate::MAINNET.provider();

for (ens_name, res) in &[
// HTTPS
Expand Down
17 changes: 4 additions & 13 deletions ethers-providers/tests/provider.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#![cfg(not(target_arch = "wasm32"))]
use ethers_providers::{Http, Middleware, Provider};
use ethers_providers::{Http, Middleware, Provider, RINKEBY};
use std::{convert::TryFrom, time::Duration};

#[cfg(not(feature = "celo"))]
Expand All @@ -12,10 +12,7 @@ mod eth_tests {

#[tokio::test]
async fn non_existing_data_works() {
let provider = Provider::<Http>::try_from(
"https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
)
.unwrap();
let provider = RINKEBY.provider();

assert!(provider.get_transaction(H256::zero()).await.unwrap().is_none());
assert!(provider.get_transaction_receipt(H256::zero()).await.unwrap().is_none());
Expand All @@ -25,10 +22,7 @@ mod eth_tests {

#[tokio::test]
async fn client_version() {
let provider = Provider::<Http>::try_from(
"https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
)
.unwrap();
let provider = RINKEBY.provider();

// e.g., Geth/v1.10.6-omnibus-1af33248/linux-amd64/go1.16.6
assert!(provider
Expand Down Expand Up @@ -95,10 +89,7 @@ mod eth_tests {

#[tokio::test]
async fn eip1559_fee_estimation() {
let provider = Provider::<Http>::try_from(
"https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
)
.unwrap();
let provider = ethers_providers::MAINNET.provider();

let (_max_fee_per_gas, _max_priority_fee_per_gas) =
provider.estimate_eip1559_fees(None).await.unwrap();
Expand Down