kona_protocol/batch/tx_data/
wrapper.rs1use alloy_consensus::{Transaction, TxEnvelope, TxType};
4use alloy_primitives::{Address, PrimitiveSignature as Signature, U256};
5use alloy_rlp::{Bytes, Decodable, Encodable};
6
7use crate::{
8 SpanBatchEip1559TransactionData, SpanBatchEip2930TransactionData,
9 SpanBatchEip7702TransactionData, SpanBatchError, SpanBatchLegacyTransactionData,
10 SpanDecodingError,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum SpanBatchTransactionData {
16 Legacy(SpanBatchLegacyTransactionData),
18 Eip2930(SpanBatchEip2930TransactionData),
20 Eip1559(SpanBatchEip1559TransactionData),
22 Eip7702(SpanBatchEip7702TransactionData),
24}
25
26impl Encodable for SpanBatchTransactionData {
27 fn encode(&self, out: &mut dyn alloy_rlp::BufMut) {
28 match self {
29 Self::Legacy(data) => {
30 data.encode(out);
31 }
32 Self::Eip2930(data) => {
33 out.put_u8(TxType::Eip2930 as u8);
34 data.encode(out);
35 }
36 Self::Eip1559(data) => {
37 out.put_u8(TxType::Eip1559 as u8);
38 data.encode(out);
39 }
40 Self::Eip7702(data) => {
41 out.put_u8(TxType::Eip7702 as u8);
42 data.encode(out);
43 }
44 }
45 }
46}
47
48impl Decodable for SpanBatchTransactionData {
49 fn decode(r: &mut &[u8]) -> Result<Self, alloy_rlp::Error> {
50 if !r.is_empty() && r[0] > 0x7F {
51 return Ok(Self::Legacy(SpanBatchLegacyTransactionData::decode(r)?));
53 }
54 Self::decode_typed(r)
56 }
57}
58
59impl TryFrom<&TxEnvelope> for SpanBatchTransactionData {
60 type Error = SpanBatchError;
61
62 fn try_from(tx_envelope: &TxEnvelope) -> Result<Self, Self::Error> {
63 match tx_envelope {
64 TxEnvelope::Legacy(s) => {
65 let s = s.tx();
66 Ok(Self::Legacy(SpanBatchLegacyTransactionData {
67 value: s.value,
68 gas_price: U256::from(s.gas_price),
69 data: Bytes::from(s.input().to_vec()),
70 }))
71 }
72 TxEnvelope::Eip2930(s) => {
73 let s = s.tx();
74 Ok(Self::Eip2930(SpanBatchEip2930TransactionData {
75 value: s.value,
76 gas_price: U256::from(s.gas_price),
77 data: Bytes::from(s.input().to_vec()),
78 access_list: s.access_list.clone(),
79 }))
80 }
81 TxEnvelope::Eip1559(s) => {
82 let s = s.tx();
83 Ok(Self::Eip1559(SpanBatchEip1559TransactionData {
84 value: s.value,
85 max_fee_per_gas: U256::from(s.max_fee_per_gas),
86 max_priority_fee_per_gas: U256::from(s.max_priority_fee_per_gas),
87 data: Bytes::from(s.input().to_vec()),
88 access_list: s.access_list.clone(),
89 }))
90 }
91 TxEnvelope::Eip7702(s) => {
92 let s = s.tx();
93 Ok(Self::Eip7702(SpanBatchEip7702TransactionData {
94 value: s.value,
95 max_fee_per_gas: U256::from(s.max_fee_per_gas),
96 max_priority_fee_per_gas: U256::from(s.max_priority_fee_per_gas),
97 data: Bytes::from(s.input().to_vec()),
98 access_list: s.access_list.clone(),
99 authorization_list: s.authorization_list.clone(),
100 }))
101 }
102 _ => Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionType)),
103 }
104 }
105}
106
107impl SpanBatchTransactionData {
108 pub const fn tx_type(&self) -> TxType {
110 match self {
111 Self::Legacy(_) => TxType::Legacy,
112 Self::Eip2930(_) => TxType::Eip2930,
113 Self::Eip1559(_) => TxType::Eip1559,
114 Self::Eip7702(_) => TxType::Eip7702,
115 }
116 }
117
118 pub fn decode_typed(b: &[u8]) -> Result<Self, alloy_rlp::Error> {
120 if b.len() <= 1 {
121 return Err(alloy_rlp::Error::Custom("Invalid transaction data"));
122 }
123
124 match b[0].try_into().map_err(|_| alloy_rlp::Error::Custom("Invalid tx type"))? {
125 TxType::Eip2930 => {
126 Ok(Self::Eip2930(SpanBatchEip2930TransactionData::decode(&mut &b[1..])?))
127 }
128 TxType::Eip1559 => {
129 Ok(Self::Eip1559(SpanBatchEip1559TransactionData::decode(&mut &b[1..])?))
130 }
131 TxType::Eip7702 => {
132 Ok(Self::Eip7702(SpanBatchEip7702TransactionData::decode(&mut &b[1..])?))
133 }
134 _ => Err(alloy_rlp::Error::Custom("Invalid transaction type")),
135 }
136 }
137
138 pub fn to_signed_tx(
140 &self,
141 nonce: u64,
142 gas: u64,
143 to: Option<Address>,
144 chain_id: u64,
145 signature: Signature,
146 is_protected: bool,
147 ) -> Result<TxEnvelope, SpanBatchError> {
148 Ok(match self {
149 Self::Legacy(data) => TxEnvelope::Legacy(data.to_signed_tx(
150 nonce,
151 gas,
152 to,
153 chain_id,
154 signature,
155 is_protected,
156 )?),
157 Self::Eip2930(data) => {
158 TxEnvelope::Eip2930(data.to_signed_tx(nonce, gas, to, chain_id, signature)?)
159 }
160 Self::Eip1559(data) => {
161 TxEnvelope::Eip1559(data.to_signed_tx(nonce, gas, to, chain_id, signature)?)
162 }
163 Self::Eip7702(data) => {
164 let Some(addr) = to else {
165 return Err(SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData));
166 };
167 TxEnvelope::Eip7702(data.to_signed_tx(nonce, gas, addr, chain_id, signature)?)
168 }
169 })
170 }
171}