diff --git a/crates/erc20_payment_lib/src/signer.rs b/crates/erc20_payment_lib/src/signer.rs index ddb21182..6b4c0dde 100644 --- a/crates/erc20_payment_lib/src/signer.rs +++ b/crates/erc20_payment_lib/src/signer.rs @@ -1,129 +1,7 @@ -use crate::contracts::DUMMY_RPC_PROVIDER; -use crate::eth::get_eth_addr_from_secret; -use erc20_payment_lib_common::err_custom_create; -use erc20_payment_lib_common::error::PaymentError; -use futures_util::future::BoxFuture; -use futures_util::FutureExt; -use secp256k1::SecretKey; -use std::fmt::{Debug, Display, Formatter}; -use std::sync::Arc; -use tokio::time::timeout; +mod account; +mod external; +mod private; -use web3::types::{Address, SignedTransaction, TransactionParameters, H160}; - -#[derive(Clone)] -pub struct SignerAccount { - pub address: Address, - pub signer: Arc>, -} - -impl Debug for SignerAccount { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "SignerAccount {{ address: {:#x} }}", self.address) - } -} - -impl Display for SignerAccount { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{:#x}", self.address) - } -} - -impl SignerAccount { - pub fn new(address: H160, signer: Arc>) -> Self { - Self { address, signer } - } - - pub async fn check_if_sign_possible(&self) -> Result<(), PaymentError> { - match timeout( - std::time::Duration::from_secs(5), - self.signer.check_if_sign_possible(self.address), - ) - .await - { - Ok(Ok(())) => Ok(()), - Ok(Err(err)) => Err(err_custom_create!("Sign returned error {err:?}")), - Err(err) => Err(err_custom_create!("Sign check timed out {err:?}")), - } - } - - pub async fn sign(&self, tp: TransactionParameters) -> Result { - match timeout( - std::time::Duration::from_secs(5), - self.signer.sign(self.address, tp), - ) - .await - { - Ok(Ok(signed)) => Ok(signed), - Ok(Err(err)) => Err(err_custom_create!("Sign returned error {err:?}")), - Err(err) => Err(err_custom_create!("Sign check timed out {err:?}")), - } - } -} - -#[derive(Debug)] -pub struct SignerError { - pub message: String, -} - -pub trait Signer: Send + Sync { - /// Check if signer can sign transaction for given public address - fn check_if_sign_possible(&self, pub_address: H160) -> BoxFuture<'_, Result<(), SignerError>>; - - /// Sign transaction for given public address (look at PrivateKeySigner for example) - fn sign( - &self, - pub_address: H160, - tp: TransactionParameters, - ) -> BoxFuture<'_, Result>; -} - -/// PrivateKeySigner is implementation of Signer trait that stores private keys in memory and use -/// them to sign transactions matching them by public addresses -pub struct PrivateKeySigner { - secret_keys: Vec, -} - -impl PrivateKeySigner { - pub fn new(secret_keys: Vec) -> Self { - Self { secret_keys } - } - - fn get_private_key(&self, pub_address: H160) -> Result<&SecretKey, SignerError> { - self.secret_keys - .iter() - .find(|sk| get_eth_addr_from_secret(sk) == pub_address) - .ok_or(SignerError { - message: "Failed to find private key for address: {from_addr}".to_string(), - }) - } -} - -impl Signer for PrivateKeySigner { - fn check_if_sign_possible(&self, pub_address: H160) -> BoxFuture<'_, Result<(), SignerError>> { - async move { - self.get_private_key(pub_address)?; - Ok(()) - } - .boxed() - } - - fn sign( - &self, - pub_address: H160, - tp: TransactionParameters, - ) -> BoxFuture<'_, Result> { - async move { - let secret_key = self.get_private_key(pub_address)?; - let signed = DUMMY_RPC_PROVIDER - .accounts() - .sign_transaction(tp, secret_key) - .await - .map_err(|err| SignerError { - message: format!("Error when signing transaction in PrivateKeySigner {err}"), - })?; - Ok(signed) - } - .boxed() - } -} +pub use account::*; +pub use external::*; +pub use private::*; diff --git a/crates/erc20_payment_lib/src/signer/account.rs b/crates/erc20_payment_lib/src/signer/account.rs new file mode 100644 index 00000000..75494ec2 --- /dev/null +++ b/crates/erc20_payment_lib/src/signer/account.rs @@ -0,0 +1,58 @@ +use erc20_payment_lib_common::err_custom_create; +use erc20_payment_lib_common::error::PaymentError; +use std::fmt::{Debug, Display, Formatter}; +use std::sync::Arc; +use tokio::time::timeout; + +use super::Signer; +use web3::types::{Address, SignedTransaction, TransactionParameters, H160}; + +#[derive(Clone)] +pub struct SignerAccount { + pub address: Address, + pub signer: Arc>, +} + +impl Debug for SignerAccount { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "SignerAccount {{ address: {:#x} }}", self.address) + } +} + +impl Display for SignerAccount { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{:#x}", self.address) + } +} + +impl SignerAccount { + pub fn new(address: H160, signer: Arc>) -> Self { + Self { address, signer } + } + + pub async fn check_if_sign_possible(&self) -> Result<(), PaymentError> { + match timeout( + std::time::Duration::from_secs(5), + self.signer.check_if_sign_possible(self.address), + ) + .await + { + Ok(Ok(())) => Ok(()), + Ok(Err(err)) => Err(err_custom_create!("Sign returned error {err:?}")), + Err(err) => Err(err_custom_create!("Sign check timed out {err:?}")), + } + } + + pub async fn sign(&self, tp: TransactionParameters) -> Result { + match timeout( + std::time::Duration::from_secs(5), + self.signer.sign(self.address, tp), + ) + .await + { + Ok(Ok(signed)) => Ok(signed), + Ok(Err(err)) => Err(err_custom_create!("Sign returned error {err:?}")), + Err(err) => Err(err_custom_create!("Sign check timed out {err:?}")), + } + } +} diff --git a/crates/erc20_payment_lib/src/signer/external.rs b/crates/erc20_payment_lib/src/signer/external.rs new file mode 100644 index 00000000..edd10af9 --- /dev/null +++ b/crates/erc20_payment_lib/src/signer/external.rs @@ -0,0 +1,21 @@ +use futures_util::future::BoxFuture; +use std::fmt::Debug; + +use web3::types::{SignedTransaction, TransactionParameters, H160}; + +#[derive(Debug)] +pub struct SignerError { + pub message: String, +} + +pub trait Signer: Send + Sync { + /// Check if signer can sign transaction for given public address + fn check_if_sign_possible(&self, pub_address: H160) -> BoxFuture<'_, Result<(), SignerError>>; + + /// Sign transaction for given public address (look at PrivateKeySigner for example) + fn sign( + &self, + pub_address: H160, + tp: TransactionParameters, + ) -> BoxFuture<'_, Result>; +} diff --git a/crates/erc20_payment_lib/src/signer/private.rs b/crates/erc20_payment_lib/src/signer/private.rs new file mode 100644 index 00000000..ebd22bf8 --- /dev/null +++ b/crates/erc20_payment_lib/src/signer/private.rs @@ -0,0 +1,58 @@ +use crate::contracts::DUMMY_RPC_PROVIDER; +use crate::eth::get_eth_addr_from_secret; +use futures_util::future::BoxFuture; +use futures_util::FutureExt; +use secp256k1::SecretKey; + +use super::{Signer, SignerError}; +use web3::types::{SignedTransaction, TransactionParameters, H160}; + +/// PrivateKeySigner is implementation of Signer trait that stores private keys in memory and use +/// them to sign transactions matching them by public addresses +pub struct PrivateKeySigner { + secret_keys: Vec, +} + +impl PrivateKeySigner { + pub fn new(secret_keys: Vec) -> Self { + Self { secret_keys } + } + + fn get_private_key(&self, pub_address: H160) -> Result<&SecretKey, SignerError> { + self.secret_keys + .iter() + .find(|sk| get_eth_addr_from_secret(sk) == pub_address) + .ok_or(SignerError { + message: "Failed to find private key for address: {from_addr}".to_string(), + }) + } +} + +impl Signer for PrivateKeySigner { + fn check_if_sign_possible(&self, pub_address: H160) -> BoxFuture<'_, Result<(), SignerError>> { + async move { + self.get_private_key(pub_address)?; + Ok(()) + } + .boxed() + } + + fn sign( + &self, + pub_address: H160, + tp: TransactionParameters, + ) -> BoxFuture<'_, Result> { + async move { + let secret_key = self.get_private_key(pub_address)?; + let signed = DUMMY_RPC_PROVIDER + .accounts() + .sign_transaction(tp, secret_key) + .await + .map_err(|err| SignerError { + message: format!("Error when signing transaction in PrivateKeySigner {err}"), + })?; + Ok(signed) + } + .boxed() + } +}