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:
|
||||
- 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
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -210,7 +210,6 @@ mod tests {
|
|||
use super::*;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn can_launch_anvil() {
|
||||
let _ = Anvil::new().spawn();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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() };
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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!)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
//!
|
||||
|
|
Loading…
Reference in New Issue