Skip to main content

fireblocks_sdk/
transaction_status.rs

1use serde::{Deserialize, Serialize};
2
3/// TransactionStatus : The primary status of the transaction.
4///
5/// For details, see [Primary transaction statuses](https://developers.fireblocks.com/reference/primary-transaction-statuses)
6/// The primary status of the transaction.  For details, see [Primary transaction statuses](https://developers.fireblocks.com/reference/primary-transaction-statuses)
7#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
8pub enum TransactionStatus {
9    #[serde(rename = "SUBMITTED")]
10    Submitted,
11    #[serde(rename = "PENDING_AML_SCREENING")]
12    PendingAmlScreening,
13    #[serde(rename = "PENDING_ENRICHMENT")]
14    PendingEnrichment,
15    #[serde(rename = "PENDING_AUTHORIZATION")]
16    PendingAuthorization,
17    #[serde(rename = "QUEUED")]
18    Queued,
19    #[serde(rename = "PENDING_SIGNATURE")]
20    PendingSignature,
21    #[serde(rename = "PENDING_3RD_PARTY_MANUAL_APPROVAL")]
22    Pending3RdPartyManualApproval,
23    #[serde(rename = "PENDING_3RD_PARTY")]
24    Pending3RdParty,
25    #[serde(rename = "BROADCASTING")]
26    Broadcasting,
27    #[serde(rename = "COMPLETED")]
28    Completed,
29    #[serde(rename = "CONFIRMING")]
30    Confirming,
31    #[serde(rename = "CANCELLING")]
32    Cancelling,
33    #[serde(rename = "CANCELLED")]
34    Cancelled,
35    #[serde(rename = "BLOCKED")]
36    Blocked,
37    #[serde(rename = "REJECTED")]
38    Rejected,
39    #[serde(rename = "FAILED")]
40    Failed,
41    Other(String),
42}
43
44impl TransactionStatus {
45    pub const fn is_done(&self) -> bool {
46        matches!(
47            self,
48            Self::Cancelling
49                | Self::Cancelled
50                | Self::Blocked
51                | Self::Completed
52                | Self::Failed
53                | Self::Rejected
54        )
55    }
56}
57
58impl std::fmt::Display for TransactionStatus {
59    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
60        match self {
61            Self::Submitted => write!(f, "SUBMITTED"),
62            Self::PendingAmlScreening => write!(f, "PENDING_AML_SCREENING"),
63            Self::PendingEnrichment => write!(f, "PENDING_ENRICHMENT"),
64            Self::PendingAuthorization => write!(f, "PENDING_AUTHORIZATION"),
65            Self::Queued => write!(f, "QUEUED"),
66            Self::PendingSignature => write!(f, "PENDING_SIGNATURE"),
67            Self::Pending3RdPartyManualApproval => write!(f, "PENDING_3RD_PARTY_MANUAL_APPROVAL"),
68            Self::Pending3RdParty => write!(f, "PENDING_3RD_PARTY"),
69            Self::Broadcasting => write!(f, "BROADCASTING"),
70            Self::Completed => write!(f, "COMPLETED"),
71            Self::Confirming => write!(f, "CONFIRMING"),
72            Self::Cancelling => write!(f, "CANCELLING"),
73            Self::Cancelled => write!(f, "CANCELLED"),
74            Self::Blocked => write!(f, "BLOCKED"),
75            Self::Rejected => write!(f, "REJECTED"),
76            Self::Failed => write!(f, "FAILED"),
77            Self::Other(s) => write!(f, "{s}"),
78        }
79    }
80}
81
82impl From<String> for TransactionStatus {
83    fn from(s: String) -> Self {
84        match s.as_str() {
85            "SUBMITTED" => Self::Submitted,
86            "PENDING_AML_SCREENING" => Self::PendingAmlScreening,
87            "PENDING_ENRICHMENT" => Self::PendingEnrichment,
88            "PENDING_AUTHORIZATION" => Self::PendingAuthorization,
89            "QUEUED" => Self::Queued,
90            "PENDING_SIGNATURE" => Self::PendingSignature,
91            "PENDING_3RD_PARTY_MANUAL_APPROVAL" => Self::Pending3RdPartyManualApproval,
92            "PENDING_3RD_PARTY" => Self::Pending3RdParty,
93            "BROADCASTING" => Self::Broadcasting,
94            "COMPLETED" => Self::Completed,
95            "CONFIRMING" => Self::Confirming,
96            "CANCELLING" => Self::Cancelling,
97            "CANCELLED" => Self::Cancelled,
98            "BLOCKED" => Self::Blocked,
99            "REJECTED" => Self::Rejected,
100            "FAILED" => Self::Failed,
101            _ => Self::Other(s),
102        }
103    }
104}
105
106impl From<&str> for TransactionStatus {
107    fn from(s: &str) -> Self {
108        Self::from(s.to_string())
109    }
110}
111
112impl Default for TransactionStatus {
113    fn default() -> Self {
114        Self::Submitted
115    }
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    #[test]
123    fn test_transaction_status_display() {
124        // Test all variants of TransactionStatus to ensure Display works correctly
125        let test_cases = [
126            (TransactionStatus::Submitted, "SUBMITTED"),
127            (
128                TransactionStatus::PendingAmlScreening,
129                "PENDING_AML_SCREENING",
130            ),
131            (TransactionStatus::PendingEnrichment, "PENDING_ENRICHMENT"),
132            (
133                TransactionStatus::PendingAuthorization,
134                "PENDING_AUTHORIZATION",
135            ),
136            (TransactionStatus::Queued, "QUEUED"),
137            (TransactionStatus::PendingSignature, "PENDING_SIGNATURE"),
138            (
139                TransactionStatus::Pending3RdPartyManualApproval,
140                "PENDING_3RD_PARTY_MANUAL_APPROVAL",
141            ),
142            (TransactionStatus::Pending3RdParty, "PENDING_3RD_PARTY"),
143            (TransactionStatus::Broadcasting, "BROADCASTING"),
144            (TransactionStatus::Completed, "COMPLETED"),
145            (TransactionStatus::Confirming, "CONFIRMING"),
146            (TransactionStatus::Cancelling, "CANCELLING"),
147            (TransactionStatus::Cancelled, "CANCELLED"),
148            (TransactionStatus::Blocked, "BLOCKED"),
149            (TransactionStatus::Rejected, "REJECTED"),
150            (TransactionStatus::Failed, "FAILED"),
151        ];
152
153        for (status, expected) in test_cases {
154            assert_eq!(status.to_string(), expected);
155        }
156    }
157
158    #[test]
159    fn test_is_done_final_statuses() {
160        // Test that all final statuses return true
161        let final_statuses = [
162            TransactionStatus::Cancelling,
163            TransactionStatus::Cancelled,
164            TransactionStatus::Blocked,
165            TransactionStatus::Completed,
166            TransactionStatus::Failed,
167            TransactionStatus::Rejected,
168        ];
169
170        for status in final_statuses {
171            assert!(status.is_done());
172        }
173    }
174
175    #[test]
176    fn test_is_done_in_progress_statuses() {
177        // Test that all in-progress statuses return false
178        let in_progress_statuses = [
179            TransactionStatus::Submitted,
180            TransactionStatus::PendingAmlScreening,
181            TransactionStatus::PendingEnrichment,
182            TransactionStatus::PendingAuthorization,
183            TransactionStatus::Queued,
184            TransactionStatus::PendingSignature,
185            TransactionStatus::Pending3RdPartyManualApproval,
186            TransactionStatus::Pending3RdParty,
187            TransactionStatus::Broadcasting,
188            TransactionStatus::Confirming,
189        ];
190
191        for status in in_progress_statuses {
192            assert!(!status.is_done());
193        }
194    }
195
196    #[test]
197    fn test_from_string() {
198        // Test all known variants
199        let test_cases = [
200            ("SUBMITTED", TransactionStatus::Submitted),
201            (
202                "PENDING_AML_SCREENING",
203                TransactionStatus::PendingAmlScreening,
204            ),
205            ("PENDING_ENRICHMENT", TransactionStatus::PendingEnrichment),
206            (
207                "PENDING_AUTHORIZATION",
208                TransactionStatus::PendingAuthorization,
209            ),
210            ("QUEUED", TransactionStatus::Queued),
211            ("PENDING_SIGNATURE", TransactionStatus::PendingSignature),
212            (
213                "PENDING_3RD_PARTY_MANUAL_APPROVAL",
214                TransactionStatus::Pending3RdPartyManualApproval,
215            ),
216            ("PENDING_3RD_PARTY", TransactionStatus::Pending3RdParty),
217            ("BROADCASTING", TransactionStatus::Broadcasting),
218            ("COMPLETED", TransactionStatus::Completed),
219            ("CONFIRMING", TransactionStatus::Confirming),
220            ("CANCELLING", TransactionStatus::Cancelling),
221            ("CANCELLED", TransactionStatus::Cancelled),
222            ("BLOCKED", TransactionStatus::Blocked),
223            ("REJECTED", TransactionStatus::Rejected),
224            ("FAILED", TransactionStatus::Failed),
225        ];
226
227        for (input, expected) in test_cases {
228            // Test From<String>
229            let status: TransactionStatus = String::from(input).into();
230            assert_eq!(status, expected);
231
232            // Test From<&str>
233            let status: TransactionStatus = input.into();
234            assert_eq!(status, expected);
235        }
236
237        // Test unknown variant becomes Other
238        let unknown_status: TransactionStatus = String::from("UNKNOWN_STATUS").into();
239        assert_eq!(
240            unknown_status,
241            TransactionStatus::Other("UNKNOWN_STATUS".to_string())
242        );
243
244        let unknown_status: TransactionStatus = "UNKNOWN_STATUS".into();
245        assert_eq!(
246            unknown_status,
247            TransactionStatus::Other("UNKNOWN_STATUS".to_string())
248        );
249    }
250
251    #[test]
252    fn test_string_conversion_roundtrip() {
253        // Test that converting to string and back works
254        let statuses = [
255            TransactionStatus::Submitted,
256            TransactionStatus::PendingAmlScreening,
257            TransactionStatus::Completed,
258            TransactionStatus::Failed,
259            TransactionStatus::Other("CUSTOM_STATUS".to_string()),
260        ];
261
262        for status in statuses {
263            let string_repr = status.to_string();
264            let parsed_status: TransactionStatus = string_repr.into();
265            assert_eq!(status, parsed_status);
266        }
267    }
268}