pub mod builder;
use std::{cell::Cell, fmt::Display};
pub use builder::*;
use serde::{Serialize, Serializer};
use crate::{
core::{GetTransactionResponse, TxHash},
middlewares::Middleware,
providers::{JsonRpcClient, Provider},
Error,
};
#[derive(Debug)]
pub struct Transaction<'a, T: JsonRpcClient> {
pub id: TxHash,
client: &'a Provider<T>,
status: Cell<TxStatus>,
}
#[derive(Debug, Clone, Copy)]
pub enum TxStatus {
Initialized,
Pending,
Confirmed,
Rejected,
}
impl<'a, T: JsonRpcClient> Transaction<'a, T> {
pub fn new(id: TxHash, client: &'a Provider<T>) -> Self {
Self {
id,
client,
status: Cell::new(TxStatus::Initialized),
}
}
pub async fn confirm(&self) -> Result<GetTransactionResponse, Error> {
self.try_confirm(tokio::time::Duration::from_secs(10), 33).await
}
pub async fn try_confirm(&self, interval: tokio::time::Duration, max_attempt: u32) -> Result<GetTransactionResponse, Error> {
self.status.set(TxStatus::Pending);
for _ in 0..max_attempt {
let res = match self.client.get_transaction(&self.id).await {
Ok(res) => res,
Err(_) => {
tokio::time::sleep(interval).await;
continue;
}
};
self.status.set(if res.receipt.success {
TxStatus::Confirmed
} else {
TxStatus::Rejected
});
return Ok(res);
}
Err(Error::UnableToConfirmTransaction(max_attempt))
}
}
#[derive(Debug, Default, PartialEq, Clone)]
pub struct Version {
msg_version: u16,
chain_id: u16,
}
impl Version {
pub fn new(chain_id: u16) -> Self {
Self {
chain_id,
msg_version: 1,
}
}
pub fn pack(&self) -> u32 {
(self.chain_id as u32) << 16 | (self.msg_version as u32)
}
pub fn is_valid(&self) -> bool {
(self.chain_id > 0) && (self.msg_version > 0)
}
}
impl Display for Version {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "chain_id: {}, msg_version: {}", self.chain_id, self.msg_version)
}
}
impl Serialize for Version {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let packed = self.pack();
serializer.serialize_u32(packed)
}
}