use std::io::{self, Error, ErrorKind};
use avalanche_types::key;
use primitive_types::{H160, H256, U256};
use tokio::time::{sleep, Duration, Instant};
pub const DEFAULT_GAS: u64 = 21000;
#[derive(Clone, Debug)]
pub struct Tx<T>
where
T: key::secp256k1::ReadOnly + key::secp256k1::SignOnly + Clone,
{
pub inner: crate::wallet::eth::Eth<T>,
pub receiver: H160,
pub amount: U256,
pub gas: U256,
pub gas_price: U256,
pub nonce: Option<primitive_types::U256>,
pub data: Option<Vec<u8>>,
pub check_acceptance: bool,
pub poll_initial_wait: Duration,
pub poll_interval: Duration,
pub poll_timeout: Duration,
pub dry_mode: bool,
}
impl<T> Tx<T>
where
T: key::secp256k1::ReadOnly + key::secp256k1::SignOnly + Clone,
{
pub fn new(ev: &crate::wallet::eth::Eth<T>) -> Self {
Self {
inner: ev.clone(),
receiver: H160::zero(),
amount: U256::from(0),
gas: U256::from(DEFAULT_GAS),
gas_price: U256::from(0),
nonce: None,
data: None,
check_acceptance: false,
poll_initial_wait: Duration::from_millis(500),
poll_interval: Duration::from_millis(700),
poll_timeout: Duration::from_secs(300),
dry_mode: false,
}
}
#[must_use]
pub fn receiver(mut self, receiver: H160) -> Self {
self.receiver = receiver;
self
}
#[must_use]
pub fn amount(mut self, amount: U256) -> Self {
self.amount = amount;
self
}
#[must_use]
pub fn gas(mut self, gas: U256) -> Self {
self.gas = gas;
self
}
#[must_use]
pub fn gas_price(mut self, gas_price: U256) -> Self {
self.gas_price = gas_price;
self
}
#[must_use]
pub fn nonce(mut self, nonce: U256) -> Self {
self.nonce = Some(nonce);
self
}
#[must_use]
pub fn data(mut self, data: Vec<u8>) -> Self {
self.data = Some(data);
self
}
#[must_use]
pub fn check_acceptance(mut self, check_acceptance: bool) -> Self {
self.check_acceptance = check_acceptance;
self
}
#[must_use]
pub fn poll_initial_wait(mut self, poll_initial_wait: Duration) -> Self {
self.poll_initial_wait = poll_initial_wait;
self
}
#[must_use]
pub fn poll_interval(mut self, poll_interval: Duration) -> Self {
self.poll_interval = poll_interval;
self
}
#[must_use]
pub fn poll_timeout(mut self, poll_timeout: Duration) -> Self {
self.poll_timeout = poll_timeout;
self
}
#[must_use]
pub fn dry_mode(mut self, dry_mode: bool) -> Self {
self.dry_mode = dry_mode;
self
}
pub async fn issue(&self) -> io::Result<H256> {
let picked_http_rpc = self.inner.inner.pick_http_rpc();
log::info!(
"transferring EVM {} AVAX from {} to {} via {} (chain RPC {})",
self.amount,
self.inner.inner.h160_address,
self.receiver,
picked_http_rpc.1,
self.inner.chain_rpc_url_path
);
log::info!("initial waiting {:?}", self.poll_initial_wait);
sleep(self.poll_initial_wait).await;
log::info!("polling to confirm transaction");
let (start, mut success) = (Instant::now(), false);
loop {
let elapsed = start.elapsed();
if elapsed.gt(&self.poll_timeout) {
break;
}
if 1 == 1 {
success = true;
break;
}
sleep(self.poll_interval).await;
}
if !success {
return Err(Error::new(
ErrorKind::Other,
"failed to check acceptance in time",
));
}
return Err(Error::new(ErrorKind::Other, "not implemented"));
}
}