1use alloy_consensus::{TxEnvelope, TxType, TypedTransaction};
2use alloy_eips::eip2930::AccessList;
3use alloy_network::{
4 BuildResult, Network, NetworkWallet, TransactionBuilder, TransactionBuilderError,
5};
6use alloy_primitives::{Address, Bytes, ChainId, Signature, TxKind, U256};
7use alloy_provider::fillers::{
8 ChainIdFiller, GasFiller, JoinFill, NonceFiller, RecommendedFillers,
9};
10
11pub use pod_types::rpc::receipt::PodReceiptResponse;
12
13use alloy_rpc_types::TransactionRequest;
14use pod_types::Timestamp;
15use serde::{Deserialize, Serialize};
16use std::ops::{Deref, DerefMut};
17
18#[derive(Debug, Clone, Copy)]
19pub struct PodNetwork;
20
21#[derive(Debug, Serialize, Deserialize, Clone)]
22pub struct PodTransactionRequest {
23 #[serde(flatten)]
24 pub inner: TransactionRequest,
25}
26
27impl Default for PodTransactionRequest {
28 fn default() -> Self {
29 let mut inner = TransactionRequest::default();
30 inner.set_max_fee_per_gas(1_000_000_000);
31 inner.set_max_priority_fee_per_gas(0);
32 Self { inner }
33 }
34}
35
36impl Deref for PodTransactionRequest {
37 type Target = TransactionRequest;
38
39 fn deref(&self) -> &Self::Target {
40 &self.inner
41 }
42}
43
44impl DerefMut for PodTransactionRequest {
45 fn deref_mut(&mut self) -> &mut Self::Target {
46 &mut self.inner
47 }
48}
49
50impl From<PodTransactionRequest> for TransactionRequest {
51 fn from(value: PodTransactionRequest) -> Self {
52 value.inner
53 }
54}
55
56impl From<TypedTransaction> for PodTransactionRequest {
57 fn from(value: TypedTransaction) -> Self {
58 Self {
59 inner: value.into(),
60 }
61 }
62}
63
64impl From<TxEnvelope> for PodTransactionRequest {
65 fn from(value: TxEnvelope) -> Self {
66 Self {
67 inner: value.into(),
68 }
69 }
70}
71
72impl TransactionBuilder<PodNetwork> for PodTransactionRequest {
73 fn chain_id(&self) -> Option<ChainId> {
74 self.chain_id
75 }
76
77 fn set_chain_id(&mut self, chain_id: ChainId) {
78 self.chain_id = Some(chain_id);
79 }
80
81 fn nonce(&self) -> Option<u64> {
82 self.nonce
83 }
84
85 fn set_nonce(&mut self, nonce: u64) {
86 self.nonce = Some(nonce);
87 }
88
89 fn take_nonce(&mut self) -> Option<u64> {
90 self.nonce.take()
91 }
92
93 fn input(&self) -> Option<&Bytes> {
94 self.input.input()
95 }
96
97 fn set_input<T: Into<Bytes>>(&mut self, input: T) {
98 self.input.input = Some(input.into());
99 }
100
101 fn from(&self) -> Option<Address> {
102 self.from
103 }
104
105 fn set_from(&mut self, from: Address) {
106 self.from = Some(from);
107 }
108
109 fn kind(&self) -> Option<TxKind> {
110 self.to
111 }
112
113 fn clear_kind(&mut self) {
114 self.to = None;
115 }
116
117 fn set_kind(&mut self, kind: TxKind) {
118 self.to = Some(kind);
119 }
120
121 fn value(&self) -> Option<U256> {
122 self.value
123 }
124
125 fn set_value(&mut self, value: U256) {
126 self.value = Some(value)
127 }
128
129 fn gas_price(&self) -> Option<u128> {
130 self.gas_price
131 }
132
133 fn set_gas_price(&mut self, gas_price: u128) {
134 self.gas_price = Some(gas_price);
135 }
136
137 fn max_fee_per_gas(&self) -> Option<u128> {
138 self.max_fee_per_gas
139 }
140
141 fn set_max_fee_per_gas(&mut self, max_fee_per_gas: u128) {
142 self.max_fee_per_gas = Some(max_fee_per_gas);
143 }
144
145 fn max_priority_fee_per_gas(&self) -> Option<u128> {
146 self.max_priority_fee_per_gas
147 }
148
149 fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: u128) {
150 self.max_priority_fee_per_gas = Some(max_priority_fee_per_gas);
151 }
152
153 fn gas_limit(&self) -> Option<u64> {
154 self.gas
155 }
156
157 fn set_gas_limit(&mut self, gas_limit: u64) {
158 self.gas = Some(gas_limit);
159 }
160
161 fn access_list(&self) -> Option<&AccessList> {
162 self.access_list.as_ref()
163 }
164
165 fn set_access_list(&mut self, access_list: AccessList) {
166 self.access_list = Some(access_list);
167 }
168
169 fn complete_type(&self, ty: TxType) -> Result<(), Vec<&'static str>> {
170 match ty {
171 TxType::Eip1559 => self.complete_1559(),
172 _ => unimplemented!(), }
174 }
175
176 fn can_submit(&self) -> bool {
177 self.from.is_some()
181 }
182
183 fn can_build(&self) -> bool {
184 self.max_fee_per_gas.is_some() && self.max_priority_fee_per_gas.is_some()
186 }
187
188 #[doc(alias = "output_transaction_type")]
189 fn output_tx_type(&self) -> TxType {
190 TxType::Eip1559
191 }
192
193 #[doc(alias = "output_transaction_type_checked")]
194 fn output_tx_type_checked(&self) -> Option<TxType> {
195 self.buildable_type()
196 }
197
198 fn prep_for_submission(&mut self) {
199 self.transaction_type = Some(self.preferred_type() as u8);
200 self.trim_conflicting_keys();
201 self.populate_blob_hashes();
202 }
203
204 fn build_unsigned(self) -> BuildResult<TypedTransaction, PodNetwork> {
205 if let Err((tx_type, missing)) = self.missing_keys() {
206 return Err(
207 TransactionBuilderError::InvalidTransactionRequest(tx_type, missing)
208 .into_unbuilt(self),
209 );
210 }
211 Ok(self
212 .inner
213 .build_typed_tx()
214 .expect("checked by missing_keys"))
215 }
216
217 async fn build<W: NetworkWallet<PodNetwork>>(
218 self,
219 wallet: &W,
220 ) -> Result<<PodNetwork as Network>::TxEnvelope, TransactionBuilderError<PodNetwork>> {
221 Ok(wallet.sign_request(self).await?)
222 }
223}
224
225#[derive(Debug, Serialize, Deserialize, Clone)]
226pub struct AttestationData {
227 pub public_key: Address,
228 pub signature: Signature,
229 pub timestamp: Timestamp,
230}
231
232impl Network for PodNetwork {
233 type TxType = TxType;
234 type TxEnvelope = alloy_consensus::TxEnvelope;
235 type UnsignedTx = TypedTransaction;
236 type ReceiptEnvelope = alloy_consensus::ReceiptEnvelope;
237 type Header = alloy_consensus::Header;
238 type TransactionRequest = PodTransactionRequest;
239 type TransactionResponse = alloy_rpc_types::Transaction;
240 type ReceiptResponse = PodReceiptResponse;
241 type HeaderResponse = alloy_rpc_types::Header;
242 type BlockResponse = alloy_rpc_types::Block;
243}
244
245impl RecommendedFillers for PodNetwork {
246 type RecommendedFillers = JoinFill<GasFiller, JoinFill<NonceFiller, ChainIdFiller>>;
247
248 fn recommended_fillers() -> Self::RecommendedFillers {
249 JoinFill::new(
250 GasFiller,
251 JoinFill::new(NonceFiller::default(), ChainIdFiller::default()),
252 )
253 }
254}