erc20_payment_lib 0.5.1

Payment processor for ERC20 tokens
Documentation
use chrono::{DateTime, Utc};
use erc20_payment_lib_common::err_custom_create;
use erc20_payment_lib_common::error::PaymentError;
use serde::Serialize;
use std::fmt::{Debug, Display, Formatter};
use std::sync::{Arc, Mutex};
use tokio::task::JoinHandle;
use tokio::time::timeout;

use super::Signer;
use web3::types::{Address, SignedTransaction, TransactionParameters, H160};

#[derive(Clone, Serialize)]
pub struct SignerAccount {
    pub address: Address,
    #[serde(skip)]
    pub signer: Arc<Box<dyn Signer + Send + Sync>>,
    pub(crate) external_gather_time: Arc<Mutex<Option<DateTime<Utc>>>>,
    #[serde(skip)]
    pub(crate) jh: Arc<Mutex<Vec<Option<JoinHandle<()>>>>>,
}

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<Box<dyn Signer + Send + Sync>>) -> Self {
        Self {
            address,
            signer,
            external_gather_time: Arc::new(Mutex::new(None)),
            jh: Arc::new(Mutex::new(Vec::new())),
        }
    }

    pub fn is_active(&self) -> bool {
        let jh_guard = self.jh.lock().unwrap();
        for jh in jh_guard.iter() {
            if let Some(jh) = (*jh).as_ref() {
                if !jh.is_finished() {
                    return true;
                }
            }
        }
        false
    }

    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<SignedTransaction, PaymentError> {
        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:?}")),
        }
    }
}