feat: rotating infura keys (#1017)
* feat: add providers which rotate api keys * test: use rotating key in provider instead of hardcoded * chore: fmt
This commit is contained in:
parent
367f3444ec
commit
ae125bcfc7
|
@ -1322,6 +1322,7 @@ dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"http",
|
"http",
|
||||||
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
|
|
@ -4,14 +4,11 @@
|
||||||
async fn nonce_manager() {
|
async fn nonce_manager() {
|
||||||
use ethers_core::types::*;
|
use ethers_core::types::*;
|
||||||
use ethers_middleware::{nonce_manager::NonceManagerMiddleware, signer::SignerMiddleware};
|
use ethers_middleware::{nonce_manager::NonceManagerMiddleware, signer::SignerMiddleware};
|
||||||
use ethers_providers::{Http, Middleware, Provider};
|
use ethers_providers::Middleware;
|
||||||
use ethers_signers::{LocalWallet, Signer};
|
use ethers_signers::{LocalWallet, Signer};
|
||||||
use std::{convert::TryFrom, time::Duration};
|
use std::time::Duration;
|
||||||
|
|
||||||
let provider =
|
let provider = ethers_providers::RINKEBY.provider().interval(Duration::from_millis(2000u64));
|
||||||
Provider::<Http>::try_from("https://rinkeby.infura.io/v3/fd8b88b56aa84f6da87b60f5441d6778")
|
|
||||||
.unwrap()
|
|
||||||
.interval(Duration::from_millis(2000u64));
|
|
||||||
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||||
|
|
||||||
let wallet = std::env::var("RINKEBY_PRIVATE_KEY")
|
let wallet = std::env::var("RINKEBY_PRIVATE_KEY")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use ethers_providers::{Http, JsonRpcClient, Middleware, Provider};
|
use ethers_providers::{Http, JsonRpcClient, Middleware, Provider, RINKEBY};
|
||||||
|
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::{BlockNumber, TransactionRequest},
|
types::{BlockNumber, TransactionRequest},
|
||||||
|
@ -8,7 +8,7 @@ use ethers_core::{
|
||||||
use ethers_middleware::signer::SignerMiddleware;
|
use ethers_middleware::signer::SignerMiddleware;
|
||||||
use ethers_signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer};
|
use ethers_signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer};
|
||||||
use once_cell::sync::Lazy;
|
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(|| {
|
static WALLETS: Lazy<TestWallets> = Lazy::new(|| {
|
||||||
TestWallets {
|
TestWallets {
|
||||||
|
@ -54,10 +54,7 @@ async fn send_eth() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
async fn pending_txs_with_confirmations_testnet() {
|
async fn pending_txs_with_confirmations_testnet() {
|
||||||
let provider =
|
let provider = RINKEBY.provider().interval(Duration::from_millis(3000));
|
||||||
Provider::<Http>::try_from("https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
|
||||||
.unwrap()
|
|
||||||
.interval(Duration::from_millis(3000));
|
|
||||||
let chain_id = provider.get_chainid().await.unwrap();
|
let chain_id = provider.get_chainid().await.unwrap();
|
||||||
let wallet = WALLETS.next().with_chain_id(chain_id.as_u64());
|
let wallet = WALLETS.next().with_chain_id(chain_id.as_u64());
|
||||||
let address = wallet.address();
|
let address = wallet.address();
|
||||||
|
@ -97,9 +94,7 @@ async fn generic_pending_txs_test<M: Middleware>(provider: M, who: Address) {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
async fn typed_txs() {
|
async fn typed_txs() {
|
||||||
let provider =
|
let provider = RINKEBY.provider();
|
||||||
Provider::<Http>::try_from("https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let chain_id = provider.get_chainid().await.unwrap();
|
let chain_id = provider.get_chainid().await.unwrap();
|
||||||
let wallet = WALLETS.next().with_chain_id(chain_id.as_u64());
|
let wallet = WALLETS.next().with_chain_id(chain_id.as_u64());
|
||||||
|
|
|
@ -39,6 +39,7 @@ tracing = { version = "0.1.32", default-features = false }
|
||||||
tracing-futures = { version = "0.2.5", default-features = false, features = ["std-future"] }
|
tracing-futures = { version = "0.2.5", default-features = false, features = ["std-future"] }
|
||||||
|
|
||||||
bytes = { version = "1.1.0", default-features = false, optional = true }
|
bytes = { version = "1.1.0", default-features = false, optional = true }
|
||||||
|
once_cell = "1.10.0"
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
# tokio
|
# tokio
|
||||||
|
|
|
@ -657,3 +657,53 @@ pub trait CeloMiddleware: Middleware {
|
||||||
self.provider().get_validators_bls_public_keys(block_id).await.map_err(FromErr::from)
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1488,12 +1488,10 @@ mod tests {
|
||||||
};
|
};
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
const INFURA: &str = "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27";
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
|
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
|
||||||
async fn mainnet_resolve_name() {
|
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();
|
let addr = provider.resolve_name("registrar.firefly.eth").await.unwrap();
|
||||||
assert_eq!(addr, "6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap());
|
assert_eq!(addr, "6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap());
|
||||||
|
@ -1508,7 +1506,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
|
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
|
||||||
async fn mainnet_lookup_address() {
|
async fn mainnet_lookup_address() {
|
||||||
let provider = Provider::<HttpProvider>::try_from(INFURA).unwrap();
|
let provider = crate::MAINNET.provider();
|
||||||
|
|
||||||
let name = provider
|
let name = provider
|
||||||
.lookup_address("6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap())
|
.lookup_address("6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap())
|
||||||
|
@ -1525,7 +1523,7 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn mainnet_resolve_avatar() {
|
async fn mainnet_resolve_avatar() {
|
||||||
let provider = Provider::<HttpProvider>::try_from(INFURA).unwrap();
|
let provider = crate::MAINNET.provider();
|
||||||
|
|
||||||
for (ens_name, res) in &[
|
for (ens_name, res) in &[
|
||||||
// HTTPS
|
// HTTPS
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
use ethers_providers::{Http, Middleware, Provider};
|
use ethers_providers::{Http, Middleware, Provider, RINKEBY};
|
||||||
use std::{convert::TryFrom, time::Duration};
|
use std::{convert::TryFrom, time::Duration};
|
||||||
|
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
|
@ -12,10 +12,7 @@ mod eth_tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn non_existing_data_works() {
|
async fn non_existing_data_works() {
|
||||||
let provider = Provider::<Http>::try_from(
|
let provider = RINKEBY.provider();
|
||||||
"https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert!(provider.get_transaction(H256::zero()).await.unwrap().is_none());
|
assert!(provider.get_transaction(H256::zero()).await.unwrap().is_none());
|
||||||
assert!(provider.get_transaction_receipt(H256::zero()).await.unwrap().is_none());
|
assert!(provider.get_transaction_receipt(H256::zero()).await.unwrap().is_none());
|
||||||
|
@ -25,10 +22,7 @@ mod eth_tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn client_version() {
|
async fn client_version() {
|
||||||
let provider = Provider::<Http>::try_from(
|
let provider = RINKEBY.provider();
|
||||||
"https://rinkeby.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// e.g., Geth/v1.10.6-omnibus-1af33248/linux-amd64/go1.16.6
|
// e.g., Geth/v1.10.6-omnibus-1af33248/linux-amd64/go1.16.6
|
||||||
assert!(provider
|
assert!(provider
|
||||||
|
@ -95,10 +89,7 @@ mod eth_tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn eip1559_fee_estimation() {
|
async fn eip1559_fee_estimation() {
|
||||||
let provider = Provider::<Http>::try_from(
|
let provider = ethers_providers::MAINNET.provider();
|
||||||
"https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (_max_fee_per_gas, _max_priority_fee_per_gas) =
|
let (_max_fee_per_gas, _max_priority_fee_per_gas) =
|
||||||
provider.estimate_eip1559_fees(None).await.unwrap();
|
provider.estimate_eip1559_fees(None).await.unwrap();
|
||||||
|
|
Loading…
Reference in New Issue