|
1 | 1 | //! Wrappers for transactions.
|
2 | 2 |
|
| 3 | +use alloy_consensus::{Transaction, TxEnvelope}; |
| 4 | +use alloy_primitives::{Address, TxKind, U256}; |
3 | 5 | use alloy_provider::{network::AnyNetwork, Provider};
|
4 |
| -use alloy_rpc_types::{AnyTransactionReceipt, BlockId}; |
| 6 | +use alloy_rpc_types::{AnyTransactionReceipt, BlockId, TransactionRequest}; |
5 | 7 | use alloy_serde::WithOtherFields;
|
6 | 8 | use alloy_transport::Transport;
|
7 | 9 | use eyre::Result;
|
@@ -144,3 +146,88 @@ mod tests {
|
144 | 146 | assert_eq!(extract_revert_reason(error_string_2), None);
|
145 | 147 | }
|
146 | 148 | }
|
| 149 | + |
| 150 | +/// Used for broadcasting transactions |
| 151 | +/// A transaction can either be a [`TransactionRequest`] waiting to be signed |
| 152 | +/// or a [`TxEnvelope`], already signed |
| 153 | +#[derive(Clone, Debug, Serialize, Deserialize)] |
| 154 | +#[serde(untagged)] |
| 155 | +pub enum TransactionMaybeSigned { |
| 156 | + Signed { |
| 157 | + #[serde(flatten)] |
| 158 | + tx: TxEnvelope, |
| 159 | + from: Address, |
| 160 | + }, |
| 161 | + Unsigned(WithOtherFields<TransactionRequest>), |
| 162 | +} |
| 163 | + |
| 164 | +impl TransactionMaybeSigned { |
| 165 | + /// Creates a new (unsigned) transaction for broadcast |
| 166 | + pub fn new(tx: WithOtherFields<TransactionRequest>) -> Self { |
| 167 | + Self::Unsigned(tx) |
| 168 | + } |
| 169 | + |
| 170 | + /// Creates a new signed transaction for broadcast. |
| 171 | + pub fn new_signed( |
| 172 | + tx: TxEnvelope, |
| 173 | + ) -> core::result::Result<Self, alloy_primitives::SignatureError> { |
| 174 | + let from = tx.recover_signer()?; |
| 175 | + Ok(Self::Signed { tx, from }) |
| 176 | + } |
| 177 | + |
| 178 | + pub fn as_unsigned_mut(&mut self) -> Option<&mut WithOtherFields<TransactionRequest>> { |
| 179 | + match self { |
| 180 | + Self::Unsigned(tx) => Some(tx), |
| 181 | + _ => None, |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + pub fn from(&self) -> Option<Address> { |
| 186 | + match self { |
| 187 | + Self::Signed { from, .. } => Some(*from), |
| 188 | + Self::Unsigned(tx) => tx.from, |
| 189 | + } |
| 190 | + } |
| 191 | + |
| 192 | + pub fn input(&self) -> Option<&[u8]> { |
| 193 | + match self { |
| 194 | + Self::Signed { tx, .. } => Some(tx.input()), |
| 195 | + Self::Unsigned(tx) => tx.input.input().map(|i| i.as_ref()), |
| 196 | + } |
| 197 | + } |
| 198 | + |
| 199 | + pub fn to(&self) -> Option<TxKind> { |
| 200 | + match self { |
| 201 | + Self::Signed { tx, .. } => Some(tx.to()), |
| 202 | + Self::Unsigned(tx) => tx.to, |
| 203 | + } |
| 204 | + } |
| 205 | + |
| 206 | + pub fn value(&self) -> Option<U256> { |
| 207 | + match self { |
| 208 | + Self::Signed { tx, .. } => Some(tx.value()), |
| 209 | + Self::Unsigned(tx) => tx.value, |
| 210 | + } |
| 211 | + } |
| 212 | + |
| 213 | + pub fn gas(&self) -> Option<u128> { |
| 214 | + match self { |
| 215 | + Self::Signed { tx, .. } => Some(tx.gas_limit()), |
| 216 | + Self::Unsigned(tx) => tx.gas, |
| 217 | + } |
| 218 | + } |
| 219 | +} |
| 220 | + |
| 221 | +impl From<TransactionRequest> for TransactionMaybeSigned { |
| 222 | + fn from(tx: TransactionRequest) -> Self { |
| 223 | + Self::new(WithOtherFields::new(tx)) |
| 224 | + } |
| 225 | +} |
| 226 | + |
| 227 | +impl TryFrom<TxEnvelope> for TransactionMaybeSigned { |
| 228 | + type Error = alloy_primitives::SignatureError; |
| 229 | + |
| 230 | + fn try_from(tx: TxEnvelope) -> core::result::Result<Self, Self::Error> { |
| 231 | + Self::new_signed(tx) |
| 232 | + } |
| 233 | +} |
0 commit comments