inf_circle_sdk/dev_wallet/
dto.rs

1use crate::{
2    helper::{serialize_bool_as_string, serialize_datetime_as_string, PaginationParams},
3    types::Blockchain,
4};
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8#[derive(Clone, Debug, Serialize, Deserialize)]
9#[serde(rename_all = "UPPERCASE")]
10pub enum FeeLevel {
11    Low,
12    Medium,
13    High,
14}
15
16impl FeeLevel {
17    pub fn as_str(&self) -> &'static str {
18        match self {
19            FeeLevel::Low => "LOW",
20            FeeLevel::Medium => "MEDIUM",
21            FeeLevel::High => "HIGH",
22        }
23    }
24}
25
26/// Request structure for creating wallets
27#[derive(Debug, Serialize, Deserialize)]
28#[serde(rename_all = "camelCase")]
29pub struct CreateDevWalletRequest {
30    /// System-generated unique identifier of the wallet set
31    pub wallet_set_id: String,
32
33    /// Base64 encrypted entity secret ciphertext
34    pub entity_secret_ciphertext: String,
35
36    /// Target blockchains for wallet creation
37    pub blockchains: Vec<Blockchain>,
38
39    /// UUID v4 for idempotency
40    pub idempotency_key: String,
41
42    /// Account type (SCA or EOA)
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub account_type: Option<String>,
45
46    /// Number of wallets per blockchain
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub count: Option<u32>,
49
50    /// Metadata for wallets
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub metadata: Option<Vec<DevWalletMetadata>>,
53
54    /// Wallet name/description
55    #[serde(skip_serializing_if = "Option::is_none")]
56    pub name: Option<String>,
57
58    /// Reference identifier
59    #[serde(skip_serializing_if = "Option::is_none")]
60    pub ref_id: Option<String>,
61}
62
63/// Wallet metadata structure
64#[derive(Debug, Serialize, Deserialize, Clone)]
65#[serde(rename_all = "camelCase")]
66pub struct DevWalletMetadata {
67    /// Name or description
68    #[serde(skip_serializing_if = "Option::is_none")]
69    pub name: Option<String>,
70
71    /// Reference identifier
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub ref_id: Option<String>,
74}
75
76/// Request structure for updating a wallet
77#[derive(Debug, Serialize, Deserialize)]
78#[serde(rename_all = "camelCase")]
79pub struct UpdateDevWalletRequest {
80    /// Wallet name/description
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub name: Option<String>,
83
84    /// Reference identifier
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub ref_id: Option<String>,
87}
88
89/// Wallet response structure
90#[derive(Debug, Deserialize, Serialize)]
91#[serde(rename_all = "camelCase")]
92pub struct DevWalletResponse {
93    pub wallet: DevWallet,
94}
95
96/// Wallet response structure
97#[derive(Debug, Deserialize, Serialize, Clone)]
98#[serde(rename_all = "camelCase")]
99pub struct DevWallet {
100    /// Unique wallet identifier
101    pub id: String,
102
103    /// Blockchain address
104    pub address: String,
105
106    /// Blockchain network
107    pub blockchain: Blockchain,
108
109    /// Creation timestamp
110    pub create_date: DateTime<Utc>,
111
112    /// Last update timestamp
113    pub update_date: DateTime<Utc>,
114
115    /// Custody type (DEVELOPER)
116    pub custody_type: String,
117
118    /// Wallet name
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub name: Option<String>,
121
122    /// Reference identifier
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub ref_id: Option<String>,
125
126    /// Wallet state
127    pub state: String,
128
129    /// User identifier
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub user_id: Option<String>,
132
133    /// Wallet set identifier
134    pub wallet_set_id: String,
135
136    /// Initial public key
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub initial_public_key: Option<String>,
139
140    /// Account type (EOA or SCA)
141    pub account_type: String,
142}
143
144/// Request structure for signing a message
145#[derive(Debug, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct SignMessageRequest {
148    /// A base64 string expression of the entity secret ciphertext. The entity secret should be encrypted by the entity public key. Circle mandates that the entity secret ciphertext is unique for each API request.
149    pub entity_secret_ciphertext: String,
150
151    /// The user friendly message that needs to be signed. If it is a hex string, encoded_by_hex needs to be TRUE. The hex string should start with "0x" and have even length.
152    pub message: String,
153
154    /// System-generated unique identifier of the resource.
155    pub wallet_id: String,
156
157    /// Indicator of whether the input message is encoded by hex. If TRUE, then the message should be a hex string. By default, it is False.
158    #[serde(skip_serializing_if = "Option::is_none")]
159    pub encoded_by_hex: Option<bool>,
160
161    /// The human readable explanation for this sign action. Useful for presenting with extra information.
162    #[serde(skip_serializing_if = "Option::is_none")]
163    pub memo: Option<String>,
164}
165
166/// Request structure for signing a data
167#[derive(Debug, Serialize, Deserialize)]
168#[serde(rename_all = "camelCase")]
169pub struct SignDataRequest {
170    /// A base64 string expression of the entity secret ciphertext. The entity secret should be encrypted by the entity public key. Circle mandates that the entity secret ciphertext is unique for each API request.
171    pub entity_secret_ciphertext: String,
172
173    /// The data that needs to be signed.
174    pub data: String,
175
176    /// System-generated unique identifier of the resource.
177    pub wallet_id: String,
178
179    /// The human readable explanation for this sign action. Useful for presenting with extra information.
180    #[serde(skip_serializing_if = "Option::is_none")]
181    pub memo: Option<String>,
182}
183
184/// Response structure for signing a transaction
185#[derive(Debug, Serialize, Deserialize)]
186#[serde(rename_all = "camelCase")]
187pub struct SignTransactionRequest {
188    /// A base64 string expression of the entity secret ciphertext. The entity secret should be encrypted by the entity public key. Circle mandates that the entity secret ciphertext is unique for each API request.
189    pub entity_secret_ciphertext: String,
190
191    /// The raw transaction that needs to be signed.
192    #[serde(skip_serializing_if = "Option::is_none")]
193    pub raw_transaction: Option<String>,
194
195    /// The transaction that needs to be signed.
196    #[serde(skip_serializing_if = "Option::is_none")]
197    pub transaction: Option<String>,
198
199    /// System-generated unique identifier of the resource.
200    pub wallet_id: String,
201
202    /// The human readable explanation for this sign action. Useful for presenting with extra information.
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub memo: Option<String>,
205}
206
207/// Response structure for signing a transaction
208#[derive(Debug, Deserialize, Serialize)]
209#[serde(rename_all = "camelCase")]
210pub struct SignTransactionResponse {
211    /// Each chain encode signatures in a different way, please refer to Signing APIs doc and the blockchain's document.
212    pub signature: String,
213
214    /// Signed transaction. Base64 encoded for NEAR and Solana chains. Hex encoded for EVM chains.
215    pub signed_transaction: String,
216
217    /// Blockchain-generated identifier of the transaction. Present if the wallet blockchain is not Solana.
218    #[serde(skip_serializing_if = "Option::is_none")]
219    pub tx_hash: Option<String>,
220}
221
222/// Request structure for signing a delegate action
223#[derive(Debug, Serialize, Deserialize)]
224#[serde(rename_all = "camelCase")]
225pub struct SignDelegateRequest {
226    /// A base64 string expression of the entity secret ciphertext. The entity secret should be encrypted by the entity public key. Circle mandates that the entity secret ciphertext is unique for each API request.
227    pub entity_secret_ciphertext: String,
228
229    /// Unsigned delegate action string that needs to be signed. Must be base64 encoded.
230    pub unsigned_delegate_action: String,
231
232    /// System-generated unique identifier of the resource.
233    pub wallet_id: String,
234}
235
236/// Response structure for signing a delegate action
237#[derive(Debug, Deserialize, Serialize)]
238#[serde(rename_all = "camelCase")]
239pub struct SignDelegateResponse {
240    /// Each chain encode signatures in a different way, please refer to Signing APIs doc and the blockchain's document.
241    pub signature: String,
242
243    /// Signed delegate action is a base64 encoded string for NEAR.
244    pub signed_delegate_action: String,
245}
246
247/// Response structure for wallet operations
248#[derive(Debug, Deserialize, Serialize)]
249pub struct DevWalletsResponse {
250    pub wallets: Vec<DevWallet>,
251}
252
253/// Response structure for sign message
254#[derive(Debug, Deserialize, Serialize)]
255pub struct SignatureResponse {
256    /// Each chain encode signatures in a different way, please refer to Signing APIs doc and the blockchain's document.
257    pub signature: String,
258}
259
260/// Account type enum
261pub enum AccountType {
262    Eoa,
263    Sca,
264}
265
266impl AccountType {
267    pub fn as_str(&self) -> &'static str {
268        match self {
269            AccountType::Eoa => "EOA",
270            AccountType::Sca => "SCA",
271        }
272    }
273}
274
275/// Query parameters for listing wallets
276#[derive(Debug, Serialize, Default)]
277#[serde(rename_all = "camelCase")]
278pub struct ListDevWalletsParams {
279    /// Filter by blockchain address
280    #[serde(skip_serializing_if = "Option::is_none")]
281    pub address: Option<String>,
282
283    /// Filter by blockchain
284    #[serde(skip_serializing_if = "Option::is_none")]
285    pub blockchain: Option<String>,
286
287    /// Filter by SCA version
288    #[serde(skip_serializing_if = "Option::is_none")]
289    pub sca_core: Option<String>,
290
291    /// Filter by wallet set ID
292    #[serde(rename = "walletSetId", skip_serializing_if = "Option::is_none")]
293    pub wallet_set_id: Option<String>,
294
295    /// Filter by reference ID
296    #[serde(rename = "refId", skip_serializing_if = "Option::is_none")]
297    pub ref_id: Option<String>,
298
299    /// Filter by creation date (from)
300    #[serde(
301        skip_serializing_if = "Option::is_none",
302        serialize_with = "serialize_datetime_as_string"
303    )]
304    pub from: Option<DateTime<Utc>>,
305
306    /// Filter by creation date (to)
307    #[serde(
308        skip_serializing_if = "Option::is_none",
309        serialize_with = "serialize_datetime_as_string"
310    )]
311    pub to: Option<DateTime<Utc>>,
312
313    /// Pagination parameters
314    #[serde(flatten)]
315    pub pagination: PaginationParams,
316
317    #[serde(skip_serializing_if = "Option::is_none")]
318    pub order: Option<String>,
319}
320
321/// Query parameters for listing wallets with token balances
322#[derive(Debug, Serialize, Default, Deserialize)]
323#[serde(rename_all = "camelCase")]
324pub struct ListWalletsWithBalancesParams {
325    /// Required: Filter by blockchain
326    pub blockchain: String,
327
328    /// Filter by the blockchain address of the wallet
329    #[serde(skip_serializing_if = "Option::is_none")]
330    pub address: Option<String>,
331
332    /// Filter by SCA version
333    #[serde(skip_serializing_if = "Option::is_none")]
334    pub sca_core: Option<String>,
335
336    /// Filter by wallet set ID
337    #[serde(skip_serializing_if = "Option::is_none")]
338    pub wallet_set_id: Option<String>,
339
340    /// Filter by reference identifier
341    #[serde(skip_serializing_if = "Option::is_none")]
342    pub ref_id: Option<String>,
343
344    /// Filters wallets with a balance greater than or equal to the specified amount.
345    /// If tokenAddress is provided, the filter applies to the specified token;
346    /// otherwise, it applies to the native token.
347    #[serde(skip_serializing_if = "Option::is_none", rename = "amount__gte")]
348    pub amount_gte: Option<String>,
349
350    /// Filter by token address
351    #[serde(skip_serializing_if = "Option::is_none")]
352    pub token_address: Option<String>,
353
354    /// Queries items created since the specified date-time (inclusive) in ISO 8601 format
355    #[serde(
356        skip_serializing_if = "Option::is_none",
357        serialize_with = "serialize_datetime_as_string"
358    )]
359    pub from: Option<DateTime<Utc>>,
360
361    /// Queries items created before the specified date-time (inclusive) in ISO 8601 format
362    #[serde(
363        skip_serializing_if = "Option::is_none",
364        serialize_with = "serialize_datetime_as_string"
365    )]
366    pub to: Option<DateTime<Utc>>,
367
368    /// Pagination parameters
369    #[serde(flatten)]
370    pub pagination: PaginationParams,
371}
372
373/// Query standard parameters
374#[derive(Debug, Serialize, Default, Deserialize)]
375#[serde(rename_all = "camelCase")]
376pub struct QueryParams {
377    /// Return all resources with monitored and non-monitored tokens
378    #[serde(
379        skip_serializing_if = "Option::is_none",
380        serialize_with = "serialize_bool_as_string"
381    )]
382    pub include_all: Option<bool>,
383
384    /// Filter by token name
385    #[serde(skip_serializing_if = "Option::is_none")]
386    pub name: Option<String>,
387
388    /// Filter by token address
389    #[serde(skip_serializing_if = "Option::is_none")]
390    pub token_address: Option<String>,
391
392    /// Filter by the token standard (ERC20/ERC721/ERC1155 for EVM chains,
393    /// Fungible/FungibleAsset/NonFungible/NonFungibleEdition/ProgrammableNonFungible/ProgrammableNonFungibleEdition for Solana,
394    /// FungibleAsset for Aptos)
395    #[serde(skip_serializing_if = "Option::is_none")]
396    pub standard: Option<String>,
397
398    /// Pagination parameters
399    #[serde(flatten)]
400    pub pagination: PaginationParams,
401}
402
403/// Parameters for listing transactions
404#[derive(Debug, Serialize, Default, Deserialize)]
405#[serde(rename_all = "camelCase")]
406pub struct ListTransactionsParams {
407    /// Filter by blockchain
408    #[serde(skip_serializing_if = "Option::is_none")]
409    pub blockchain: Option<String>,
410
411    /// Filter by the custody type
412    #[serde(skip_serializing_if = "Option::is_none")]
413    pub custody_type: Option<String>,
414
415    /// Filter by the destination address
416    #[serde(skip_serializing_if = "Option::is_none")]
417    pub destination_address: Option<String>,
418
419    /// Return all resources with monitored and non-monitored tokens
420    #[serde(
421        skip_serializing_if = "Option::is_none",
422        serialize_with = "serialize_bool_as_string"
423    )]
424    pub include_all: Option<bool>,
425
426    /// Filter by the operation of the transaction
427    #[serde(skip_serializing_if = "Option::is_none")]
428    pub operation: Option<String>,
429
430    /// Filter by the state of the transaction
431    #[serde(skip_serializing_if = "Option::is_none")]
432    pub state: Option<String>,
433
434    /// Filter on the transaction hash of the transaction
435    #[serde(skip_serializing_if = "Option::is_none")]
436    pub tx_hash: Option<String>,
437
438    /// Filter by the transaction type
439    #[serde(skip_serializing_if = "Option::is_none")]
440    pub tx_type: Option<String>,
441
442    /// Filter by the wallet IDs (comma separated list of ids)
443    #[serde(skip_serializing_if = "Option::is_none")]
444    pub wallet_ids: Option<String>,
445
446    /// Queries items created since the specified date-time (inclusive) in ISO 8601 format
447    #[serde(
448        skip_serializing_if = "Option::is_none",
449        serialize_with = "serialize_datetime_as_string"
450    )]
451    pub from: Option<DateTime<Utc>>,
452
453    /// Queries items created before the specified date-time (inclusive) in ISO 8601 format
454    #[serde(
455        skip_serializing_if = "Option::is_none",
456        serialize_with = "serialize_datetime_as_string"
457    )]
458    pub to: Option<DateTime<Utc>>,
459
460    /// Specifies the sort order of the collection by CreateDate
461    /// Valid values: ASC, DESC (default)
462    #[serde(skip_serializing_if = "Option::is_none")]
463    pub order: Option<String>,
464
465    /// Pagination parameters
466    #[serde(flatten)]
467    pub pagination: PaginationParams,
468}
469
470/// Parameters for get transaction
471#[derive(Debug, Serialize, Default, Deserialize)]
472#[serde(rename_all = "camelCase")]
473pub struct TransactionParams {
474    /// Filter by the transaction type
475    pub tx_type: String,
476}
477
478/// Token balances data wrapper
479#[derive(Debug, Deserialize, Serialize)]
480#[serde(rename_all = "camelCase")]
481pub struct TokenBalancesResponse {
482    pub token_balances: Vec<TokenBalance>,
483}
484
485/// Individual token balance
486#[derive(Debug, Deserialize, Serialize)]
487#[serde(rename_all = "camelCase")]
488pub struct TokenBalance {
489    /// Balance amount as string
490    pub amount: String,
491
492    /// Token information
493    pub token: Token,
494
495    /// Last update timestamp
496    pub update_date: DateTime<Utc>,
497}
498
499/// Token information
500#[derive(Debug, Deserialize, Serialize)]
501#[serde(rename_all = "camelCase")]
502pub struct Token {
503    /// Unique token identifier
504    pub id: String,
505
506    /// Token name
507    pub name: Option<String>,
508
509    /// Token standard (e.g., ERC20)
510    pub standard: Option<String>,
511
512    /// Blockchain network
513    pub blockchain: String,
514
515    /// Number of decimals
516    pub decimals: Option<u32>,
517
518    /// Whether this is a native token
519    pub is_native: bool,
520
521    /// Token symbol
522    pub symbol: Option<String>,
523
524    /// Token contract address
525    pub token_address: Option<String>,
526
527    /// Last update timestamp
528    pub update_date: DateTime<Utc>,
529
530    /// Creation timestamp
531    pub create_date: DateTime<Utc>,
532}
533
534/// Wallets with balances response structure
535#[derive(Debug, Deserialize, Serialize)]
536#[serde(rename_all = "camelCase")]
537pub struct WalletsWithBalancesResponse {
538    pub wallets: Vec<WalletWithBalances>,
539}
540
541/// Wallet with balances
542#[derive(Debug, Deserialize, Serialize)]
543#[serde(rename_all = "camelCase")]
544pub struct WalletWithBalances {
545    /// Unique wallet identifier
546    pub id: String,
547
548    /// Blockchain address
549    pub address: String,
550
551    /// Blockchain network
552    pub blockchain: String,
553
554    /// Creation timestamp
555    pub create_date: DateTime<Utc>,
556
557    /// Last update timestamp
558    pub update_date: DateTime<Utc>,
559
560    /// Custody type (DEVELOPER)
561    pub custody_type: String,
562
563    /// Wallet name
564    #[serde(skip_serializing_if = "Option::is_none")]
565    pub name: Option<String>,
566
567    /// Reference identifier
568    #[serde(skip_serializing_if = "Option::is_none")]
569    pub ref_id: Option<String>,
570
571    /// Wallet state
572    pub state: String,
573
574    /// User identifier
575    #[serde(skip_serializing_if = "Option::is_none")]
576    pub user_id: Option<String>,
577
578    /// Wallet set identifier
579    pub wallet_set_id: String,
580
581    /// Initial public key
582    #[serde(skip_serializing_if = "Option::is_none")]
583    pub initial_public_key: Option<String>,
584
585    /// Account type (EOA or SCA)
586    pub account_type: String,
587
588    /// Token balances
589    pub token_balances: Vec<TokenBalance>,
590}
591
592/// NFTs response structure
593#[derive(Debug, Deserialize, Serialize)]
594#[serde(rename_all = "camelCase")]
595pub struct NftsResponse {
596    pub nfts: Vec<Nft>,
597}
598
599/// Individual NFT
600#[derive(Debug, Deserialize, Serialize)]
601#[serde(rename_all = "camelCase")]
602pub struct Nft {
603    /// NFT amount as string
604    pub amount: String,
605
606    /// NFT metadata URI
607    pub metadata: Option<String>,
608
609    /// NFT token ID
610    pub nft_token_id: Option<String>,
611
612    /// Token information
613    pub token: Token,
614
615    /// Last update timestamp
616    pub update_date: DateTime<Utc>,
617}
618
619/// Transactions data wrapper
620#[derive(Debug, Deserialize, Serialize)]
621#[serde(rename_all = "camelCase")]
622pub struct TransactionsResponse {
623    pub transactions: Vec<Transaction>,
624}
625
626/// Transaction response structure
627#[derive(Debug, Deserialize, Serialize)]
628#[serde(rename_all = "camelCase")]
629pub struct TransactionResponse {
630    pub transaction: Transaction,
631}
632
633/// Individual transaction
634#[derive(Debug, Deserialize, Serialize)]
635#[serde(rename_all = "camelCase")]
636pub struct Transaction {
637    /// System-generated unique identifier of the resource
638    pub id: String,
639
640    /// The contract ABI function signature or callData field
641    #[serde(skip_serializing_if = "Option::is_none")]
642    pub abi_function_signature: Option<String>,
643
644    /// The contract ABI function signature parameters
645    #[serde(skip_serializing_if = "Option::is_none")]
646    pub abi_parameters: Option<Vec<serde_json::Value>>,
647
648    /// Transfer amounts in decimal number format
649    #[serde(skip_serializing_if = "Option::is_none")]
650    pub amounts: Option<Vec<String>>,
651
652    /// Transaction amount in USD decimal format
653    #[serde(skip_serializing_if = "Option::is_none")]
654    pub amount_in_usd: Option<String>,
655
656    /// Identifier for the block that includes the transaction
657    #[serde(skip_serializing_if = "Option::is_none")]
658    pub block_hash: Option<String>,
659
660    /// Block height of the transaction
661    #[serde(skip_serializing_if = "Option::is_none")]
662    pub block_height: Option<i64>,
663
664    /// The blockchain network
665    pub blockchain: String,
666
667    /// The blockchain address of the contract
668    #[serde(skip_serializing_if = "Option::is_none")]
669    pub contract_address: Option<String>,
670
671    /// Date and time the resource was created
672    pub create_date: DateTime<Utc>,
673
674    /// Describes who controls the digital assets in a wallet
675    #[serde(skip_serializing_if = "Option::is_none")]
676    pub custody_type: Option<String>,
677
678    /// Blockchain generated unique identifier
679    #[serde(skip_serializing_if = "Option::is_none")]
680    pub destination_address: Option<String>,
681
682    /// Description of the error
683    #[serde(skip_serializing_if = "Option::is_none")]
684    pub error_reason: Option<String>,
685
686    /// Additional detail associated with the corresponding transaction's error reason
687    #[serde(skip_serializing_if = "Option::is_none")]
688    pub error_details: Option<String>,
689
690    /// The estimated fee for the transaction
691    #[serde(skip_serializing_if = "Option::is_none")]
692    pub estimated_fee: Option<EstimatedFee>,
693
694    /// Date the transaction was first confirmed in a block
695    #[serde(skip_serializing_if = "Option::is_none")]
696    pub first_confirm_date: Option<DateTime<Utc>>,
697
698    /// Gas fee, in native token, paid to the network for the transaction
699    #[serde(skip_serializing_if = "Option::is_none")]
700    pub network_fee: Option<String>,
701
702    /// Gas fee, in USD, paid to the network for the transaction
703    #[serde(skip_serializing_if = "Option::is_none")]
704    pub network_fee_in_usd: Option<String>,
705
706    /// List of NFTs associated with the transaction
707    #[serde(skip_serializing_if = "Option::is_none")]
708    pub nfts: Option<Vec<String>>,
709
710    /// Operation type of the transaction
711    #[serde(skip_serializing_if = "Option::is_none")]
712    pub operation: Option<String>,
713
714    /// Optional reference or description used to identify the transaction
715    #[serde(skip_serializing_if = "Option::is_none")]
716    pub ref_id: Option<String>,
717
718    /// Blockchain generated unique identifier
719    #[serde(skip_serializing_if = "Option::is_none")]
720    pub source_address: Option<String>,
721
722    /// Current state of the transaction
723    pub state: String,
724
725    /// System-generated unique identifier of the resource
726    #[serde(skip_serializing_if = "Option::is_none")]
727    pub token_id: Option<String>,
728
729    /// Transaction type
730    pub transaction_type: String,
731
732    /// Blockchain generated identifier of the transaction
733    #[serde(skip_serializing_if = "Option::is_none")]
734    pub tx_hash: Option<String>,
735
736    /// Date and time the resource was last updated
737    pub update_date: DateTime<Utc>,
738
739    /// Unique system generated identifier for the user
740    #[serde(skip_serializing_if = "Option::is_none")]
741    pub user_id: Option<String>,
742
743    /// System-generated unique identifier of the resource
744    #[serde(skip_serializing_if = "Option::is_none")]
745    pub wallet_id: Option<String>,
746
747    /// Transaction screening evaluation
748    #[serde(skip_serializing_if = "Option::is_none")]
749    pub transaction_screening_evaluation: Option<TransactionScreeningEvaluation>,
750}
751
752/// Estimated fee for the transaction
753#[derive(Debug, Deserialize, Serialize)]
754#[serde(rename_all = "camelCase")]
755pub struct EstimatedFee {
756    /// The maximum units of gas to use for the transaction
757    #[serde(skip_serializing_if = "Option::is_none")]
758    pub gas_limit: Option<String>,
759
760    /// The maximum price of gas, in gwei, to use per each unit of gas
761    #[serde(skip_serializing_if = "Option::is_none")]
762    pub gas_price: Option<String>,
763
764    /// The maximum price per unit of gas for EIP-1559 support
765    #[serde(skip_serializing_if = "Option::is_none")]
766    pub max_fee: Option<String>,
767
768    /// The "tip" to add to the base fee for EIP-1559 support
769    #[serde(skip_serializing_if = "Option::is_none")]
770    pub priority_fee: Option<String>,
771
772    /// The estimated base fee for EIP-1559 support
773    #[serde(skip_serializing_if = "Option::is_none")]
774    pub base_fee: Option<String>,
775
776    /// The estimated network fee
777    #[serde(skip_serializing_if = "Option::is_none")]
778    pub network_fee: Option<String>,
779
780    /// The estimated network fee with lower buffer
781    #[serde(skip_serializing_if = "Option::is_none")]
782    pub network_fee_raw: Option<String>,
783
784    /// Defines the blockchain fee level
785    #[serde(skip_serializing_if = "Option::is_none")]
786    pub fee_level: Option<String>,
787}
788
789/// Transaction screening evaluation
790#[derive(Debug, Deserialize, Serialize)]
791#[serde(rename_all = "camelCase")]
792pub struct TransactionScreeningEvaluation {
793    /// Name of the matched rule found in screening
794    #[serde(skip_serializing_if = "Option::is_none")]
795    pub rule_name: Option<String>,
796
797    /// Actions to take for the decision
798    #[serde(skip_serializing_if = "Option::is_none")]
799    pub actions: Option<Vec<String>>,
800
801    /// Date and time the resource was created
802    #[serde(skip_serializing_if = "Option::is_none")]
803    pub screening_date: Option<DateTime<Utc>>,
804
805    /// Risk signals found
806    #[serde(skip_serializing_if = "Option::is_none")]
807    pub reasons: Option<Vec<RiskSignal>>,
808}
809
810/// Risk signal
811#[derive(Debug, Deserialize, Serialize)]
812#[serde(rename_all = "camelCase")]
813pub struct RiskSignal {
814    /// Source of the risk signal
815    pub source: String,
816
817    /// Value of the source
818    pub source_value: String,
819
820    /// Risk score of the signal
821    pub risk_score: String,
822
823    /// List of risk categories for the signal
824    pub risk_categories: Vec<String>,
825
826    /// Type of the signal
827    pub r#type: String,
828}
829
830/// Request structure for creating a transfer transaction
831#[derive(Debug, Serialize, Deserialize)]
832#[serde(rename_all = "camelCase")]
833pub struct CreateTransferTransactionRequest {
834    /// Unique system generated identifier of the wallet. Required when sourceAddress and blockchain are not provided.
835    pub wallet_id: Option<String>,
836
837    /// Blockchain generated unique identifier, associated with wallet (account), smart contract or other blockchain objects.
838    pub wallet_address: Option<String>,
839
840    /// A base64 string expression of the entity secret ciphertext. The entity secret should be encrypted by the entity public key.
841    pub entity_secret_ciphertext: String,
842
843    /// Blockchain generated unique identifier, associated with wallet (account), smart contract or other blockchain objects.
844    pub destination_address: String,
845
846    /// Universally unique identifier (UUID v4) idempotency key.
847    pub idempotency_key: String,
848
849    /// Transfer amounts in decimal number format. For ERC721 token transfer, the amounts field is required to be ["1"].
850    pub amounts: Vec<String>,
851
852    /// A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH) that will be used to pay gas for the transaction.
853    /// Cannot be used with gasPrice, priorityFee, or maxFee.
854    #[serde(skip_serializing_if = "Option::is_none")]
855    pub fee_level: Option<FeeLevel>,
856
857    /// The maximum units of gas to use for the transaction. Required if feeLevel is not provided.
858    #[serde(skip_serializing_if = "Option::is_none")]
859    pub gas_limit: Option<String>,
860
861    /// For blockchains without EIP-1559 support, the maximum price of gas, in gwei, to use per each unit of gas.
862    /// Requires gasLimit. Cannot be used with feeLevel, priorityFee, or maxFee.
863    #[serde(skip_serializing_if = "Option::is_none")]
864    pub gas_price: Option<String>,
865
866    /// For blockchains with EIP-1559 support, the maximum price per unit of gas, in gwei.
867    /// Requires priorityFee and gasLimit. Cannot be used with feeLevel or gasPrice.
868    #[serde(skip_serializing_if = "Option::is_none")]
869    pub max_fee: Option<String>,
870
871    /// For blockchains with EIP-1559 support, the "tip", in gwei, to add to the base fee as an incentive for validators.
872    /// Requires maxFee and gasLimit. Cannot be used with feeLevel or gasPrice.
873    #[serde(skip_serializing_if = "Option::is_none")]
874    pub priority_fee: Option<String>,
875
876    /// List of NFT token IDs corresponding with the NFTs to transfer.
877    /// Batch transfers are supported only for ERC-1155 tokens. The length of NFT token IDs must match the length of amounts.
878    #[serde(skip_serializing_if = "Option::is_none")]
879    pub nft_token_ids: Option<Vec<String>>,
880
881    /// Optional reference or description used to identify the transaction.
882    #[serde(skip_serializing_if = "Option::is_none")]
883    pub ref_id: Option<String>,
884
885    /// System generated identifier of the token. Excluded with tokenAddress and tokenBlockchain.
886    #[serde(skip_serializing_if = "Option::is_none")]
887    pub token_id: Option<String>,
888
889    /// Blockchain address of the transferred token. Empty for native tokens. Excluded with tokenId.
890    #[serde(skip_serializing_if = "Option::is_none")]
891    pub token_address: Option<String>,
892
893    /// Blockchain of the transferred token. Required if tokenId is not provided.
894    /// The blockchain and tokenId fields are mutually exclusive.
895    #[serde(skip_serializing_if = "Option::is_none")]
896    pub blockchain: Option<Blockchain>,
897}
898
899/// Response structure for creating a transfer transaction
900/// Note: The outer `data` wrapper is already unwrapped by HttpClient
901#[derive(Debug, Deserialize, Serialize)]
902#[serde(rename_all = "camelCase")]
903pub struct CreateTransferTransactionResponse {
904    /// System-generated unique identifier of the resource
905    pub id: String,
906
907    /// Current state of the transaction
908    pub state: String,
909}
910
911/// Request structure for validating an address
912#[derive(Debug, Serialize, Deserialize)]
913pub struct ValidateAddressBody {
914    pub address: String,
915}
916
917/// Response structure for validating an address
918#[derive(Debug, Deserialize, Serialize)]
919#[serde(rename_all = "camelCase")]
920pub struct ValidateAddressResponse {
921    pub is_valid: bool,
922}
923
924/// ABI parameter types for contract execution
925#[derive(Debug, Serialize, Clone, Deserialize)]
926#[serde(untagged)]
927pub enum AbiParameter {
928    String(String),
929    Integer(i64),
930    Boolean(bool),
931    Array(Vec<AbiParameter>),
932}
933
934/// Request structure for estimating contract execution fee
935#[derive(Debug, Serialize, Deserialize)]
936#[serde(rename_all = "camelCase")]
937pub struct EstimateContractExecutionFeeBody {
938    /// The blockchain address of the contract to be executed
939    pub contract_address: String,
940
941    /// The contract ABI function signature (e.g., "burn(uint256)")
942    /// Cannot be used simultaneously with callData
943    #[serde(skip_serializing_if = "Option::is_none")]
944    pub abi_function_signature: Option<String>,
945
946    /// The contract ABI function signature parameters
947    /// Should be used exclusively with abiFunctionSignature
948    #[serde(skip_serializing_if = "Option::is_none")]
949    pub abi_parameters: Option<Vec<AbiParameter>>,
950
951    /// The raw transaction data (hexadecimal string with 0x prefix)
952    /// Mutually exclusive with abiFunctionSignature and abiParameters
953    #[serde(skip_serializing_if = "Option::is_none")]
954    pub call_data: Option<String>,
955
956    /// The amount of native token to send (optional, for payable functions only)
957    #[serde(skip_serializing_if = "Option::is_none")]
958    pub amount: Option<String>,
959
960    /// Blockchain associated with the transaction
961    /// Required along with sourceAddress if walletId is not provided
962    #[serde(skip_serializing_if = "Option::is_none")]
963    pub blockchain: Option<String>,
964
965    /// Source address of the transaction
966    /// Required along with blockchain if walletId is not provided
967    #[serde(skip_serializing_if = "Option::is_none")]
968    pub source_address: Option<String>,
969
970    /// Unique system generated identifier of the wallet
971    /// Mutually exclusive with sourceAddress and blockchain
972    #[serde(skip_serializing_if = "Option::is_none")]
973    pub wallet_id: Option<String>,
974}
975
976/// Fee estimation data for contract execution
977#[derive(Debug, Deserialize, Serialize)]
978#[serde(rename_all = "camelCase")]
979pub struct EstimateContractExecutionFeeResponse {
980    /// High fee level estimation
981    pub high: EstimatedFee,
982
983    /// Low fee level estimation
984    pub low: EstimatedFee,
985
986    /// Medium fee level estimation
987    pub medium: EstimatedFee,
988
989    /// ERC-4337 gas field: amount of gas for main execution call (SCA only)
990    #[serde(skip_serializing_if = "Option::is_none")]
991    pub call_gas_limit: Option<String>,
992
993    /// ERC-4337 gas field: amount of gas for verification step (SCA only)
994    #[serde(skip_serializing_if = "Option::is_none")]
995    pub verification_gas_limit: Option<String>,
996
997    /// ERC-4337 gas field: gas to compensate bundler for pre-verification (SCA only)
998    #[serde(skip_serializing_if = "Option::is_none")]
999    pub pre_verification_gas: Option<String>,
1000}
1001
1002/// Request structure for estimating transfer transaction fee
1003#[derive(Debug, Serialize, Deserialize)]
1004#[serde(rename_all = "camelCase")]
1005pub struct EstimateTransferFeeRequest {
1006    /// Blockchain address of the destination
1007    pub destination_address: String,
1008
1009    /// Transfer amounts in decimal number format (at least one required)
1010    /// For ERC721 token transfer, must be ["1"]
1011    pub amounts: Vec<String>,
1012
1013    /// List of NFT token IDs (batch transfers supported for ERC-1155 only)
1014    /// Length must match amounts length
1015    #[serde(skip_serializing_if = "Option::is_none")]
1016    pub nft_token_ids: Option<Vec<String>>,
1017
1018    /// Source address of the transaction
1019    /// Required with blockchain if walletId is not provided
1020    #[serde(skip_serializing_if = "Option::is_none")]
1021    pub source_address: Option<String>,
1022
1023    /// System generated identifier of the token
1024    /// Excluded with tokenAddress and blockchain
1025    #[serde(skip_serializing_if = "Option::is_none")]
1026    pub token_id: Option<String>,
1027
1028    /// Blockchain address of the transferred token (empty for native tokens)
1029    /// Excluded with tokenId
1030    #[serde(skip_serializing_if = "Option::is_none")]
1031    pub token_address: Option<String>,
1032
1033    /// Blockchain of the transferred token
1034    /// Required if tokenId is not provided
1035    #[serde(skip_serializing_if = "Option::is_none")]
1036    pub blockchain: Option<String>,
1037
1038    /// Unique system generated identifier of the wallet
1039    /// Mutually exclusive with sourceAddress and blockchain
1040    #[serde(skip_serializing_if = "Option::is_none")]
1041    pub wallet_id: Option<String>,
1042}
1043
1044/// Response structure for estimating transfer transaction fee
1045/// Reuses the same structure as contract execution fee estimation
1046pub type EstimateTransferFeeResponse = EstimateContractExecutionFeeResponse;
1047
1048/// ABI parameter types for contract queries
1049#[derive(Debug, Serialize, Clone, Deserialize)]
1050#[serde(untagged)]
1051pub enum ContractAbiParameter {
1052    String(String),
1053    Integer(i64),
1054    Boolean(bool),
1055    Array(Vec<ContractAbiParameter>),
1056}
1057
1058/// Request structure for querying a contract
1059#[derive(Debug, Serialize, Deserialize)]
1060#[serde(rename_all = "camelCase")]
1061pub struct QueryContractRequest {
1062    /// The blockchain network (required)
1063    pub blockchain: String,
1064
1065    /// Address of the contract to be queried (required)
1066    pub address: String,
1067
1068    /// The contract ABI function signature (e.g., "balanceOf(address)")
1069    /// Cannot be used simultaneously with callData
1070    #[serde(skip_serializing_if = "Option::is_none")]
1071    pub abi_function_signature: Option<String>,
1072
1073    /// The contract ABI function signature parameters
1074    /// Should be used exclusively with abiFunctionSignature
1075    #[serde(skip_serializing_if = "Option::is_none")]
1076    pub abi_parameters: Option<Vec<ContractAbiParameter>>,
1077
1078    /// The contract's ABI in a JSON stringified format
1079    #[serde(skip_serializing_if = "Option::is_none")]
1080    pub abi_json: Option<String>,
1081
1082    /// CallData is input data that encodes method and parameters
1083    /// Mutually exclusive with abiFunctionSignature and abiParameters
1084    #[serde(skip_serializing_if = "Option::is_none")]
1085    pub call_data: Option<String>,
1086
1087    /// FromAddress is the address that will populate msg.sender in the contract call
1088    #[serde(skip_serializing_if = "Option::is_none")]
1089    pub from_address: Option<String>,
1090}
1091
1092/// Output value types for contract query results
1093#[derive(Debug, Deserialize, Serialize, Clone)]
1094#[serde(untagged)]
1095pub enum ContractOutputValue {
1096    String(String),
1097    Number(f64),
1098    Boolean(bool),
1099}
1100
1101/// Response data for contract query
1102#[derive(Debug, Deserialize, Serialize)]
1103#[serde(rename_all = "camelCase")]
1104pub struct QueryContractResponse {
1105    /// Output for the ABI interaction
1106    /// May be null if the contract call returns no values
1107    #[serde(skip_serializing_if = "Option::is_none")]
1108    pub output_values: Option<Vec<ContractOutputValue>>,
1109
1110    /// OutputData is output in hex format
1111    pub output_data: String,
1112}
1113
1114/// SCA Core version enum for wallet upgrades
1115#[derive(Debug, Clone, Serialize, Deserialize)]
1116pub enum ScaCore {
1117    #[serde(rename = "circle_6900_singleowner_v3")]
1118    Circle6900SingleownerV3,
1119}
1120
1121impl ScaCore {
1122    pub fn as_str(&self) -> &'static str {
1123        match self {
1124            ScaCore::Circle6900SingleownerV3 => "circle_6900_singleowner_v3",
1125        }
1126    }
1127}
1128
1129/// Request structure for creating a wallet upgrade transaction
1130#[derive(Debug, Serialize, Deserialize)]
1131#[serde(rename_all = "camelCase")]
1132pub struct CreateWalletUpgradeTransactionRequest {
1133    /// Unique system generated identifier of the wallet
1134    pub wallet_id: String,
1135
1136    /// A base64 string expression of the entity secret ciphertext
1137    pub entity_secret_ciphertext: String,
1138
1139    /// Version of the SCA available for upgrade
1140    pub new_sca_core: String,
1141
1142    /// UUID v4 for idempotency
1143    pub idempotency_key: String,
1144
1145    /// A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH)
1146    /// Cannot be used with gasPrice, priorityFee, or maxFee
1147    #[serde(skip_serializing_if = "Option::is_none")]
1148    pub fee_level: Option<FeeLevel>,
1149
1150    /// The maximum units of gas to use for the transaction
1151    #[serde(skip_serializing_if = "Option::is_none")]
1152    pub gas_limit: Option<String>,
1153
1154    /// For blockchains without EIP-1559 support, the maximum price of gas, in gwei
1155    /// Requires gasLimit. Cannot be used with feeLevel, priorityFee, or maxFee
1156    #[serde(skip_serializing_if = "Option::is_none")]
1157    pub gas_price: Option<String>,
1158
1159    /// For blockchains with EIP-1559 support, the maximum price per unit of gas, in gwei
1160    /// Requires priorityFee and gasLimit. Cannot be used with feeLevel or gasPrice
1161    #[serde(skip_serializing_if = "Option::is_none")]
1162    pub max_fee: Option<String>,
1163
1164    /// For blockchains with EIP-1559 support, the "tip", in gwei
1165    /// Requires maxFee and gasLimit. Cannot be used with feeLevel or gasPrice
1166    #[serde(skip_serializing_if = "Option::is_none")]
1167    pub priority_fee: Option<String>,
1168
1169    /// Optional reference or description used to identify the transaction
1170    #[serde(skip_serializing_if = "Option::is_none")]
1171    pub ref_id: Option<String>,
1172}
1173
1174/// Response structure for creating a wallet upgrade transaction
1175#[derive(Debug, Deserialize, Serialize)]
1176#[serde(rename_all = "camelCase")]
1177pub struct CreateWalletUpgradeTransactionResponse {
1178    /// System-generated unique identifier of the resource
1179    pub id: String,
1180
1181    /// Current state of the transaction
1182    pub state: String,
1183}
1184
1185/// Request structure for creating a contract execution transaction
1186#[derive(Debug, Serialize, Deserialize)]
1187#[serde(rename_all = "camelCase")]
1188pub struct CreateContractExecutionTransactionRequest {
1189    /// Unique system generated identifier of the wallet
1190    pub wallet_id: String,
1191
1192    /// A base64 string expression of the entity secret ciphertext
1193    pub entity_secret_ciphertext: String,
1194
1195    /// The blockchain address of the contract to be executed
1196    pub contract_address: String,
1197
1198    /// UUID v4 for idempotency
1199    pub idempotency_key: String,
1200
1201    /// The contract ABI function signature (e.g., "burn(uint256)")
1202    /// Cannot be used simultaneously with callData
1203    #[serde(skip_serializing_if = "Option::is_none")]
1204    pub abi_function_signature: Option<String>,
1205
1206    /// The contract ABI function signature parameters
1207    /// Should be used exclusively with abiFunctionSignature
1208    #[serde(skip_serializing_if = "Option::is_none")]
1209    pub abi_parameters: Option<Vec<AbiParameter>>,
1210
1211    /// The raw transaction data (hexadecimal string with 0x prefix)
1212    /// Mutually exclusive with abiFunctionSignature and abiParameters
1213    #[serde(skip_serializing_if = "Option::is_none")]
1214    pub call_data: Option<String>,
1215
1216    /// The amount of native token to send (optional, for payable functions only)
1217    #[serde(skip_serializing_if = "Option::is_none")]
1218    pub amount: Option<String>,
1219
1220    /// A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH)
1221    /// Cannot be used with gasPrice, priorityFee, or maxFee
1222    #[serde(skip_serializing_if = "Option::is_none")]
1223    pub fee_level: Option<FeeLevel>,
1224
1225    /// The maximum units of gas to use for the transaction
1226    #[serde(skip_serializing_if = "Option::is_none")]
1227    pub gas_limit: Option<String>,
1228
1229    /// For blockchains without EIP-1559 support, the maximum price of gas, in gwei
1230    /// Requires gasLimit. Cannot be used with feeLevel, priorityFee, or maxFee
1231    #[serde(skip_serializing_if = "Option::is_none")]
1232    pub gas_price: Option<String>,
1233
1234    /// For blockchains with EIP-1559 support, the maximum price per unit of gas, in gwei
1235    /// Requires priorityFee and gasLimit. Cannot be used with feeLevel or gasPrice
1236    #[serde(skip_serializing_if = "Option::is_none")]
1237    pub max_fee: Option<String>,
1238
1239    /// For blockchains with EIP-1559 support, the "tip", in gwei
1240    /// Requires maxFee and gasLimit. Cannot be used with feeLevel or gasPrice
1241    #[serde(skip_serializing_if = "Option::is_none")]
1242    pub priority_fee: Option<String>,
1243
1244    /// Optional reference or description used to identify the transaction
1245    #[serde(skip_serializing_if = "Option::is_none")]
1246    pub ref_id: Option<String>,
1247}
1248
1249/// Response structure for creating a contract execution transaction
1250#[derive(Debug, Deserialize, Serialize)]
1251#[serde(rename_all = "camelCase")]
1252pub struct CreateContractExecutionTransactionResponse {
1253    /// System-generated unique identifier of the resource
1254    pub id: String,
1255
1256    /// Current state of the transaction
1257    pub state: String,
1258}
1259
1260/// Request structure for canceling a transaction
1261#[derive(Debug, Serialize, Deserialize)]
1262#[serde(rename_all = "camelCase")]
1263pub struct CancelTransactionRequest {
1264    /// A base64 string expression of the entity secret ciphertext
1265    pub entity_secret_ciphertext: String,
1266
1267    /// UUID v4 for idempotency
1268    pub idempotency_key: String,
1269}
1270
1271/// Response structure for canceling a transaction
1272#[derive(Debug, Deserialize, Serialize)]
1273#[serde(rename_all = "camelCase")]
1274pub struct CancelTransactionResponse {
1275    /// System-generated unique identifier of the resource
1276    pub id: String,
1277
1278    /// Current state of the transaction
1279    pub state: String,
1280}
1281
1282/// Request structure for accelerating a transaction
1283#[derive(Debug, Serialize, Deserialize)]
1284#[serde(rename_all = "camelCase")]
1285pub struct AccelerateTransactionRequest {
1286    /// A base64 string expression of the entity secret ciphertext
1287    pub entity_secret_ciphertext: String,
1288
1289    /// UUID v4 for idempotency
1290    pub idempotency_key: String,
1291}
1292
1293/// Response structure for accelerating a transaction
1294#[derive(Debug, Deserialize, Serialize)]
1295#[serde(rename_all = "camelCase")]
1296pub struct AccelerateTransactionResponse {
1297    /// System-generated unique identifier of the resource
1298    pub id: String,
1299}
1300
1301/// Request structure for requesting testnet tokens from faucet
1302#[derive(Debug, Serialize, Clone, Deserialize)]
1303#[serde(rename_all = "camelCase")]
1304pub struct RequestTestnetTokensRequest {
1305    /// The testnet blockchain network
1306    pub blockchain: Blockchain,
1307
1308    /// Blockchain address to receive tokens
1309    pub address: String,
1310
1311    /// Request native testnet tokens
1312    #[serde(skip_serializing_if = "Option::is_none")]
1313    pub native: Option<bool>,
1314
1315    /// Request USDC testnet tokens
1316    #[serde(skip_serializing_if = "Option::is_none")]
1317    pub usdc: Option<bool>,
1318
1319    /// Request EURC testnet tokens
1320    #[serde(skip_serializing_if = "Option::is_none")]
1321    pub eurc: Option<bool>,
1322}