test: replace ganache with anvil (#1286)

* ci: install anvil

* test: use anvil instead of ganache

* ci: fix anvil ver

* ci: re-enable example tests

* test: remove unnecessary assertions

* test: enable anvil launch test

* docs: typo

* test: fix anvil chain id

* ci: install ganache

Ganache is needed for the Ganache tests

* chore: remove legacy feature from some examples

* ci: correctly build examples

* test: use correct account balance for anvil

* chore: remove sub_id == 1 check

this was only possible in ganache because it gives serial
sub ids, but in every other reasonable client the ids are generated
randomly, so we cannot test for its value

* test: ensure txs are different

There is a bug in Ganache's mempool which accepts duplicate transactions (here with the same nonce), whereas here we pre-set all the nonces so that they end up having a different transaction hash.

* test: ignore ganache tests

* fix: terzor api changes

* ci(examples): install Anvil, remove geth/ganache

* test(provider): Anvil instead of Geth

some tests start to fail now

* fix: revert usage of Anvil in ipc tests

Anvil does not support IPC yet

* fix: update examples script

* ci: use anvil for wasm example

* replace last ganache usage

Co-authored-by: Oliver Nordbjerg <hi@notbjerg.me>
Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
This commit is contained in:
Matthias Seitz 2022-06-01 17:22:39 +02:00 committed by GitHub
parent 1a699ad72e
commit 89bc6420bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 306 additions and 296 deletions

View File

@ -21,12 +21,10 @@ jobs:
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Set up node
uses: actions/setup-node@v1
- name: Install Anvil
uses: foundry-rs/foundry-toolchain@v1
with:
node-version: 10
- name: Install ganache
run: npm install -g ganache
version: nightly
- name: Install Solc
run: |
mkdir -p "$HOME/bin"
@ -66,13 +64,11 @@ jobs:
steps:
- name: Checkout sources
uses: actions/checkout@v2
- name: Set up node
uses: actions/setup-node@v1
with:
node-version: 10
# TODO: can we combine these shared steps in github actions?
- name: Install ganache
run: npm install -g ganache
- name: Install Anvil
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- name: Install Solc
run: |
mkdir -p "$HOME/bin"
@ -133,12 +129,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install node
uses: actions/setup-node@v1
with:
node-version: 10
- name: Checkout sources
uses: actions/checkout@v2
- name: Install rust
uses: actions-rs/toolchain@v1
with:
@ -147,6 +139,11 @@ jobs:
profile: minimal
override: true
- name: Install Anvil
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- uses: Swatinem/rust-cache@v1
with:
cache-on-failure: true
@ -157,11 +154,8 @@ jobs:
command: check
args: --target wasm32-unknown-unknown
- name: Launch Ganache
run: |
cd examples/ethers-wasm
npm install
npm run ganache &
- name: Launch Anvil
run: anvil --block-time 2 -m "stuff inherit faith park genre spread huge knee ecology private marble supreme" &
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
@ -176,59 +170,66 @@ jobs:
cd examples/ethers-wasm
wasm-pack test --headless --chrome
# TODO: Re-enable once we figure out why examples are running forever.
# examples:
# name: Examples
# runs-on: ubuntu-latest
# steps:
# - name: Checkout sources
# uses: actions/checkout@v2
# - name: Set up node
# uses: actions/setup-node@v1
# with:
# node-version: 10
# - name: Install ganache
# run: npm install -g ganache
# - name: Install Solc
# run: |
# mkdir -p "$HOME/bin"
# wget -q https://github.com/ethereum/solidity/releases/download/v0.8.10/solc-static-linux -O $HOME/bin/solc
# chmod u+x "$HOME/bin/solc"
# export PATH=$HOME/bin:$PATH
# solc --version
examples:
name: Examples
runs-on: ubuntu-latest
steps:
- name: Checkout sources
uses: actions/checkout@v2
# - name: Install geth
# run: |
# mkdir -p "$HOME/bin"
# wget -q https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.23-8c2f2715.tar.gz
# tar -xvf geth-linux-amd64-1.9.23-8c2f2715.tar.gz
# mv geth-linux-amd64-1.9.23-8c2f2715/geth $HOME/bin/geth
# chmod u+x "$HOME/bin/geth"
# export PATH=$HOME/bin:$PATH
# geth version
# - name: Install stable toolchain
# uses: actions-rs/toolchain@v1
# with:
# profile: minimal
# toolchain: stable
# override: true
# components: rustfmt, clippy
# - uses: Swatinem/rust-cache@v1
# with:
# cache-on-failure: true
# - name: Build all examples
# run: |
# export PATH=$HOME/bin:$PATH
# for file in examples/*.rs; do
# name="$(echo "$file" | cut -f 1 -d '.')"
# echo "building $name"
# cargo build -p ethers --example "$(basename "$name")"
# done
# - name: Run all examples
# run: |
# export PATH=$HOME/bin:$PATH
# chmod +x ./scripts/examples.sh
# ./scripts/examples.sh
- name: Install Anvil
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
- name: Install Solc
run: |
mkdir -p "$HOME/bin"
wget -q https://github.com/ethereum/solidity/releases/download/v0.8.10/solc-static-linux -O $HOME/bin/solc
chmod u+x "$HOME/bin/solc"
export PATH=$HOME/bin:$PATH
solc --version
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v1
with:
cache-on-failure: true
- name: Build all examples
run: |
export PATH=$HOME/bin:$PATH
examples=$(cargo metadata --format-version 1 | \
jq -c '.packages[]
| select(.name == "ethers")
| .targets[]
| select(.kind[] | contains("example"))
| with_entries(select([.key]
| inside(["name", "required-features"])))'
)
for example in $examples; do
name="$(echo "$example" | jq -r '.name')"
args=(
-p ethers
--example "$name"
)
features="$(echo "$example" | jq -r 'try(."required-features" | join(","))')"
if [[ ! -z "$features" ]]; then
args+=(--features "$features")
fi
echo "building $name"
cargo build "${args[@]}"
done
- name: Run all examples
run: |
export PATH=$HOME/bin:$PATH
chmod +x ./scripts/examples.sh
./scripts/examples.sh
windows-build:
runs-on: windows-latest

View File

@ -115,17 +115,14 @@ opt-level = "s"
[[example]]
name = "contract_human_readable"
path = "examples/contract_human_readable.rs"
required-features = ["legacy"]
[[example]]
name = "contract_with_abi"
path = "examples/contract_with_abi.rs"
required-features = ["legacy"]
[[example]]
name = "contract_with_abi_and_bytecode"
path = "examples/contract_with_abi_and_bytecode.rs"
required-features = ["legacy"]
[[example]]
name = "ipc"
@ -151,3 +148,8 @@ required-features = ["trezor"]
name = "yubi"
path = "examples/yubi.rs"
required-features = ["yubi"]
[[example]]
name = "paginated_logs"
path = "examples/paginated_logs.rs"
required-features = ["rustls"]

View File

@ -32,7 +32,7 @@ ethers = { git = "https://github.com/gakonst/ethers-rs" }
Tests require the following installed:
1. [`solc`](https://solidity.readthedocs.io/en/latest/installing-solidity.html) (>=0.8.10). We also recommend using [solc-select](https://github.com/crytic/solc-select) for more flexibility.
2. [`ganache-cli`](https://github.com/trufflesuite/ganache-cli#installation)
2. [`anvil`](https://github.com/foundry-rs/foundry/blob/master/anvil/README.md)
3. [`geth`](https://github.com/ethereum/go-ethereum)
In addition, it is recommended that you set the `ETHERSCAN_API_KEY` environment variable

View File

@ -4,7 +4,7 @@ use ethers_contract::{abigen, EthCall, EthEvent};
use ethers_core::{
abi::{AbiDecode, AbiEncode, Address, Tokenizable},
types::{transaction::eip2718::TypedTransaction, Eip1559TransactionRequest, U256},
utils::Ganache,
utils::Anvil,
};
use ethers_middleware::SignerMiddleware;
use ethers_providers::{MockProvider, Provider};
@ -305,10 +305,10 @@ async fn can_handle_underscore_functions() {
"ethers-contract/tests/solidity-contracts/simplestorage_abi.json",
);
// launcht the network & connect to it
let ganache = ethers_core::utils::Ganache::new().spawn();
let from = ganache.addresses()[0];
let provider = Provider::try_from(ganache.endpoint())
// launch the network & connect to it
let anvil = Anvil::new().spawn();
let from = anvil.addresses()[0];
let provider = Provider::try_from(anvil.endpoint())
.unwrap()
.with_sender(from)
.interval(std::time::Duration::from_millis(10));
@ -484,9 +484,9 @@ fn can_handle_case_sensitive_calls() {
#[tokio::test]
async fn can_deploy_greeter() {
abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter.json",);
let ganache = ethers_core::utils::Ganache::new().spawn();
let from = ganache.addresses()[0];
let provider = Provider::try_from(ganache.endpoint())
let anvil = Anvil::new().spawn();
let from = anvil.addresses()[0];
let provider = Provider::try_from(anvil.endpoint())
.unwrap()
.with_sender(from)
.interval(std::time::Duration::from_millis(10));
@ -502,9 +502,9 @@ async fn can_deploy_greeter() {
#[tokio::test]
async fn can_abiencoderv2_output() {
abigen!(AbiEncoderv2Test, "ethers-contract/tests/solidity-contracts/abiencoderv2test_abi.json",);
let ganache = ethers_core::utils::Ganache::new().spawn();
let from = ganache.addresses()[0];
let provider = Provider::try_from(ganache.endpoint())
let anvil = Anvil::new().spawn();
let from = anvil.addresses()[0];
let provider = Provider::try_from(anvil.endpoint())
.unwrap()
.with_sender(from)
.interval(std::time::Duration::from_millis(10));
@ -575,7 +575,7 @@ fn can_handle_overloaded_events() {
async fn can_send_struct_param() {
abigen!(StructContract, "./tests/solidity-contracts/StructContract.json");
let server = Ganache::default().spawn();
let server = Anvil::new().spawn();
let wallet: LocalWallet = server.keys()[0].clone().into();
let provider = Provider::try_from(server.endpoint()).unwrap();
let client = Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(1337u64)));

View File

@ -10,7 +10,7 @@ use ethers_contract::EthEvent;
mod derive;
use ethers_contract::{Contract, ContractFactory};
use ethers_core::{abi::Abi, types::Bytes, utils::GanacheInstance};
use ethers_core::{abi::Abi, types::Bytes, utils::AnvilInstance};
use ethers_providers::{Http, Middleware, Provider};
use ethers_solc::Solc;
use std::{convert::TryFrom, sync::Arc, time::Duration};
@ -38,16 +38,16 @@ pub fn compile_contract(name: &str, filename: &str) -> (Abi, Bytes) {
}
/// connects the private key to http://localhost:8545
pub fn connect(ganache: &GanacheInstance, idx: usize) -> Arc<Provider<Http>> {
let sender = ganache.addresses()[idx];
let provider = Provider::<Http>::try_from(ganache.endpoint())
pub fn connect(anvil: &AnvilInstance, idx: usize) -> Arc<Provider<Http>> {
let sender = anvil.addresses()[idx];
let provider = Provider::<Http>::try_from(anvil.endpoint())
.unwrap()
.interval(Duration::from_millis(10u64))
.with_sender(sender);
Arc::new(provider)
}
/// Launches a ganache instance and deploys the SimpleStorage contract
/// Launches a Anvil instance and deploys the SimpleStorage contract
pub async fn deploy<M: Middleware>(client: Arc<M>, abi: Abi, bytecode: Bytes) -> Contract<M> {
let factory = ContractFactory::new(abi, bytecode, client);
let deployer = factory.deploy("initial value".to_string()).unwrap();

View File

@ -11,7 +11,7 @@ mod eth_tests {
use ethers_core::{
abi::{Detokenize, Token, Tokenizable},
types::{transaction::eip712::Eip712, Address, BlockId, Bytes, I256, U256},
utils::{keccak256, Ganache},
utils::{keccak256, Anvil},
};
use ethers_derive_eip712::*;
use ethers_middleware::signer::SignerMiddleware;
@ -23,15 +23,15 @@ mod eth_tests {
async fn deploy_and_call_contract() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
// launch ganache
let ganache = Ganache::new().spawn();
// launch anvil
let anvil = Anvil::new().spawn();
// Instantiate the clients. We assume that clients consume the provider and the wallet
// (which makes sense), so for multi-client tests, you must clone the provider.
let addrs = ganache.addresses().to_vec();
let addrs = anvil.addresses().to_vec();
let addr2 = addrs[1];
let client = connect(&ganache, 0);
let client2 = connect(&ganache, 1);
let client = connect(&anvil, 0);
let client2 = connect(&anvil, 1);
// create a factory which will be used to deploy instances of the contract
let factory = ContractFactory::new(abi, bytecode, client.clone());
@ -97,8 +97,8 @@ mod eth_tests {
#[cfg(feature = "abigen")]
async fn get_past_events() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
let ganache = Ganache::new().spawn();
let client = connect(&ganache, 0);
let anvil = Anvil::new().spawn();
let client = connect(&anvil, 0);
let address = client.get_accounts().await.unwrap()[0];
let contract = deploy(client.clone(), abi, bytecode).await;
@ -136,9 +136,9 @@ mod eth_tests {
#[cfg(feature = "abigen")]
async fn get_events_with_meta() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
let ganache = Ganache::new().spawn();
let client = connect(&ganache, 0);
let address = ganache.addresses()[0];
let anvil = Anvil::new().spawn();
let client = connect(&anvil, 0);
let address = anvil.addresses()[0];
let contract = deploy(client.clone(), abi, bytecode).await;
// and we can fetch the events
@ -168,8 +168,8 @@ mod eth_tests {
#[tokio::test]
async fn call_past_state() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
let ganache = Ganache::new().spawn();
let client = connect(&ganache, 0);
let anvil = Anvil::new().spawn();
let client = connect(&anvil, 0);
let contract = deploy(client.clone(), abi, bytecode).await;
let deployed_block = client.get_block_number().await.unwrap();
@ -257,24 +257,21 @@ mod eth_tests {
#[cfg(feature = "abigen")]
async fn watch_events() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
let ganache = Ganache::new().spawn();
let client = connect(&ganache, 0);
let anvil = Anvil::new().spawn();
let client = connect(&anvil, 0);
let contract = deploy(client.clone(), abi.clone(), bytecode).await;
// We spawn the event listener:
let event = contract.event::<ValueChanged>();
let mut stream = event.stream().await.unwrap();
assert_eq!(stream.id, 1.into());
// Also set up a subscription for the same thing
let ws = Provider::connect(ganache.ws_endpoint()).await.unwrap();
let ws = Provider::connect(anvil.ws_endpoint()).await.unwrap();
let contract2 = ethers_contract::Contract::new(contract.address(), abi, ws);
let event2 = contract2.event::<ValueChanged>();
let mut subscription = event2.subscribe().await.unwrap();
assert_eq!(subscription.id, 2.into());
let mut subscription_meta = event2.subscribe().await.unwrap().with_meta();
assert_eq!(subscription_meta.0.id, 3.into());
let num_calls = 3u64;
@ -303,12 +300,12 @@ mod eth_tests {
#[tokio::test]
async fn watch_subscription_events_multiple_addresses() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
let ganache = Ganache::new().spawn();
let client = connect(&ganache, 0);
let anvil = Anvil::new().spawn();
let client = connect(&anvil, 0);
let contract_1 = deploy(client.clone(), abi.clone(), bytecode.clone()).await;
let contract_2 = deploy(client.clone(), abi.clone(), bytecode).await;
let ws = Provider::connect(ganache.ws_endpoint()).await.unwrap();
let ws = Provider::connect(anvil.ws_endpoint()).await.unwrap();
let filter = Filter::new()
.address(ValueOrArray::Array(vec![contract_1.address(), contract_2.address()]));
let mut stream = ws.subscribe_logs(&filter).await.unwrap();
@ -332,11 +329,11 @@ mod eth_tests {
#[tokio::test]
async fn signer_on_node() {
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
// spawn ganache
let ganache = Ganache::new().spawn();
// spawn anvil
let anvil = Anvil::new().spawn();
// connect
let provider = Provider::<Http>::try_from(ganache.endpoint())
let provider = Provider::<Http>::try_from(anvil.endpoint())
.unwrap()
.interval(std::time::Duration::from_millis(50u64));
@ -373,9 +370,8 @@ mod eth_tests {
// get ABI and bytecode for the SimpleStorage contract
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
// launch ganache
// some tests expect 100 ether (-e === --wallet.defaultBalance in ether)
let ganache = Ganache::new().arg("-e").arg("100").spawn();
// launch anvil
let anvil = Anvil::new().spawn();
// Instantiate the clients. We assume that clients consume the provider and the wallet
// (which makes sense), so for multi-client tests, you must clone the provider.
@ -383,13 +379,13 @@ mod eth_tests {
// `client2` is used to deploy the first SimpleStorage contract
// `client3` is used to deploy the second SimpleStorage contract
// `client4` is used to make the aggregate call
let addrs = ganache.addresses().to_vec();
let addrs = anvil.addresses().to_vec();
let addr2 = addrs[1];
let addr3 = addrs[2];
let client = connect(&ganache, 0);
let client2 = connect(&ganache, 1);
let client3 = connect(&ganache, 2);
let client4 = connect(&ganache, 3);
let client = connect(&anvil, 0);
let client2 = connect(&anvil, 1);
let client3 = connect(&anvil, 2);
let client4 = connect(&anvil, 3);
// create a factory which will be used to deploy instances of the contract
let multicall_factory =
@ -491,7 +487,7 @@ mod eth_tests {
assert_eq!(return_data.2, multicall_contract.address());
assert_eq!(return_data.3, multicall_contract.address());
let addrs = ganache.addresses();
let addrs = anvil.addresses();
// query ETH balances of multiple addresses
// these keys haven't been used to do any tx
// so should have 100 ETH
@ -502,9 +498,9 @@ mod eth_tests {
.eth_balance_of(addrs[6]);
let balances: (U256, U256, U256) = multicall.call().await.unwrap();
assert_eq!(balances.0, U256::from(100_000_000_000_000_000_000u128));
assert_eq!(balances.1, U256::from(100_000_000_000_000_000_000u128));
assert_eq!(balances.2, U256::from(100_000_000_000_000_000_000u128));
assert_eq!(balances.0, U256::from(10_000_000_000_000_000_000_000u128));
assert_eq!(balances.1, U256::from(10_000_000_000_000_000_000_000u128));
assert_eq!(balances.2, U256::from(10_000_000_000_000_000_000_000u128));
// clear multicall so we can test `call_raw` w/ >16 calls
multicall.clear_calls();
@ -569,13 +565,13 @@ mod eth_tests {
// get ABI and bytecode for the DeriveEip712Test contract
let (abi, bytecode) = compile_contract("DeriveEip712Test", "DeriveEip712Test.sol");
// launch ganache
let ganache = Ganache::new().spawn();
// launch anvil
let anvil = Anvil::new().spawn();
let wallet: LocalWallet = ganache.keys()[0].clone().into();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let provider = Provider::<Http>::try_from(ganache.endpoint())
.expect("failed to instantiate provider from ganache endpoint")
let provider = Provider::<Http>::try_from(anvil.endpoint())
.expect("failed to instantiate provider from anvil endpoint")
.interval(Duration::from_millis(10u64));
let client =

View File

@ -210,7 +210,6 @@ mod tests {
use super::*;
#[test]
#[ignore]
fn can_launch_anvil() {
let _ = Anvil::new().spawn();
}

View File

@ -222,11 +222,13 @@ mod tests {
use super::*;
#[test]
#[ignore]
fn configurable_startup_timeout() {
Ganache::new().startup_timeout_millis(100000_u64).spawn();
}
#[test]
#[ignore]
fn default_startup_works() {
Ganache::new().spawn();
}

View File

@ -27,7 +27,7 @@ pub enum EtherscanError {
RateLimitExceeded,
#[error(transparent)]
IO(#[from] std::io::Error),
#[error("Local networks (e.g. ganache, geth --dev) cannot be indexed by etherscan")]
#[error("Local networks (e.g. anvil, ganache, geth --dev) cannot be indexed by etherscan")]
LocalNetworksNotSupported,
#[error("Unknown error: {0}")]
Unknown(String),

View File

@ -336,7 +336,7 @@ mod tests {
use super::*;
use ethers_core::{
types::TransactionRequest,
utils::{self, keccak256, Ganache},
utils::{self, keccak256, Anvil},
};
use ethers_providers::Provider;
use ethers_signers::LocalWallet;
@ -360,11 +360,10 @@ mod tests {
let chain_id = 1u64;
// Signer middlewares now rely on a working provider which it can query the chain id from,
// so we make sure ganache is started with the chain id that the expected tx was signed
// so we make sure Anvil is started with the chain id that the expected tx was signed
// with
let ganache =
Ganache::new().args(vec!["--chain.chainId".to_string(), chain_id.to_string()]).spawn();
let provider = Provider::try_from(ganache.endpoint()).unwrap();
let anvil = Anvil::new().args(vec!["--chain-id".to_string(), chain_id.to_string()]).spawn();
let provider = Provider::try_from(anvil.endpoint()).unwrap();
let key = "4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318"
.parse::<LocalWallet>()
.unwrap()
@ -384,11 +383,11 @@ mod tests {
}
#[tokio::test]
async fn ganache_consistent_chainid() {
let ganache = Ganache::new().spawn();
let provider = Provider::try_from(ganache.endpoint()).unwrap();
async fn anvil_consistent_chainid() {
let anvil = Anvil::new().spawn();
let provider = Provider::try_from(anvil.endpoint()).unwrap();
let chain_id = provider.get_chainid().await.unwrap();
assert_eq!(chain_id, U256::from(1337));
assert_eq!(chain_id, U256::from(31337));
// Intentionally do not set the chain id here so we ensure that the signer pulls the
// provider's chain id.
@ -406,9 +405,9 @@ mod tests {
}
#[tokio::test]
async fn ganache_consistent_chainid_not_default() {
let ganache = Ganache::new().args(vec!["--chain.chainId", "13371337"]).spawn();
let provider = Provider::try_from(ganache.endpoint()).unwrap();
async fn anvil_consistent_chainid_not_default() {
let anvil = Anvil::new().args(vec!["--chain-id", "13371337"]).spawn();
let provider = Provider::try_from(anvil.endpoint()).unwrap();
let chain_id = provider.get_chainid().await.unwrap();
assert_eq!(chain_id, U256::from(13371337));
@ -429,9 +428,9 @@ mod tests {
#[tokio::test]
async fn handles_tx_from_field() {
let ganache = Ganache::new().spawn();
let acc = ganache.addresses()[0];
let provider = Provider::try_from(ganache.endpoint()).unwrap();
let anvil = Anvil::new().spawn();
let acc = anvil.addresses()[0];
let provider = Provider::try_from(anvil.endpoint()).unwrap();
let key = LocalWallet::new(&mut rand::thread_rng()).with_chain_id(1u32);
provider
.send_transaction(
@ -459,7 +458,7 @@ mod tests {
assert_eq!(tx.from, client.address());
// signing a TransactionRequest with a from address that is not the
// signer should result in the default ganache account being used
// signer should result in the default anvil account being used
let request_from_other = request.from(acc);
let hash = *client.send_transaction(request_from_other, None).await.unwrap();
let tx = client.get_transaction(hash).await.unwrap().unwrap();

View File

@ -4,7 +4,7 @@ use std::convert::TryFrom;
use async_trait::async_trait;
use ethers_core::{types::*, utils::Ganache};
use ethers_core::{types::*, utils::Anvil};
use ethers_middleware::gas_oracle::{
EthGasStation, Etherchain, Etherscan, GasCategory, GasOracle, GasOracleError,
GasOracleMiddleware,
@ -31,14 +31,14 @@ impl GasOracle for FakeGasOracle {
#[tokio::test]
async fn using_gas_oracle() {
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
let from = ganache.addresses()[0];
let from = anvil.addresses()[0];
// connect to the network
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
// this is set because ganache now sets 875000000 as the first block's base fee
// this is set because anvil now sets 875000000 as the first block's base fee
let base_fee = 875000000;
// assign a gas oracle to use
let gas_oracle = FakeGasOracle { gas_price: (base_fee + 1337).into() };

View File

@ -22,16 +22,16 @@ static WALLETS: Lazy<TestWallets> = Lazy::new(|| {
#[tokio::test]
#[cfg(not(feature = "celo"))]
async fn send_eth() {
use ethers_core::utils::Ganache;
use ethers_core::utils::Anvil;
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
// this private key belongs to the above mnemonic
let wallet: LocalWallet = ganache.keys()[0].clone().into();
let wallet2: LocalWallet = ganache.keys()[1].clone().into();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let wallet2: LocalWallet = anvil.keys()[1].clone().into();
// connect to the network
let provider = Provider::<Http>::try_from(ganache.endpoint())
let provider = Provider::<Http>::try_from(anvil.endpoint())
.unwrap()
.interval(Duration::from_millis(10u64));
let chain_id = provider.get_chainid().await.unwrap().as_u64();
@ -156,17 +156,17 @@ async fn test_send_transaction() {
#[tokio::test]
#[cfg(not(feature = "celo"))]
async fn send_transaction_handles_tx_from_field() {
use ethers_core::utils::Ganache;
use ethers_core::utils::Anvil;
// launch ganache
let ganache = Ganache::new().spawn();
// launch anvil
let anvil = Anvil::new().spawn();
// grab 2 wallets
let signer: LocalWallet = ganache.keys()[0].clone().into();
let other: LocalWallet = ganache.keys()[1].clone().into();
let signer: LocalWallet = anvil.keys()[0].clone().into();
let other: LocalWallet = anvil.keys()[1].clone().into();
// connect to the network
let provider = Provider::try_from(ganache.endpoint()).unwrap();
let provider = Provider::try_from(anvil.endpoint()).unwrap();
let provider =
SignerMiddleware::new_with_provider_chain(provider, signer.clone()).await.unwrap();

View File

@ -1,7 +1,7 @@
#![cfg(not(target_arch = "wasm32"))]
#[cfg(not(feature = "celo"))]
mod tests {
use ethers_core::{rand::thread_rng, types::TransactionRequest, utils::Ganache};
use ethers_core::{rand::thread_rng, types::TransactionRequest, utils::Anvil};
use ethers_middleware::{
gas_escalator::{Frequency, GasEscalatorMiddleware, GeometricGasPrice},
gas_oracle::{EthGasStation, GasCategory, GasOracleMiddleware},
@ -52,13 +52,13 @@ mod tests {
#[tokio::test]
async fn can_stack_middlewares() {
let ganache = Ganache::new().block_time(5u64).spawn();
let anvil = Anvil::new().block_time(5u64).spawn();
let gas_oracle = EthGasStation::new(None).category(GasCategory::SafeLow);
let signer: LocalWallet = ganache.keys()[0].clone().into();
let signer: LocalWallet = anvil.keys()[0].clone().into();
let address = signer.address();
// the base provider
let provider = Arc::new(Provider::<Http>::try_from(ganache.endpoint()).unwrap());
let provider = Arc::new(Provider::<Http>::try_from(anvil.endpoint()).unwrap());
let chain_id = provider.get_chainid().await.unwrap().as_u64();
let signer = signer.with_chain_id(chain_id);

View File

@ -1,7 +1,7 @@
#![cfg(not(target_arch = "wasm32"))]
#![allow(unused)]
use ethers_contract::{BaseContract, ContractFactory};
use ethers_core::{abi::Abi, types::*, utils::Ganache};
use ethers_core::{abi::Abi, types::*, utils::Anvil};
use ethers_middleware::{
transformer::{DsProxy, TransformerMiddleware},
SignerMiddleware,
@ -29,10 +29,10 @@ async fn ds_proxy_transformer() {
// randomness
let mut rng = rand::thread_rng();
// spawn ganache and instantiate a signer middleware.
let ganache = Ganache::new().spawn();
let wallet: LocalWallet = ganache.keys()[0].clone().into();
let provider = Provider::<Http>::try_from(ganache.endpoint())
// spawn anvil and instantiate a signer middleware.
let anvil = Anvil::new().spawn();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let provider = Provider::<Http>::try_from(anvil.endpoint())
.unwrap()
.interval(Duration::from_millis(10u64));
let chain_id = provider.get_chainid().await.unwrap().as_u64();
@ -88,10 +88,10 @@ async fn ds_proxy_code() {
// randomness
let mut rng = rand::thread_rng();
// spawn ganache and instantiate a signer middleware.
let ganache = Ganache::new().spawn();
let wallet: LocalWallet = ganache.keys()[1].clone().into();
let provider = Provider::<Http>::try_from(ganache.endpoint())
// spawn anvil and instantiate a signer middleware.
let anvil = Anvil::new().spawn();
let wallet: LocalWallet = anvil.keys()[1].clone().into();
let provider = Provider::<Http>::try_from(anvil.endpoint())
.unwrap()
.interval(Duration::from_millis(10u64));
let chain_id = provider.get_chainid().await.unwrap().as_u64();

View File

@ -30,15 +30,15 @@ use wasm_timer::Delay;
///
///```
/// # use ethers_providers::{Provider, Http};
/// # use ethers_core::utils::Ganache;
/// # use ethers_core::utils::Anvil;
/// # use std::convert::TryFrom;
/// use ethers_providers::Middleware;
/// use ethers_core::types::TransactionRequest;
///
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// # let ganache = Ganache::new().spawn();
/// # let client = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
/// # let anvil = Anvil::new().spawn();
/// # let client = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
/// # let accounts = client.get_accounts().await?;
/// # let from = accounts[0];
/// # let to = accounts[1];

View File

@ -1204,7 +1204,7 @@ impl<P: JsonRpcClient> Provider<P> {
}
#[cfg(test)]
/// ganache-only function for mining empty blocks
/// Anvil and Ganache-only function for mining empty blocks
pub async fn mine(&self, num_blocks: usize) -> Result<(), ProviderError> {
for _ in 0..num_blocks {
self.inner.request::<_, U256>("evm_mine", None::<()>).await.map_err(Into::into)?;
@ -1365,13 +1365,13 @@ impl Provider<RetryClient<HttpProvider>> {
///```
/// use ethers_providers::{Provider, Http, Middleware, DevRpcMiddleware};
/// use ethers_core::types::TransactionRequest;
/// use ethers_core::utils::Ganache;
/// use ethers_core::utils::Anvil;
/// use std::convert::TryFrom;
///
/// # #[tokio::main(flavor = "current_thread")]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let ganache = Ganache::new().spawn();
/// let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
/// let anvil = Anvil::new().spawn();
/// let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
/// let client = DevRpcMiddleware::new(provider);
///
/// // snapshot the initial state
@ -1450,7 +1450,7 @@ pub mod dev_rpc {
Self(inner)
}
// both ganache and hardhat increment snapshot id even if no state has changed
// Ganache, Hardhat and Anvil increment snapshot ID even if no state has changed
pub async fn snapshot(&self) -> Result<U256, DevRpcMiddlewareError<M>> {
self.provider().request::<(), U256>("evm_snapshot", ()).await.map_err(From::from)
}
@ -1474,14 +1474,13 @@ pub mod dev_rpc {
mod tests {
use super::*;
use crate::{Http, Provider};
use ethers_core::utils::Ganache;
use ethers_core::utils::Anvil;
use std::convert::TryFrom;
#[tokio::test]
async fn test_snapshot() {
// launch ganache
let ganache = Ganache::new().spawn();
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
let anvil = Anvil::new().spawn();
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
let client = DevRpcMiddleware::new(provider);
// snapshot initial state
@ -1544,7 +1543,7 @@ mod tests {
types::{
transaction::eip2930::AccessList, Eip1559TransactionRequest, TransactionRequest, H256,
},
utils::Geth,
utils::Anvil,
};
use futures_util::StreamExt;
@ -1625,7 +1624,7 @@ mod tests {
#[cfg_attr(feature = "celo", ignore)]
async fn test_new_block_filter() {
let num_blocks = 3;
let geth = Geth::new().block_time(2u64).spawn();
let geth = Anvil::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(geth.endpoint())
.unwrap()
.interval(Duration::from_millis(1000));
@ -1644,16 +1643,15 @@ mod tests {
#[tokio::test]
#[cfg_attr(feature = "celo", ignore)]
async fn test_is_signer() {
use ethers_core::utils::Ganache;
use ethers_core::utils::Anvil;
use std::str::FromStr;
let ganache = Ganache::new().spawn();
let provider = Provider::<Http>::try_from(ganache.endpoint())
.unwrap()
.with_sender(ganache.addresses()[0]);
let anvil = Anvil::new().spawn();
let provider =
Provider::<Http>::try_from(anvil.endpoint()).unwrap().with_sender(anvil.addresses()[0]);
assert!(provider.is_signer().await);
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
assert!(!provider.is_signer().await);
let sender = Address::from_str("635B4764D1939DfAcD3a8014726159abC277BecC")
@ -1670,7 +1668,7 @@ mod tests {
async fn test_new_pending_txs_filter() {
let num_txs = 5;
let geth = Geth::new().block_time(2u64).spawn();
let geth = Anvil::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(geth.endpoint())
.unwrap()
.interval(Duration::from_millis(1000));
@ -1693,10 +1691,10 @@ mod tests {
async fn receipt_on_unmined_tx() {
use ethers_core::{
types::TransactionRequest,
utils::{parse_ether, Ganache},
utils::{parse_ether, Anvil},
};
let ganache = Ganache::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
let anvil = Anvil::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
let accounts = provider.get_accounts().await.unwrap();
let tx = TransactionRequest::pay(accounts[0], parse_ether(1u64).unwrap()).from(accounts[0]);
@ -1724,10 +1722,10 @@ mod tests {
// Celo blocks can not get parsed when used with Ganache
#[cfg(not(feature = "celo"))]
async fn block_subscribe() {
use ethers_core::utils::Ganache;
use ethers_core::utils::Anvil;
use futures_util::StreamExt;
let ganache = Ganache::new().block_time(2u64).spawn();
let provider = Provider::connect(ganache.ws_endpoint()).await.unwrap();
let anvil = Anvil::new().block_time(2u64).spawn();
let provider = Provider::connect(anvil.ws_endpoint()).await.unwrap();
let stream = provider.subscribe_blocks().await.unwrap();
let blocks = stream.take(3).map(|x| x.number.unwrap().as_u64()).collect::<Vec<_>>().await;

View File

@ -265,7 +265,7 @@ mod tests {
use crate::{Http, Ws};
use ethers_core::{
types::{TransactionReceipt, TransactionRequest},
utils::{Ganache, Geth},
utils::Anvil,
};
use futures_util::{FutureExt, StreamExt};
use std::{collections::HashSet, convert::TryFrom};
@ -273,7 +273,7 @@ mod tests {
#[tokio::test]
async fn can_stream_pending_transactions() {
let num_txs = 5;
let geth = Geth::new().block_time(2u64).spawn();
let geth = Anvil::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(geth.endpoint())
.unwrap()
.interval(Duration::from_millis(1000));
@ -327,17 +327,17 @@ mod tests {
#[tokio::test]
async fn can_stream_transactions() {
let ganache = Ganache::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(ganache.endpoint())
.unwrap()
.with_sender(ganache.addresses()[0]);
let anvil = Anvil::new().block_time(2u64).spawn();
let provider =
Provider::<Http>::try_from(anvil.endpoint()).unwrap().with_sender(anvil.addresses()[0]);
let accounts = provider.get_accounts().await.unwrap();
let tx = TransactionRequest::new().from(accounts[0]).to(accounts[0]).value(1e18 as u64);
let txs = vec![tx.clone().nonce(0u64), tx.clone().nonce(1u64), tx.clone().nonce(2u64)];
let txs =
futures_util::future::join_all(std::iter::repeat(tx.clone()).take(3).map(|tx| async {
futures_util::future::join_all(txs.into_iter().map(|tx| async {
provider.send_transaction(tx, None).await.unwrap().await.unwrap()
}))
.await;

View File

@ -488,13 +488,13 @@ mod tests {
use super::*;
use ethers_core::{
types::{Block, TxHash, U256},
utils::Ganache,
utils::Anvil,
};
#[tokio::test]
async fn request() {
let ganache = Ganache::new().block_time(1u64).spawn();
let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap();
let anvil = Anvil::new().block_time(1u64).spawn();
let ws = Ws::connect(anvil.ws_endpoint()).await.unwrap();
let block_num: U256 = ws.request("eth_blockNumber", ()).await.unwrap();
std::thread::sleep(std::time::Duration::new(3, 0));
@ -504,8 +504,8 @@ mod tests {
#[tokio::test]
async fn subscription() {
let ganache = Ganache::new().block_time(1u64).spawn();
let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap();
let anvil = Anvil::new().block_time(1u64).spawn();
let ws = Ws::connect(anvil.ws_endpoint()).await.unwrap();
// Subscribing requires sending the sub request and then subscribing to
// the returned sub_id
@ -519,14 +519,13 @@ mod tests {
blocks.push(block.number.unwrap_or_default().as_u64());
}
assert_eq!(sub_id, 1.into());
assert_eq!(blocks, vec![1, 2, 3])
}
#[tokio::test]
async fn deserialization_fails() {
let ganache = Ganache::new().block_time(1u64).spawn();
let (ws, _) = tokio_tungstenite::connect_async(ganache.ws_endpoint()).await.unwrap();
let anvil = Anvil::new().block_time(1u64).spawn();
let (ws, _) = tokio_tungstenite::connect_async(anvil.ws_endpoint()).await.unwrap();
let malformed_data = String::from("not a valid message");
let (_, stream) = mpsc::unbounded();
let resp = WsServer::new(ws, stream).handle_text(malformed_data).await;

View File

@ -7,7 +7,7 @@ mod eth_tests {
use super::*;
use ethers_core::{
types::{Address, BlockId, TransactionRequest, H256},
utils::Ganache,
utils::Anvil,
};
use ethers_providers::RINKEBY;
@ -45,8 +45,8 @@ mod eth_tests {
use ethers_core::types::H256;
use ethers_providers::{StreamExt, Ws};
let ganache = Ganache::new().block_time(2u64).spawn();
let (ws, _) = tokio_tungstenite::connect_async(ganache.ws_endpoint()).await.unwrap();
let anvil = Anvil::new().block_time(2u64).spawn();
let (ws, _) = tokio_tungstenite::connect_async(anvil.ws_endpoint()).await.unwrap();
let provider = Provider::new(Ws::new(ws)).interval(Duration::from_millis(500u64));
let stream = provider.watch_blocks().await.unwrap().stream();
@ -56,9 +56,9 @@ mod eth_tests {
}
#[tokio::test]
async fn pending_txs_with_confirmations_ganache() {
let ganache = Ganache::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(ganache.endpoint())
async fn pending_txs_with_confirmations_anvil() {
let anvil = Anvil::new().block_time(2u64).spawn();
let provider = Provider::<Http>::try_from(anvil.endpoint())
.unwrap()
.interval(Duration::from_millis(500u64));
let accounts = provider.get_accounts().await.unwrap();
@ -66,10 +66,10 @@ mod eth_tests {
}
#[tokio::test]
async fn websocket_pending_txs_with_confirmations_ganache() {
async fn websocket_pending_txs_with_confirmations_anvil() {
use ethers_providers::Ws;
let ganache = Ganache::new().block_time(2u64).spawn();
let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap();
let anvil = Anvil::new().block_time(2u64).spawn();
let ws = Ws::connect(anvil.ws_endpoint()).await.unwrap();
let provider = Provider::new(ws);
let accounts = provider.get_accounts().await.unwrap();
generic_pending_txs_test(provider, accounts[0]).await;

View File

@ -1,14 +1,14 @@
#![cfg(not(target_arch = "wasm32"))]
use ethers_core::{
types::{TransactionRequest, U256},
utils::Geth,
utils::Anvil,
};
use ethers_providers::{Http, Middleware, Provider};
use std::convert::TryFrom;
#[tokio::test]
async fn txpool() {
let geth = Geth::new().block_time(20u64).spawn();
let geth = Anvil::new().block_time(20u64).spawn();
let provider = Provider::<Http>::try_from(geth.endpoint()).unwrap();
let account = provider.get_accounts().await.unwrap()[0];

View File

@ -1,7 +1,7 @@
use ethers::{
prelude::*,
solc::{Project, ProjectPathsConfig},
utils::Ganache,
utils::Anvil,
};
use eyre::Result;
use std::{convert::TryFrom, path::PathBuf, sync::Arc, time::Duration};
@ -33,13 +33,13 @@ async fn main() -> Result<()> {
let contract = output.find("SimpleStorage").expect("could not find contract").clone();
let (abi, bytecode, _) = contract.into_parts();
// 2. instantiate our wallet & ganache
let ganache = Ganache::new().spawn();
let wallet: LocalWallet = ganache.keys()[0].clone().into();
// 2. instantiate our wallet & anvil
let anvil = Anvil::new().spawn();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
// 3. connect to the network
let provider =
Provider::<Http>::try_from(ganache.endpoint())?.interval(Duration::from_millis(10u64));
Provider::<Http>::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64));
// 4. instantiate the client with the wallet
let client = SignerMiddleware::new(provider, wallet);
@ -49,7 +49,7 @@ async fn main() -> Result<()> {
let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone());
// 6. deploy it with the constructor arguments
let contract = factory.deploy("initial value".to_string())?.legacy().send().await?;
let contract = factory.deploy("initial value".to_string())?.send().await?;
// 7. get the contract's address
let addr = contract.address();
@ -59,7 +59,7 @@ async fn main() -> Result<()> {
// 9. call the `setValue` method
// (first `await` returns a PendingTransaction, second one waits for it to be mined)
let _receipt = contract.set_value("hi".to_owned()).legacy().send().await?.await?;
let _receipt = contract.set_value("hi".to_owned()).send().await?.await?;
// 10. get all events
let logs = contract.value_changed_filter().from_block(0u64).query().await?;

View File

@ -1,4 +1,4 @@
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use eyre::Result;
use std::{convert::TryFrom, path::Path, sync::Arc, time::Duration};
@ -13,8 +13,8 @@ abigen!(
#[tokio::main]
async fn main() -> Result<()> {
// 1. compile the contract (note this requires that you are inside the `examples` directory) and
// launch ganache
let ganache = Ganache::new().spawn();
// launch anvil
let anvil = Anvil::new().spawn();
// set the path to the contract, `CARGO_MANIFEST_DIR` points to the directory containing the
// manifest of `ethers`. which will be `../` relative to this file
@ -24,11 +24,11 @@ async fn main() -> Result<()> {
compiled.find("SimpleStorage").expect("could not find contract").into_parts_or_default();
// 2. instantiate our wallet
let wallet: LocalWallet = ganache.keys()[0].clone().into();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
// 3. connect to the network
let provider =
Provider::<Http>::try_from(ganache.endpoint())?.interval(Duration::from_millis(10u64));
Provider::<Http>::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64));
// 4. instantiate the client with the wallet
let client = SignerMiddleware::new(provider, wallet);
@ -38,7 +38,7 @@ async fn main() -> Result<()> {
let factory = ContractFactory::new(abi, bytecode, client.clone());
// 6. deploy it with the constructor arguments
let contract = factory.deploy("initial value".to_string())?.legacy().send().await?;
let contract = factory.deploy("initial value".to_string())?.send().await?;
// 7. get the contract's address
let addr = contract.address();
@ -48,7 +48,7 @@ async fn main() -> Result<()> {
// 9. call the `setValue` method
// (first `await` returns a PendingTransaction, second one waits for it to be mined)
let _receipt = contract.set_value("hi".to_owned()).legacy().send().await?.await?;
let _receipt = contract.set_value("hi".to_owned()).send().await?.await?;
// 10. get all events
let logs = contract.value_changed_filter().from_block(0u64).query().await?;

View File

@ -1,4 +1,4 @@
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use eyre::Result;
use std::{convert::TryFrom, sync::Arc, time::Duration};
@ -11,22 +11,22 @@ abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter.json",);
#[tokio::main]
async fn main() -> Result<()> {
// 1. compile the contract (note this requires that you are inside the `examples` directory) and
// launch ganache
let ganache = Ganache::new().spawn();
// launch anvil
let anvil = Anvil::new().spawn();
// 2. instantiate our wallet
let wallet: LocalWallet = ganache.keys()[0].clone().into();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
// 3. connect to the network
let provider =
Provider::<Http>::try_from(ganache.endpoint())?.interval(Duration::from_millis(10u64));
Provider::<Http>::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64));
// 4. instantiate the client with the wallet
let client = Arc::new(SignerMiddleware::new(provider, wallet));
// 5. deploy contract, note the `legacy` call required for non EIP-1559
// 5. deploy contract
let greeter_contract =
Greeter::deploy(client, "Hello World!".to_string()).unwrap().legacy().send().await.unwrap();
Greeter::deploy(client, "Hello World!".to_string()).unwrap().send().await.unwrap();
// 6. call contract function
let greeting = greeter_contract.greet().call().await.unwrap();

View File

@ -1,6 +1,6 @@
//! Main entry point for ContractMonitor
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use std::{convert::TryFrom, sync::Arc, time::Duration};
abigen!(VerifierContract, "ethers-contract/tests/solidity-contracts/verifier_abi.json");
@ -9,10 +9,10 @@ abigen!(VerifierContract, "ethers-contract/tests/solidity-contracts/verifier_abi
/// have structs as input.
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
let provider =
Provider::<Http>::try_from(ganache.endpoint())?.interval(Duration::from_millis(10u64));
let wallet: LocalWallet = ganache.keys()[0].clone().into();
Provider::<Http>::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64));
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let client = SignerMiddleware::new(provider, wallet);
let client = Arc::new(client);

View File

@ -1,16 +1,15 @@
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use eyre::Result;
use std::convert::TryFrom;
#[tokio::main]
async fn main() -> Result<()> {
// fork mainnet
let ganache = Ganache::new()
.fork("https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
.spawn();
let from = ganache.addresses()[0].clone();
let anvil =
Anvil::new().fork("https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27").spawn();
let from = anvil.addresses()[0].clone();
// connect to the network
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap().with_sender(from);
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap().with_sender(from);
// craft the transaction
let tx = TransactionRequest::new().to("vitalik.eth").value(100_000);

View File

@ -1,16 +1,16 @@
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use eyre::Result;
use std::convert::TryFrom;
#[tokio::main]
async fn main() -> Result<()> {
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
let wallet: LocalWallet = ganache.keys()[0].clone().into();
let wallet2: LocalWallet = ganache.keys()[1].clone().into();
let wallet: LocalWallet = anvil.keys()[0].clone().into();
let wallet2: LocalWallet = anvil.keys()[1].clone().into();
// connect to the network
let provider = Provider::<Http>::try_from(ganache.endpoint())?;
let provider = Provider::<Http>::try_from(anvil.endpoint())?;
// connect the wallet to the provider
let client = SignerMiddleware::new(provider, wallet);

View File

@ -1,22 +1,22 @@
//! Example usage for the `QuorumProvider` that requests multiple backends and only returns
//! a value if the configured `Quorum` was reached.
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use std::{str::FromStr, time::Duration};
#[tokio::main]
async fn main() -> eyre::Result<()> {
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
// create a quorum provider with some providers
let quorum = QuorumProvider::dyn_rpc()
.add_provider(WeightedProvider::new(Box::new(Http::from_str(&ganache.endpoint())?)))
.add_provider(WeightedProvider::new(Box::new(Http::from_str(&anvil.endpoint())?)))
.add_provider(WeightedProvider::with_weight(
Box::new(Ws::connect(ganache.ws_endpoint()).await?),
Box::new(Ws::connect(anvil.ws_endpoint()).await?),
2,
))
.add_provider(WeightedProvider::with_weight(
Box::new(Ws::connect(ganache.ws_endpoint()).await?),
Box::new(Ws::connect(anvil.ws_endpoint()).await?),
2,
))
// the quorum provider will yield the response if >50% of the weighted inner provider

View File

@ -1,15 +1,15 @@
//! Example usage for the `RwClinet` that uses a didicated client to send transaction and nother one
//! Example usage for the `RwClient` that uses a didicated client to send transaction and nother one
//! for read ops
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use std::{str::FromStr, time::Duration};
#[tokio::main]
async fn main() -> eyre::Result<()> {
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
let http = Http::from_str(&ganache.endpoint())?;
let ws = Ws::connect(ganache.ws_endpoint()).await?;
let http = Http::from_str(&anvil.endpoint())?;
let ws = Ws::connect(anvil.ws_endpoint()).await?;
let provider = Provider::rw(http, ws).interval(Duration::from_millis(10u64));

View File

@ -1,13 +1,13 @@
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use eyre::Result;
use std::convert::TryFrom;
#[tokio::main]
async fn main() -> Result<()> {
let ganache = Ganache::new().spawn();
let anvil = Anvil::new().spawn();
// connect to the network
let provider = Provider::<Http>::try_from(ganache.endpoint())?;
let provider = Provider::<Http>::try_from(anvil.endpoint())?;
let accounts = provider.get_accounts().await?;
let from = accounts[0];
let to = accounts[1];
@ -16,18 +16,16 @@ async fn main() -> Result<()> {
let tx = TransactionRequest::new().to(to).value(1000).from(from); // specify the `from` field so that the client knows which account to use
let balance_before = provider.get_balance(from, None).await?;
let nonce1 = provider.get_transaction_count(from, None).await?;
// broadcast it via the eth_sendTransaction API
let tx = provider.send_transaction(tx, None).await?.await?;
println!("{}", serde_json::to_string(&tx)?);
let nonce1 = provider.get_transaction_count(from, Some(BlockNumber::Latest.into())).await?;
let nonce2 = provider.get_transaction_count(from, None).await?;
let nonce2 =
provider.get_transaction_count(from, Some(BlockNumber::Number(0.into()).into())).await?;
assert!(nonce2 < nonce1);
assert!(nonce1 < nonce2);
let balance_after = provider.get_balance(from, None).await?;
assert!(balance_after < balance_before);

View File

@ -10,7 +10,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// (here: mainnet) for EIP155 support.
// EIP1559 support
// No EIP712 support yet.
let trezor = Trezor::new(TrezorHDPath::TrezorLive(0), 1).await?;
let trezor = Trezor::new(TrezorHDPath::TrezorLive(0), 1, None).await?;
let client = SignerMiddleware::new(provider, trezor);
// Create and broadcast a transaction (ENS disabled!)

View File

@ -1,10 +1,10 @@
use ethers::{prelude::*, utils::Ganache};
use ethers::{prelude::*, utils::Anvil};
use std::time::Duration;
#[tokio::main]
async fn main() -> eyre::Result<()> {
let ganache = Ganache::new().block_time(1u64).spawn();
let ws = Ws::connect(ganache.ws_endpoint()).await?;
let anvil = Anvil::new().block_time(1u64).spawn();
let ws = Ws::connect(anvil.ws_endpoint()).await?;
let provider = Provider::new(ws).interval(Duration::from_millis(2000));
let mut stream = provider.watch_blocks().await?.take(5);
while let Some(block) = stream.next().await {

View File

@ -1,7 +1,24 @@
set -e
# shellcheck shell=bash
# examples that we can't run because they require some additional infra, docker or ledger for example
ignored=(
"moonbeam_with_abi"
"ipc"
"ledger"
"paginated_logs"
"subscribe_logs"
"trezor"
"yubi"
)
# run all examples
for file in examples/*.rs; do
name="$(echo "$file" | cut -f 1 -d '.')"
if [[ "${ignored[*]}" =~ $(basename "$name") ]]; then
echo "skipping: $file"
continue
fi
echo "running: $file"
cargo r -p ethers --example "$(basename "$name")"
done

View File

@ -29,7 +29,7 @@
//!
//! Contains all the [necessary data structures](core::types) for interacting
//! with Ethereum, along with cryptographic utilities for signing and verifying
//! ECDSA signatures on `secp256k1`. Bindings to the solidity compiler and `ganache-cli`
//! ECDSA signatures on `secp256k1`. Bindings to the Solidity compiler, Anvil and `ganache-cli`
//! are also provided as helpers. To simplify your imports, consider using the re-exported
//! modules described in the next subsection.
//!