starknet_rust_providers/sequencer/models/
transaction_receipt.rs

1use serde::Deserialize;
2use serde_with::serde_as;
3
4use starknet_rust_core::{
5    serde::unsigned_field_element::{UfeHex, UfePendingBlockHash},
6    types::{ExecutionResources, Felt},
7};
8
9use super::{L1Address, TransactionFailureReason};
10
11#[serde_as]
12#[derive(Debug, Deserialize)]
13#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
14pub struct ConfirmedReceipt {
15    #[serde_as(as = "UfeHex")]
16    pub transaction_hash: Felt,
17    pub transaction_index: u64,
18    // This field is actually always present since v0.12.1, but we're keeping it optional until
19    // mainnet is upgraded.
20    #[serde(default)]
21    pub execution_status: Option<TransactionExecutionStatus>,
22    #[serde(default)]
23    pub revert_error: Option<String>,
24    #[serde(default)]
25    pub execution_resources: Option<DetailedExecutionResources>,
26    pub l1_to_l2_consumed_message: Option<L1ToL2Message>,
27    pub l2_to_l1_messages: Vec<L2ToL1Message>,
28    pub events: Vec<Event>,
29    #[serde_as(as = "UfeHex")]
30    pub actual_fee: Felt,
31}
32
33#[derive(Debug, Deserialize, PartialEq, Eq)]
34#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
35#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
36pub enum TransactionStatus {
37    /// Transaction has not been received yet (i.e. not written to storage)
38    NotReceived,
39    /// Transaction was received by the sequenced
40    Received,
41    /// Transaction passed the validation and entered the pending block
42    Pending,
43    /// The transaction failed validation and was skipped (applies both to a
44    /// pending and actual created block)
45    Rejected,
46    Reverted,
47    /// Transaction passed the validation and entered a created block
48    AcceptedOnL2,
49    /// Transaction was accepted on-chain
50    AcceptedOnL1,
51}
52
53impl TransactionStatus {
54    /// Returns `true` if the transaction status is `NotReceived`.
55    pub const fn is_not_received(&self) -> bool {
56        matches!(self, Self::NotReceived)
57    }
58
59    /// Returns `true` if the transaction status is `Received`.
60    pub const fn is_received(&self) -> bool {
61        matches!(self, Self::Received)
62    }
63
64    /// Returns `true` if the transaction status is `Pending`.
65    pub const fn is_pending(&self) -> bool {
66        matches!(self, Self::Pending)
67    }
68
69    /// Returns `true` if the transaction status is `Rejected`.
70    pub const fn is_rejected(&self) -> bool {
71        matches!(self, Self::Rejected)
72    }
73
74    /// Returns `true` if the transaction status is `Reverted`.
75    pub const fn is_reverted(&self) -> bool {
76        matches!(self, Self::Reverted)
77    }
78
79    /// Returns `true` if the transaction status is `AcceptedOnL2`.
80    pub const fn is_accepted_on_l2(&self) -> bool {
81        matches!(self, Self::AcceptedOnL2)
82    }
83
84    /// Returns `true` if the transaction status is `AcceptedOnL1`.
85    pub const fn is_accepted_on_l1(&self) -> bool {
86        matches!(self, Self::AcceptedOnL1)
87    }
88}
89
90#[derive(Debug, Deserialize, PartialEq, Eq)]
91#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
92#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
93pub enum TransactionExecutionStatus {
94    Succeeded,
95    Reverted,
96    Rejected,
97}
98
99#[derive(Debug, Deserialize, PartialEq, Eq)]
100#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
101#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
102pub enum TransactionFinalityStatus {
103    NotReceived,
104    Received,
105    AcceptedOnL2,
106    AcceptedOnL1,
107}
108
109#[derive(Debug, Deserialize)]
110#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
111pub struct DetailedExecutionResources {
112    pub n_steps: u64,
113    pub n_memory_holes: u64,
114    pub builtin_instance_counter: BuiltinInstanceCounter,
115    pub data_availability: Option<ExecutionResources>,
116    pub total_gas_consumed: Option<ExecutionResources>,
117}
118
119#[derive(Debug, Deserialize)]
120#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
121pub struct BuiltinInstanceCounter {
122    pub pedersen_builtin: Option<u64>,
123    pub range_check_builtin: Option<u64>,
124    pub bitwise_builtin: Option<u64>,
125    pub output_builtin: Option<u64>,
126    pub ecdsa_builtin: Option<u64>,
127    pub ec_op_builtin: Option<u64>,
128    pub poseidon_builtin: Option<u64>,
129    pub keccak_builtin: Option<u64>,
130    pub segment_arena_builtin: Option<u64>,
131    pub add_mod: Option<u64>,
132    pub mul_mod: Option<u64>,
133    pub range_check96: Option<u64>,
134}
135
136#[serde_as]
137#[derive(Debug, Deserialize)]
138#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
139pub struct L1ToL2Message {
140    pub from_address: L1Address,
141    #[serde_as(as = "UfeHex")]
142    pub to_address: Felt,
143    #[serde_as(deserialize_as = "UfeHex")]
144    pub selector: Felt,
145    #[serde_as(deserialize_as = "Vec<UfeHex>")]
146    pub payload: Vec<Felt>,
147    #[serde_as(deserialize_as = "Option<UfeHex>")]
148    pub nonce: Option<Felt>,
149}
150
151#[serde_as]
152#[derive(Debug, Deserialize)]
153#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
154pub struct L2ToL1Message {
155    #[serde_as(as = "UfeHex")]
156    pub from_address: Felt,
157    pub to_address: L1Address,
158    #[serde_as(deserialize_as = "Vec<UfeHex>")]
159    pub payload: Vec<Felt>,
160}
161
162#[serde_as]
163#[derive(Debug, Deserialize)]
164#[cfg_attr(feature = "no_unknown_fields", serde(deny_unknown_fields))]
165pub struct Event {
166    #[serde_as(as = "UfeHex")]
167    pub from_address: Felt,
168    #[serde_as(deserialize_as = "Vec<UfeHex>")]
169    pub keys: Vec<Felt>,
170    #[serde_as(deserialize_as = "Vec<UfeHex>")]
171    pub data: Vec<Felt>,
172}