use crate::{
build_generic_tx,
calldata::{self},
send_generic_transaction,
};
use bytes::Bytes;
use ethrex_common::H256;
use ethrex_common::{Address, U256, types::TxType};
use ethrex_l2_common::calldata::Value;
use ethrex_l2_rpc::signer::LocalSigner;
use ethrex_rpc::{
EthClient,
clients::{EthClientError, Overrides, eth::errors::CalldataEncodeError},
};
use secp256k1::SecretKey;
#[derive(Debug)]
pub struct L1ToL2TransactionData {
pub to: Address,
pub gas_limit: u64,
pub value: U256,
pub calldata: Bytes,
}
impl L1ToL2TransactionData {
pub fn new(to: Address, gas_limit: u64, value: U256, calldata: Bytes) -> Self {
Self {
to,
gas_limit,
value,
calldata,
}
}
pub fn to_calldata(&self) -> Result<Vec<u8>, CalldataEncodeError> {
let values = vec![Value::Tuple(vec![
Value::Address(self.to),
Value::Uint(U256::from(self.gas_limit)),
Value::Uint(self.value),
Value::Bytes(self.calldata.clone()),
])];
calldata::encode_calldata("sendToL2((address,uint256,uint256,bytes))", &values)
}
}
#[allow(clippy::too_many_arguments)]
pub async fn send_l1_to_l2_tx(
l1_from: Address,
l1_value: Option<impl Into<U256>>,
l1_gas_limit: Option<u64>,
l1_to_l2_tx_data: L1ToL2TransactionData,
sender_private_key: &SecretKey,
bridge_address: Address,
eth_client: &EthClient,
) -> Result<H256, EthClientError> {
let l1_calldata = l1_to_l2_tx_data.to_calldata()?;
let l1_tx_overrides = Overrides {
value: l1_value.map(Into::into),
from: Some(l1_from),
gas_limit: l1_gas_limit,
..Overrides::default()
};
let mut l1_to_l2_tx = build_generic_tx(
eth_client,
TxType::EIP1559,
bridge_address,
l1_from,
l1_calldata.into(),
l1_tx_overrides,
)
.await?;
l1_to_l2_tx.gas = l1_to_l2_tx.gas.map(|gas| gas * 2);
let signer = LocalSigner::new(*sender_private_key).into();
send_generic_transaction(eth_client, l1_to_l2_tx, &signer).await
}