Upgrade to Tokio 1.0 and remove async-std (#120)
* feat(providers): tokio 1.0 BREAKING: This removes async-std as a compatibility option * feat: tokio 1.0 in rest of crates * fix: patch Cargo.toml until deps are released * fix(contract): load ws deps * feat: bytes 1.0 (#121) * feat(core): move to bytes::Bytes * feat: adjust rest of crates to Bytes * chore: bump deps CI fails due to: https://github.com/snapview/tokio-tungstenite/pull/142#discussion_r550445144 * chore: use latest tokio-tungstenite * ci: split tests into jobs (#129) * Switch to `hex` (#128) * fix(core): replace rustc_hex with hex * fix(providers): replace rustc_hex with hex * chore: replace rustc-hex with hex * chore: cargo fmt * fix(ledger): copy address from string correctly * chore: fix flaky tests Fixes #105
This commit is contained in:
parent
7eec705cec
commit
5c1f8f532a
|
@ -15,16 +15,12 @@ jobs:
|
|||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Install ganache-cli
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
- name: Install ganache
|
||||
run: npm install -g ganache-cli
|
||||
- name: Install libusb (for Ledger)
|
||||
run: sudo apt update && sudo apt install pkg-config libudev-dev
|
||||
|
||||
- name: Install Solc
|
||||
run: |
|
||||
mkdir -p "$HOME/bin"
|
||||
|
@ -42,7 +38,6 @@ jobs:
|
|||
chmod u+x "$HOME/bin/geth"
|
||||
export PATH=$HOME/bin:$PATH
|
||||
geth version
|
||||
|
||||
- name: Install stable toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
|
@ -50,19 +45,69 @@ jobs:
|
|||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: cargo test
|
||||
run: |
|
||||
export PATH=$HOME/bin:$PATH
|
||||
cargo test
|
||||
|
||||
feature-tests:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Install ganache-cli
|
||||
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-cli
|
||||
- name: Install Solc
|
||||
run: |
|
||||
mkdir -p "$HOME/bin"
|
||||
wget -q https://github.com/ethereum/solidity/releases/download/v0.6.6/solc-static-linux -O $HOME/bin/solc
|
||||
chmod u+x "$HOME/bin/solc"
|
||||
export PATH=$HOME/bin:$PATH
|
||||
solc --version
|
||||
- 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 libusb (for Ledger)
|
||||
run: sudo apt update && sudo apt install pkg-config libudev-dev
|
||||
- name: Install stable toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- name: cargo test (Celo)
|
||||
run: |
|
||||
export PATH=$HOME/bin:$PATH
|
||||
cargo test --all-features
|
||||
|
||||
lint:
|
||||
name: Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout sources
|
||||
uses: actions/checkout@v2
|
||||
- name: Install stable toolchain
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
profile: minimal
|
||||
toolchain: stable
|
||||
override: true
|
||||
components: rustfmt, clippy
|
||||
- name: cargo fmt
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: cargo clippy
|
||||
run: cargo clippy -- -D warnings
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,3 +8,7 @@ members = [
|
|||
"./ethers-core",
|
||||
"./ethers-middleware",
|
||||
]
|
||||
|
||||
[patch.crates-io]
|
||||
reqwest = { git = "https://github.com/seanmonstar/reqwest", branch = "master" }
|
||||
tokio-tungstenite = { git = "https://github.com/dnaka91/tokio-tungstenite", branch = "tokio-1.0" }
|
||||
|
|
|
@ -17,16 +17,17 @@ ethers-contract-abigen = { version = "0.1.3", path = "ethers-contract-abigen", o
|
|||
ethers-contract-derive = { version = "0.1.3", path = "ethers-contract-derive", optional = true }
|
||||
|
||||
serde = { version = "1.0.118", default-features = false }
|
||||
serde_json = { version = "1.0.60", default-features = false }
|
||||
rustc-hex = { version = "2.1.0", default-features = false }
|
||||
thiserror = { version = "1.0.22", default-features = false }
|
||||
serde_json = { version = "1.0.61", default-features = false }
|
||||
thiserror = { version = "1.0.23", default-features = false }
|
||||
once_cell = { version = "1.5.2", default-features = false }
|
||||
pin-project = {version = "1.0.2", default-features = false }
|
||||
futures-util = { version = "0.3.8", default-features = false }
|
||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||
|
||||
[dev-dependencies]
|
||||
ethers = { version = "0.1.3", path = "../ethers" }
|
||||
tokio = { version = "0.2.21", default-features = false, features = ["macros"] }
|
||||
ethers-providers = { version = "0.1.3", path = "../ethers-providers", default-features = false, features = ["ws"] }
|
||||
tokio = { version = "1.0", default-features = false, features = ["macros"] }
|
||||
|
||||
ethers-signers = { version = "0.1.3", path = "../ethers-signers" }
|
||||
ethers-middleware = { version = "0.1.3", path = "../ethers-middleware" }
|
||||
|
|
|
@ -12,16 +12,15 @@ keywords = ["ethereum", "web3", "celo", "ethers"]
|
|||
[dependencies]
|
||||
ethers-core = { version = "0.1.3", path = "../../ethers-core" }
|
||||
|
||||
anyhow = "1.0.36"
|
||||
anyhow = "1.0.37"
|
||||
curl = "0.4"
|
||||
Inflector = "0.11"
|
||||
proc-macro2 = "1.0"
|
||||
quote = "1.0"
|
||||
syn = "1.0.12"
|
||||
url = "2.1"
|
||||
serde_json = "1.0.53"
|
||||
once_cell = "1.3.1"
|
||||
rustc-hex = { version = "2.1.0", default-features = false }
|
||||
serde_json = "1.0.61"
|
||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
|
|
|
@ -8,7 +8,6 @@ use anyhow::{anyhow, Context as _, Result};
|
|||
use inflector::Inflector;
|
||||
use proc_macro2::{Literal, TokenStream};
|
||||
use quote::quote;
|
||||
use rustc_hex::ToHex;
|
||||
use syn::Ident;
|
||||
|
||||
/// Expands a context into a method struct containing all the generated bindings
|
||||
|
@ -46,7 +45,7 @@ fn expand_function(function: &Function, alias: Option<Ident>) -> Result<TokenStr
|
|||
let doc = util::expand_doc(&format!(
|
||||
"Calls the contract's `{}` (0x{}) function",
|
||||
function.name,
|
||||
function.selector().to_hex::<String>()
|
||||
hex::encode(function.selector())
|
||||
));
|
||||
Ok(quote! {
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ use ethers_core::{
|
|||
};
|
||||
use ethers_providers::Middleware;
|
||||
|
||||
use rustc_hex::ToHex;
|
||||
use std::{collections::HashMap, fmt::Debug, hash::Hash, sync::Arc};
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -107,7 +106,7 @@ impl BaseContract {
|
|||
.methods
|
||||
.get(&signature)
|
||||
.map(|(name, index)| &self.abi.functions[name][*index])
|
||||
.ok_or_else(|| Error::InvalidName(signature.to_hex::<String>()))?)
|
||||
.ok_or_else(|| Error::InvalidName(hex::encode(signature)))?)
|
||||
}
|
||||
|
||||
/// Returns a reference to the contract's ABI
|
||||
|
@ -139,7 +138,7 @@ pub(crate) fn decode_event<D: Detokenize>(
|
|||
let tokens = event
|
||||
.parse_log(RawLog {
|
||||
topics,
|
||||
data: data.0,
|
||||
data: data.to_vec(),
|
||||
})?
|
||||
.params
|
||||
.into_iter()
|
||||
|
@ -199,7 +198,6 @@ where
|
|||
mod tests {
|
||||
use super::*;
|
||||
use ethers_core::{abi::parse_abi, types::U256};
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
#[test]
|
||||
fn can_parse_function_inputs() {
|
||||
|
@ -214,7 +212,7 @@ mod tests {
|
|||
|
||||
let encoded = abi.encode("approve", (spender, amount)).unwrap();
|
||||
|
||||
assert_eq!(encoded.0.to_hex::<String>(), "095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
assert_eq!(hex::encode(&encoded), "095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
|
||||
let (spender2, amount2): (Address, U256) = abi.decode("approve", encoded).unwrap();
|
||||
assert_eq!(spender, spender2);
|
||||
|
@ -239,8 +237,7 @@ mod tests {
|
|||
.map(|hash| hash.parse::<H256>().unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
let data = Bytes::from(
|
||||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
.from_hex::<Vec<u8>>()
|
||||
hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use ethers_core::{
|
|||
};
|
||||
use ethers_providers::Middleware;
|
||||
|
||||
use rustc_hex::ToHex;
|
||||
use std::{fmt::Debug, marker::PhantomData, sync::Arc};
|
||||
|
||||
/// A Contract is an abstraction of an executable program on the Ethereum Blockchain.
|
||||
|
@ -219,7 +218,7 @@ impl<M: Middleware> Contract<M> {
|
|||
.methods
|
||||
.get(&signature)
|
||||
.map(|(name, index)| &self.base_contract.abi.functions[name][*index])
|
||||
.ok_or_else(|| Error::InvalidName(signature.to_hex::<String>()))?;
|
||||
.ok_or_else(|| Error::InvalidName(hex::encode(signature)))?;
|
||||
self.method_func(function, args)
|
||||
}
|
||||
|
||||
|
|
|
@ -143,9 +143,9 @@ impl<M: Middleware> ContractFactory<M> {
|
|||
return Err(ContractError::ConstructorError);
|
||||
}
|
||||
(None, true) => self.bytecode.clone(),
|
||||
(Some(constructor), _) => {
|
||||
Bytes(constructor.encode_input(self.bytecode.0.clone(), ¶ms)?)
|
||||
}
|
||||
(Some(constructor), _) => constructor
|
||||
.encode_input(self.bytecode.to_vec(), ¶ms)?
|
||||
.into(),
|
||||
};
|
||||
|
||||
// create the tx object. Since we're deploying a contract, `to` is `None`
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use ethers_core::{
|
||||
abi::{Detokenize, Function, Token},
|
||||
types::{Address, BlockNumber, NameOrAddress, TxHash, U256},
|
||||
types::{Address, BlockNumber, Bytes, NameOrAddress, TxHash, U256},
|
||||
};
|
||||
use ethers_providers::Middleware;
|
||||
|
||||
|
@ -139,7 +139,7 @@ pub struct Multicall<M> {
|
|||
/// with `data`
|
||||
pub struct Call {
|
||||
target: Address,
|
||||
data: Vec<u8>,
|
||||
data: Bytes,
|
||||
function: Function,
|
||||
}
|
||||
|
||||
|
@ -207,7 +207,7 @@ impl<M: Middleware> Multicall<M> {
|
|||
(Some(NameOrAddress::Address(target)), Some(data)) => {
|
||||
let call = Call {
|
||||
target,
|
||||
data: data.0,
|
||||
data,
|
||||
function: call.function,
|
||||
};
|
||||
self.calls.push(call);
|
||||
|
@ -357,7 +357,7 @@ impl<M: Middleware> Multicall<M> {
|
|||
let calls: Vec<(Address, Vec<u8>)> = self
|
||||
.calls
|
||||
.iter()
|
||||
.map(|call| (call.target, call.data.clone()))
|
||||
.map(|call| (call.target, call.data.to_vec()))
|
||||
.collect();
|
||||
|
||||
// Construct the ContractCall for `aggregate` function to broadcast the transaction
|
||||
|
|
|
@ -384,9 +384,12 @@ mod celo_tests {
|
|||
assert_eq!(value, "initial value");
|
||||
|
||||
// make a state mutating transaction
|
||||
// gas estimation costs are sometimes under-reported on celo,
|
||||
// so we manually set it to avoid failures
|
||||
let call = contract
|
||||
.method::<_, H256>("setValue", "hi".to_owned())
|
||||
.unwrap();
|
||||
.unwrap()
|
||||
.gas(100000);
|
||||
let pending_tx = call.send().await.unwrap();
|
||||
let _receipt = pending_tx.await.unwrap();
|
||||
|
||||
|
|
|
@ -26,10 +26,11 @@ tiny-keccak = { version = "2.0.2", default-features = false }
|
|||
|
||||
# misc
|
||||
serde = { version = "1.0.118", default-features = false, features = ["derive"] }
|
||||
serde_json = { version = "1.0.60", default-features = false }
|
||||
rustc-hex = { version = "2.1.0", default-features = false }
|
||||
thiserror = { version = "1.0.22", default-features = false }
|
||||
serde_json = { version = "1.0.61", default-features = false }
|
||||
thiserror = { version = "1.0.23", default-features = false }
|
||||
glob = { version = "0.3.0", default-features = false }
|
||||
bytes = { version = "1.0.0", features = ["serde"] }
|
||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||
|
||||
[dev-dependencies]
|
||||
ethers = { version = "0.1.3", path = "../ethers" }
|
||||
|
|
|
@ -161,7 +161,7 @@ impl Tokenizable for Bytes {
|
|||
}
|
||||
|
||||
fn into_token(self) -> Token {
|
||||
Token::Bytes(self.0)
|
||||
Token::Bytes(self.to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,33 +1,31 @@
|
|||
use rustc_hex::{FromHex, ToHex};
|
||||
use serde::de::{Error, Unexpected};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
/// Wrapper type around Vec<u8> to deserialize/serialize "0x" prefixed ethereum hex strings
|
||||
/// Wrapper type around Bytes to deserialize/serialize "0x" prefixed ethereum hex strings
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
|
||||
pub struct Bytes(
|
||||
#[serde(
|
||||
serialize_with = "serialize_bytes",
|
||||
deserialize_with = "deserialize_bytes"
|
||||
)]
|
||||
pub Vec<u8>,
|
||||
pub bytes::Bytes,
|
||||
);
|
||||
|
||||
impl AsRef<[u8]> for Bytes {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0[..]
|
||||
impl Bytes {
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
self.as_ref().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl Bytes {
|
||||
/// Returns an empty bytes vector
|
||||
pub fn new() -> Self {
|
||||
Bytes(vec![])
|
||||
impl AsRef<[u8]> for Bytes {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<u8>> for Bytes {
|
||||
fn from(src: Vec<u8>) -> Self {
|
||||
Self(src)
|
||||
Self(src.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,18 +34,18 @@ where
|
|||
S: Serializer,
|
||||
T: AsRef<[u8]>,
|
||||
{
|
||||
s.serialize_str(&format!("0x{}", x.as_ref().to_hex::<String>()))
|
||||
s.serialize_str(&format!("0x{}", hex::encode(x.as_ref())))
|
||||
}
|
||||
|
||||
pub fn deserialize_bytes<'de, D>(d: D) -> Result<Vec<u8>, D::Error>
|
||||
pub fn deserialize_bytes<'de, D>(d: D) -> Result<bytes::Bytes, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value = String::deserialize(d)?;
|
||||
if value.len() >= 2 && &value[0..2] == "0x" {
|
||||
let bytes = FromHex::from_hex(&value[2..])
|
||||
.map_err(|e| Error::custom(format!("Invalid hex: {}", e)))?;
|
||||
Ok(bytes)
|
||||
let bytes: Vec<u8> =
|
||||
hex::decode(&value[2..]).map_err(|e| Error::custom(format!("Invalid hex: {}", e)))?;
|
||||
Ok(bytes.into())
|
||||
} else {
|
||||
Err(Error::invalid_value(Unexpected::Str(&value), &"0x prefix"))
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::{
|
|||
utils::keccak256,
|
||||
};
|
||||
use serde::{ser::SerializeStruct, Deserialize, Serialize, Serializer};
|
||||
use std::str::FromStr;
|
||||
|
||||
/// A log produced by a transaction.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -147,11 +146,6 @@ impl Filter {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn address_str(mut self, address: &str) -> Result<Self, rustc_hex::FromHexError> {
|
||||
self.address = Some(Address::from_str(address)?);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// given the event in string form, it hashes it and adds it to the topics to monitor
|
||||
pub fn event(self, event_name: &str) -> Self {
|
||||
let hash = H256::from(keccak256(event_name.as_bytes()));
|
||||
|
@ -259,7 +253,7 @@ mod tests {
|
|||
|
||||
let event = "ValueChanged(address,string,string)";
|
||||
let t0 = H256::from(keccak256(event.as_bytes()));
|
||||
let addr = Address::from_str("f817796F60D268A36a57b8D2dF1B97B14C0D0E1d").unwrap();
|
||||
let addr: Address = "f817796F60D268A36a57b8D2dF1B97B14C0D0E1d".parse().unwrap();
|
||||
let filter = Filter::new();
|
||||
|
||||
let ser = serialize(&filter.clone());
|
||||
|
|
|
@ -11,7 +11,7 @@ mod transaction;
|
|||
pub use transaction::{Transaction, TransactionReceipt, TransactionRequest};
|
||||
|
||||
mod bytes;
|
||||
pub use bytes::Bytes;
|
||||
pub use self::bytes::Bytes;
|
||||
|
||||
mod block;
|
||||
pub use block::{Block, BlockId, BlockNumber};
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::{
|
|||
utils::hash_message,
|
||||
};
|
||||
|
||||
use rustc_hex::{FromHex, ToHex};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{convert::TryFrom, fmt, str::FromStr};
|
||||
|
||||
|
@ -26,7 +25,7 @@ pub enum SignatureError {
|
|||
InvalidLength(usize),
|
||||
/// When parsing a signature from string to hex
|
||||
#[error(transparent)]
|
||||
DecodingError(#[from] rustc_hex::FromHexError),
|
||||
DecodingError(#[from] hex::FromHexError),
|
||||
/// Thrown when signature verification failed (i.e. when the address that
|
||||
/// produced the signature did not match the expected address)
|
||||
#[error("Signature verification failed. Expected {0}, got {1}")]
|
||||
|
@ -66,7 +65,7 @@ pub struct Signature {
|
|||
impl fmt::Display for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let sig = <[u8; 65]>::from(self);
|
||||
write!(f, "{}", sig.to_hex::<String>())
|
||||
write!(f, "{}", hex::encode(sig))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -174,7 +173,7 @@ impl FromStr for Signature {
|
|||
type Err = SignatureError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let bytes = s.from_hex::<Vec<u8>>()?;
|
||||
let bytes = hex::decode(s)?;
|
||||
Signature::try_from(&bytes[..])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
|||
|
||||
use rlp::RlpStream;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
|
||||
// Number of tx fields before signing
|
||||
#[cfg(not(feature = "celo"))]
|
||||
|
@ -94,12 +93,6 @@ impl TransactionRequest {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the `to` field in the transaction to the provided value
|
||||
pub fn send_to_str(mut self, to: &str) -> Result<Self, rustc_hex::FromHexError> {
|
||||
self.to = Some(Address::from_str(to)?.into());
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Sets the `to` field in the transaction to the provided value
|
||||
pub fn to<T: Into<NameOrAddress>>(mut self, to: T) -> Self {
|
||||
self.to = Some(to.into());
|
||||
|
@ -196,7 +189,7 @@ impl TransactionRequest {
|
|||
|
||||
rlp_opt(rlp, self.to.as_ref());
|
||||
rlp_opt(rlp, self.value);
|
||||
rlp_opt(rlp, self.data.as_ref().map(|d| &d.0[..]));
|
||||
rlp_opt(rlp, self.data.as_ref().map(|d| d.as_ref()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,7 +321,7 @@ impl Transaction {
|
|||
}
|
||||
|
||||
pub fn hash(&self) -> H256 {
|
||||
keccak256(&self.rlp().0).into()
|
||||
keccak256(&self.rlp().as_ref()).into()
|
||||
}
|
||||
|
||||
pub fn rlp(&self) -> Bytes {
|
||||
|
@ -343,7 +336,7 @@ impl Transaction {
|
|||
|
||||
rlp_opt(&mut rlp, self.to);
|
||||
rlp.append(&self.value);
|
||||
rlp.append(&self.input.0);
|
||||
rlp.append(&self.input.as_ref());
|
||||
rlp.append(&self.v);
|
||||
rlp.append(&self.r);
|
||||
rlp.append(&self.s);
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::{
|
|||
utils::{secret_key_to_address, unused_port},
|
||||
};
|
||||
use k256::{ecdsa::SigningKey, SecretKey as K256SecretKey};
|
||||
use rustc_hex::FromHex;
|
||||
use std::{
|
||||
io::{BufRead, BufReader},
|
||||
process::{Child, Command},
|
||||
|
@ -161,9 +160,7 @@ impl Ganache {
|
|||
|
||||
if is_private_key && line.starts_with('(') {
|
||||
let key_str = &line[6..line.len() - 1];
|
||||
let key_hex = key_str
|
||||
.from_hex::<Vec<u8>>()
|
||||
.expect("could not parse as hex");
|
||||
let key_hex = hex::decode(key_str).expect("could not parse as hex");
|
||||
let key = K256SecretKey::from_bytes(&key_hex).expect("did not get private key");
|
||||
addresses.push(secret_key_to_address(&SigningKey::from(&key)));
|
||||
private_keys.push(key);
|
||||
|
|
|
@ -59,13 +59,12 @@ pub fn serialize<T: serde::Serialize>(t: &T) -> serde_json::Value {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rustc_hex::ToHex;
|
||||
|
||||
#[test]
|
||||
// from https://emn178.github.io/online-tools/keccak_256.html
|
||||
fn test_keccak256() {
|
||||
assert_eq!(
|
||||
keccak256(b"hello").to_hex::<String>(),
|
||||
hex::encode(keccak256(b"hello")),
|
||||
"1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ pub use rlp;
|
|||
|
||||
use crate::types::{Address, Bytes, U256};
|
||||
use k256::{ecdsa::SigningKey, EncodedPoint as K256PublicKey};
|
||||
use rustc_hex::ToHex;
|
||||
use std::convert::TryInto;
|
||||
|
||||
/// 1 Ether = 1e18 Wei == 0x0de0b6b3a7640000 Wei
|
||||
|
@ -125,10 +124,10 @@ pub fn to_checksum(addr: &Address, chain_id: Option<u8>) -> String {
|
|||
Some(chain_id) => format!("{}0x{:x}", chain_id, addr),
|
||||
None => format!("{:x}", addr),
|
||||
};
|
||||
let hash = keccak256(&prefixed_addr).to_hex::<String>();
|
||||
let hash = hex::encode(keccak256(&prefixed_addr));
|
||||
let hash = hash.as_bytes();
|
||||
|
||||
let addr_hex = addr.as_bytes().to_hex::<String>();
|
||||
let addr_hex = hex::encode(addr.as_bytes());
|
||||
let addr_hex = addr_hex.as_bytes();
|
||||
|
||||
addr_hex
|
||||
|
@ -161,7 +160,6 @@ pub(crate) fn unused_port() -> u16 {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
#[test]
|
||||
fn wei_in_ether() {
|
||||
|
@ -324,8 +322,8 @@ mod tests {
|
|||
),
|
||||
] {
|
||||
let from = from.parse::<Address>().unwrap();
|
||||
let salt = salt.from_hex::<Vec<u8>>().unwrap();
|
||||
let init_code = init_code.from_hex::<Vec<u8>>().unwrap();
|
||||
let salt = hex::decode(salt).unwrap();
|
||||
let init_code = hex::decode(init_code).unwrap();
|
||||
let expected = expected.parse::<Address>().unwrap();
|
||||
assert_eq!(expected, get_create2_address(from, salt, init_code))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{abi::Abi, types::Bytes};
|
||||
use glob::glob;
|
||||
use rustc_hex::FromHex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::HashMap, fmt, io::BufRead, path::PathBuf, process::Command};
|
||||
use thiserror::Error;
|
||||
|
@ -145,9 +144,7 @@ impl Solc {
|
|||
.expect("could not parse `solc` abi, this should never happen");
|
||||
|
||||
// parse the bytecode
|
||||
let bytecode = contract
|
||||
.bin
|
||||
.from_hex::<Vec<u8>>()
|
||||
let bytecode = hex::decode(contract.bin)
|
||||
.expect("solc did not produce valid bytecode")
|
||||
.into();
|
||||
(name, CompiledContract { abi, bytecode })
|
||||
|
|
|
@ -30,15 +30,13 @@ serde-aux = { version = "2.1.0", default-features = false }
|
|||
reqwest = { version = "0.10.10", default-features = false, features = ["json", "rustls-tls"] }
|
||||
url = { version = "2.2.0", default-features = false }
|
||||
|
||||
# optional for runtime
|
||||
tokio = { version = "0.2.22", optional = true }
|
||||
async-std = { version = "1.6.5", optional = true }
|
||||
tokio = { version = "1.0" }
|
||||
|
||||
[dev-dependencies]
|
||||
ethers = { version = "0.1.3", path = "../ethers" }
|
||||
futures-executor = { version = "0.3.5", features = ["thread-pool"] }
|
||||
rustc-hex = "2.1.0"
|
||||
tokio = { version = "0.2.21", default-features = false, features = ["rt-core", "macros"] }
|
||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||
tokio = { version = "1.0", default-features = false, features = ["rt", "macros", "time"] }
|
||||
|
||||
[features]
|
||||
celo = ["ethers-core/celo", "ethers-providers/celo", "ethers-signers/celo"]
|
||||
|
|
|
@ -12,18 +12,8 @@ use std::sync::Arc;
|
|||
use std::{pin::Pin, time::Instant};
|
||||
use thiserror::Error;
|
||||
|
||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||
use tracing_futures::Instrument;
|
||||
|
||||
#[cfg(all(not(feature = "tokio"), feature = "async-std"))]
|
||||
use async_std::task::spawn;
|
||||
#[cfg(all(feature = "tokio", not(feature = "async-std")))]
|
||||
use tokio::spawn;
|
||||
#[cfg(all(feature = "tokio", all(feature = "async-std")))]
|
||||
// this should never happen, used to silence clippy warnings
|
||||
fn spawn<T>(_: T) {
|
||||
unimplemented!("do not use both tokio and async-std!")
|
||||
}
|
||||
use tracing_futures::Instrument;
|
||||
|
||||
/// Trait for fetching updated gas prices after a transaction has been first
|
||||
/// broadcast
|
||||
|
@ -46,10 +36,6 @@ pub enum Frequency {
|
|||
/// A Gas escalator allows bumping transactions' gas price to avoid getting them
|
||||
/// stuck in the memory pool.
|
||||
///
|
||||
/// If the crate is compiled with the `tokio` or `async-std` features, it will
|
||||
/// automatically start bumping transactions in the background. Otherwise, you need
|
||||
/// to spawn the `escalate` call yourself with an executor of choice.
|
||||
///
|
||||
/// ```no_run
|
||||
/// use ethers::{
|
||||
/// providers::{Provider, Http},
|
||||
|
@ -135,7 +121,6 @@ where
|
|||
txs: Arc::new(Mutex::new(Vec::new())),
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "async-std", feature = "tokio"))]
|
||||
{
|
||||
let this2 = this.clone();
|
||||
spawn(async move {
|
||||
|
|
|
@ -135,7 +135,7 @@ where
|
|||
|
||||
// Get the actual transaction hash
|
||||
let rlp = tx.rlp_signed(&signature);
|
||||
let hash = keccak256(&rlp.0);
|
||||
let hash = keccak256(&rlp.as_ref());
|
||||
|
||||
// This function should not be called with ENS names
|
||||
let to = tx.to.map(|to| match to {
|
||||
|
@ -298,7 +298,6 @@ where
|
|||
mod tests {
|
||||
use super::*;
|
||||
use ethers::{providers::Provider, signers::LocalWallet};
|
||||
use rustc_hex::FromHex;
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -337,7 +336,7 @@ mod tests {
|
|||
.unwrap()
|
||||
);
|
||||
|
||||
let expected_rlp = Bytes("f869808504e3b29200831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a0c9cf86333bcb065d140032ecaab5d9281bde80f21b9687b3e94161de42d51895a0727a108a0b8d101465414033c3f705a9c7b826e596766046ee1183dbc8aeaa68".from_hex().unwrap());
|
||||
let expected_rlp = Bytes::from(hex::decode("f869808504e3b29200831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a0c9cf86333bcb065d140032ecaab5d9281bde80f21b9687b3e94161de42d51895a0727a108a0b8d101465414033c3f705a9c7b826e596766046ee1183dbc8aeaa68").unwrap());
|
||||
assert_eq!(tx.rlp(), expected_rlp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ async fn gas_escalator_live() {
|
|||
.unwrap();
|
||||
|
||||
// Wait a bunch of seconds and refresh etherscan to see the transactions get bumped
|
||||
tokio::time::delay_for(std::time::Duration::from_secs(100)).await;
|
||||
tokio::time::sleep(std::time::Duration::from_secs(100)).await;
|
||||
|
||||
// TODO: Figure out how to test this behavior properly in a local network. If the gas price was bumped
|
||||
// then the tx hash will be different
|
||||
|
|
|
@ -35,47 +35,16 @@ pin-project = { version = "1.0.2", default-features = false }
|
|||
tracing = { version = "0.1.22", default-features = false }
|
||||
tracing-futures = { version = "0.2.4", default-features = false }
|
||||
|
||||
# ws support async-std and tokio runtimes for the convenience methods
|
||||
async-tungstenite = { version = "0.6.0", default-features = false, optional = true }
|
||||
async-std = { version = "1.6.2", default-features = false, optional = true }
|
||||
tokio = { version = "0.2.21", default-features = false, optional = true }
|
||||
# needed for tls
|
||||
real-tokio-native-tls = { package = "tokio-native-tls", version = "0.1.0", default-features = false, optional = true }
|
||||
async-tls = { version = "0.7.0", optional = true }
|
||||
# tokio
|
||||
tokio = { version = "1.0", default-features = false, optional = true }
|
||||
tokio-tungstenite = { version = "0.12.0", default-features = false, features = ["connect", "tls"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
ethers = { version = "0.1.3", path = "../ethers" }
|
||||
|
||||
rustc-hex = "2.1.0"
|
||||
tokio = { version = "0.2.21", default-features = false, features = ["rt-core", "macros"] }
|
||||
async-std = { version = "1.6.2", default-features = false, features = ["attributes"] }
|
||||
async-tungstenite = { version = "0.6.0", default-features = false, features = ["tokio-runtime"] }
|
||||
tokio = { version = "1.0", default-features = false, features = ["rt", "macros"] }
|
||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||
|
||||
[features]
|
||||
# slightly opinionated, but for convenience we default to tokio-tls
|
||||
# to allow websockets w/ TLS support
|
||||
default = ["tokio-tls"]
|
||||
default = ["ws"]
|
||||
celo = ["ethers-core/celo"]
|
||||
ws = ["async-tungstenite"]
|
||||
|
||||
tokio-runtime = [
|
||||
"ws",
|
||||
"tokio",
|
||||
"async-tungstenite/tokio-runtime"
|
||||
]
|
||||
tokio-tls = [
|
||||
"tokio-runtime",
|
||||
"async-tungstenite/tokio-native-tls",
|
||||
"real-tokio-native-tls"
|
||||
]
|
||||
|
||||
async-std-runtime = [
|
||||
"ws",
|
||||
"async-std",
|
||||
"async-tungstenite/async-std-runtime"
|
||||
]
|
||||
async-std-tls = [
|
||||
"async-std-runtime",
|
||||
"async-tungstenite/async-tls",
|
||||
"async-tls"
|
||||
]
|
||||
ws = ["tokio", "tokio-tungstenite"]
|
||||
|
|
|
@ -69,7 +69,6 @@ pub fn namehash(name: &str) -> H256 {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
fn assert_hex(hash: H256, val: &str) {
|
||||
let v = if val.starts_with("0x") {
|
||||
|
@ -78,14 +77,11 @@ mod tests {
|
|||
val
|
||||
};
|
||||
|
||||
assert_eq!(hash.0.to_vec(), v.from_hex::<Vec<u8>>().unwrap());
|
||||
assert_eq!(hash.0.to_vec(), hex::decode(v).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_namehash() {
|
||||
dbg!("00000000000C2E074eC69A0dFb2997BA6C7d2e1e"
|
||||
.from_hex::<Vec<u8>>()
|
||||
.unwrap());
|
||||
for (name, expected) in &[
|
||||
(
|
||||
"",
|
||||
|
|
|
@ -30,28 +30,9 @@
|
|||
//!
|
||||
//! # Websockets
|
||||
//!
|
||||
//! The crate has support for WebSockets. If none of the provided async runtime
|
||||
//! features are enabled, you must manually instantiate the WS connection and wrap
|
||||
//! it with with a [`Ws::new`](method@crate::Ws::new) call.
|
||||
//! The crate has support for WebSockets via Tokio.
|
||||
//!
|
||||
//! ```ignore
|
||||
//! use ethers::providers::Ws;
|
||||
//!
|
||||
//! let ws = Ws::new(...);
|
||||
//! ```
|
||||
//!
|
||||
//! If you have compiled the library with any of the following features, you may
|
||||
//! instantiate the websocket instance with the `connect` call and your URL:
|
||||
//! - `tokio-runtime`: Uses `tokio` as the runtime
|
||||
//! - `async-std-runtime`: Uses `async-std-runtime`
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # #[cfg(any(
|
||||
//! # feature = "tokio-runtime",
|
||||
//! # feature = "tokio-tls",
|
||||
//! # feature = "async-std-runtime",
|
||||
//! # feature = "async-std-tls",
|
||||
//! # ))]
|
||||
//! # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! # use ethers::providers::Ws;
|
||||
//! let ws = Ws::connect("ws://localhost:8545").await?;
|
||||
|
@ -59,24 +40,6 @@
|
|||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! TLS support is also provided via the following feature flags:
|
||||
//! - `tokio-tls`
|
||||
//! - `async-tls`
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # #[cfg(any(
|
||||
//! # feature = "tokio-runtime",
|
||||
//! # feature = "tokio-tls",
|
||||
//! # feature = "async-std-runtime",
|
||||
//! # feature = "async-std-tls",
|
||||
//! # ))]
|
||||
//! # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! # use ethers::providers::Ws;
|
||||
//! let ws = Ws::connect("wss://localhost:8545").await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! # Ethereum Name Service
|
||||
//!
|
||||
//! The provider may also be used to resolve [Ethereum Name Service](https://ens.domains) (ENS) names
|
||||
|
|
|
@ -685,11 +685,11 @@ impl<P: JsonRpcClient> Provider<P> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "tokio-runtime", feature = "async-std-runtime"))]
|
||||
#[cfg(feature = "ws")]
|
||||
impl Provider<crate::Ws> {
|
||||
/// Direct connection to a websocket endpoint
|
||||
pub async fn connect(
|
||||
url: impl async_tungstenite::tungstenite::client::IntoClientRequest + Unpin,
|
||||
url: impl tokio_tungstenite::tungstenite::client::IntoClientRequest + Unpin,
|
||||
) -> Result<Self, ProviderError> {
|
||||
let ws = crate::Ws::connect(url).await?;
|
||||
Ok(Self::new(ws))
|
||||
|
@ -730,8 +730,8 @@ impl Provider<MockProvider> {
|
|||
///
|
||||
/// If the provided bytes were not an interpretation of an address
|
||||
fn decode_bytes<T: Detokenize>(param: ParamType, bytes: Bytes) -> T {
|
||||
let tokens =
|
||||
abi::decode(&[param], &bytes.0).expect("could not abi-decode bytes to address tokens");
|
||||
let tokens = abi::decode(&[param], &bytes.as_ref())
|
||||
.expect("could not abi-decode bytes to address tokens");
|
||||
T::from_tokens(tokens).expect("could not parse tokens as address")
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ where
|
|||
}
|
||||
|
||||
#[pinned_drop]
|
||||
impl<'a, P, R> PinnedDrop for SubscriptionStream<'a, P, R>
|
||||
impl<P, R> PinnedDrop for SubscriptionStream<'_, P, R>
|
||||
where
|
||||
P: PubsubClient,
|
||||
R: DeserializeOwned,
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
|||
use ethers_core::types::U256;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use async_tungstenite::tungstenite::{self, protocol::Message};
|
||||
use futures_channel::{mpsc, oneshot};
|
||||
use futures_util::{
|
||||
sink::{Sink, SinkExt},
|
||||
|
@ -22,53 +21,21 @@ use std::{
|
|||
},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
// `connect_async` adapter
|
||||
#[cfg(all(feature = "async-std-runtime", not(feature = "tokio-runtime")))]
|
||||
use async_tungstenite::async_std::connect_async;
|
||||
#[cfg(feature = "tokio-runtime")]
|
||||
use async_tungstenite::tokio::connect_async;
|
||||
use tokio_tungstenite::{
|
||||
connect_async,
|
||||
tungstenite::{self, protocol::Message},
|
||||
};
|
||||
|
||||
/// A JSON-RPC Client over Websockets.
|
||||
///
|
||||
/// If the library is not compiled with any runtime support, then you will have
|
||||
/// to manually instantiate a websocket connection and call `Provider::new` on it.
|
||||
///
|
||||
/// ```ignore
|
||||
/// use ethers::providers::Ws;
|
||||
///
|
||||
/// let ws = Ws::new(...)
|
||||
/// ```
|
||||
///
|
||||
/// If you have compiled the library with any of the following features, you may
|
||||
/// instantiate the websocket instance with the `connect` call and your URL:
|
||||
/// - `tokio-runtime`: Uses `tokio` as the runtime
|
||||
/// - `tokio-tls`: Same as `tokio-runtime` but with TLS support
|
||||
/// - `async-std-runtime`: Uses `async-std-runtime`
|
||||
/// - `async-tls`: Same as `async-std-runtime` but with TLS support
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #[cfg(any(
|
||||
/// # feature = "tokio-runtime",
|
||||
/// # feature = "tokio-tls",
|
||||
/// # feature = "async-std-runtime",
|
||||
/// # feature = "async-std-tls",
|
||||
/// # ))]
|
||||
/// # async fn foo() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use ethers::providers::Ws;
|
||||
///
|
||||
/// let ws = Ws::connect("ws://localhost:8545").await?;
|
||||
///
|
||||
/// // If built with TLS support (otherwise will get a "TLS Support not compiled in" error)
|
||||
/// let ws = Ws::connect("wss://localhost:8545").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// This feature is built using [`async-tungstenite`](https://docs.rs/async-tungstenite). If you need other runtimes,
|
||||
/// consider importing `async-tungstenite` with the [corresponding feature
|
||||
/// flag](https://github.com/sdroege/async-tungstenite/blob/master/Cargo.toml#L15-L22)
|
||||
/// for your runtime.
|
||||
#[derive(Clone)]
|
||||
pub struct Ws {
|
||||
id: Arc<AtomicU64>,
|
||||
|
@ -123,8 +90,7 @@ impl Ws {
|
|||
}
|
||||
}
|
||||
|
||||
/// Initializes a new WebSocket Client, assuming usage of tokio or async-std
|
||||
#[cfg(any(feature = "tokio-runtime", feature = "async-std-runtime"))]
|
||||
/// Initializes a new WebSocket Client
|
||||
pub async fn connect(
|
||||
url: impl tungstenite::client::IntoClientRequest + Unpin,
|
||||
) -> Result<Self, ClientError> {
|
||||
|
@ -214,7 +180,6 @@ where
|
|||
}
|
||||
|
||||
/// Spawns the event loop
|
||||
#[allow(unused)]
|
||||
fn spawn(mut self)
|
||||
where
|
||||
S: 'static,
|
||||
|
@ -225,12 +190,7 @@ where
|
|||
}
|
||||
};
|
||||
|
||||
#[cfg(all(not(feature = "async-std-runtime"), feature = "tokio-runtime"))]
|
||||
tokio::spawn(f);
|
||||
// TODO: Ensure that this works with both async-std and tokio.
|
||||
// Remove allow(unused) when fixed.
|
||||
#[cfg(all(feature = "async-std-runtime", not(feature = "tokio-runtime")))]
|
||||
async_std::task::spawn(f);
|
||||
}
|
||||
|
||||
/// Processes 1 item selected from the incoming `requests` or `ws`
|
||||
|
|
|
@ -41,30 +41,17 @@ mod eth_tests {
|
|||
}
|
||||
|
||||
// Without TLS this would error with "TLS Support not compiled in"
|
||||
#[test]
|
||||
#[cfg(any(feature = "async-std-tls", feature = "tokio-tls"))]
|
||||
fn ssl_websocket() {
|
||||
// this is extremely ugly but I couldn't figure out a better way of having
|
||||
// a shared async test for both runtimes
|
||||
#[cfg(feature = "async-std-tls")]
|
||||
let block_on = async_std::task::block_on;
|
||||
#[cfg(feature = "tokio-tls")]
|
||||
let mut runtime = tokio::runtime::Runtime::new().unwrap();
|
||||
#[cfg(feature = "tokio-tls")]
|
||||
let mut block_on = |x| runtime.block_on(x);
|
||||
|
||||
#[tokio::test]
|
||||
async fn ssl_websocket() {
|
||||
use ethers::providers::Ws;
|
||||
block_on(async move {
|
||||
let ws = Ws::connect("wss://rinkeby.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
||||
.await
|
||||
.unwrap();
|
||||
let provider = Provider::new(ws);
|
||||
let _number = provider.get_block_number().await.unwrap();
|
||||
});
|
||||
let ws = Ws::connect("wss://rinkeby.infura.io/ws/v3/c60b0bb42f8a4c6481ecd229eddaca27")
|
||||
.await
|
||||
.unwrap();
|
||||
let provider = Provider::new(ws);
|
||||
let _number = provider.get_block_number().await.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[cfg(feature = "tokio-runtime")]
|
||||
async fn watch_blocks_websocket() {
|
||||
use ethers::{
|
||||
providers::{StreamExt, Ws},
|
||||
|
@ -72,7 +59,7 @@ mod eth_tests {
|
|||
};
|
||||
|
||||
let ganache = Ganache::new().block_time(2u64).spawn();
|
||||
let (ws, _) = async_tungstenite::tokio::connect_async(ganache.ws_endpoint())
|
||||
let (ws, _) = tokio_tungstenite::connect_async(ganache.ws_endpoint())
|
||||
.await
|
||||
.unwrap();
|
||||
let provider = Provider::new(Ws::new(ws)).interval(Duration::from_millis(500u64));
|
||||
|
@ -149,7 +136,6 @@ mod celo_tests {
|
|||
use super::*;
|
||||
use ethers::types::{Randomness, H256};
|
||||
use futures_util::stream::StreamExt;
|
||||
use rustc_hex::FromHex;
|
||||
|
||||
#[tokio::test]
|
||||
// https://alfajores-blockscout.celo-testnet.org/tx/0x544ea96cddb16aeeaedaf90885c1e02be4905f3eb43d6db3f28cac4dbe76a625/internal_transactions
|
||||
|
@ -176,14 +162,16 @@ mod celo_tests {
|
|||
assert_eq!(
|
||||
block.randomness,
|
||||
Randomness {
|
||||
committed: "003e12deb86292844274493e9ab6e57ed1e276202c16799d97af723eb0d3253f"
|
||||
.from_hex::<Vec<u8>>()
|
||||
.unwrap()
|
||||
.into(),
|
||||
revealed: "1333b3b45e0385da48a01b4459aeda7607867ef6a41167cfdeefa49b9fdce6d7"
|
||||
.from_hex::<Vec<u8>>()
|
||||
.unwrap()
|
||||
.into(),
|
||||
committed: hex::decode(
|
||||
"003e12deb86292844274493e9ab6e57ed1e276202c16799d97af723eb0d3253f"
|
||||
)
|
||||
.unwrap()
|
||||
.into(),
|
||||
revealed: hex::decode(
|
||||
"1333b3b45e0385da48a01b4459aeda7607867ef6a41167cfdeefa49b9fdce6d7"
|
||||
)
|
||||
.unwrap()
|
||||
.into(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,23 +16,23 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
[dependencies]
|
||||
ethers-core = { version = "0.1.3", path = "../ethers-core" }
|
||||
thiserror = { version = "1.0.22", default-features = false }
|
||||
futures-util = { version = "0.3.8", default-features = false }
|
||||
futures-executor = { version = "0.3.8", default-features = false }
|
||||
serde = { version = "1.0.118", default-features = false }
|
||||
|
||||
coins-ledger = { git = "https://github.com/summa-tx/bitcoins-rs", default-features = false, optional = true, branch = "master" }
|
||||
rustc-hex = { version = "2.1.0", default-features = false }
|
||||
hex = { version = "0.4.2", default-features = false, features = ["std"] }
|
||||
async-trait = { version = "0.1.40", default-features = false }
|
||||
elliptic-curve = { version = "0.8.4", default-features = false }
|
||||
sha2 = { version = "0.9.2", default-features = false }
|
||||
rand = { version = "0.7.3", default-features = false }
|
||||
yubihsm = { version = "0.37.0", features = ["secp256k1", "http", "usb"], optional = true }
|
||||
futures-util = "0.3.8"
|
||||
futures-executor = "0.3.8"
|
||||
|
||||
[dev-dependencies]
|
||||
ethers = { version = "0.1.3", path = "../ethers" }
|
||||
yubihsm = { version = "0.37.0", features = ["secp256k1", "usb", "mockhsm"] }
|
||||
|
||||
tokio = { version = "0.2.21", default-features = false, features = ["macros"] }
|
||||
tokio = { version = "1.0", default-features = false, features = ["macros"] }
|
||||
serde_json = { version = "1.0.55", default-features = false }
|
||||
|
||||
[features]
|
||||
|
|
|
@ -95,8 +95,10 @@ impl LedgerEthereum {
|
|||
let address = {
|
||||
// extract the address from the response
|
||||
let offset = 1 + result[0] as usize;
|
||||
let address = &result[offset + 1..offset + 1 + result[offset] as usize];
|
||||
std::str::from_utf8(address)?.parse::<Address>()?
|
||||
let address_str = &result[offset + 1..offset + 1 + result[offset] as usize];
|
||||
let mut address = [0; 20];
|
||||
address.copy_from_slice(&hex::decode(address_str)?);
|
||||
Address::from(address)
|
||||
};
|
||||
|
||||
Ok(address)
|
||||
|
@ -207,7 +209,6 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::Signer;
|
||||
use ethers::prelude::*;
|
||||
use rustc_hex::FromHex;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -239,11 +240,12 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
// approve uni v2 router 0xff
|
||||
let data = "095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff".from_hex::<Vec<u8>>().unwrap();
|
||||
let data = hex::decode("095ea7b30000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap();
|
||||
|
||||
let tx_req = TransactionRequest::new()
|
||||
.send_to_str("2ed7afa17473e17ac59908f088b4371d28585476")
|
||||
.unwrap()
|
||||
.to("2ed7afa17473e17ac59908f088b4371d28585476"
|
||||
.parse::<Address>()
|
||||
.unwrap())
|
||||
.gas(1000000)
|
||||
.gas_price(400e9 as u64)
|
||||
.nonce(5)
|
||||
|
|
|
@ -34,7 +34,7 @@ pub enum LedgerError {
|
|||
UnexpectedNullResponse,
|
||||
|
||||
#[error(transparent)]
|
||||
HexError(#[from] rustc_hex::FromHexError),
|
||||
HexError(#[from] hex::FromHexError),
|
||||
|
||||
#[error("Error when decoding UTF8 Response: {0}")]
|
||||
Utf8Error(#[from] std::str::Utf8Error),
|
||||
|
|
|
@ -9,7 +9,6 @@ use ethers_core::{
|
|||
types::Address,
|
||||
utils::keccak256,
|
||||
};
|
||||
use rustc_hex::FromHex;
|
||||
use std::str::FromStr;
|
||||
|
||||
impl Clone for Wallet<SigningKey> {
|
||||
|
@ -87,9 +86,7 @@ impl FromStr for Wallet<SigningKey> {
|
|||
type Err = K256Error;
|
||||
|
||||
fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
let src = src
|
||||
.from_hex::<Vec<u8>>()
|
||||
.expect("invalid hex when reading PrivateKey");
|
||||
let src = hex::decode(src).expect("invalid hex when reading PrivateKey");
|
||||
let sk = SigningKey::from_bytes(&src).unwrap(); // TODO
|
||||
Ok(sk.into())
|
||||
}
|
||||
|
|
|
@ -67,13 +67,11 @@ impl From<YubiSigner<Secp256k1>> for Wallet<YubiSigner<Secp256k1>> {
|
|||
mod tests {
|
||||
use super::*;
|
||||
use crate::Signer;
|
||||
use rustc_hex::FromHex;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[tokio::test]
|
||||
async fn from_key() {
|
||||
let key = "2d8c44dc2dd2f0bea410e342885379192381e82d855b1b112f9b55544f1e0900"
|
||||
.from_hex::<Vec<u8>>()
|
||||
let key = hex::decode("2d8c44dc2dd2f0bea410e342885379192381e82d855b1b112f9b55544f1e0900")
|
||||
.unwrap();
|
||||
|
||||
let connector = yubihsm::Connector::mockhsm();
|
||||
|
|
|
@ -20,16 +20,6 @@ rustdoc-args = ["--cfg", "docsrs"]
|
|||
features = ["full"]
|
||||
|
||||
[features]
|
||||
abigen = ["contract", "ethers-contract/abigen"]
|
||||
default = ["full"]
|
||||
full = [
|
||||
"contract",
|
||||
"providers",
|
||||
"signers",
|
||||
"core",
|
||||
"middleware",
|
||||
]
|
||||
|
||||
celo = [
|
||||
"ethers-core/celo",
|
||||
"ethers-providers/celo",
|
||||
|
@ -38,27 +28,23 @@ celo = [
|
|||
"ethers-middleware/celo",
|
||||
]
|
||||
|
||||
core = ["ethers-core"]
|
||||
contract = ["ethers-contract"]
|
||||
providers = ["ethers-providers"]
|
||||
middleware = ["ethers-middleware"]
|
||||
signers = ["ethers-signers"]
|
||||
ledger = ["ethers-signers/ledger"]
|
||||
yubi = ["ethers-signers/yubi"]
|
||||
ws = ["ethers-providers/ws"]
|
||||
abigen = ["ethers-contract/abigen"]
|
||||
|
||||
[dependencies]
|
||||
ethers-contract = { version = "0.1.3", path = "../ethers-contract", optional = true }
|
||||
ethers-core = { version = "0.1.3", path = "../ethers-core", optional = true }
|
||||
ethers-providers = { version = "0.1.3", path = "../ethers-providers", optional = true }
|
||||
ethers-signers = { version = "0.1.3", path = "../ethers-signers", optional = true }
|
||||
ethers-middleware = { version = "0.1.3", path = "../ethers-middleware", optional = true }
|
||||
ethers-contract = { version = "0.1.3", path = "../ethers-contract" }
|
||||
ethers-core = { version = "0.1.3", path = "../ethers-core" }
|
||||
ethers-providers = { version = "0.1.3", path = "../ethers-providers" }
|
||||
ethers-signers = { version = "0.1.3", path = "../ethers-signers" }
|
||||
ethers-middleware = { version = "0.1.3", path = "../ethers-middleware" }
|
||||
|
||||
[dev-dependencies]
|
||||
ethers-contract = { version = "0.1.3", path = "../ethers-contract", features = ["abigen"] }
|
||||
ethers-providers = { version = "0.1.3", path = "../ethers-providers" }
|
||||
|
||||
anyhow = "1.0.31"
|
||||
anyhow = "1.0.36"
|
||||
rand = "0.7"
|
||||
serde = { version = "1.0.110", features = ["derive"] }
|
||||
serde_json = "1.0.53"
|
||||
tokio = { version = "0.2.21", features = ["macros"] }
|
||||
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }
|
||||
|
|
|
@ -82,50 +82,28 @@
|
|||
//! [`utils`]: core::utils
|
||||
//! [`abi`]: core::abi
|
||||
//! [`types`]: core::types
|
||||
|
||||
#[cfg(feature = "contract")]
|
||||
pub use ethers_contract as contract;
|
||||
|
||||
#[cfg(feature = "providers")]
|
||||
pub use ethers_providers as providers;
|
||||
|
||||
#[cfg(feature = "signers")]
|
||||
pub use ethers_signers as signers;
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
pub use ethers_core as core;
|
||||
|
||||
#[cfg(feature = "middleware")]
|
||||
pub use ethers_middleware as middleware;
|
||||
pub use ethers_providers as providers;
|
||||
pub use ethers_signers as signers;
|
||||
|
||||
// Re-export ethers_core::utils/types/abi
|
||||
// We hide these docs so that the rustdoc links send the visitor
|
||||
// to the corresponding crate, instead of the re-export
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "core")]
|
||||
pub use ethers_core::abi;
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "core")]
|
||||
pub use ethers_core::types;
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature = "core")]
|
||||
pub use ethers_core::utils;
|
||||
|
||||
/// Easy imports of frequently used type definitions and traits
|
||||
#[doc(hidden)]
|
||||
pub mod prelude {
|
||||
#[cfg(feature = "contract")]
|
||||
pub use ethers_contract::*;
|
||||
|
||||
#[cfg(feature = "providers")]
|
||||
pub use ethers_providers::*;
|
||||
|
||||
#[cfg(feature = "signers")]
|
||||
pub use ethers_signers::*;
|
||||
|
||||
#[cfg(feature = "middleware")]
|
||||
pub use ethers_middleware::*;
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
pub use ethers_core::types::*;
|
||||
pub use ethers_middleware::*;
|
||||
pub use ethers_providers::*;
|
||||
pub use ethers_signers::*;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue