This commit is contained in:
Georgios Konstantopoulos 2020-05-26 13:24:19 +03:00
parent e7c9e19409
commit 2bec170968
No known key found for this signature in database
GPG Key ID: FA607837CD26EDBC
16 changed files with 126 additions and 119 deletions

29
Cargo.lock generated
View File

@ -74,6 +74,14 @@ name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "core-foundation"
version = "0.7.0"
@ -158,6 +166,15 @@ dependencies = [
"url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ethers-signers"
version = "0.1.0"
dependencies = [
"ethers-providers 0.1.0",
"ethers-types 0.1.0",
"ethers-utils 0.1.0",
]
[[package]]
name = "ethers-types"
version = "0.1.0"
@ -169,6 +186,7 @@ dependencies = [
"rustc-hex 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"zeroize 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@ -199,6 +217,11 @@ name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@ -617,7 +640,11 @@ name = "rand"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.70 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1267,6 +1294,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1"
"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
"checksum crunchy 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
@ -1278,6 +1306,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum ethereum-types 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "473aecff686bd8e7b9db0165cbbb53562376b39bf35b427f0c60446a9e1634b0"
"checksum fixed-hash 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "11498d382790b7a8f2fd211780bec78619bba81cdad3a283997c0c41f836759c"
"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
"checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"

View File

@ -6,7 +6,7 @@ members = [
# "./crates/ethers-contract",
# "./crates/ethers-derive",
"./crates/ethers-providers",
# "./crates/ethers-signers",
"./crates/ethers-signers",
"./crates/ethers-types",
"./crates/ethers-utils",
]

View File

@ -7,12 +7,11 @@ use reqwest::{Client, Error as ReqwestError};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{
convert::TryFrom,
fmt,
sync::atomic::{AtomicU64, Ordering},
};
use thiserror::Error;
use url::{ParseError, Url};
use url::Url;
/// An HTTP Client
#[derive(Debug)]
@ -69,14 +68,6 @@ impl Provider {
}
}
impl TryFrom<&str> for super::Provider<Provider> {
type Error = ParseError;
fn try_from(src: &str) -> Result<Self, Self::Error> {
Ok(super::Provider(Provider::new(Url::parse(src)?)))
}
}
impl Clone for Provider {
fn clone(&self) -> Self {
Self {

View File

@ -4,13 +4,15 @@
//!
//! TODO: WebSockets, multiple backends, popular APIs etc.
mod provider;
mod http;
mod provider;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
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>;
@ -26,4 +28,3 @@ pub trait JsonRpcClient: Debug {
params: Option<T>,
) -> Result<R, Self::Error>;
}

View File

@ -4,9 +4,11 @@ use ethers_types::{
};
use ethers_utils as utils;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::{error::Error, fmt::Debug};
use crate::{http::Provider as HttpProvider, JsonRpcClient};
use serde::Deserialize;
use url::{ParseError, Url};
use std::{convert::TryFrom, fmt::Debug};
/// An abstract provider for interacting with the [Ethereum JSON RPC
/// API](https://github.com/ethereum/wiki/wiki/JSON-RPC)
@ -148,3 +150,11 @@ impl<P: JsonRpcClient> Provider<P> {
self.0.request("eth_getBalance", Some(&[from, block])).await
}
}
impl TryFrom<&str> for Provider<HttpProvider> {
type Error = ParseError;
fn try_from(src: &str) -> Result<Self, Self::Error> {
Ok(Provider(HttpProvider::new(Url::parse(src)?)))
}
}

View File

@ -4,6 +4,7 @@ version = "0.1.0"
authors = ["Georgios Konstantopoulos <me@gakonst.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ethers-types = { path = "../ethers-types" }
ethers-providers = { path = "../ethers-providers" }
ethers-utils = { path = "../ethers-utils" }

View File

@ -1,9 +1,7 @@
use crate::{
providers::{JsonRpcClient, Provider},
signers::Signer,
types::{Address, BlockNumber, Overrides, TransactionRequest, TxHash},
utils,
};
use crate::Signer;
use ethers_providers::{JsonRpcClient, Provider};
use ethers_types::{Address, BlockNumber, TransactionRequest, TxHash};
use std::ops::Deref;
@ -79,40 +77,6 @@ impl<'a, S: Signer, P: JsonRpcClient> Client<'a, S, P> {
Ok(())
}
/// client.call_contract(
/// addr,
/// "transfer(address,uint256)"
/// vec![0x1234, 100]
/// None,
/// None,
/// )
pub async fn call_contract(
&self,
to: impl Into<Address>,
signature: &str,
args: &[ethabi::Token],
overrides: Option<Overrides>,
block: Option<BlockNumber>,
) -> Result<TxHash, P::Error> {
// create the data field from the function signature and the arguments
let data = [&utils::id(signature)[..], &ethabi::encode(args)].concat();
let overrides = overrides.unwrap_or_default();
let tx = TransactionRequest {
to: Some(to.into()),
data: Some(data.into()),
// forward the overriden data
from: overrides.from, // let it figure it out itself
gas: overrides.gas,
gas_price: overrides.gas_price,
nonce: overrides.nonce,
value: overrides.value,
};
self.send_transaction(tx, block).await
}
pub fn address(&self) -> Address {
self.signer
.as_ref()

View File

@ -1,7 +1,39 @@
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
//! Ethereum compatible signers
//!
//! Currently supported:
//! - [x] Private Key
//! - [ ] Encrypted Json
//! - [ ] Ledger
//! - [ ] Trezor
//!
//! Implement the `Signer` trait to add support for new signers, e.g. with Ledger.
//!
//! 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;
mod client;
pub(crate) use client::Client;
use ethers_types::{Address, Signature, Transaction, TransactionRequest};
use std::error::Error;
/// Trait for signing transactions and messages
///
/// Implement this trait to support different signing modes, e.g. Ledger, hosted etc.
pub trait Signer {
type Error: Error;
/// Signs the hash of the provided message after prefixing it
fn sign_message<S: AsRef<[u8]>>(&self, message: S) -> Signature;
/// Signs the transaction
fn sign_transaction(&self, message: TransactionRequest) -> Result<Transaction, Self::Error>;
/// Returns the signer's Ethereum Address
fn address(&self) -> Address;
}

View File

@ -1,32 +0,0 @@
//! Sign and broadcast transactions
//!
//! Implement the `Signer` trait to add support for new signers, e.g. with Ledger.
//!
//! 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;
mod client;
pub(crate) use client::Client;
use crate::types::{Address, Signature, Transaction, TransactionRequest};
use std::error::Error;
/// Trait for signing transactions and messages
///
/// Implement this trait to support different signing modes, e.g. Ledger, hosted etc.
pub trait Signer {
type Error: Error;
/// Signs the hash of the provided message after prefixing it
fn sign_message<S: AsRef<[u8]>>(&self, message: S) -> Signature;
/// Signs the transaction
fn sign_transaction(&self, message: TransactionRequest) -> Result<Transaction, Self::Error>;
/// Returns the signer's Ethereum Address
fn address(&self) -> Address;
}

View File

@ -2,7 +2,7 @@
//! a transaction that is designed to work with testnet does not accidentally work
//! with mainnet because the URL was changed.
use crate::types::U64;
use ethers_types::U64;
pub trait Network {
const CHAIN_ID: Option<U64>;
@ -28,7 +28,7 @@ impl Network for EIP155Disabled {
pub mod instantiated {
use super::*;
use crate::signers::Wallet;
use crate::Wallet;
/// A Wallet instantiated with chain_id = 1 for Ethereum Mainnet.
pub type MainnetWallet = Wallet<Mainnet>;

View File

@ -1,10 +1,12 @@
use crate::{
providers::{JsonRpcClient, Provider},
signers::{Client, Network, Signer},
types::{Address, PrivateKey, PublicKey, Signature, Transaction, TransactionRequest, TxError},
use crate::{Client, Network, Signer};
use ethers_providers::{JsonRpcClient, Provider};
use ethers_types::{
rand::Rng, secp256k1, Address, PrivateKey, PublicKey, Signature, Transaction,
TransactionRequest, TxError,
};
use rand::Rng;
use std::{marker::PhantomData, str::FromStr};
/// A keypair

View File

@ -4,8 +4,6 @@ version = "0.1.0"
authors = ["Georgios Konstantopoulos <me@gakonst.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ethers-utils = { path = "../ethers-utils" }
@ -19,3 +17,7 @@ thiserror = { version = "1.0.19", default-features = false }
secp256k1 = { version = "0.17.2", default-features = false, features = ["std", "recovery", "rand"] }
rand = { version = "0.5.1", default-features = false } # this should be the same rand crate version as the one in secp
zeroize = { version = "1.1.0", default-features = false }
[dev-dependencies]
serde_json = { version = "1.0.53", default-features = false }
rand = { version = "0.5.1" }

View File

@ -208,7 +208,7 @@ impl From<PrivateKey> for Address {
#[cfg(test)]
mod tests {
use super::*;
use crate::types::Bytes;
use crate::Bytes;
use rustc_hex::FromHex;
#[test]

View File

@ -23,3 +23,10 @@ pub use block::{Block, BlockId, BlockNumber};
mod log;
pub use log::{Filter, Log, ValueOrArray};
// re-export the non-standard rand version so that other crates don't use the
// wrong one by accident
pub use rand;
// re-export libsecp
pub use secp256k1;

View File

@ -192,7 +192,7 @@ impl From<H256> for RecoveryMessage {
#[cfg(test)]
mod tests {
use super::*;
use crate::types::PrivateKey;
use crate::PrivateKey;
#[test]
fn recover_signature_from_message() {

View File

@ -11,24 +11,24 @@ use std::str::FromStr;
pub struct Overrides {
/// Sender address or ENS name
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) from: Option<Address>,
pub from: Option<Address>,
/// Supplied gas (None for sensible default)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) gas: Option<U256>,
pub gas: Option<U256>,
/// Gas price (None for sensible default)
#[serde(rename = "gasPrice")]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) gas_price: Option<U256>,
pub gas_price: Option<U256>,
/// Transfered value (None for no transfer)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) value: Option<U256>,
pub value: Option<U256>,
/// Transaction nonce (None for next available nonce)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) nonce: Option<U256>,
pub nonce: Option<U256>,
}
/// Parameters for sending a transaction
@ -36,33 +36,33 @@ pub struct Overrides {
pub struct TransactionRequest {
/// Sender address or ENS name
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) from: Option<Address>,
pub from: Option<Address>,
/// Recipient address (None for contract creation)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) to: Option<Address>,
pub to: Option<Address>,
/// Supplied gas (None for sensible default)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) gas: Option<U256>,
pub gas: Option<U256>,
/// Gas price (None for sensible default)
#[serde(rename = "gasPrice")]
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) gas_price: Option<U256>,
pub gas_price: Option<U256>,
/// Transfered value (None for no transfer)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) value: Option<U256>,
pub value: Option<U256>,
/// The compiled code of a contract OR the first 4 bytes of the hash of the
/// invoked method signature and encoded parameters. For details see Ethereum Contract ABI
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) data: Option<Bytes>,
pub data: Option<Bytes>,
/// Transaction nonce (None for next available nonce)
#[serde(skip_serializing_if = "Option::is_none")]
pub(crate) nonce: Option<U256>,
pub nonce: Option<U256>,
}
impl TransactionRequest {