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