lints and more examples

This commit is contained in:
Georgios Konstantopoulos 2020-05-24 19:14:27 +03:00
parent 4b6fbf00a8
commit 8a8e33c9c8
No known key found for this signature in database
GPG Key ID: FA607837CD26EDBC
9 changed files with 62 additions and 19 deletions

View File

@ -4,16 +4,21 @@ use std::str::FromStr;
#[tokio::main]
async fn main() -> Result<(), failure::Error> {
// connect to the network
let provider = HttpProvider::try_from("http://localhost:8545")?;
// create a wallet and connect it to the provider
let client = MainnetWallet::from_str(
"d8ebe1e50cfea1f9961908d9df28e64bb163fee9ee48320361b2eb0a54974269",
)?
.connect(&provider);
// get the account's nonce
let nonce = provider
.get_transaction_count(client.signer.address, None)
.await?;
// craft the transaction
let tx = UnsignedTransaction {
to: Some("986eE0C8B91A58e490Ee59718Cca41056Cf55f24".parse().unwrap()),
gas: 21000.into(),
@ -23,8 +28,10 @@ async fn main() -> Result<(), failure::Error> {
nonce,
};
// send it!
let tx = client.send_transaction(tx).await?;
// get the mined tx
let tx = client.get_transaction(tx.hash).await?;
println!("{}", serde_json::to_string(&tx)?);

17
examples/sign.rs Normal file
View File

@ -0,0 +1,17 @@
use ethers::{MainnetWallet as Wallet, Signer};
fn main() {
let message = "Some data";
let wallet = Wallet::new(&mut rand::thread_rng());
// sign a message
let signature = wallet.sign_message(message);
println!("Produced signature {}", signature);
// recover the address that signed it
let recovered = signature.recover(message).unwrap();
assert_eq!(recovered, wallet.address);
println!("Verified signature produced by {:?}!", wallet.address);
}

View File

@ -6,20 +6,23 @@ use std::convert::TryFrom;
#[tokio::main]
async fn main() -> Result<(), failure::Error> {
// connect to the network
let provider = HttpProvider::try_from("http://localhost:8545")?;
let from = "4916064D2E9C1b2ccC466EEc3d30B2b08F1C130D".parse()?;
let tx_hash = provider
.send_transaction(TransactionRequest {
from,
to: Some("9A7e5d4bcA656182e66e33340d776D1542143006".parse()?),
value: Some(1000u64.into()),
gas: None,
gas_price: None,
data: None,
nonce: None,
})
.await?;
// craft the tx
let tx = TransactionRequest {
from,
to: Some("9A7e5d4bcA656182e66e33340d776D1542143006".parse()?),
value: Some(1000u64.into()),
gas: None,
gas_price: None,
data: None,
nonce: None,
};
// broadcast it via the eth_sendTransaction API
let tx_hash = provider.send_transaction(tx).await?;
let tx = provider.get_transaction(tx_hash).await?;

View File

@ -19,7 +19,7 @@ pub mod providers;
pub use providers::HttpProvider;
pub mod signers;
pub use signers::{AnyWallet, MainnetWallet};
pub use signers::{AnyWallet, MainnetWallet, Signer};
/// Ethereum related datatypes
pub mod types;

View File

@ -6,6 +6,7 @@
mod http;
use crate::{
signers::{Client, Signer},
types::{Address, BlockNumber, Bytes, Transaction, TransactionRequest, TxHash, U256},
utils,
};
@ -37,6 +38,14 @@ pub struct Provider<P>(P);
// JSON RPC bindings
impl<P: JsonRpcClient> Provider<P> {
/// Connects to a signer and returns a client
pub fn connect<S: Signer>(&self, signer: S) -> Client<S, P> {
Client {
signer,
provider: self,
}
}
pub async fn get_block_number(&self) -> Result<U256, P::Error> {
self.0.request("eth_blockNumber", None::<()>).await
}

View File

@ -6,7 +6,7 @@ use crate::{
#[derive(Clone, Debug)]
pub struct Client<'a, S, P> {
pub(super) provider: &'a Provider<P>,
pub provider: &'a Provider<P>,
pub signer: S,
}

View File

@ -1,3 +1,4 @@
//! Sign and broadcast transactions
mod networks;
pub use networks::instantiated::*;
use networks::Network;
@ -6,7 +7,7 @@ mod wallet;
pub use wallet::Wallet;
mod client;
use client::Client;
pub(crate) use client::Client;
use crate::types::{Signature, Transaction, UnsignedTransaction};

View File

@ -4,12 +4,13 @@ use crate::{
utils::hash_message,
};
use rustc_hex::ToHex;
use secp256k1::{
recovery::{RecoverableSignature, RecoveryId},
Error as Secp256k1Error, Message, Secp256k1,
};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::{convert::TryFrom, fmt};
use thiserror::Error;
/// An error involving a signature.
@ -47,6 +48,13 @@ pub struct Signature {
pub v: u8,
}
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>())
}
}
impl Signature {
/// Recovers the Ethereum address which was used to sign the given message.
///
@ -106,9 +114,7 @@ impl<'a> TryFrom<&'a [u8]> for Signature {
/// Parses a raw signature which is expected to be 65 bytes long where
/// the first 32 bytes is the `r` value, the second 32 bytes the `s` value
/// and the final byte is the `v` value in 'Electrum' notation.
fn try_from(raw_signature: &'a [u8]) -> Result<Self, Self::Error> {
let bytes = raw_signature.as_ref();
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
if bytes.len() != 65 {
return Err(SignatureError::InvalidLength(bytes.len()));
}

View File

@ -87,7 +87,7 @@ impl UnsignedTransaction {
rlp.begin_list(9);
self.rlp_base(&mut rlp);
rlp.append(&chain_id.unwrap_or(U64::zero()));
rlp.append(&chain_id.unwrap_or_else(U64::zero));
rlp.append(&0u8);
rlp.append(&0u8);