integrate ENS at the provider level
This commit is contained in:
parent
2e5ef68219
commit
6109003559
|
@ -82,11 +82,11 @@ impl Context {
|
|||
|
||||
#struct_decl
|
||||
|
||||
impl<'a, S: Signer, P: JsonRpcClient> #name<'a, S, P> {
|
||||
impl<'a, P: JsonRpcClient, N: Network, S: Signer> #name<'a, P, N, S> {
|
||||
/// Creates a new contract instance with the specified `ethers`
|
||||
/// client at the given `Address`. The contract derefs to a `ethers::Contract`
|
||||
/// object
|
||||
pub fn new<T: Into<Address>>(address: T, client: &'a Client<'a, S, P>) -> Self {
|
||||
pub fn new<T: Into<Address>>(address: T, client: &'a Client<'a, P, N, S>) -> Self {
|
||||
let contract = Contract::new(client, &ABI, address.into());
|
||||
Self(contract)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ pub(crate) fn imports() -> TokenStream {
|
|||
Contract, ContractCall, Event, Lazy,
|
||||
signers::{Client, Signer},
|
||||
types::*, // import all the types so that we can codegen for everything
|
||||
providers::JsonRpcClient,
|
||||
providers::{JsonRpcClient, networks::Network},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -29,17 +29,17 @@ pub(crate) fn struct_declaration(cx: &Context) -> TokenStream {
|
|||
|
||||
// Struct declaration
|
||||
#[derive(Clone)]
|
||||
pub struct #name<'a, S, P>(Contract<'a, S, P>);
|
||||
pub struct #name<'a, P, N, S>(Contract<'a, P, N, S>);
|
||||
|
||||
|
||||
// Deref to the inner contract in order to access more specific functions functions
|
||||
impl<'a, S, P> std::ops::Deref for #name<'a, S, P> {
|
||||
type Target = Contract<'a, S, P>;
|
||||
impl<'a, P, N, S> std::ops::Deref for #name<'a, P, N, S> {
|
||||
type Target = Contract<'a, P, N, S>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.0 }
|
||||
}
|
||||
|
||||
impl<'a, S: Signer, P: JsonRpcClient> std::fmt::Debug for #name<'a, S, P> {
|
||||
impl<'a, P: JsonRpcClient, N: Network, S: Signer> std::fmt::Debug for #name<'a, P, N, S> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.debug_tuple(stringify!(#name))
|
||||
.field(&self.address())
|
||||
|
|
|
@ -52,7 +52,7 @@ fn expand_filter(event: &Event) -> Result<TokenStream> {
|
|||
Ok(quote! {
|
||||
|
||||
#doc
|
||||
pub fn #name<'b>(&'a self) -> Event<'a, 'b, P, #result> where 'a: 'b, {
|
||||
pub fn #name<'b>(&'a self) -> Event<'a, 'b, P, N, #result> where 'a: 'b, {
|
||||
self.0.event(#ev_name).expect("event not found (this should never happen)")
|
||||
}
|
||||
})
|
||||
|
@ -314,7 +314,7 @@ mod tests {
|
|||
|
||||
assert_quote!(expand_filter(&event).unwrap(), {
|
||||
#[doc = "Gets the contract's `Transfer` event"]
|
||||
pub fn transfer<'b>(&'a self) -> Event<'a, 'b, P, Transfer>
|
||||
pub fn transfer<'b>(&'a self) -> Event<'a, 'b, P, N, Transfer>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
|
|
|
@ -40,9 +40,9 @@ fn expand_function(function: &Function, alias: Option<Ident>) -> Result<TokenStr
|
|||
let outputs = expand_fn_outputs(&function.outputs)?;
|
||||
|
||||
let result = if function.constant {
|
||||
quote! { ContractCall<'a, S, P, #outputs> }
|
||||
quote! { ContractCall<'a, P, N, S, #outputs> }
|
||||
} else {
|
||||
quote! { ContractCall<'a, S, P, H256> }
|
||||
quote! { ContractCall<'a, P, N, S, H256> }
|
||||
};
|
||||
|
||||
let arg = expand_inputs_call_arg(&function.inputs);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ethers_abi::{Detokenize, Function};
|
||||
use ethers_providers::JsonRpcClient;
|
||||
use ethers_providers::{networks::Network, JsonRpcClient};
|
||||
use ethers_signers::{Client, Signer};
|
||||
use ethers_types::{Address, BlockNumber, TransactionRequest, H256, U256};
|
||||
|
||||
|
@ -7,15 +7,15 @@ use std::{fmt::Debug, marker::PhantomData};
|
|||
|
||||
use thiserror::Error as ThisError;
|
||||
|
||||
pub struct ContractCall<'a, S, P, D> {
|
||||
pub struct ContractCall<'a, P, N, S, D> {
|
||||
pub(crate) tx: TransactionRequest,
|
||||
pub(crate) function: Function,
|
||||
pub(crate) client: &'a Client<'a, S, P>,
|
||||
pub(crate) client: &'a Client<'a, P, N, S>,
|
||||
pub(crate) block: Option<BlockNumber>,
|
||||
pub(crate) datatype: PhantomData<D>,
|
||||
}
|
||||
|
||||
impl<'a, S, P, D: Detokenize> ContractCall<'a, S, P, D> {
|
||||
impl<'a, P, N, S, D: Detokenize> ContractCall<'a, S, P, N, D> {
|
||||
/// Sets the `from` field in the transaction to the provided value
|
||||
pub fn from<T: Into<Address>>(mut self, from: T) -> Self {
|
||||
self.tx.from = Some(from.into());
|
||||
|
@ -55,9 +55,13 @@ where
|
|||
CallError(P::Error),
|
||||
}
|
||||
|
||||
impl<'a, S: Signer, P: JsonRpcClient, D: Detokenize> ContractCall<'a, S, P, D>
|
||||
impl<'a, P, N, S, D> ContractCall<'a, P, N, S, D>
|
||||
where
|
||||
S: Signer,
|
||||
P: JsonRpcClient,
|
||||
P::Error: 'static,
|
||||
N: Network,
|
||||
D: Detokenize,
|
||||
{
|
||||
/// Queries the blockchain via an `eth_call` for the provided transaction.
|
||||
///
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{ContractCall, Event};
|
||||
|
||||
use ethers_abi::{Abi, Detokenize, Error, EventExt, Function, FunctionExt, Tokenize};
|
||||
use ethers_providers::JsonRpcClient;
|
||||
use ethers_providers::{networks::Network, JsonRpcClient};
|
||||
use ethers_signers::{Client, Signer};
|
||||
use ethers_types::{Address, Filter, Selector, TransactionRequest};
|
||||
|
||||
|
@ -13,8 +13,8 @@ use std::{collections::HashMap, fmt::Debug, hash::Hash, marker::PhantomData};
|
|||
// TODO: Should we separate the lifetimes for the two references?
|
||||
// https://stackoverflow.com/a/29862184
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Contract<'a, S, P> {
|
||||
client: &'a Client<'a, S, P>,
|
||||
pub struct Contract<'a, P, N, S> {
|
||||
client: &'a Client<'a, P, N, S>,
|
||||
abi: &'a Abi,
|
||||
address: Address,
|
||||
|
||||
|
@ -25,9 +25,9 @@ pub struct Contract<'a, S, P> {
|
|||
methods: HashMap<Selector, (String, usize)>,
|
||||
}
|
||||
|
||||
impl<'a, S: Signer, P: JsonRpcClient> Contract<'a, S, P> {
|
||||
impl<'a, P: JsonRpcClient, N: Network, S: Signer> Contract<'a, P, N, S> {
|
||||
/// Creates a new contract from the provided client, abi and address
|
||||
pub fn new(client: &'a Client<'a, S, P>, abi: &'a Abi, address: Address) -> Self {
|
||||
pub fn new(client: &'a Client<'a, P, N, S>, abi: &'a Abi, address: Address) -> Self {
|
||||
let methods = create_mapping(&abi.functions, |function| function.selector());
|
||||
|
||||
Self {
|
||||
|
@ -41,7 +41,7 @@ impl<'a, S: Signer, P: JsonRpcClient> Contract<'a, S, P> {
|
|||
/// Returns an `Event` builder for the provided event name. If there are
|
||||
/// multiple functions with the same name due to overloading, consider using
|
||||
/// the `method_hash` method instead, since this will use the first match.
|
||||
pub fn event<'b, D: Detokenize>(&'a self, name: &str) -> Result<Event<'a, 'b, P, D>, Error>
|
||||
pub fn event<'b, D: Detokenize>(&'a self, name: &str) -> Result<Event<'a, 'b, P, N, D>, Error>
|
||||
where
|
||||
'a: 'b,
|
||||
{
|
||||
|
@ -62,7 +62,7 @@ impl<'a, S: Signer, P: JsonRpcClient> Contract<'a, S, P> {
|
|||
&self,
|
||||
name: &str,
|
||||
args: T,
|
||||
) -> Result<ContractCall<'a, S, P, D>, Error> {
|
||||
) -> Result<ContractCall<'a, P, N, S, D>, Error> {
|
||||
// get the function
|
||||
let function = self.abi.function(name)?;
|
||||
self.method_func(function, args)
|
||||
|
@ -74,7 +74,7 @@ impl<'a, S: Signer, P: JsonRpcClient> Contract<'a, S, P> {
|
|||
&self,
|
||||
signature: Selector,
|
||||
args: T,
|
||||
) -> Result<ContractCall<'a, S, P, D>, Error> {
|
||||
) -> Result<ContractCall<'a, P, N, S, D>, Error> {
|
||||
let function = self
|
||||
.methods
|
||||
.get(&signature)
|
||||
|
@ -87,7 +87,7 @@ impl<'a, S: Signer, P: JsonRpcClient> Contract<'a, S, P> {
|
|||
&self,
|
||||
function: &Function,
|
||||
args: T,
|
||||
) -> Result<ContractCall<'a, S, P, D>, Error> {
|
||||
) -> Result<ContractCall<'a, P, N, S, D>, Error> {
|
||||
// create the calldata
|
||||
let data = function.encode_input(&args.into_tokens())?;
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
use crate::ContractError;
|
||||
|
||||
use ethers_abi::{Detokenize, Event as AbiEvent, RawLog};
|
||||
use ethers_providers::{JsonRpcClient, Provider};
|
||||
use ethers_providers::{networks::Network, JsonRpcClient, Provider};
|
||||
|
||||
use ethers_types::{BlockNumber, Filter, ValueOrArray, H256};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
pub struct Event<'a, 'b, P, D> {
|
||||
pub struct Event<'a, 'b, P, N, D> {
|
||||
pub filter: Filter,
|
||||
pub(crate) provider: &'a Provider<P>,
|
||||
pub(crate) provider: &'a Provider<P, N>,
|
||||
pub(crate) event: &'b AbiEvent,
|
||||
pub(crate) datatype: PhantomData<D>,
|
||||
}
|
||||
|
||||
// TODO: Improve these functions
|
||||
impl<'a, 'b, P, D: Detokenize> Event<'a, 'b, P, D> {
|
||||
impl<'a, 'b, P, N, D: Detokenize> Event<'a, 'b, P, N, D> {
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn from_block<T: Into<BlockNumber>>(mut self, block: T) -> Self {
|
||||
self.filter.from_block = Some(block.into());
|
||||
|
@ -40,7 +40,7 @@ impl<'a, 'b, P, D: Detokenize> Event<'a, 'b, P, D> {
|
|||
}
|
||||
|
||||
// TODO: Can we get rid of the static?
|
||||
impl<'a, 'b, P: JsonRpcClient, D: Detokenize> Event<'a, 'b, P, D>
|
||||
impl<'a, 'b, P: JsonRpcClient, N: Network, D: Detokenize> Event<'a, 'b, P, N, D>
|
||||
where
|
||||
P::Error: 'static,
|
||||
{
|
||||
|
|
|
@ -74,7 +74,9 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_namehash() {
|
||||
dbg!(ethers_utils::id("name(bytes32)"));
|
||||
dbg!("00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
.from_hex::<Vec<u8>>()
|
||||
.unwrap());
|
||||
for (name, expected) in &[
|
||||
(
|
||||
"",
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
mod http;
|
||||
mod provider;
|
||||
|
||||
pub mod networks;
|
||||
|
||||
/// ENS support
|
||||
pub mod ens;
|
||||
|
||||
|
@ -17,7 +19,7 @@ use std::{error::Error, fmt::Debug};
|
|||
pub use provider::Provider;
|
||||
|
||||
/// An HTTP provider for interacting with an Ethereum-compatible blockchain
|
||||
pub type HttpProvider = Provider<http::Provider>;
|
||||
pub type HttpProvider<N> = Provider<http::Provider, N>;
|
||||
|
||||
#[async_trait]
|
||||
/// Implement this trait in order to plug in different backends
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
//! a transaction that is designed to work with testnet does not accidentally work
|
||||
//! with mainnet because the URL was changed.
|
||||
|
||||
use ethers_types::U64;
|
||||
use ethers_types::{Address, H160, U64};
|
||||
|
||||
pub trait Network {
|
||||
const CHAIN_ID: Option<U64>;
|
||||
const ENS_ADDRESS: Option<Address>;
|
||||
|
||||
// TODO: Default providers? e.g. `mainnet.infura.io/XXX`?
|
||||
}
|
||||
|
@ -15,25 +16,19 @@ pub struct Mainnet;
|
|||
|
||||
impl Network for Mainnet {
|
||||
const CHAIN_ID: Option<U64> = Some(U64([1]));
|
||||
|
||||
// 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e
|
||||
const ENS_ADDRESS: Option<Address> = Some(H160([
|
||||
// cannot set type aliases as constructors
|
||||
0, 0, 0, 0, 0, 12, 46, 7, 78, 198, 154, 13, 251, 41, 151, 186, 108, 125, 46, 30,
|
||||
]));
|
||||
}
|
||||
|
||||
/// No EIP155
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct EIP155Disabled;
|
||||
pub struct Any;
|
||||
|
||||
// EIP155 being disabled means no chainId will be used
|
||||
impl Network for EIP155Disabled {
|
||||
impl Network for Any {
|
||||
const CHAIN_ID: Option<U64> = None;
|
||||
}
|
||||
|
||||
pub mod instantiated {
|
||||
use super::*;
|
||||
use crate::Wallet;
|
||||
|
||||
/// A Wallet instantiated with chain_id = 1 for Ethereum Mainnet.
|
||||
pub type MainnetWallet = Wallet<Mainnet>;
|
||||
|
||||
/// A wallet which does not use EIP-155 and does not take the chain id into account
|
||||
/// when creating transactions
|
||||
pub type AnyWallet = Wallet<EIP155Disabled>;
|
||||
const ENS_ADDRESS: Option<Address> = None;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{ens, http::Provider as HttpProvider, JsonRpcClient};
|
||||
use crate::{ens, http::Provider as HttpProvider, networks::Network, JsonRpcClient};
|
||||
|
||||
use ethers_abi::{Detokenize, ParamType};
|
||||
use ethers_types::{
|
||||
|
@ -10,15 +10,15 @@ use ethers_utils as utils;
|
|||
use serde::Deserialize;
|
||||
use url::{ParseError, Url};
|
||||
|
||||
use std::{convert::TryFrom, fmt::Debug};
|
||||
use std::{convert::TryFrom, fmt::Debug, marker::PhantomData};
|
||||
|
||||
/// An abstract provider for interacting with the [Ethereum JSON RPC
|
||||
/// API](https://github.com/ethereum/wiki/wiki/JSON-RPC)
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Provider<P>(P, Option<Address>);
|
||||
pub struct Provider<P, N>(P, PhantomData<N>, Option<Address>);
|
||||
|
||||
// JSON RPC bindings
|
||||
impl<P: JsonRpcClient> Provider<P> {
|
||||
impl<P: JsonRpcClient, N: Network> Provider<P, N> {
|
||||
////// Blockchain Status
|
||||
//
|
||||
// Functions for querying the state of the blockchain
|
||||
|
@ -206,10 +206,13 @@ impl<P: JsonRpcClient> Provider<P> {
|
|||
ens_name: &str,
|
||||
selector: Selector,
|
||||
) -> Result<Option<T>, P::Error> {
|
||||
let ens_addr = if let Some(ens_addr) = self.1 {
|
||||
ens_addr
|
||||
} else {
|
||||
return Ok(None);
|
||||
// Get the ENS address, prioritize the local override variable
|
||||
let ens_addr = match self.2 {
|
||||
Some(ens_addr) => ens_addr,
|
||||
None => match N::ENS_ADDRESS {
|
||||
Some(ens_addr) => ens_addr,
|
||||
None => return Ok(None),
|
||||
},
|
||||
};
|
||||
|
||||
// first get the resolver responsible for this name
|
||||
|
@ -231,8 +234,8 @@ impl<P: JsonRpcClient> Provider<P> {
|
|||
Ok(Some(decode_bytes(param, data)))
|
||||
}
|
||||
|
||||
pub fn ens<T: Into<Address>>(mut self, ens_addr: T) -> Self {
|
||||
self.1 = Some(ens_addr.into());
|
||||
pub fn ens<T: Into<Address>>(mut self, ens: T) -> Self {
|
||||
self.2 = Some(ens.into());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -248,30 +251,30 @@ fn decode_bytes<T: Detokenize>(param: ParamType, bytes: Bytes) -> T {
|
|||
T::from_tokens(tokens).expect("could not parse tokens as address")
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Provider<HttpProvider> {
|
||||
impl<N: Network> TryFrom<&str> for Provider<HttpProvider, N> {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(src: &str) -> Result<Self, Self::Error> {
|
||||
Ok(Provider(HttpProvider::new(Url::parse(src)?), None))
|
||||
Ok(Provider(
|
||||
HttpProvider::new(Url::parse(src)?),
|
||||
PhantomData,
|
||||
None,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod ens_tests {
|
||||
use super::*;
|
||||
use crate::networks::Mainnet;
|
||||
|
||||
#[tokio::test]
|
||||
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
|
||||
async fn mainnet_resolve_name() {
|
||||
let mainnet_ens_addr = "00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
.parse::<Address>()
|
||||
.unwrap();
|
||||
|
||||
let provider = Provider::<HttpProvider>::try_from(
|
||||
let provider = Provider::<HttpProvider, Mainnet>::try_from(
|
||||
"https://mainnet.infura.io/v3/9408f47dedf04716a03ef994182cf150",
|
||||
)
|
||||
.unwrap()
|
||||
.ens(mainnet_ens_addr);
|
||||
.unwrap();
|
||||
|
||||
let addr = provider
|
||||
.resolve_name("registrar.firefly.eth")
|
||||
|
@ -297,15 +300,10 @@ mod ens_tests {
|
|||
#[tokio::test]
|
||||
// Test vector from: https://docs.ethers.io/ethers.js/v5-beta/api-providers.html#id2
|
||||
async fn mainnet_lookup_address() {
|
||||
let mainnet_ens_addr = "00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
.parse::<Address>()
|
||||
.unwrap();
|
||||
|
||||
let provider = Provider::<HttpProvider>::try_from(
|
||||
let provider = Provider::<HttpProvider, Mainnet>::try_from(
|
||||
"https://mainnet.infura.io/v3/9408f47dedf04716a03ef994182cf150",
|
||||
)
|
||||
.unwrap()
|
||||
.ens(mainnet_ens_addr);
|
||||
.unwrap();
|
||||
|
||||
let name = provider
|
||||
.lookup_address("6fC21092DA55B392b045eD78F4732bff3C580e2c".parse().unwrap())
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
use crate::Signer;
|
||||
|
||||
use ethers_providers::{JsonRpcClient, Provider};
|
||||
use ethers_providers::{networks::Network, JsonRpcClient, Provider};
|
||||
use ethers_types::{Address, BlockNumber, TransactionRequest, TxHash};
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Client<'a, S, P> {
|
||||
pub(crate) provider: &'a Provider<P>,
|
||||
pub struct Client<'a, P, N, S> {
|
||||
pub(crate) provider: &'a Provider<P, N>,
|
||||
pub(crate) signer: Option<S>,
|
||||
}
|
||||
|
||||
impl<'a, S, P> From<&'a Provider<P>> for Client<'a, S, P> {
|
||||
fn from(provider: &'a Provider<P>) -> Self {
|
||||
impl<'a, P, N, S> From<&'a Provider<P, N>> for Client<'a, P, N, S> {
|
||||
fn from(provider: &'a Provider<P, N>) -> Self {
|
||||
Client {
|
||||
provider,
|
||||
signer: None,
|
||||
|
@ -20,7 +20,12 @@ impl<'a, S, P> From<&'a Provider<P>> for Client<'a, S, P> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S: Signer, P: JsonRpcClient> Client<'a, S, P> {
|
||||
impl<'a, P, N, S> Client<'a, P, N, S>
|
||||
where
|
||||
S: Signer,
|
||||
P: JsonRpcClient,
|
||||
N: Network,
|
||||
{
|
||||
/// Signs the transaction and then broadcasts its RLP encoding via the `eth_sendRawTransaction`
|
||||
/// API
|
||||
pub async fn send_transaction(
|
||||
|
@ -84,7 +89,7 @@ impl<'a, S: Signer, P: JsonRpcClient> Client<'a, S, P> {
|
|||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn provider(&self) -> &Provider<P> {
|
||||
pub fn provider(&self) -> &Provider<P, N> {
|
||||
self.provider
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +97,11 @@ impl<'a, S: Signer, P: JsonRpcClient> Client<'a, S, P> {
|
|||
// Abuse Deref to use the Provider's methods without re-writing everything.
|
||||
// This is an anti-pattern and should not be encouraged, but this improves the UX while
|
||||
// keeping the LoC low
|
||||
impl<'a, S, P> Deref for Client<'a, S, P> {
|
||||
type Target = &'a Provider<P>;
|
||||
impl<'a, P, N, S> Deref for Client<'a, P, N, S>
|
||||
where
|
||||
N: 'a,
|
||||
{
|
||||
type Target = &'a Provider<P, N>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.provider
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
//!
|
||||
//! TODO: We might need a `SignerAsync` trait for HSM use cases?
|
||||
|
||||
mod networks;
|
||||
pub use networks::instantiated::*;
|
||||
use networks::Network;
|
||||
|
||||
mod wallet;
|
||||
pub use wallet::Wallet;
|
||||
|
||||
|
@ -37,3 +33,12 @@ pub trait Signer {
|
|||
/// Returns the signer's Ethereum Address
|
||||
fn address(&self) -> Address;
|
||||
}
|
||||
|
||||
use ethers_providers::networks::{Any, Mainnet};
|
||||
|
||||
/// A Wallet instantiated with chain_id = 1 for Ethereum Mainnet.
|
||||
pub type MainnetWallet = Wallet<Mainnet>;
|
||||
|
||||
/// A wallet which does not use EIP-155 and does not take the chain id into account
|
||||
/// when creating transactions
|
||||
pub type AnyWallet = Wallet<Any>;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{Client, Network, Signer};
|
||||
use crate::{Client, Signer};
|
||||
|
||||
use ethers_providers::{JsonRpcClient, Provider};
|
||||
use ethers_providers::{networks::Network, JsonRpcClient, Provider};
|
||||
|
||||
use ethers_types::{
|
||||
rand::Rng, secp256k1, Address, PrivateKey, PublicKey, Signature, Transaction,
|
||||
|
@ -52,7 +52,7 @@ impl<N: Network> Wallet<N> {
|
|||
}
|
||||
|
||||
/// Connects to a provider and returns a client
|
||||
pub fn connect<P: JsonRpcClient>(self, provider: &Provider<P>) -> Client<Wallet<N>, P> {
|
||||
pub fn connect<P: JsonRpcClient>(self, provider: &Provider<P, N>) -> Client<P, N, Wallet<N>> {
|
||||
Client {
|
||||
signer: Some(self),
|
||||
provider,
|
||||
|
|
|
@ -4,7 +4,7 @@ pub type Selector = [u8; 4];
|
|||
|
||||
// Re-export common ethereum datatypes with more specific names
|
||||
pub use ethereum_types::H256 as TxHash;
|
||||
pub use ethereum_types::{Address, Bloom, H256, U128, U256, U64};
|
||||
pub use ethereum_types::{Address, Bloom, H160, H256, U128, U256, U64};
|
||||
|
||||
mod transaction;
|
||||
pub use transaction::{Overrides, Transaction, TransactionReceipt, TransactionRequest};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use ethers::{
|
||||
providers::HttpProvider,
|
||||
providers::{networks::Any, HttpProvider},
|
||||
types::{Address, Filter},
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
|
@ -8,7 +8,7 @@ use std::convert::TryFrom;
|
|||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// connect to the network
|
||||
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
||||
let provider = HttpProvider::<Any>::try_from("http://localhost:8545")?;
|
||||
|
||||
let filter = Filter::new()
|
||||
.address_str("f817796F60D268A36a57b8D2dF1B97B14C0D0E1d")?
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use anyhow::Result;
|
||||
use ethers::{
|
||||
providers::HttpProvider,
|
||||
providers::{networks::Any, HttpProvider},
|
||||
types::{BlockNumber, TransactionRequest},
|
||||
};
|
||||
use std::convert::TryFrom;
|
||||
|
@ -8,7 +8,7 @@ use std::convert::TryFrom;
|
|||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
// connect to the network
|
||||
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
||||
let provider = HttpProvider::<Any>::try_from("http://localhost:8545")?;
|
||||
let accounts = provider.get_accounts().await?;
|
||||
let from = accounts[0];
|
||||
|
||||
|
|
Loading…
Reference in New Issue