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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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: String,
836
837    /// A base64 string expression of the entity secret ciphertext. The entity secret should be encrypted by the entity public key.
838    pub entity_secret_ciphertext: String,
839
840    /// Blockchain generated unique identifier, associated with wallet (account), smart contract or other blockchain objects.
841    pub destination_address: String,
842
843    /// Universally unique identifier (UUID v4) idempotency key.
844    pub idempotency_key: String,
845
846    /// Transfer amounts in decimal number format. For ERC721 token transfer, the amounts field is required to be ["1"].
847    pub amounts: Vec<String>,
848
849    /// A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH) that will be used to pay gas for the transaction.
850    /// Cannot be used with gasPrice, priorityFee, or maxFee.
851    #[serde(skip_serializing_if = "Option::is_none")]
852    pub fee_level: Option<FeeLevel>,
853
854    /// The maximum units of gas to use for the transaction. Required if feeLevel is not provided.
855    #[serde(skip_serializing_if = "Option::is_none")]
856    pub gas_limit: Option<String>,
857
858    /// For blockchains without EIP-1559 support, the maximum price of gas, in gwei, to use per each unit of gas.
859    /// Requires gasLimit. Cannot be used with feeLevel, priorityFee, or maxFee.
860    #[serde(skip_serializing_if = "Option::is_none")]
861    pub gas_price: Option<String>,
862
863    /// For blockchains with EIP-1559 support, the maximum price per unit of gas, in gwei.
864    /// Requires priorityFee and gasLimit. Cannot be used with feeLevel or gasPrice.
865    #[serde(skip_serializing_if = "Option::is_none")]
866    pub max_fee: Option<String>,
867
868    /// For blockchains with EIP-1559 support, the "tip", in gwei, to add to the base fee as an incentive for validators.
869    /// Requires maxFee and gasLimit. Cannot be used with feeLevel or gasPrice.
870    #[serde(skip_serializing_if = "Option::is_none")]
871    pub priority_fee: Option<String>,
872
873    /// List of NFT token IDs corresponding with the NFTs to transfer.
874    /// Batch transfers are supported only for ERC-1155 tokens. The length of NFT token IDs must match the length of amounts.
875    #[serde(skip_serializing_if = "Option::is_none")]
876    pub nft_token_ids: Option<Vec<String>>,
877
878    /// Optional reference or description used to identify the transaction.
879    #[serde(skip_serializing_if = "Option::is_none")]
880    pub ref_id: Option<String>,
881
882    /// System generated identifier of the token. Excluded with tokenAddress and tokenBlockchain.
883    #[serde(skip_serializing_if = "Option::is_none")]
884    pub token_id: Option<String>,
885
886    /// Blockchain address of the transferred token. Empty for native tokens. Excluded with tokenId.
887    #[serde(skip_serializing_if = "Option::is_none")]
888    pub token_address: Option<String>,
889
890    /// Blockchain of the transferred token. Required if tokenId is not provided.
891    /// The blockchain and tokenId fields are mutually exclusive.
892    #[serde(skip_serializing_if = "Option::is_none")]
893    pub blockchain: Option<Blockchain>,
894}
895
896/// Response structure for creating a transfer transaction
897/// Note: The outer `data` wrapper is already unwrapped by HttpClient
898#[derive(Debug, Deserialize, Serialize)]
899#[serde(rename_all = "camelCase")]
900pub struct CreateTransferTransactionResponse {
901    /// System-generated unique identifier of the resource
902    pub id: String,
903
904    /// Current state of the transaction
905    pub state: String,
906}
907
908/// Request structure for validating an address
909#[derive(Debug, Serialize)]
910pub struct ValidateAddressBody {
911    pub address: String,
912}
913
914/// Response structure for validating an address
915#[derive(Debug, Deserialize, Serialize)]
916#[serde(rename_all = "camelCase")]
917pub struct ValidateAddressResponse {
918    pub is_valid: bool,
919}
920
921/// ABI parameter types for contract execution
922#[derive(Debug, Serialize, Clone)]
923#[serde(untagged)]
924pub enum AbiParameter {
925    String(String),
926    Integer(i64),
927    Boolean(bool),
928    Array(Vec<AbiParameter>),
929}
930
931/// Request structure for estimating contract execution fee
932#[derive(Debug, Serialize)]
933#[serde(rename_all = "camelCase")]
934pub struct EstimateContractExecutionFeeBody {
935    /// The blockchain address of the contract to be executed
936    pub contract_address: String,
937
938    /// The contract ABI function signature (e.g., "burn(uint256)")
939    /// Cannot be used simultaneously with callData
940    #[serde(skip_serializing_if = "Option::is_none")]
941    pub abi_function_signature: Option<String>,
942
943    /// The contract ABI function signature parameters
944    /// Should be used exclusively with abiFunctionSignature
945    #[serde(skip_serializing_if = "Option::is_none")]
946    pub abi_parameters: Option<Vec<AbiParameter>>,
947
948    /// The raw transaction data (hexadecimal string with 0x prefix)
949    /// Mutually exclusive with abiFunctionSignature and abiParameters
950    #[serde(skip_serializing_if = "Option::is_none")]
951    pub call_data: Option<String>,
952
953    /// The amount of native token to send (optional, for payable functions only)
954    #[serde(skip_serializing_if = "Option::is_none")]
955    pub amount: Option<String>,
956
957    /// Blockchain associated with the transaction
958    /// Required along with sourceAddress if walletId is not provided
959    #[serde(skip_serializing_if = "Option::is_none")]
960    pub blockchain: Option<String>,
961
962    /// Source address of the transaction
963    /// Required along with blockchain if walletId is not provided
964    #[serde(skip_serializing_if = "Option::is_none")]
965    pub source_address: Option<String>,
966
967    /// Unique system generated identifier of the wallet
968    /// Mutually exclusive with sourceAddress and blockchain
969    #[serde(skip_serializing_if = "Option::is_none")]
970    pub wallet_id: Option<String>,
971}
972
973/// Fee estimation data for contract execution
974#[derive(Debug, Deserialize, Serialize)]
975#[serde(rename_all = "camelCase")]
976pub struct EstimateContractExecutionFeeResponse {
977    /// High fee level estimation
978    pub high: EstimatedFee,
979
980    /// Low fee level estimation
981    pub low: EstimatedFee,
982
983    /// Medium fee level estimation
984    pub medium: EstimatedFee,
985
986    /// ERC-4337 gas field: amount of gas for main execution call (SCA only)
987    #[serde(skip_serializing_if = "Option::is_none")]
988    pub call_gas_limit: Option<String>,
989
990    /// ERC-4337 gas field: amount of gas for verification step (SCA only)
991    #[serde(skip_serializing_if = "Option::is_none")]
992    pub verification_gas_limit: Option<String>,
993
994    /// ERC-4337 gas field: gas to compensate bundler for pre-verification (SCA only)
995    #[serde(skip_serializing_if = "Option::is_none")]
996    pub pre_verification_gas: Option<String>,
997}
998
999/// Request structure for estimating transfer transaction fee
1000#[derive(Debug, Serialize)]
1001#[serde(rename_all = "camelCase")]
1002pub struct EstimateTransferFeeRequest {
1003    /// Blockchain address of the destination
1004    pub destination_address: String,
1005
1006    /// Transfer amounts in decimal number format (at least one required)
1007    /// For ERC721 token transfer, must be ["1"]
1008    pub amounts: Vec<String>,
1009
1010    /// List of NFT token IDs (batch transfers supported for ERC-1155 only)
1011    /// Length must match amounts length
1012    #[serde(skip_serializing_if = "Option::is_none")]
1013    pub nft_token_ids: Option<Vec<String>>,
1014
1015    /// Source address of the transaction
1016    /// Required with blockchain if walletId is not provided
1017    #[serde(skip_serializing_if = "Option::is_none")]
1018    pub source_address: Option<String>,
1019
1020    /// System generated identifier of the token
1021    /// Excluded with tokenAddress and blockchain
1022    #[serde(skip_serializing_if = "Option::is_none")]
1023    pub token_id: Option<String>,
1024
1025    /// Blockchain address of the transferred token (empty for native tokens)
1026    /// Excluded with tokenId
1027    #[serde(skip_serializing_if = "Option::is_none")]
1028    pub token_address: Option<String>,
1029
1030    /// Blockchain of the transferred token
1031    /// Required if tokenId is not provided
1032    #[serde(skip_serializing_if = "Option::is_none")]
1033    pub blockchain: Option<String>,
1034
1035    /// Unique system generated identifier of the wallet
1036    /// Mutually exclusive with sourceAddress and blockchain
1037    #[serde(skip_serializing_if = "Option::is_none")]
1038    pub wallet_id: Option<String>,
1039}
1040
1041/// Response structure for estimating transfer transaction fee
1042/// Reuses the same structure as contract execution fee estimation
1043pub type EstimateTransferFeeResponse = EstimateContractExecutionFeeResponse;
1044
1045/// ABI parameter types for contract queries
1046#[derive(Debug, Serialize, Clone)]
1047#[serde(untagged)]
1048pub enum ContractAbiParameter {
1049    String(String),
1050    Integer(i64),
1051    Boolean(bool),
1052    Array(Vec<ContractAbiParameter>),
1053}
1054
1055/// Request structure for querying a contract
1056#[derive(Debug, Serialize)]
1057#[serde(rename_all = "camelCase")]
1058pub struct QueryContractRequest {
1059    /// The blockchain network (required)
1060    pub blockchain: String,
1061
1062    /// Address of the contract to be queried (required)
1063    pub address: String,
1064
1065    /// The contract ABI function signature (e.g., "balanceOf(address)")
1066    /// Cannot be used simultaneously with callData
1067    #[serde(skip_serializing_if = "Option::is_none")]
1068    pub abi_function_signature: Option<String>,
1069
1070    /// The contract ABI function signature parameters
1071    /// Should be used exclusively with abiFunctionSignature
1072    #[serde(skip_serializing_if = "Option::is_none")]
1073    pub abi_parameters: Option<Vec<ContractAbiParameter>>,
1074
1075    /// The contract's ABI in a JSON stringified format
1076    #[serde(skip_serializing_if = "Option::is_none")]
1077    pub abi_json: Option<String>,
1078
1079    /// CallData is input data that encodes method and parameters
1080    /// Mutually exclusive with abiFunctionSignature and abiParameters
1081    #[serde(skip_serializing_if = "Option::is_none")]
1082    pub call_data: Option<String>,
1083
1084    /// FromAddress is the address that will populate msg.sender in the contract call
1085    #[serde(skip_serializing_if = "Option::is_none")]
1086    pub from_address: Option<String>,
1087}
1088
1089/// Output value types for contract query results
1090#[derive(Debug, Deserialize, Serialize, Clone)]
1091#[serde(untagged)]
1092pub enum ContractOutputValue {
1093    String(String),
1094    Number(f64),
1095    Boolean(bool),
1096}
1097
1098/// Response data for contract query
1099#[derive(Debug, Deserialize, Serialize)]
1100#[serde(rename_all = "camelCase")]
1101pub struct QueryContractResponse {
1102    /// Output for the ABI interaction
1103    /// May be null if the contract call returns no values
1104    #[serde(skip_serializing_if = "Option::is_none")]
1105    pub output_values: Option<Vec<ContractOutputValue>>,
1106
1107    /// OutputData is output in hex format
1108    pub output_data: String,
1109}
1110
1111/// SCA Core version enum for wallet upgrades
1112#[derive(Debug, Clone, Serialize)]
1113pub enum ScaCore {
1114    #[serde(rename = "circle_6900_singleowner_v3")]
1115    Circle6900SingleownerV3,
1116}
1117
1118impl ScaCore {
1119    pub fn as_str(&self) -> &'static str {
1120        match self {
1121            ScaCore::Circle6900SingleownerV3 => "circle_6900_singleowner_v3",
1122        }
1123    }
1124}
1125
1126/// Request structure for creating a wallet upgrade transaction
1127#[derive(Debug, Serialize)]
1128#[serde(rename_all = "camelCase")]
1129pub struct CreateWalletUpgradeTransactionRequest {
1130    /// Unique system generated identifier of the wallet
1131    pub wallet_id: String,
1132
1133    /// A base64 string expression of the entity secret ciphertext
1134    pub entity_secret_ciphertext: String,
1135
1136    /// Version of the SCA available for upgrade
1137    pub new_sca_core: String,
1138
1139    /// UUID v4 for idempotency
1140    pub idempotency_key: String,
1141
1142    /// A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH)
1143    /// Cannot be used with gasPrice, priorityFee, or maxFee
1144    #[serde(skip_serializing_if = "Option::is_none")]
1145    pub fee_level: Option<FeeLevel>,
1146
1147    /// The maximum units of gas to use for the transaction
1148    #[serde(skip_serializing_if = "Option::is_none")]
1149    pub gas_limit: Option<String>,
1150
1151    /// For blockchains without EIP-1559 support, the maximum price of gas, in gwei
1152    /// Requires gasLimit. Cannot be used with feeLevel, priorityFee, or maxFee
1153    #[serde(skip_serializing_if = "Option::is_none")]
1154    pub gas_price: Option<String>,
1155
1156    /// For blockchains with EIP-1559 support, the maximum price per unit of gas, in gwei
1157    /// Requires priorityFee and gasLimit. Cannot be used with feeLevel or gasPrice
1158    #[serde(skip_serializing_if = "Option::is_none")]
1159    pub max_fee: Option<String>,
1160
1161    /// For blockchains with EIP-1559 support, the "tip", in gwei
1162    /// Requires maxFee and gasLimit. Cannot be used with feeLevel or gasPrice
1163    #[serde(skip_serializing_if = "Option::is_none")]
1164    pub priority_fee: Option<String>,
1165
1166    /// Optional reference or description used to identify the transaction
1167    #[serde(skip_serializing_if = "Option::is_none")]
1168    pub ref_id: Option<String>,
1169}
1170
1171/// Response structure for creating a wallet upgrade transaction
1172#[derive(Debug, Deserialize, Serialize)]
1173#[serde(rename_all = "camelCase")]
1174pub struct CreateWalletUpgradeTransactionResponse {
1175    /// System-generated unique identifier of the resource
1176    pub id: String,
1177
1178    /// Current state of the transaction
1179    pub state: String,
1180}
1181
1182/// Request structure for creating a contract execution transaction
1183#[derive(Debug, Serialize)]
1184#[serde(rename_all = "camelCase")]
1185pub struct CreateContractExecutionTransactionRequest {
1186    /// Unique system generated identifier of the wallet
1187    pub wallet_id: String,
1188
1189    /// A base64 string expression of the entity secret ciphertext
1190    pub entity_secret_ciphertext: String,
1191
1192    /// The blockchain address of the contract to be executed
1193    pub contract_address: String,
1194
1195    /// UUID v4 for idempotency
1196    pub idempotency_key: String,
1197
1198    /// The contract ABI function signature (e.g., "burn(uint256)")
1199    /// Cannot be used simultaneously with callData
1200    #[serde(skip_serializing_if = "Option::is_none")]
1201    pub abi_function_signature: Option<String>,
1202
1203    /// The contract ABI function signature parameters
1204    /// Should be used exclusively with abiFunctionSignature
1205    #[serde(skip_serializing_if = "Option::is_none")]
1206    pub abi_parameters: Option<Vec<AbiParameter>>,
1207
1208    /// The raw transaction data (hexadecimal string with 0x prefix)
1209    /// Mutually exclusive with abiFunctionSignature and abiParameters
1210    #[serde(skip_serializing_if = "Option::is_none")]
1211    pub call_data: Option<String>,
1212
1213    /// The amount of native token to send (optional, for payable functions only)
1214    #[serde(skip_serializing_if = "Option::is_none")]
1215    pub amount: Option<String>,
1216
1217    /// A dynamic blockchain fee level setting (LOW, MEDIUM, or HIGH)
1218    /// Cannot be used with gasPrice, priorityFee, or maxFee
1219    #[serde(skip_serializing_if = "Option::is_none")]
1220    pub fee_level: Option<FeeLevel>,
1221
1222    /// The maximum units of gas to use for the transaction
1223    #[serde(skip_serializing_if = "Option::is_none")]
1224    pub gas_limit: Option<String>,
1225
1226    /// For blockchains without EIP-1559 support, the maximum price of gas, in gwei
1227    /// Requires gasLimit. Cannot be used with feeLevel, priorityFee, or maxFee
1228    #[serde(skip_serializing_if = "Option::is_none")]
1229    pub gas_price: Option<String>,
1230
1231    /// For blockchains with EIP-1559 support, the maximum price per unit of gas, in gwei
1232    /// Requires priorityFee and gasLimit. Cannot be used with feeLevel or gasPrice
1233    #[serde(skip_serializing_if = "Option::is_none")]
1234    pub max_fee: Option<String>,
1235
1236    /// For blockchains with EIP-1559 support, the "tip", in gwei
1237    /// Requires maxFee and gasLimit. Cannot be used with feeLevel or gasPrice
1238    #[serde(skip_serializing_if = "Option::is_none")]
1239    pub priority_fee: Option<String>,
1240
1241    /// Optional reference or description used to identify the transaction
1242    #[serde(skip_serializing_if = "Option::is_none")]
1243    pub ref_id: Option<String>,
1244}
1245
1246/// Response structure for creating a contract execution transaction
1247#[derive(Debug, Deserialize, Serialize)]
1248#[serde(rename_all = "camelCase")]
1249pub struct CreateContractExecutionTransactionResponse {
1250    /// System-generated unique identifier of the resource
1251    pub id: String,
1252
1253    /// Current state of the transaction
1254    pub state: String,
1255}
1256
1257/// Request structure for canceling a transaction
1258#[derive(Debug, Serialize)]
1259#[serde(rename_all = "camelCase")]
1260pub struct CancelTransactionRequest {
1261    /// A base64 string expression of the entity secret ciphertext
1262    pub entity_secret_ciphertext: String,
1263
1264    /// UUID v4 for idempotency
1265    pub idempotency_key: String,
1266}
1267
1268/// Response structure for canceling a transaction
1269#[derive(Debug, Deserialize, Serialize)]
1270#[serde(rename_all = "camelCase")]
1271pub struct CancelTransactionResponse {
1272    /// System-generated unique identifier of the resource
1273    pub id: String,
1274
1275    /// Current state of the transaction
1276    pub state: String,
1277}
1278
1279/// Request structure for accelerating a transaction
1280#[derive(Debug, Serialize)]
1281#[serde(rename_all = "camelCase")]
1282pub struct AccelerateTransactionRequest {
1283    /// A base64 string expression of the entity secret ciphertext
1284    pub entity_secret_ciphertext: String,
1285
1286    /// UUID v4 for idempotency
1287    pub idempotency_key: String,
1288}
1289
1290/// Response structure for accelerating a transaction
1291#[derive(Debug, Deserialize, Serialize)]
1292#[serde(rename_all = "camelCase")]
1293pub struct AccelerateTransactionResponse {
1294    /// System-generated unique identifier of the resource
1295    pub id: String,
1296}
1297
1298/// Request structure for requesting testnet tokens from faucet
1299#[derive(Debug, Serialize, Clone)]
1300#[serde(rename_all = "camelCase")]
1301pub struct RequestTestnetTokensRequest {
1302    /// The testnet blockchain network
1303    pub blockchain: Blockchain,
1304
1305    /// Blockchain address to receive tokens
1306    pub address: String,
1307
1308    /// Request native testnet tokens
1309    #[serde(skip_serializing_if = "Option::is_none")]
1310    pub native: Option<bool>,
1311
1312    /// Request USDC testnet tokens
1313    #[serde(skip_serializing_if = "Option::is_none")]
1314    pub usdc: Option<bool>,
1315
1316    /// Request EURC testnet tokens
1317    #[serde(skip_serializing_if = "Option::is_none")]
1318    pub eurc: Option<bool>,
1319}