lints and more examples
This commit is contained in:
parent
4b6fbf00a8
commit
8a8e33c9c8
|
@ -4,16 +4,21 @@ use std::str::FromStr;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), failure::Error> {
|
async fn main() -> Result<(), failure::Error> {
|
||||||
|
// connect to the network
|
||||||
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
||||||
|
|
||||||
|
// create a wallet and connect it to the provider
|
||||||
let client = MainnetWallet::from_str(
|
let client = MainnetWallet::from_str(
|
||||||
"d8ebe1e50cfea1f9961908d9df28e64bb163fee9ee48320361b2eb0a54974269",
|
"d8ebe1e50cfea1f9961908d9df28e64bb163fee9ee48320361b2eb0a54974269",
|
||||||
)?
|
)?
|
||||||
.connect(&provider);
|
.connect(&provider);
|
||||||
|
|
||||||
|
// get the account's nonce
|
||||||
let nonce = provider
|
let nonce = provider
|
||||||
.get_transaction_count(client.signer.address, None)
|
.get_transaction_count(client.signer.address, None)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// craft the transaction
|
||||||
let tx = UnsignedTransaction {
|
let tx = UnsignedTransaction {
|
||||||
to: Some("986eE0C8B91A58e490Ee59718Cca41056Cf55f24".parse().unwrap()),
|
to: Some("986eE0C8B91A58e490Ee59718Cca41056Cf55f24".parse().unwrap()),
|
||||||
gas: 21000.into(),
|
gas: 21000.into(),
|
||||||
|
@ -23,8 +28,10 @@ async fn main() -> Result<(), failure::Error> {
|
||||||
nonce,
|
nonce,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// send it!
|
||||||
let tx = client.send_transaction(tx).await?;
|
let tx = client.send_transaction(tx).await?;
|
||||||
|
|
||||||
|
// get the mined tx
|
||||||
let tx = client.get_transaction(tx.hash).await?;
|
let tx = client.get_transaction(tx.hash).await?;
|
||||||
|
|
||||||
println!("{}", serde_json::to_string(&tx)?);
|
println!("{}", serde_json::to_string(&tx)?);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -6,11 +6,12 @@ use std::convert::TryFrom;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), failure::Error> {
|
async fn main() -> Result<(), failure::Error> {
|
||||||
|
// connect to the network
|
||||||
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
let provider = HttpProvider::try_from("http://localhost:8545")?;
|
||||||
let from = "4916064D2E9C1b2ccC466EEc3d30B2b08F1C130D".parse()?;
|
let from = "4916064D2E9C1b2ccC466EEc3d30B2b08F1C130D".parse()?;
|
||||||
|
|
||||||
let tx_hash = provider
|
// craft the tx
|
||||||
.send_transaction(TransactionRequest {
|
let tx = TransactionRequest {
|
||||||
from,
|
from,
|
||||||
to: Some("9A7e5d4bcA656182e66e33340d776D1542143006".parse()?),
|
to: Some("9A7e5d4bcA656182e66e33340d776D1542143006".parse()?),
|
||||||
value: Some(1000u64.into()),
|
value: Some(1000u64.into()),
|
||||||
|
@ -18,8 +19,10 @@ async fn main() -> Result<(), failure::Error> {
|
||||||
gas_price: None,
|
gas_price: None,
|
||||||
data: None,
|
data: None,
|
||||||
nonce: None,
|
nonce: None,
|
||||||
})
|
};
|
||||||
.await?;
|
|
||||||
|
// broadcast it via the eth_sendTransaction API
|
||||||
|
let tx_hash = provider.send_transaction(tx).await?;
|
||||||
|
|
||||||
let tx = provider.get_transaction(tx_hash).await?;
|
let tx = provider.get_transaction(tx_hash).await?;
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub mod providers;
|
||||||
pub use providers::HttpProvider;
|
pub use providers::HttpProvider;
|
||||||
|
|
||||||
pub mod signers;
|
pub mod signers;
|
||||||
pub use signers::{AnyWallet, MainnetWallet};
|
pub use signers::{AnyWallet, MainnetWallet, Signer};
|
||||||
|
|
||||||
/// Ethereum related datatypes
|
/// Ethereum related datatypes
|
||||||
pub mod types;
|
pub mod types;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
mod http;
|
mod http;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
signers::{Client, Signer},
|
||||||
types::{Address, BlockNumber, Bytes, Transaction, TransactionRequest, TxHash, U256},
|
types::{Address, BlockNumber, Bytes, Transaction, TransactionRequest, TxHash, U256},
|
||||||
utils,
|
utils,
|
||||||
};
|
};
|
||||||
|
@ -37,6 +38,14 @@ pub struct Provider<P>(P);
|
||||||
|
|
||||||
// JSON RPC bindings
|
// JSON RPC bindings
|
||||||
impl<P: JsonRpcClient> Provider<P> {
|
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> {
|
pub async fn get_block_number(&self) -> Result<U256, P::Error> {
|
||||||
self.0.request("eth_blockNumber", None::<()>).await
|
self.0.request("eth_blockNumber", None::<()>).await
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Client<'a, S, P> {
|
pub struct Client<'a, S, P> {
|
||||||
pub(super) provider: &'a Provider<P>,
|
pub provider: &'a Provider<P>,
|
||||||
pub signer: S,
|
pub signer: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Sign and broadcast transactions
|
||||||
mod networks;
|
mod networks;
|
||||||
pub use networks::instantiated::*;
|
pub use networks::instantiated::*;
|
||||||
use networks::Network;
|
use networks::Network;
|
||||||
|
@ -6,7 +7,7 @@ mod wallet;
|
||||||
pub use wallet::Wallet;
|
pub use wallet::Wallet;
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
use client::Client;
|
pub(crate) use client::Client;
|
||||||
|
|
||||||
use crate::types::{Signature, Transaction, UnsignedTransaction};
|
use crate::types::{Signature, Transaction, UnsignedTransaction};
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,13 @@ use crate::{
|
||||||
utils::hash_message,
|
utils::hash_message,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use rustc_hex::ToHex;
|
||||||
use secp256k1::{
|
use secp256k1::{
|
||||||
recovery::{RecoverableSignature, RecoveryId},
|
recovery::{RecoverableSignature, RecoveryId},
|
||||||
Error as Secp256k1Error, Message, Secp256k1,
|
Error as Secp256k1Error, Message, Secp256k1,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::convert::TryFrom;
|
use std::{convert::TryFrom, fmt};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// An error involving a signature.
|
/// An error involving a signature.
|
||||||
|
@ -47,6 +48,13 @@ pub struct Signature {
|
||||||
pub v: u8,
|
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 {
|
impl Signature {
|
||||||
/// Recovers the Ethereum address which was used to sign the given message.
|
/// 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
|
/// 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
|
/// 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.
|
/// and the final byte is the `v` value in 'Electrum' notation.
|
||||||
fn try_from(raw_signature: &'a [u8]) -> Result<Self, Self::Error> {
|
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
|
||||||
let bytes = raw_signature.as_ref();
|
|
||||||
|
|
||||||
if bytes.len() != 65 {
|
if bytes.len() != 65 {
|
||||||
return Err(SignatureError::InvalidLength(bytes.len()));
|
return Err(SignatureError::InvalidLength(bytes.len()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl UnsignedTransaction {
|
||||||
rlp.begin_list(9);
|
rlp.begin_list(9);
|
||||||
self.rlp_base(&mut rlp);
|
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);
|
||||||
rlp.append(&0u8);
|
rlp.append(&0u8);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue