1use serde::{Deserialize, Serialize};
7
8use super::{
9 common::{Blockchain, CustodyType, FeeLevel, PageParams, TransactionFee},
10 wallet::Nft,
11};
12
13#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
17#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
18pub enum TransactionState {
19 Cancelled,
21 Confirmed,
23 Complete,
25 Denied,
27 Failed,
29 Initiated,
31 Cleared,
33 Queued,
35 Sent,
37 Stuck,
39}
40
41#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
43#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
44pub enum TransactionType {
45 Inbound,
47 Outbound,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
53#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
54pub enum Operation {
55 Transfer,
57 ContractExecution,
59 ContractDeployment,
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
67#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
68pub enum RiskAction {
69 Approve,
71 Review,
73 FreezeWallet,
75 Deny,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
81#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
82pub enum RiskScore {
83 Unknown,
85 Low,
87 Medium,
89 High,
91 Severe,
93 Blocklist,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
99#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
100pub enum RiskCategory {
101 Sanctions,
103 SanctionsDesignatedFacilitator,
105 SanctionsAdminDesignated,
107 SanctionsSector,
109 FinancialServiceProvider,
111 MixerOrPrivacyWallet,
113 Ransomware,
115 Child,
117 TerroristFinancing,
119 FraudShop,
121 Exchange,
123 Unhosted,
125 Darknet,
127 Gambling,
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
133#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
134pub enum RiskType {
135 Ownership,
137 Counterparty,
139 Indirect,
141}
142
143#[derive(Debug, Clone, Deserialize, Serialize)]
147#[serde(rename_all = "camelCase")]
148pub struct RiskSignal {
149 pub source: String,
151 pub source_value: String,
153 pub risk_score: RiskScore,
155 pub risk_categories: Vec<RiskCategory>,
157 #[serde(rename = "type")]
159 pub risk_type: RiskType,
160}
161
162#[derive(Debug, Clone, Deserialize, Serialize)]
164#[serde(rename_all = "camelCase")]
165pub struct TransactionScreeningDecision {
166 pub screening_date: String,
168 pub rule_name: Option<String>,
170 pub actions: Option<Vec<RiskAction>>,
172 pub reasons: Option<Vec<RiskSignal>>,
174}
175
176#[derive(Debug, Clone, Deserialize, Serialize)]
180#[serde(rename_all = "camelCase")]
181pub struct Transaction {
182 pub id: String,
184 pub state: TransactionState,
186 pub blockchain: Blockchain,
188 pub transaction_type: TransactionType,
190 pub create_date: String,
192 pub update_date: String,
194
195 pub abi_function_signature: Option<String>,
197 pub abi_parameters: Option<Vec<serde_json::Value>>,
199 pub amounts: Option<Vec<String>>,
201 pub amount_in_usd: Option<String>,
203 pub block_hash: Option<String>,
205 pub block_height: Option<i64>,
207 pub contract_address: Option<String>,
209 pub custody_type: Option<CustodyType>,
211 pub destination_address: Option<String>,
213 pub error_reason: Option<String>,
215 pub error_details: Option<String>,
217 pub estimated_fee: Option<TransactionFee>,
219 pub fee_level: Option<FeeLevel>,
221 pub first_confirm_date: Option<String>,
223 pub network_fee: Option<String>,
225 pub network_fee_in_usd: Option<String>,
227 pub nfts: Option<Vec<Nft>>,
229 pub operation: Option<Operation>,
231 pub ref_id: Option<String>,
233 pub source_address: Option<String>,
235 pub token_id: Option<String>,
237 pub tx_hash: Option<String>,
239 pub user_id: Option<String>,
241 pub wallet_id: Option<String>,
243 pub transaction_screening_evaluation: Option<TransactionScreeningDecision>,
245}
246
247#[derive(Debug, Clone, Deserialize, Serialize)]
251#[serde(rename_all = "camelCase")]
252pub struct TransactionsData {
253 pub transactions: Vec<Transaction>,
255}
256
257#[derive(Debug, Clone, Deserialize, Serialize)]
259#[serde(rename_all = "camelCase")]
260pub struct Transactions {
261 pub data: TransactionsData,
263}
264
265#[derive(Debug, Clone, Deserialize, Serialize)]
267#[serde(rename_all = "camelCase")]
268pub struct TransactionData {
269 pub transaction: Transaction,
271}
272
273#[derive(Debug, Clone, Deserialize, Serialize)]
275#[serde(rename_all = "camelCase")]
276pub struct TransactionResponse {
277 pub data: TransactionData,
279}
280
281#[derive(Debug, Clone, Deserialize, Serialize)]
283#[serde(rename_all = "camelCase")]
284pub struct LowestNonceTransactionFeeInfo {
285 pub new_high_estimated_fee: TransactionFee,
287 pub fee_difference_amount: String,
289}
290
291#[derive(Debug, Clone, Deserialize, Serialize)]
293#[serde(rename_all = "camelCase")]
294pub struct LowestNonceTransactionData {
295 pub transaction: Transaction,
297 pub fee_info: LowestNonceTransactionFeeInfo,
299}
300
301#[derive(Debug, Clone, Deserialize, Serialize)]
303#[serde(rename_all = "camelCase")]
304pub struct GetLowestNonceTransactionResponse {
305 pub data: LowestNonceTransactionData,
307}
308
309#[derive(Debug, Clone, Default, Deserialize, Serialize)]
311#[serde(rename_all = "camelCase")]
312pub struct EstimateFeeData {
313 pub high: Option<TransactionFee>,
315 pub low: Option<TransactionFee>,
317 pub medium: Option<TransactionFee>,
319 pub call_gas_limit: Option<String>,
321 pub verification_gas_limit: Option<String>,
323 pub pre_verification_gas: Option<String>,
325}
326
327#[derive(Debug, Clone, Deserialize, Serialize)]
329#[serde(rename_all = "camelCase")]
330pub struct EstimateTransactionFee {
331 pub data: EstimateFeeData,
333}
334
335#[derive(Debug, Clone, Deserialize, Serialize)]
337#[serde(rename_all = "camelCase")]
338pub struct ValidateAddressData {
339 pub is_valid: bool,
341}
342
343#[derive(Debug, Clone, Deserialize, Serialize)]
345#[serde(rename_all = "camelCase")]
346pub struct ValidateAddressResponse {
347 pub data: ValidateAddressData,
349}
350
351#[derive(Debug, Clone, Deserialize, Serialize)]
355#[serde(rename_all = "camelCase")]
356pub struct CreateTransferTxRequest {
357 pub idempotency_key: String,
359 pub wallet_id: String,
361 pub destination_address: String,
363 pub amounts: Option<Vec<String>>,
365 pub fee_level: Option<FeeLevel>,
367 pub gas_limit: Option<String>,
369 pub gas_price: Option<String>,
371 pub max_fee: Option<String>,
373 pub priority_fee: Option<String>,
375 pub nft_token_ids: Option<Vec<String>>,
377 pub ref_id: Option<String>,
379 pub token_id: Option<String>,
381 pub token_address: Option<String>,
383 pub blockchain: Option<Blockchain>,
385}
386
387#[derive(Debug, Clone, Deserialize, Serialize)]
389#[serde(rename_all = "camelCase")]
390pub struct AccelerateTxRequest {
391 pub idempotency_key: String,
393}
394
395#[derive(Debug, Clone, Deserialize, Serialize)]
397#[serde(rename_all = "camelCase")]
398pub struct CancelTxRequest {
399 pub idempotency_key: String,
401}
402
403#[derive(Debug, Clone, Deserialize, Serialize)]
405#[serde(rename_all = "camelCase")]
406pub struct CreateContractExecutionTxRequest {
407 pub idempotency_key: String,
409 pub wallet_id: String,
411 pub contract_address: String,
413 pub abi_function_signature: Option<String>,
415 pub abi_parameters: Option<Vec<serde_json::Value>>,
417 pub call_data: Option<String>,
419 pub amount: Option<String>,
421 pub fee_level: Option<FeeLevel>,
423 pub gas_limit: Option<String>,
425 pub gas_price: Option<String>,
427 pub max_fee: Option<String>,
429 pub priority_fee: Option<String>,
431 pub ref_id: Option<String>,
433}
434
435#[derive(Debug, Clone, Deserialize, Serialize)]
437#[serde(rename_all = "camelCase")]
438pub struct CreateWalletUpgradeTxRequest {
439 pub idempotency_key: String,
441 pub wallet_id: String,
443 pub new_sca_core: String,
445 pub fee_level: Option<FeeLevel>,
447 pub gas_limit: Option<String>,
449 pub gas_price: Option<String>,
451 pub max_fee: Option<String>,
453 pub priority_fee: Option<String>,
455 pub ref_id: Option<String>,
457}
458
459#[derive(Debug, Clone, Deserialize, Serialize)]
461#[serde(rename_all = "camelCase")]
462pub struct EstimateTransferFeeRequest {
463 pub amounts: Vec<String>,
465 pub destination_address: String,
467 pub nft_token_ids: Option<Vec<String>>,
469 pub source_address: Option<String>,
471 pub token_id: Option<String>,
473 pub token_address: Option<String>,
475 pub blockchain: Option<Blockchain>,
477 pub wallet_id: Option<String>,
479}
480
481#[derive(Debug, Clone, Deserialize, Serialize)]
483#[serde(rename_all = "camelCase")]
484pub struct EstimateContractExecFeeRequest {
485 pub contract_address: String,
487 pub abi_function_signature: Option<String>,
489 pub abi_parameters: Option<Vec<serde_json::Value>>,
491 pub call_data: Option<String>,
493 pub amount: Option<String>,
495 pub blockchain: Option<Blockchain>,
497 pub source_address: Option<String>,
499 pub wallet_id: Option<String>,
501}
502
503#[derive(Debug, Clone, Deserialize, Serialize)]
505#[serde(rename_all = "camelCase")]
506pub struct ValidateAddressRequest {
507 pub address: String,
509 pub blockchain: Blockchain,
511}
512
513#[derive(Debug, Clone, Default, Deserialize, Serialize)]
515#[serde(rename_all = "camelCase")]
516pub struct ListTransactionsParams {
517 pub blockchain: Option<Blockchain>,
519 pub destination_address: Option<String>,
521 pub include_all: Option<bool>,
523 pub operation: Option<Operation>,
525 pub state: Option<TransactionState>,
527 pub tx_hash: Option<String>,
529 pub tx_type: Option<TransactionType>,
531 pub user_id: Option<String>,
533 pub wallet_ids: Option<String>,
535 pub from: Option<String>,
537 pub to: Option<String>,
539 #[serde(flatten)]
541 pub page: PageParams,
542}
543
544#[derive(Debug, Clone, Default, Deserialize, Serialize)]
546#[serde(rename_all = "camelCase")]
547pub struct GetLowestNonceTxParams {
548 pub blockchain: Option<Blockchain>,
550 pub address: Option<String>,
552 pub wallet_id: Option<String>,
554}
555
556#[cfg(test)]
559mod tests {
560 use super::*;
561
562 #[test]
563 fn transaction_state_screaming() -> Result<(), Box<dyn std::error::Error>> {
564 assert_eq!(serde_json::to_string(&TransactionState::Complete)?, "\"COMPLETE\"");
565 assert_eq!(serde_json::to_string(&TransactionState::Confirmed)?, "\"CONFIRMED\"");
566 assert_eq!(serde_json::to_string(&TransactionState::Queued)?, "\"QUEUED\"");
567 Ok(())
568 }
569
570 #[test]
571 fn risk_action_screaming() -> Result<(), Box<dyn std::error::Error>> {
572 assert_eq!(serde_json::to_string(&RiskAction::FreezeWallet)?, "\"FREEZE_WALLET\"");
573 Ok(())
574 }
575
576 #[test]
577 fn validate_address_request_camel_case() -> Result<(), Box<dyn std::error::Error>> {
578 let req =
579 ValidateAddressRequest { address: "0xabc".to_string(), blockchain: Blockchain::Eth };
580 let s = serde_json::to_string(&req)?;
581 assert!(s.contains("\"address\""), "address key in {s}");
582 assert!(s.contains("\"blockchain\""), "blockchain key in {s}");
583 Ok(())
584 }
585
586 #[test]
587 fn transfer_tx_request_camel_case() -> Result<(), Box<dyn std::error::Error>> {
588 let req = CreateTransferTxRequest {
589 idempotency_key: "key".to_string(),
590 wallet_id: "w1".to_string(),
591 destination_address: "0xdest".to_string(),
592 amounts: Some(vec!["1.0".to_string()]),
593 fee_level: Some(FeeLevel::High),
594 gas_limit: None,
595 gas_price: None,
596 max_fee: None,
597 priority_fee: None,
598 nft_token_ids: None,
599 ref_id: None,
600 token_id: None,
601 token_address: None,
602 blockchain: None,
603 };
604 let s = serde_json::to_string(&req)?;
605 assert!(s.contains("idempotencyKey"), "{s}");
606 assert!(s.contains("walletId"), "{s}");
607 assert!(s.contains("destinationAddress"), "{s}");
608 Ok(())
609 }
610}