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:
parent
1a699ad72e
commit
89bc6420bb
|
@ -21,12 +21,10 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Set up node
|
- name: Install Anvil
|
||||||
uses: actions/setup-node@v1
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
with:
|
with:
|
||||||
node-version: 10
|
version: nightly
|
||||||
- name: Install ganache
|
|
||||||
run: npm install -g ganache
|
|
||||||
- name: Install Solc
|
- name: Install Solc
|
||||||
run: |
|
run: |
|
||||||
mkdir -p "$HOME/bin"
|
mkdir -p "$HOME/bin"
|
||||||
|
@ -66,13 +64,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sources
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v2
|
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?
|
# TODO: can we combine these shared steps in github actions?
|
||||||
- name: Install ganache
|
- name: Install Anvil
|
||||||
run: npm install -g ganache
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
|
with:
|
||||||
|
version: nightly
|
||||||
- name: Install Solc
|
- name: Install Solc
|
||||||
run: |
|
run: |
|
||||||
mkdir -p "$HOME/bin"
|
mkdir -p "$HOME/bin"
|
||||||
|
@ -133,12 +129,8 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout sources
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v2
|
||||||
- name: Install node
|
|
||||||
uses: actions/setup-node@v1
|
|
||||||
with:
|
|
||||||
node-version: 10
|
|
||||||
- name: Install rust
|
- name: Install rust
|
||||||
uses: actions-rs/toolchain@v1
|
uses: actions-rs/toolchain@v1
|
||||||
with:
|
with:
|
||||||
|
@ -147,6 +139,11 @@ jobs:
|
||||||
profile: minimal
|
profile: minimal
|
||||||
override: true
|
override: true
|
||||||
|
|
||||||
|
- name: Install Anvil
|
||||||
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
|
with:
|
||||||
|
version: nightly
|
||||||
|
|
||||||
- uses: Swatinem/rust-cache@v1
|
- uses: Swatinem/rust-cache@v1
|
||||||
with:
|
with:
|
||||||
cache-on-failure: true
|
cache-on-failure: true
|
||||||
|
@ -157,11 +154,8 @@ jobs:
|
||||||
command: check
|
command: check
|
||||||
args: --target wasm32-unknown-unknown
|
args: --target wasm32-unknown-unknown
|
||||||
|
|
||||||
- name: Launch Ganache
|
- name: Launch Anvil
|
||||||
run: |
|
run: anvil --block-time 2 -m "stuff inherit faith park genre spread huge knee ecology private marble supreme" &
|
||||||
cd examples/ethers-wasm
|
|
||||||
npm install
|
|
||||||
npm run ganache &
|
|
||||||
|
|
||||||
- name: Install wasm-pack
|
- name: Install wasm-pack
|
||||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||||
|
@ -176,59 +170,66 @@ jobs:
|
||||||
cd examples/ethers-wasm
|
cd examples/ethers-wasm
|
||||||
wasm-pack test --headless --chrome
|
wasm-pack test --headless --chrome
|
||||||
|
|
||||||
# TODO: Re-enable once we figure out why examples are running forever.
|
examples:
|
||||||
# examples:
|
name: Examples
|
||||||
# name: Examples
|
runs-on: ubuntu-latest
|
||||||
# runs-on: ubuntu-latest
|
steps:
|
||||||
# steps:
|
- name: Checkout sources
|
||||||
# - name: Checkout sources
|
uses: actions/checkout@v2
|
||||||
# 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
|
|
||||||
|
|
||||||
# - name: Install geth
|
- name: Install Anvil
|
||||||
# run: |
|
uses: foundry-rs/foundry-toolchain@v1
|
||||||
# mkdir -p "$HOME/bin"
|
with:
|
||||||
# wget -q https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.23-8c2f2715.tar.gz
|
version: nightly
|
||||||
# tar -xvf geth-linux-amd64-1.9.23-8c2f2715.tar.gz
|
|
||||||
# mv geth-linux-amd64-1.9.23-8c2f2715/geth $HOME/bin/geth
|
- name: Install Solc
|
||||||
# chmod u+x "$HOME/bin/geth"
|
run: |
|
||||||
# export PATH=$HOME/bin:$PATH
|
mkdir -p "$HOME/bin"
|
||||||
# geth version
|
wget -q https://github.com/ethereum/solidity/releases/download/v0.8.10/solc-static-linux -O $HOME/bin/solc
|
||||||
# - name: Install stable toolchain
|
chmod u+x "$HOME/bin/solc"
|
||||||
# uses: actions-rs/toolchain@v1
|
export PATH=$HOME/bin:$PATH
|
||||||
# with:
|
solc --version
|
||||||
# profile: minimal
|
|
||||||
# toolchain: stable
|
- name: Install stable toolchain
|
||||||
# override: true
|
uses: actions-rs/toolchain@v1
|
||||||
# components: rustfmt, clippy
|
with:
|
||||||
# - uses: Swatinem/rust-cache@v1
|
profile: minimal
|
||||||
# with:
|
toolchain: stable
|
||||||
# cache-on-failure: true
|
override: true
|
||||||
# - name: Build all examples
|
components: rustfmt, clippy
|
||||||
# run: |
|
- uses: Swatinem/rust-cache@v1
|
||||||
# export PATH=$HOME/bin:$PATH
|
with:
|
||||||
# for file in examples/*.rs; do
|
cache-on-failure: true
|
||||||
# name="$(echo "$file" | cut -f 1 -d '.')"
|
- name: Build all examples
|
||||||
# echo "building $name"
|
run: |
|
||||||
# cargo build -p ethers --example "$(basename "$name")"
|
export PATH=$HOME/bin:$PATH
|
||||||
# done
|
examples=$(cargo metadata --format-version 1 | \
|
||||||
# - name: Run all examples
|
jq -c '.packages[]
|
||||||
# run: |
|
| select(.name == "ethers")
|
||||||
# export PATH=$HOME/bin:$PATH
|
| .targets[]
|
||||||
# chmod +x ./scripts/examples.sh
|
| select(.kind[] | contains("example"))
|
||||||
# ./scripts/examples.sh
|
| 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:
|
windows-build:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
|
@ -115,17 +115,14 @@ opt-level = "s"
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "contract_human_readable"
|
name = "contract_human_readable"
|
||||||
path = "examples/contract_human_readable.rs"
|
path = "examples/contract_human_readable.rs"
|
||||||
required-features = ["legacy"]
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "contract_with_abi"
|
name = "contract_with_abi"
|
||||||
path = "examples/contract_with_abi.rs"
|
path = "examples/contract_with_abi.rs"
|
||||||
required-features = ["legacy"]
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "contract_with_abi_and_bytecode"
|
name = "contract_with_abi_and_bytecode"
|
||||||
path = "examples/contract_with_abi_and_bytecode.rs"
|
path = "examples/contract_with_abi_and_bytecode.rs"
|
||||||
required-features = ["legacy"]
|
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "ipc"
|
name = "ipc"
|
||||||
|
@ -151,3 +148,8 @@ required-features = ["trezor"]
|
||||||
name = "yubi"
|
name = "yubi"
|
||||||
path = "examples/yubi.rs"
|
path = "examples/yubi.rs"
|
||||||
required-features = ["yubi"]
|
required-features = ["yubi"]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "paginated_logs"
|
||||||
|
path = "examples/paginated_logs.rs"
|
||||||
|
required-features = ["rustls"]
|
||||||
|
|
|
@ -32,7 +32,7 @@ ethers = { git = "https://github.com/gakonst/ethers-rs" }
|
||||||
Tests require the following installed:
|
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.
|
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)
|
3. [`geth`](https://github.com/ethereum/go-ethereum)
|
||||||
|
|
||||||
In addition, it is recommended that you set the `ETHERSCAN_API_KEY` environment variable
|
In addition, it is recommended that you set the `ETHERSCAN_API_KEY` environment variable
|
||||||
|
|
|
@ -4,7 +4,7 @@ use ethers_contract::{abigen, EthCall, EthEvent};
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{AbiDecode, AbiEncode, Address, Tokenizable},
|
abi::{AbiDecode, AbiEncode, Address, Tokenizable},
|
||||||
types::{transaction::eip2718::TypedTransaction, Eip1559TransactionRequest, U256},
|
types::{transaction::eip2718::TypedTransaction, Eip1559TransactionRequest, U256},
|
||||||
utils::Ganache,
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
use ethers_middleware::SignerMiddleware;
|
use ethers_middleware::SignerMiddleware;
|
||||||
use ethers_providers::{MockProvider, Provider};
|
use ethers_providers::{MockProvider, Provider};
|
||||||
|
@ -305,10 +305,10 @@ async fn can_handle_underscore_functions() {
|
||||||
"ethers-contract/tests/solidity-contracts/simplestorage_abi.json",
|
"ethers-contract/tests/solidity-contracts/simplestorage_abi.json",
|
||||||
);
|
);
|
||||||
|
|
||||||
// launcht the network & connect to it
|
// launch the network & connect to it
|
||||||
let ganache = ethers_core::utils::Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let from = ganache.addresses()[0];
|
let from = anvil.addresses()[0];
|
||||||
let provider = Provider::try_from(ganache.endpoint())
|
let provider = Provider::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_sender(from)
|
.with_sender(from)
|
||||||
.interval(std::time::Duration::from_millis(10));
|
.interval(std::time::Duration::from_millis(10));
|
||||||
|
@ -484,9 +484,9 @@ fn can_handle_case_sensitive_calls() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn can_deploy_greeter() {
|
async fn can_deploy_greeter() {
|
||||||
abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter.json",);
|
abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter.json",);
|
||||||
let ganache = ethers_core::utils::Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let from = ganache.addresses()[0];
|
let from = anvil.addresses()[0];
|
||||||
let provider = Provider::try_from(ganache.endpoint())
|
let provider = Provider::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_sender(from)
|
.with_sender(from)
|
||||||
.interval(std::time::Duration::from_millis(10));
|
.interval(std::time::Duration::from_millis(10));
|
||||||
|
@ -502,9 +502,9 @@ async fn can_deploy_greeter() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn can_abiencoderv2_output() {
|
async fn can_abiencoderv2_output() {
|
||||||
abigen!(AbiEncoderv2Test, "ethers-contract/tests/solidity-contracts/abiencoderv2test_abi.json",);
|
abigen!(AbiEncoderv2Test, "ethers-contract/tests/solidity-contracts/abiencoderv2test_abi.json",);
|
||||||
let ganache = ethers_core::utils::Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let from = ganache.addresses()[0];
|
let from = anvil.addresses()[0];
|
||||||
let provider = Provider::try_from(ganache.endpoint())
|
let provider = Provider::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.with_sender(from)
|
.with_sender(from)
|
||||||
.interval(std::time::Duration::from_millis(10));
|
.interval(std::time::Duration::from_millis(10));
|
||||||
|
@ -575,7 +575,7 @@ fn can_handle_overloaded_events() {
|
||||||
async fn can_send_struct_param() {
|
async fn can_send_struct_param() {
|
||||||
abigen!(StructContract, "./tests/solidity-contracts/StructContract.json");
|
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 wallet: LocalWallet = server.keys()[0].clone().into();
|
||||||
let provider = Provider::try_from(server.endpoint()).unwrap();
|
let provider = Provider::try_from(server.endpoint()).unwrap();
|
||||||
let client = Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(1337u64)));
|
let client = Arc::new(SignerMiddleware::new(provider, wallet.with_chain_id(1337u64)));
|
||||||
|
|
|
@ -10,7 +10,7 @@ use ethers_contract::EthEvent;
|
||||||
mod derive;
|
mod derive;
|
||||||
|
|
||||||
use ethers_contract::{Contract, ContractFactory};
|
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_providers::{Http, Middleware, Provider};
|
||||||
use ethers_solc::Solc;
|
use ethers_solc::Solc;
|
||||||
use std::{convert::TryFrom, sync::Arc, time::Duration};
|
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
|
/// connects the private key to http://localhost:8545
|
||||||
pub fn connect(ganache: &GanacheInstance, idx: usize) -> Arc<Provider<Http>> {
|
pub fn connect(anvil: &AnvilInstance, idx: usize) -> Arc<Provider<Http>> {
|
||||||
let sender = ganache.addresses()[idx];
|
let sender = anvil.addresses()[idx];
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(10u64))
|
.interval(Duration::from_millis(10u64))
|
||||||
.with_sender(sender);
|
.with_sender(sender);
|
||||||
Arc::new(provider)
|
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> {
|
pub async fn deploy<M: Middleware>(client: Arc<M>, abi: Abi, bytecode: Bytes) -> Contract<M> {
|
||||||
let factory = ContractFactory::new(abi, bytecode, client);
|
let factory = ContractFactory::new(abi, bytecode, client);
|
||||||
let deployer = factory.deploy("initial value".to_string()).unwrap();
|
let deployer = factory.deploy("initial value".to_string()).unwrap();
|
||||||
|
|
|
@ -11,7 +11,7 @@ mod eth_tests {
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
abi::{Detokenize, Token, Tokenizable},
|
abi::{Detokenize, Token, Tokenizable},
|
||||||
types::{transaction::eip712::Eip712, Address, BlockId, Bytes, I256, U256},
|
types::{transaction::eip712::Eip712, Address, BlockId, Bytes, I256, U256},
|
||||||
utils::{keccak256, Ganache},
|
utils::{keccak256, Anvil},
|
||||||
};
|
};
|
||||||
use ethers_derive_eip712::*;
|
use ethers_derive_eip712::*;
|
||||||
use ethers_middleware::signer::SignerMiddleware;
|
use ethers_middleware::signer::SignerMiddleware;
|
||||||
|
@ -23,15 +23,15 @@ mod eth_tests {
|
||||||
async fn deploy_and_call_contract() {
|
async fn deploy_and_call_contract() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
|
|
||||||
// launch ganache
|
// launch anvil
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// Instantiate the clients. We assume that clients consume the provider and the wallet
|
// 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.
|
// (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 addr2 = addrs[1];
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let client2 = connect(&ganache, 1);
|
let client2 = connect(&anvil, 1);
|
||||||
|
|
||||||
// create a factory which will be used to deploy instances of the contract
|
// create a factory which will be used to deploy instances of the contract
|
||||||
let factory = ContractFactory::new(abi, bytecode, client.clone());
|
let factory = ContractFactory::new(abi, bytecode, client.clone());
|
||||||
|
@ -97,8 +97,8 @@ mod eth_tests {
|
||||||
#[cfg(feature = "abigen")]
|
#[cfg(feature = "abigen")]
|
||||||
async fn get_past_events() {
|
async fn get_past_events() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let address = client.get_accounts().await.unwrap()[0];
|
let address = client.get_accounts().await.unwrap()[0];
|
||||||
let contract = deploy(client.clone(), abi, bytecode).await;
|
let contract = deploy(client.clone(), abi, bytecode).await;
|
||||||
|
|
||||||
|
@ -136,9 +136,9 @@ mod eth_tests {
|
||||||
#[cfg(feature = "abigen")]
|
#[cfg(feature = "abigen")]
|
||||||
async fn get_events_with_meta() {
|
async fn get_events_with_meta() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let address = ganache.addresses()[0];
|
let address = anvil.addresses()[0];
|
||||||
let contract = deploy(client.clone(), abi, bytecode).await;
|
let contract = deploy(client.clone(), abi, bytecode).await;
|
||||||
|
|
||||||
// and we can fetch the events
|
// and we can fetch the events
|
||||||
|
@ -168,8 +168,8 @@ mod eth_tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn call_past_state() {
|
async fn call_past_state() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let contract = deploy(client.clone(), abi, bytecode).await;
|
let contract = deploy(client.clone(), abi, bytecode).await;
|
||||||
let deployed_block = client.get_block_number().await.unwrap();
|
let deployed_block = client.get_block_number().await.unwrap();
|
||||||
|
|
||||||
|
@ -257,24 +257,21 @@ mod eth_tests {
|
||||||
#[cfg(feature = "abigen")]
|
#[cfg(feature = "abigen")]
|
||||||
async fn watch_events() {
|
async fn watch_events() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let contract = deploy(client.clone(), abi.clone(), bytecode).await;
|
let contract = deploy(client.clone(), abi.clone(), bytecode).await;
|
||||||
|
|
||||||
// We spawn the event listener:
|
// We spawn the event listener:
|
||||||
let event = contract.event::<ValueChanged>();
|
let event = contract.event::<ValueChanged>();
|
||||||
let mut stream = event.stream().await.unwrap();
|
let mut stream = event.stream().await.unwrap();
|
||||||
assert_eq!(stream.id, 1.into());
|
|
||||||
|
|
||||||
// Also set up a subscription for the same thing
|
// 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 contract2 = ethers_contract::Contract::new(contract.address(), abi, ws);
|
||||||
let event2 = contract2.event::<ValueChanged>();
|
let event2 = contract2.event::<ValueChanged>();
|
||||||
let mut subscription = event2.subscribe().await.unwrap();
|
let mut subscription = event2.subscribe().await.unwrap();
|
||||||
assert_eq!(subscription.id, 2.into());
|
|
||||||
|
|
||||||
let mut subscription_meta = event2.subscribe().await.unwrap().with_meta();
|
let mut subscription_meta = event2.subscribe().await.unwrap().with_meta();
|
||||||
assert_eq!(subscription_meta.0.id, 3.into());
|
|
||||||
|
|
||||||
let num_calls = 3u64;
|
let num_calls = 3u64;
|
||||||
|
|
||||||
|
@ -303,12 +300,12 @@ mod eth_tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn watch_subscription_events_multiple_addresses() {
|
async fn watch_subscription_events_multiple_addresses() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let contract_1 = deploy(client.clone(), abi.clone(), bytecode.clone()).await;
|
let contract_1 = deploy(client.clone(), abi.clone(), bytecode.clone()).await;
|
||||||
let contract_2 = deploy(client.clone(), abi.clone(), bytecode).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()
|
let filter = Filter::new()
|
||||||
.address(ValueOrArray::Array(vec![contract_1.address(), contract_2.address()]));
|
.address(ValueOrArray::Array(vec![contract_1.address(), contract_2.address()]));
|
||||||
let mut stream = ws.subscribe_logs(&filter).await.unwrap();
|
let mut stream = ws.subscribe_logs(&filter).await.unwrap();
|
||||||
|
@ -332,11 +329,11 @@ mod eth_tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn signer_on_node() {
|
async fn signer_on_node() {
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
// spawn ganache
|
// spawn anvil
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// connect
|
// connect
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(std::time::Duration::from_millis(50u64));
|
.interval(std::time::Duration::from_millis(50u64));
|
||||||
|
|
||||||
|
@ -373,9 +370,8 @@ mod eth_tests {
|
||||||
// get ABI and bytecode for the SimpleStorage contract
|
// get ABI and bytecode for the SimpleStorage contract
|
||||||
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
let (abi, bytecode) = compile_contract("SimpleStorage", "SimpleStorage.sol");
|
||||||
|
|
||||||
// launch ganache
|
// launch anvil
|
||||||
// some tests expect 100 ether (-e === --wallet.defaultBalance in ether)
|
let anvil = Anvil::new().spawn();
|
||||||
let ganache = Ganache::new().arg("-e").arg("100").spawn();
|
|
||||||
|
|
||||||
// Instantiate the clients. We assume that clients consume the provider and the wallet
|
// 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.
|
// (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
|
// `client2` is used to deploy the first SimpleStorage contract
|
||||||
// `client3` is used to deploy the second SimpleStorage contract
|
// `client3` is used to deploy the second SimpleStorage contract
|
||||||
// `client4` is used to make the aggregate call
|
// `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 addr2 = addrs[1];
|
||||||
let addr3 = addrs[2];
|
let addr3 = addrs[2];
|
||||||
let client = connect(&ganache, 0);
|
let client = connect(&anvil, 0);
|
||||||
let client2 = connect(&ganache, 1);
|
let client2 = connect(&anvil, 1);
|
||||||
let client3 = connect(&ganache, 2);
|
let client3 = connect(&anvil, 2);
|
||||||
let client4 = connect(&ganache, 3);
|
let client4 = connect(&anvil, 3);
|
||||||
|
|
||||||
// create a factory which will be used to deploy instances of the contract
|
// create a factory which will be used to deploy instances of the contract
|
||||||
let multicall_factory =
|
let multicall_factory =
|
||||||
|
@ -491,7 +487,7 @@ mod eth_tests {
|
||||||
assert_eq!(return_data.2, multicall_contract.address());
|
assert_eq!(return_data.2, multicall_contract.address());
|
||||||
assert_eq!(return_data.3, 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
|
// query ETH balances of multiple addresses
|
||||||
// these keys haven't been used to do any tx
|
// these keys haven't been used to do any tx
|
||||||
// so should have 100 ETH
|
// so should have 100 ETH
|
||||||
|
@ -502,9 +498,9 @@ mod eth_tests {
|
||||||
.eth_balance_of(addrs[6]);
|
.eth_balance_of(addrs[6]);
|
||||||
|
|
||||||
let balances: (U256, U256, U256) = multicall.call().await.unwrap();
|
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.0, U256::from(10_000_000_000_000_000_000_000u128));
|
||||||
assert_eq!(balances.1, U256::from(100_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(100_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
|
// clear multicall so we can test `call_raw` w/ >16 calls
|
||||||
multicall.clear_calls();
|
multicall.clear_calls();
|
||||||
|
@ -569,13 +565,13 @@ mod eth_tests {
|
||||||
// get ABI and bytecode for the DeriveEip712Test contract
|
// get ABI and bytecode for the DeriveEip712Test contract
|
||||||
let (abi, bytecode) = compile_contract("DeriveEip712Test", "DeriveEip712Test.sol");
|
let (abi, bytecode) = compile_contract("DeriveEip712Test", "DeriveEip712Test.sol");
|
||||||
|
|
||||||
// launch ganache
|
// launch anvil
|
||||||
let ganache = Ganache::new().spawn();
|
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())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.expect("failed to instantiate provider from ganache endpoint")
|
.expect("failed to instantiate provider from anvil endpoint")
|
||||||
.interval(Duration::from_millis(10u64));
|
.interval(Duration::from_millis(10u64));
|
||||||
|
|
||||||
let client =
|
let client =
|
||||||
|
|
|
@ -210,7 +210,6 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
|
||||||
fn can_launch_anvil() {
|
fn can_launch_anvil() {
|
||||||
let _ = Anvil::new().spawn();
|
let _ = Anvil::new().spawn();
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,11 +222,13 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn configurable_startup_timeout() {
|
fn configurable_startup_timeout() {
|
||||||
Ganache::new().startup_timeout_millis(100000_u64).spawn();
|
Ganache::new().startup_timeout_millis(100000_u64).spawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
#[ignore]
|
||||||
fn default_startup_works() {
|
fn default_startup_works() {
|
||||||
Ganache::new().spawn();
|
Ganache::new().spawn();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub enum EtherscanError {
|
||||||
RateLimitExceeded,
|
RateLimitExceeded,
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
IO(#[from] std::io::Error),
|
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,
|
LocalNetworksNotSupported,
|
||||||
#[error("Unknown error: {0}")]
|
#[error("Unknown error: {0}")]
|
||||||
Unknown(String),
|
Unknown(String),
|
||||||
|
|
|
@ -336,7 +336,7 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::TransactionRequest,
|
types::TransactionRequest,
|
||||||
utils::{self, keccak256, Ganache},
|
utils::{self, keccak256, Anvil},
|
||||||
};
|
};
|
||||||
use ethers_providers::Provider;
|
use ethers_providers::Provider;
|
||||||
use ethers_signers::LocalWallet;
|
use ethers_signers::LocalWallet;
|
||||||
|
@ -360,11 +360,10 @@ mod tests {
|
||||||
let chain_id = 1u64;
|
let chain_id = 1u64;
|
||||||
|
|
||||||
// Signer middlewares now rely on a working provider which it can query the chain id from,
|
// 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
|
// with
|
||||||
let ganache =
|
let anvil = Anvil::new().args(vec!["--chain-id".to_string(), chain_id.to_string()]).spawn();
|
||||||
Ganache::new().args(vec!["--chain.chainId".to_string(), chain_id.to_string()]).spawn();
|
let provider = Provider::try_from(anvil.endpoint()).unwrap();
|
||||||
let provider = Provider::try_from(ganache.endpoint()).unwrap();
|
|
||||||
let key = "4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318"
|
let key = "4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318"
|
||||||
.parse::<LocalWallet>()
|
.parse::<LocalWallet>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -384,11 +383,11 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn ganache_consistent_chainid() {
|
async fn anvil_consistent_chainid() {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let provider = Provider::try_from(ganache.endpoint()).unwrap();
|
let provider = Provider::try_from(anvil.endpoint()).unwrap();
|
||||||
let chain_id = provider.get_chainid().await.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
|
// Intentionally do not set the chain id here so we ensure that the signer pulls the
|
||||||
// provider's chain id.
|
// provider's chain id.
|
||||||
|
@ -406,9 +405,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn ganache_consistent_chainid_not_default() {
|
async fn anvil_consistent_chainid_not_default() {
|
||||||
let ganache = Ganache::new().args(vec!["--chain.chainId", "13371337"]).spawn();
|
let anvil = Anvil::new().args(vec!["--chain-id", "13371337"]).spawn();
|
||||||
let provider = Provider::try_from(ganache.endpoint()).unwrap();
|
let provider = Provider::try_from(anvil.endpoint()).unwrap();
|
||||||
let chain_id = provider.get_chainid().await.unwrap();
|
let chain_id = provider.get_chainid().await.unwrap();
|
||||||
assert_eq!(chain_id, U256::from(13371337));
|
assert_eq!(chain_id, U256::from(13371337));
|
||||||
|
|
||||||
|
@ -429,9 +428,9 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handles_tx_from_field() {
|
async fn handles_tx_from_field() {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let acc = ganache.addresses()[0];
|
let acc = anvil.addresses()[0];
|
||||||
let provider = Provider::try_from(ganache.endpoint()).unwrap();
|
let provider = Provider::try_from(anvil.endpoint()).unwrap();
|
||||||
let key = LocalWallet::new(&mut rand::thread_rng()).with_chain_id(1u32);
|
let key = LocalWallet::new(&mut rand::thread_rng()).with_chain_id(1u32);
|
||||||
provider
|
provider
|
||||||
.send_transaction(
|
.send_transaction(
|
||||||
|
@ -459,7 +458,7 @@ mod tests {
|
||||||
assert_eq!(tx.from, client.address());
|
assert_eq!(tx.from, client.address());
|
||||||
|
|
||||||
// signing a TransactionRequest with a from address that is not the
|
// 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 request_from_other = request.from(acc);
|
||||||
let hash = *client.send_transaction(request_from_other, None).await.unwrap();
|
let hash = *client.send_transaction(request_from_other, None).await.unwrap();
|
||||||
let tx = client.get_transaction(hash).await.unwrap().unwrap();
|
let tx = client.get_transaction(hash).await.unwrap().unwrap();
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::convert::TryFrom;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use ethers_core::{types::*, utils::Ganache};
|
use ethers_core::{types::*, utils::Anvil};
|
||||||
use ethers_middleware::gas_oracle::{
|
use ethers_middleware::gas_oracle::{
|
||||||
EthGasStation, Etherchain, Etherscan, GasCategory, GasOracle, GasOracleError,
|
EthGasStation, Etherchain, Etherscan, GasCategory, GasOracle, GasOracleError,
|
||||||
GasOracleMiddleware,
|
GasOracleMiddleware,
|
||||||
|
@ -31,14 +31,14 @@ impl GasOracle for FakeGasOracle {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn using_gas_oracle() {
|
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
|
// 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;
|
let base_fee = 875000000;
|
||||||
// assign a gas oracle to use
|
// assign a gas oracle to use
|
||||||
let gas_oracle = FakeGasOracle { gas_price: (base_fee + 1337).into() };
|
let gas_oracle = FakeGasOracle { gas_price: (base_fee + 1337).into() };
|
||||||
|
|
|
@ -22,16 +22,16 @@ static WALLETS: Lazy<TestWallets> = Lazy::new(|| {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
async fn send_eth() {
|
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
|
// this private key belongs to the above mnemonic
|
||||||
let wallet: LocalWallet = ganache.keys()[0].clone().into();
|
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
||||||
let wallet2: LocalWallet = ganache.keys()[1].clone().into();
|
let wallet2: LocalWallet = anvil.keys()[1].clone().into();
|
||||||
|
|
||||||
// connect to the network
|
// connect to the network
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(10u64));
|
.interval(Duration::from_millis(10u64));
|
||||||
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||||
|
@ -156,17 +156,17 @@ async fn test_send_transaction() {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
async fn send_transaction_handles_tx_from_field() {
|
async fn send_transaction_handles_tx_from_field() {
|
||||||
use ethers_core::utils::Ganache;
|
use ethers_core::utils::Anvil;
|
||||||
|
|
||||||
// launch ganache
|
// launch anvil
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// grab 2 wallets
|
// grab 2 wallets
|
||||||
let signer: LocalWallet = ganache.keys()[0].clone().into();
|
let signer: LocalWallet = anvil.keys()[0].clone().into();
|
||||||
let other: LocalWallet = ganache.keys()[1].clone().into();
|
let other: LocalWallet = anvil.keys()[1].clone().into();
|
||||||
|
|
||||||
// connect to the network
|
// connect to the network
|
||||||
let provider = Provider::try_from(ganache.endpoint()).unwrap();
|
let provider = Provider::try_from(anvil.endpoint()).unwrap();
|
||||||
let provider =
|
let provider =
|
||||||
SignerMiddleware::new_with_provider_chain(provider, signer.clone()).await.unwrap();
|
SignerMiddleware::new_with_provider_chain(provider, signer.clone()).await.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
mod tests {
|
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::{
|
use ethers_middleware::{
|
||||||
gas_escalator::{Frequency, GasEscalatorMiddleware, GeometricGasPrice},
|
gas_escalator::{Frequency, GasEscalatorMiddleware, GeometricGasPrice},
|
||||||
gas_oracle::{EthGasStation, GasCategory, GasOracleMiddleware},
|
gas_oracle::{EthGasStation, GasCategory, GasOracleMiddleware},
|
||||||
|
@ -52,13 +52,13 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn can_stack_middlewares() {
|
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 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();
|
let address = signer.address();
|
||||||
|
|
||||||
// the base provider
|
// 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 chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||||
let signer = signer.with_chain_id(chain_id);
|
let signer = signer.with_chain_id(chain_id);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
use ethers_contract::{BaseContract, ContractFactory};
|
use ethers_contract::{BaseContract, ContractFactory};
|
||||||
use ethers_core::{abi::Abi, types::*, utils::Ganache};
|
use ethers_core::{abi::Abi, types::*, utils::Anvil};
|
||||||
use ethers_middleware::{
|
use ethers_middleware::{
|
||||||
transformer::{DsProxy, TransformerMiddleware},
|
transformer::{DsProxy, TransformerMiddleware},
|
||||||
SignerMiddleware,
|
SignerMiddleware,
|
||||||
|
@ -29,10 +29,10 @@ async fn ds_proxy_transformer() {
|
||||||
// randomness
|
// randomness
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
// spawn ganache and instantiate a signer middleware.
|
// spawn anvil and instantiate a signer middleware.
|
||||||
let ganache = Ganache::new().spawn();
|
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())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(10u64));
|
.interval(Duration::from_millis(10u64));
|
||||||
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||||
|
@ -88,10 +88,10 @@ async fn ds_proxy_code() {
|
||||||
// randomness
|
// randomness
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
// spawn ganache and instantiate a signer middleware.
|
// spawn anvil and instantiate a signer middleware.
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let wallet: LocalWallet = ganache.keys()[1].clone().into();
|
let wallet: LocalWallet = anvil.keys()[1].clone().into();
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(10u64));
|
.interval(Duration::from_millis(10u64));
|
||||||
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
let chain_id = provider.get_chainid().await.unwrap().as_u64();
|
||||||
|
|
|
@ -30,15 +30,15 @@ use wasm_timer::Delay;
|
||||||
///
|
///
|
||||||
///```
|
///```
|
||||||
/// # use ethers_providers::{Provider, Http};
|
/// # use ethers_providers::{Provider, Http};
|
||||||
/// # use ethers_core::utils::Ganache;
|
/// # use ethers_core::utils::Anvil;
|
||||||
/// # use std::convert::TryFrom;
|
/// # use std::convert::TryFrom;
|
||||||
/// use ethers_providers::Middleware;
|
/// use ethers_providers::Middleware;
|
||||||
/// use ethers_core::types::TransactionRequest;
|
/// use ethers_core::types::TransactionRequest;
|
||||||
///
|
///
|
||||||
/// # #[tokio::main(flavor = "current_thread")]
|
/// # #[tokio::main(flavor = "current_thread")]
|
||||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
/// # let ganache = Ganache::new().spawn();
|
/// # let anvil = Anvil::new().spawn();
|
||||||
/// # let client = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
|
/// # let client = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
||||||
/// # let accounts = client.get_accounts().await?;
|
/// # let accounts = client.get_accounts().await?;
|
||||||
/// # let from = accounts[0];
|
/// # let from = accounts[0];
|
||||||
/// # let to = accounts[1];
|
/// # let to = accounts[1];
|
||||||
|
|
|
@ -1204,7 +1204,7 @@ impl<P: JsonRpcClient> Provider<P> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[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> {
|
pub async fn mine(&self, num_blocks: usize) -> Result<(), ProviderError> {
|
||||||
for _ in 0..num_blocks {
|
for _ in 0..num_blocks {
|
||||||
self.inner.request::<_, U256>("evm_mine", None::<()>).await.map_err(Into::into)?;
|
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_providers::{Provider, Http, Middleware, DevRpcMiddleware};
|
||||||
/// use ethers_core::types::TransactionRequest;
|
/// use ethers_core::types::TransactionRequest;
|
||||||
/// use ethers_core::utils::Ganache;
|
/// use ethers_core::utils::Anvil;
|
||||||
/// use std::convert::TryFrom;
|
/// use std::convert::TryFrom;
|
||||||
///
|
///
|
||||||
/// # #[tokio::main(flavor = "current_thread")]
|
/// # #[tokio::main(flavor = "current_thread")]
|
||||||
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
/// # 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()).unwrap();
|
/// let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
||||||
/// let client = DevRpcMiddleware::new(provider);
|
/// let client = DevRpcMiddleware::new(provider);
|
||||||
///
|
///
|
||||||
/// // snapshot the initial state
|
/// // snapshot the initial state
|
||||||
|
@ -1450,7 +1450,7 @@ pub mod dev_rpc {
|
||||||
Self(inner)
|
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>> {
|
pub async fn snapshot(&self) -> Result<U256, DevRpcMiddlewareError<M>> {
|
||||||
self.provider().request::<(), U256>("evm_snapshot", ()).await.map_err(From::from)
|
self.provider().request::<(), U256>("evm_snapshot", ()).await.map_err(From::from)
|
||||||
}
|
}
|
||||||
|
@ -1474,14 +1474,13 @@ pub mod dev_rpc {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{Http, Provider};
|
use crate::{Http, Provider};
|
||||||
use ethers_core::utils::Ganache;
|
use ethers_core::utils::Anvil;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_snapshot() {
|
async fn test_snapshot() {
|
||||||
// launch ganache
|
let anvil = Anvil::new().spawn();
|
||||||
let ganache = Ganache::new().spawn();
|
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
|
|
||||||
let client = DevRpcMiddleware::new(provider);
|
let client = DevRpcMiddleware::new(provider);
|
||||||
|
|
||||||
// snapshot initial state
|
// snapshot initial state
|
||||||
|
@ -1544,7 +1543,7 @@ mod tests {
|
||||||
types::{
|
types::{
|
||||||
transaction::eip2930::AccessList, Eip1559TransactionRequest, TransactionRequest, H256,
|
transaction::eip2930::AccessList, Eip1559TransactionRequest, TransactionRequest, H256,
|
||||||
},
|
},
|
||||||
utils::Geth,
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
|
@ -1625,7 +1624,7 @@ mod tests {
|
||||||
#[cfg_attr(feature = "celo", ignore)]
|
#[cfg_attr(feature = "celo", ignore)]
|
||||||
async fn test_new_block_filter() {
|
async fn test_new_block_filter() {
|
||||||
let num_blocks = 3;
|
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())
|
let provider = Provider::<Http>::try_from(geth.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(1000));
|
.interval(Duration::from_millis(1000));
|
||||||
|
@ -1644,16 +1643,15 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg_attr(feature = "celo", ignore)]
|
#[cfg_attr(feature = "celo", ignore)]
|
||||||
async fn test_is_signer() {
|
async fn test_is_signer() {
|
||||||
use ethers_core::utils::Ganache;
|
use ethers_core::utils::Anvil;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider =
|
||||||
.unwrap()
|
Provider::<Http>::try_from(anvil.endpoint()).unwrap().with_sender(anvil.addresses()[0]);
|
||||||
.with_sender(ganache.addresses()[0]);
|
|
||||||
assert!(provider.is_signer().await);
|
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);
|
assert!(!provider.is_signer().await);
|
||||||
|
|
||||||
let sender = Address::from_str("635B4764D1939DfAcD3a8014726159abC277BecC")
|
let sender = Address::from_str("635B4764D1939DfAcD3a8014726159abC277BecC")
|
||||||
|
@ -1670,7 +1668,7 @@ mod tests {
|
||||||
async fn test_new_pending_txs_filter() {
|
async fn test_new_pending_txs_filter() {
|
||||||
let num_txs = 5;
|
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())
|
let provider = Provider::<Http>::try_from(geth.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(1000));
|
.interval(Duration::from_millis(1000));
|
||||||
|
@ -1693,10 +1691,10 @@ mod tests {
|
||||||
async fn receipt_on_unmined_tx() {
|
async fn receipt_on_unmined_tx() {
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::TransactionRequest,
|
types::TransactionRequest,
|
||||||
utils::{parse_ether, Ganache},
|
utils::{parse_ether, Anvil},
|
||||||
};
|
};
|
||||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
let anvil = Anvil::new().block_time(2u64).spawn();
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint()).unwrap();
|
let provider = Provider::<Http>::try_from(anvil.endpoint()).unwrap();
|
||||||
|
|
||||||
let accounts = provider.get_accounts().await.unwrap();
|
let accounts = provider.get_accounts().await.unwrap();
|
||||||
let tx = TransactionRequest::pay(accounts[0], parse_ether(1u64).unwrap()).from(accounts[0]);
|
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
|
// Celo blocks can not get parsed when used with Ganache
|
||||||
#[cfg(not(feature = "celo"))]
|
#[cfg(not(feature = "celo"))]
|
||||||
async fn block_subscribe() {
|
async fn block_subscribe() {
|
||||||
use ethers_core::utils::Ganache;
|
use ethers_core::utils::Anvil;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
let anvil = Anvil::new().block_time(2u64).spawn();
|
||||||
let provider = Provider::connect(ganache.ws_endpoint()).await.unwrap();
|
let provider = Provider::connect(anvil.ws_endpoint()).await.unwrap();
|
||||||
|
|
||||||
let stream = provider.subscribe_blocks().await.unwrap();
|
let stream = provider.subscribe_blocks().await.unwrap();
|
||||||
let blocks = stream.take(3).map(|x| x.number.unwrap().as_u64()).collect::<Vec<_>>().await;
|
let blocks = stream.take(3).map(|x| x.number.unwrap().as_u64()).collect::<Vec<_>>().await;
|
||||||
|
|
|
@ -265,7 +265,7 @@ mod tests {
|
||||||
use crate::{Http, Ws};
|
use crate::{Http, Ws};
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::{TransactionReceipt, TransactionRequest},
|
types::{TransactionReceipt, TransactionRequest},
|
||||||
utils::{Ganache, Geth},
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
use futures_util::{FutureExt, StreamExt};
|
use futures_util::{FutureExt, StreamExt};
|
||||||
use std::{collections::HashSet, convert::TryFrom};
|
use std::{collections::HashSet, convert::TryFrom};
|
||||||
|
@ -273,7 +273,7 @@ mod tests {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn can_stream_pending_transactions() {
|
async fn can_stream_pending_transactions() {
|
||||||
let num_txs = 5;
|
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())
|
let provider = Provider::<Http>::try_from(geth.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(1000));
|
.interval(Duration::from_millis(1000));
|
||||||
|
@ -327,17 +327,17 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn can_stream_transactions() {
|
async fn can_stream_transactions() {
|
||||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
let anvil = Anvil::new().block_time(2u64).spawn();
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider =
|
||||||
.unwrap()
|
Provider::<Http>::try_from(anvil.endpoint()).unwrap().with_sender(anvil.addresses()[0]);
|
||||||
.with_sender(ganache.addresses()[0]);
|
|
||||||
|
|
||||||
let accounts = provider.get_accounts().await.unwrap();
|
let accounts = provider.get_accounts().await.unwrap();
|
||||||
|
|
||||||
let tx = TransactionRequest::new().from(accounts[0]).to(accounts[0]).value(1e18 as u64);
|
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 =
|
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()
|
provider.send_transaction(tx, None).await.unwrap().await.unwrap()
|
||||||
}))
|
}))
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -488,13 +488,13 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::{Block, TxHash, U256},
|
types::{Block, TxHash, U256},
|
||||||
utils::Ganache,
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn request() {
|
async fn request() {
|
||||||
let ganache = Ganache::new().block_time(1u64).spawn();
|
let anvil = Anvil::new().block_time(1u64).spawn();
|
||||||
let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap();
|
let ws = Ws::connect(anvil.ws_endpoint()).await.unwrap();
|
||||||
|
|
||||||
let block_num: U256 = ws.request("eth_blockNumber", ()).await.unwrap();
|
let block_num: U256 = ws.request("eth_blockNumber", ()).await.unwrap();
|
||||||
std::thread::sleep(std::time::Duration::new(3, 0));
|
std::thread::sleep(std::time::Duration::new(3, 0));
|
||||||
|
@ -504,8 +504,8 @@ mod tests {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn subscription() {
|
async fn subscription() {
|
||||||
let ganache = Ganache::new().block_time(1u64).spawn();
|
let anvil = Anvil::new().block_time(1u64).spawn();
|
||||||
let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap();
|
let ws = Ws::connect(anvil.ws_endpoint()).await.unwrap();
|
||||||
|
|
||||||
// Subscribing requires sending the sub request and then subscribing to
|
// Subscribing requires sending the sub request and then subscribing to
|
||||||
// the returned sub_id
|
// the returned sub_id
|
||||||
|
@ -519,14 +519,13 @@ mod tests {
|
||||||
blocks.push(block.number.unwrap_or_default().as_u64());
|
blocks.push(block.number.unwrap_or_default().as_u64());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(sub_id, 1.into());
|
|
||||||
assert_eq!(blocks, vec![1, 2, 3])
|
assert_eq!(blocks, vec![1, 2, 3])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn deserialization_fails() {
|
async fn deserialization_fails() {
|
||||||
let ganache = Ganache::new().block_time(1u64).spawn();
|
let anvil = Anvil::new().block_time(1u64).spawn();
|
||||||
let (ws, _) = tokio_tungstenite::connect_async(ganache.ws_endpoint()).await.unwrap();
|
let (ws, _) = tokio_tungstenite::connect_async(anvil.ws_endpoint()).await.unwrap();
|
||||||
let malformed_data = String::from("not a valid message");
|
let malformed_data = String::from("not a valid message");
|
||||||
let (_, stream) = mpsc::unbounded();
|
let (_, stream) = mpsc::unbounded();
|
||||||
let resp = WsServer::new(ws, stream).handle_text(malformed_data).await;
|
let resp = WsServer::new(ws, stream).handle_text(malformed_data).await;
|
||||||
|
|
|
@ -7,7 +7,7 @@ mod eth_tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::{Address, BlockId, TransactionRequest, H256},
|
types::{Address, BlockId, TransactionRequest, H256},
|
||||||
utils::Ganache,
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
use ethers_providers::RINKEBY;
|
use ethers_providers::RINKEBY;
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ mod eth_tests {
|
||||||
use ethers_core::types::H256;
|
use ethers_core::types::H256;
|
||||||
use ethers_providers::{StreamExt, Ws};
|
use ethers_providers::{StreamExt, Ws};
|
||||||
|
|
||||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
let anvil = Anvil::new().block_time(2u64).spawn();
|
||||||
let (ws, _) = tokio_tungstenite::connect_async(ganache.ws_endpoint()).await.unwrap();
|
let (ws, _) = tokio_tungstenite::connect_async(anvil.ws_endpoint()).await.unwrap();
|
||||||
let provider = Provider::new(Ws::new(ws)).interval(Duration::from_millis(500u64));
|
let provider = Provider::new(Ws::new(ws)).interval(Duration::from_millis(500u64));
|
||||||
|
|
||||||
let stream = provider.watch_blocks().await.unwrap().stream();
|
let stream = provider.watch_blocks().await.unwrap().stream();
|
||||||
|
@ -56,9 +56,9 @@ mod eth_tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn pending_txs_with_confirmations_ganache() {
|
async fn pending_txs_with_confirmations_anvil() {
|
||||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
let anvil = Anvil::new().block_time(2u64).spawn();
|
||||||
let provider = Provider::<Http>::try_from(ganache.endpoint())
|
let provider = Provider::<Http>::try_from(anvil.endpoint())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.interval(Duration::from_millis(500u64));
|
.interval(Duration::from_millis(500u64));
|
||||||
let accounts = provider.get_accounts().await.unwrap();
|
let accounts = provider.get_accounts().await.unwrap();
|
||||||
|
@ -66,10 +66,10 @@ mod eth_tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn websocket_pending_txs_with_confirmations_ganache() {
|
async fn websocket_pending_txs_with_confirmations_anvil() {
|
||||||
use ethers_providers::Ws;
|
use ethers_providers::Ws;
|
||||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
let anvil = Anvil::new().block_time(2u64).spawn();
|
||||||
let ws = Ws::connect(ganache.ws_endpoint()).await.unwrap();
|
let ws = Ws::connect(anvil.ws_endpoint()).await.unwrap();
|
||||||
let provider = Provider::new(ws);
|
let provider = Provider::new(ws);
|
||||||
let accounts = provider.get_accounts().await.unwrap();
|
let accounts = provider.get_accounts().await.unwrap();
|
||||||
generic_pending_txs_test(provider, accounts[0]).await;
|
generic_pending_txs_test(provider, accounts[0]).await;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
#![cfg(not(target_arch = "wasm32"))]
|
#![cfg(not(target_arch = "wasm32"))]
|
||||||
use ethers_core::{
|
use ethers_core::{
|
||||||
types::{TransactionRequest, U256},
|
types::{TransactionRequest, U256},
|
||||||
utils::Geth,
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
use ethers_providers::{Http, Middleware, Provider};
|
use ethers_providers::{Http, Middleware, Provider};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn txpool() {
|
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 provider = Provider::<Http>::try_from(geth.endpoint()).unwrap();
|
||||||
|
|
||||||
let account = provider.get_accounts().await.unwrap()[0];
|
let account = provider.get_accounts().await.unwrap()[0];
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use ethers::{
|
use ethers::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
solc::{Project, ProjectPathsConfig},
|
solc::{Project, ProjectPathsConfig},
|
||||||
utils::Ganache,
|
utils::Anvil,
|
||||||
};
|
};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use std::{convert::TryFrom, path::PathBuf, sync::Arc, time::Duration};
|
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 contract = output.find("SimpleStorage").expect("could not find contract").clone();
|
||||||
let (abi, bytecode, _) = contract.into_parts();
|
let (abi, bytecode, _) = contract.into_parts();
|
||||||
|
|
||||||
// 2. instantiate our wallet & ganache
|
// 2. instantiate our wallet & anvil
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let wallet: LocalWallet = ganache.keys()[0].clone().into();
|
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
||||||
|
|
||||||
// 3. connect to the network
|
// 3. connect to the network
|
||||||
let provider =
|
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
|
// 4. instantiate the client with the wallet
|
||||||
let client = SignerMiddleware::new(provider, 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());
|
let factory = ContractFactory::new(abi.unwrap(), bytecode.unwrap(), client.clone());
|
||||||
|
|
||||||
// 6. deploy it with the constructor arguments
|
// 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
|
// 7. get the contract's address
|
||||||
let addr = contract.address();
|
let addr = contract.address();
|
||||||
|
@ -59,7 +59,7 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
// 9. call the `setValue` method
|
// 9. call the `setValue` method
|
||||||
// (first `await` returns a PendingTransaction, second one waits for it to be mined)
|
// (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
|
// 10. get all events
|
||||||
let logs = contract.value_changed_filter().from_block(0u64).query().await?;
|
let logs = contract.value_changed_filter().from_block(0u64).query().await?;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use std::{convert::TryFrom, path::Path, sync::Arc, time::Duration};
|
use std::{convert::TryFrom, path::Path, sync::Arc, time::Duration};
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ abigen!(
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// 1. compile the contract (note this requires that you are inside the `examples` directory) and
|
// 1. compile the contract (note this requires that you are inside the `examples` directory) and
|
||||||
// launch ganache
|
// launch anvil
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// set the path to the contract, `CARGO_MANIFEST_DIR` points to the directory containing the
|
// 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
|
// 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();
|
compiled.find("SimpleStorage").expect("could not find contract").into_parts_or_default();
|
||||||
|
|
||||||
// 2. instantiate our wallet
|
// 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
|
// 3. connect to the network
|
||||||
let provider =
|
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
|
// 4. instantiate the client with the wallet
|
||||||
let client = SignerMiddleware::new(provider, wallet);
|
let client = SignerMiddleware::new(provider, wallet);
|
||||||
|
@ -38,7 +38,7 @@ async fn main() -> Result<()> {
|
||||||
let factory = ContractFactory::new(abi, bytecode, client.clone());
|
let factory = ContractFactory::new(abi, bytecode, client.clone());
|
||||||
|
|
||||||
// 6. deploy it with the constructor arguments
|
// 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
|
// 7. get the contract's address
|
||||||
let addr = contract.address();
|
let addr = contract.address();
|
||||||
|
@ -48,7 +48,7 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
// 9. call the `setValue` method
|
// 9. call the `setValue` method
|
||||||
// (first `await` returns a PendingTransaction, second one waits for it to be mined)
|
// (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
|
// 10. get all events
|
||||||
let logs = contract.value_changed_filter().from_block(0u64).query().await?;
|
let logs = contract.value_changed_filter().from_block(0u64).query().await?;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use std::{convert::TryFrom, sync::Arc, time::Duration};
|
use std::{convert::TryFrom, sync::Arc, time::Duration};
|
||||||
|
|
||||||
|
@ -11,22 +11,22 @@ abigen!(Greeter, "ethers-contract/tests/solidity-contracts/greeter.json",);
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// 1. compile the contract (note this requires that you are inside the `examples` directory) and
|
// 1. compile the contract (note this requires that you are inside the `examples` directory) and
|
||||||
// launch ganache
|
// launch anvil
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// 2. instantiate our wallet
|
// 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
|
// 3. connect to the network
|
||||||
let provider =
|
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
|
// 4. instantiate the client with the wallet
|
||||||
let client = Arc::new(SignerMiddleware::new(provider, 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 =
|
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
|
// 6. call contract function
|
||||||
let greeting = greeter_contract.greet().call().await.unwrap();
|
let greeting = greeter_contract.greet().call().await.unwrap();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! Main entry point for ContractMonitor
|
//! Main entry point for ContractMonitor
|
||||||
|
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use std::{convert::TryFrom, sync::Arc, time::Duration};
|
use std::{convert::TryFrom, sync::Arc, time::Duration};
|
||||||
|
|
||||||
abigen!(VerifierContract, "ethers-contract/tests/solidity-contracts/verifier_abi.json");
|
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.
|
/// have structs as input.
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
let provider =
|
let provider =
|
||||||
Provider::<Http>::try_from(ganache.endpoint())?.interval(Duration::from_millis(10u64));
|
Provider::<Http>::try_from(anvil.endpoint())?.interval(Duration::from_millis(10u64));
|
||||||
let wallet: LocalWallet = ganache.keys()[0].clone().into();
|
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
||||||
|
|
||||||
let client = SignerMiddleware::new(provider, wallet);
|
let client = SignerMiddleware::new(provider, wallet);
|
||||||
let client = Arc::new(client);
|
let client = Arc::new(client);
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
// fork mainnet
|
// fork mainnet
|
||||||
let ganache = Ganache::new()
|
let anvil =
|
||||||
.fork("https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
Anvil::new().fork("https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27").spawn();
|
||||||
.spawn();
|
let from = anvil.addresses()[0].clone();
|
||||||
let from = ganache.addresses()[0].clone();
|
|
||||||
// connect to the network
|
// 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
|
// craft the transaction
|
||||||
let tx = TransactionRequest::new().to("vitalik.eth").value(100_000);
|
let tx = TransactionRequest::new().to("vitalik.eth").value(100_000);
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
let wallet: LocalWallet = ganache.keys()[0].clone().into();
|
let wallet: LocalWallet = anvil.keys()[0].clone().into();
|
||||||
let wallet2: LocalWallet = ganache.keys()[1].clone().into();
|
let wallet2: LocalWallet = anvil.keys()[1].clone().into();
|
||||||
|
|
||||||
// connect to the network
|
// 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
|
// connect the wallet to the provider
|
||||||
let client = SignerMiddleware::new(provider, wallet);
|
let client = SignerMiddleware::new(provider, wallet);
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
//! Example usage for the `QuorumProvider` that requests multiple backends and only returns
|
//! Example usage for the `QuorumProvider` that requests multiple backends and only returns
|
||||||
//! a value if the configured `Quorum` was reached.
|
//! a value if the configured `Quorum` was reached.
|
||||||
|
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use std::{str::FromStr, time::Duration};
|
use std::{str::FromStr, time::Duration};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> eyre::Result<()> {
|
async fn main() -> eyre::Result<()> {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// create a quorum provider with some providers
|
// create a quorum provider with some providers
|
||||||
let quorum = QuorumProvider::dyn_rpc()
|
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(
|
.add_provider(WeightedProvider::with_weight(
|
||||||
Box::new(Ws::connect(ganache.ws_endpoint()).await?),
|
Box::new(Ws::connect(anvil.ws_endpoint()).await?),
|
||||||
2,
|
2,
|
||||||
))
|
))
|
||||||
.add_provider(WeightedProvider::with_weight(
|
.add_provider(WeightedProvider::with_weight(
|
||||||
Box::new(Ws::connect(ganache.ws_endpoint()).await?),
|
Box::new(Ws::connect(anvil.ws_endpoint()).await?),
|
||||||
2,
|
2,
|
||||||
))
|
))
|
||||||
// the quorum provider will yield the response if >50% of the weighted inner provider
|
// the quorum provider will yield the response if >50% of the weighted inner provider
|
||||||
|
|
|
@ -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
|
//! for read ops
|
||||||
|
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use std::{str::FromStr, time::Duration};
|
use std::{str::FromStr, time::Duration};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> eyre::Result<()> {
|
async fn main() -> eyre::Result<()> {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
let http = Http::from_str(&ganache.endpoint())?;
|
let http = Http::from_str(&anvil.endpoint())?;
|
||||||
let ws = Ws::connect(ganache.ws_endpoint()).await?;
|
let ws = Ws::connect(anvil.ws_endpoint()).await?;
|
||||||
|
|
||||||
let provider = Provider::rw(http, ws).interval(Duration::from_millis(10u64));
|
let provider = Provider::rw(http, ws).interval(Duration::from_millis(10u64));
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use eyre::Result;
|
use eyre::Result;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
let ganache = Ganache::new().spawn();
|
let anvil = Anvil::new().spawn();
|
||||||
|
|
||||||
// connect to the network
|
// 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 accounts = provider.get_accounts().await?;
|
||||||
let from = accounts[0];
|
let from = accounts[0];
|
||||||
let to = accounts[1];
|
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 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 balance_before = provider.get_balance(from, None).await?;
|
||||||
|
let nonce1 = provider.get_transaction_count(from, None).await?;
|
||||||
|
|
||||||
// broadcast it via the eth_sendTransaction API
|
// broadcast it via the eth_sendTransaction API
|
||||||
let tx = provider.send_transaction(tx, None).await?.await?;
|
let tx = provider.send_transaction(tx, None).await?.await?;
|
||||||
|
|
||||||
println!("{}", serde_json::to_string(&tx)?);
|
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 =
|
assert!(nonce1 < nonce2);
|
||||||
provider.get_transaction_count(from, Some(BlockNumber::Number(0.into()).into())).await?;
|
|
||||||
|
|
||||||
assert!(nonce2 < nonce1);
|
|
||||||
|
|
||||||
let balance_after = provider.get_balance(from, None).await?;
|
let balance_after = provider.get_balance(from, None).await?;
|
||||||
assert!(balance_after < balance_before);
|
assert!(balance_after < balance_before);
|
||||||
|
|
|
@ -10,7 +10,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// (here: mainnet) for EIP155 support.
|
// (here: mainnet) for EIP155 support.
|
||||||
// EIP1559 support
|
// EIP1559 support
|
||||||
// No EIP712 support yet.
|
// 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);
|
let client = SignerMiddleware::new(provider, trezor);
|
||||||
|
|
||||||
// Create and broadcast a transaction (ENS disabled!)
|
// Create and broadcast a transaction (ENS disabled!)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use ethers::{prelude::*, utils::Ganache};
|
use ethers::{prelude::*, utils::Anvil};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> eyre::Result<()> {
|
async fn main() -> eyre::Result<()> {
|
||||||
let ganache = Ganache::new().block_time(1u64).spawn();
|
let anvil = Anvil::new().block_time(1u64).spawn();
|
||||||
let ws = Ws::connect(ganache.ws_endpoint()).await?;
|
let ws = Ws::connect(anvil.ws_endpoint()).await?;
|
||||||
let provider = Provider::new(ws).interval(Duration::from_millis(2000));
|
let provider = Provider::new(ws).interval(Duration::from_millis(2000));
|
||||||
let mut stream = provider.watch_blocks().await?.take(5);
|
let mut stream = provider.watch_blocks().await?.take(5);
|
||||||
while let Some(block) = stream.next().await {
|
while let Some(block) = stream.next().await {
|
||||||
|
|
|
@ -1,7 +1,24 @@
|
||||||
set -e
|
set -e
|
||||||
# shellcheck shell=bash
|
# 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
|
# run all examples
|
||||||
for file in examples/*.rs; do
|
for file in examples/*.rs; do
|
||||||
name="$(echo "$file" | cut -f 1 -d '.')"
|
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")"
|
cargo r -p ethers --example "$(basename "$name")"
|
||||||
done
|
done
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
//!
|
//!
|
||||||
//! Contains all the [necessary data structures](core::types) for interacting
|
//! Contains all the [necessary data structures](core::types) for interacting
|
||||||
//! with Ethereum, along with cryptographic utilities for signing and verifying
|
//! 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
|
//! are also provided as helpers. To simplify your imports, consider using the re-exported
|
||||||
//! modules described in the next subsection.
|
//! modules described in the next subsection.
|
||||||
//!
|
//!
|
||||||
|
|
Loading…
Reference in New Issue