Skip to main content

cow_sdk_core/traits/
transaction.rs

1use serde::{Deserialize, Serialize};
2
3use crate::types::{Address, Amount, BlockHash, HexData, TransactionHash};
4/// Transaction request shape used across signer and provider traits.
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
6#[cfg_attr(
7    all(
8        target_arch = "wasm32",
9        target_os = "unknown",
10        feature = "ts-bindings-tx"
11    ),
12    derive(tsify::Tsify)
13)]
14#[cfg_attr(
15    all(
16        target_arch = "wasm32",
17        target_os = "unknown",
18        feature = "ts-bindings-tx"
19    ),
20    tsify(into_wasm_abi, from_wasm_abi)
21)]
22#[serde(rename_all = "camelCase")]
23pub struct TransactionRequest {
24    #[serde(skip_serializing_if = "Option::is_none")]
25    /// Destination address for the transaction.
26    pub to: Option<Address>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    /// Hex-encoded calldata payload.
29    pub data: Option<HexData>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    /// Native token value to transfer.
32    pub value: Option<Amount>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    /// Optional gas limit override.
35    pub gas_limit: Option<Amount>,
36}
37
38impl TransactionRequest {
39    /// Creates a transaction request shape.
40    #[inline]
41    #[must_use]
42    pub const fn new(
43        to: Option<Address>,
44        data: Option<HexData>,
45        value: Option<Amount>,
46        gas_limit: Option<Amount>,
47    ) -> Self {
48        Self {
49            to,
50            data,
51            value,
52            gas_limit,
53        }
54    }
55}
56
57/// Broadcast acknowledgement returned by signer-backed transaction submission.
58///
59/// This value confirms that a backend accepted or observed a transaction hash.
60/// It does not imply that the transaction has been mined, succeeded, or even
61/// become visible to a read provider. Use
62/// [`crate::Provider::get_transaction_receipt`] or a higher-level
63/// `cow-sdk-trading` wait helper when lifecycle state is required.
64#[non_exhaustive]
65#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
66#[serde(rename_all = "camelCase")]
67pub struct TransactionBroadcast {
68    /// Transaction hash for the submitted transaction.
69    pub transaction_hash: TransactionHash,
70}
71
72impl TransactionBroadcast {
73    /// Creates a transaction broadcast acknowledgement from its hash.
74    #[inline]
75    #[must_use]
76    pub const fn new(transaction_hash: TransactionHash) -> Self {
77        Self { transaction_hash }
78    }
79}
80
81/// Terminal transaction execution state exposed by receipt-capable providers.
82#[non_exhaustive]
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub enum TransactionStatus {
86    /// The transaction was mined successfully.
87    Success,
88    /// The transaction was mined and reverted.
89    Reverted,
90}
91
92/// Transaction receipt contract returned by provider receipt lookups.
93///
94/// [`TransactionReceipt::new`] preserves hash-only adapters by leaving every
95/// rich lifecycle field empty. Receipt-capable providers can populate the
96/// optional fields with [`TransactionReceipt::from_parts`] or the builder
97/// methods as adapter support matures.
98#[non_exhaustive]
99#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
100#[serde(rename_all = "camelCase")]
101pub struct TransactionReceipt {
102    /// Transaction hash for the observed transaction.
103    pub transaction_hash: TransactionHash,
104    /// Optional terminal execution status.
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub status: Option<TransactionStatus>,
107    /// Optional block number that included the transaction.
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub block_number: Option<u64>,
110    /// Optional block hash that included the transaction.
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub block_hash: Option<BlockHash>,
113    /// Optional gas used by the transaction.
114    #[serde(skip_serializing_if = "Option::is_none")]
115    pub gas_used: Option<Amount>,
116    /// Optional sender address.
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub from: Option<Address>,
119    /// Optional destination address.
120    #[serde(skip_serializing_if = "Option::is_none")]
121    pub to: Option<Address>,
122}
123
124impl TransactionReceipt {
125    /// Creates a hash-only transaction receipt.
126    #[inline]
127    #[must_use]
128    pub const fn new(transaction_hash: TransactionHash) -> Self {
129        Self {
130            transaction_hash,
131            status: None,
132            block_number: None,
133            block_hash: None,
134            gas_used: None,
135            from: None,
136            to: None,
137        }
138    }
139
140    /// Creates a transaction receipt from every supported receipt field.
141    #[inline]
142    #[must_use]
143    pub const fn from_parts(
144        transaction_hash: TransactionHash,
145        status: Option<TransactionStatus>,
146        block_number: Option<u64>,
147        block_hash: Option<BlockHash>,
148        gas_used: Option<Amount>,
149        from: Option<Address>,
150        to: Option<Address>,
151    ) -> Self {
152        Self {
153            transaction_hash,
154            status,
155            block_number,
156            block_hash,
157            gas_used,
158            from,
159            to,
160        }
161    }
162
163    /// Sets the terminal execution status.
164    #[must_use]
165    pub const fn with_status(mut self, status: TransactionStatus) -> Self {
166        self.status = Some(status);
167        self
168    }
169
170    /// Sets the block number that included the transaction.
171    #[must_use]
172    pub const fn with_block_number(mut self, block_number: u64) -> Self {
173        self.block_number = Some(block_number);
174        self
175    }
176
177    /// Sets the block hash that included the transaction.
178    #[must_use]
179    pub const fn with_block_hash(mut self, block_hash: BlockHash) -> Self {
180        self.block_hash = Some(block_hash);
181        self
182    }
183
184    /// Sets the gas used by the transaction.
185    #[must_use]
186    pub const fn with_gas_used(mut self, gas_used: Amount) -> Self {
187        self.gas_used = Some(gas_used);
188        self
189    }
190
191    /// Sets the sender address.
192    #[must_use]
193    pub const fn with_from(mut self, from: Address) -> Self {
194        self.from = Some(from);
195        self
196    }
197
198    /// Sets the destination address.
199    #[must_use]
200    pub const fn with_to(mut self, to: Address) -> Self {
201        self.to = Some(to);
202        self
203    }
204}
205
206/// Minimal block information contract used by provider traits.
207#[non_exhaustive]
208#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
209#[serde(rename_all = "camelCase")]
210pub struct BlockInfo {
211    /// Block number.
212    pub number: u64,
213    #[serde(skip_serializing_if = "Option::is_none")]
214    /// Optional block hash when the backend returns it.
215    pub hash: Option<BlockHash>,
216}
217
218impl BlockInfo {
219    /// Creates minimal block information.
220    #[inline]
221    #[must_use]
222    pub const fn new(number: u64, hash: Option<BlockHash>) -> Self {
223        Self { number, hash }
224    }
225}