op_alloy_protocol/batch/tx_data/
legacy.rsuse crate::{SpanBatchError, SpanDecodingError};
use alloy_consensus::{SignableTransaction, Signed, TxLegacy};
use alloy_primitives::{Address, PrimitiveSignature as Signature, TxKind, U256};
use alloy_rlp::{Bytes, RlpDecodable, RlpEncodable};
use op_alloy_consensus::OpTxEnvelope;
#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
pub struct SpanBatchLegacyTransactionData {
pub value: U256,
pub gas_price: U256,
pub data: Bytes,
}
impl SpanBatchLegacyTransactionData {
pub fn to_enveloped_tx(
&self,
nonce: u64,
gas: u64,
to: Option<Address>,
chain_id: u64,
signature: Signature,
is_protected: bool,
) -> Result<OpTxEnvelope, SpanBatchError> {
let legacy_tx = TxLegacy {
chain_id: is_protected.then_some(chain_id),
nonce,
gas_price: u128::from_be_bytes(
self.gas_price.to_be_bytes::<32>()[16..].try_into().map_err(|_| {
SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData)
})?,
),
gas_limit: gas,
to: to.map_or(TxKind::Create, TxKind::Call),
value: self.value,
input: self.data.clone().into(),
};
let signature_hash = legacy_tx.signature_hash();
let signed_legacy_tx = Signed::new_unchecked(legacy_tx, signature, signature_hash);
Ok(OpTxEnvelope::Legacy(signed_legacy_tx))
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::SpanBatchTransactionData;
use alloc::vec::Vec;
use alloy_rlp::{Decodable, Encodable as _};
#[test]
fn encode_legacy_tx_data_roundtrip() {
let legacy_tx = SpanBatchLegacyTransactionData {
value: U256::from(0xFF),
gas_price: U256::from(0xEE),
data: Bytes::from(alloc::vec![0x01, 0x02, 0x03]),
};
let mut encoded_buf = Vec::new();
SpanBatchTransactionData::Legacy(legacy_tx.clone()).encode(&mut encoded_buf);
let decoded = SpanBatchTransactionData::decode(&mut encoded_buf.as_slice()).unwrap();
let SpanBatchTransactionData::Legacy(legacy_decoded) = decoded else {
panic!("Expected SpanBatchLegacyTransactionData, got {:?}", decoded);
};
assert_eq!(legacy_tx, legacy_decoded);
}
}