use df_hyperliquid_core::client::evm::BadAmount;
use df_hyperliquid_core::client::evm::abi::AbiError;
use crate::client::read::Fields;
use crate::client::{BadLog, Call, Log};
use crate::nitro::sys::{self, L2_TO_L1_TX};
use crate::nitro::table::ARB_SYS;
use crate::utils::{Address, Dec, wei};
use crate::{B256, U256};
pub fn withdraw(destination: Address, amount: Dec) -> Result<Call, BadAmount> {
if !amount.is_positive() {
return Err(BadAmount::NotPositive(amount));
}
Ok(sys::withdraw_eth(destination, wei(amount)?))
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Withdrawal {
pub caller: Address,
pub destination: Address,
pub hash: U256,
pub position: u64,
pub arb_block: u64,
pub eth_block: u64,
pub timestamp: u64,
pub value: U256,
pub data: Vec<u8>,
}
impl Withdrawal {
pub fn from_log(log: &Log) -> Result<Withdrawal, BadLog> {
if log.address != ARB_SYS {
return Err(BadLog::NotThisEvent(L2_TO_L1_TX.name()));
}
let tokens = L2_TO_L1_TX.decode(log)?;
let abi = |error: AbiError| BadLog::Abi { event: "L2ToL1Tx", error };
let mut fields = Fields::of("L2ToL1Tx", &tokens);
Ok(Withdrawal {
caller: fields.address().map_err(abi)?,
destination: fields.address().map_err(abi)?,
hash: fields.uint().map_err(abi)?,
position: fields.u64().map_err(abi)?,
arb_block: fields.u64().map_err(abi)?,
eth_block: fields.u64().map_err(abi)?,
timestamp: fields.u64().map_err(abi)?,
value: fields.uint().map_err(abi)?,
data: fields.bytes().map_err(abi)?,
})
}
pub fn in_logs(logs: &[Log]) -> Result<Vec<Withdrawal>, BadLog> {
logs.iter().filter(|log| log.address == ARB_SYS && L2_TO_L1_TX.matches(log)).map(Withdrawal::from_log).collect()
}
#[must_use]
pub fn leaf(&self) -> B256 {
B256::from(self.hash)
}
}
#[cfg(test)]
#[path = "tests/withdraw.rs"]
mod tests;