use super::common::{AccountType, Blockchain, CustodyType, PageParams, TokenStandard, WalletState};
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum NftStandard {
#[serde(rename = "ERC721")]
Erc721,
#[serde(rename = "ERC1155")]
Erc1155,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum FtStandard {
#[serde(rename = "")]
Native,
#[serde(rename = "ERC20")]
Erc20,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum ScaCore {
#[serde(rename = "circle_4337_v1")]
Circle4337V1,
#[serde(rename = "circle_6900_singleowner_v1")]
Circle6900SingleownerV1,
#[serde(rename = "circle_6900_singleowner_v2")]
Circle6900SingleownerV2,
#[serde(rename = "circle_6900_singleowner_v3")]
Circle6900SingleownerV3,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Token {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
pub blockchain: Blockchain,
pub is_native: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub standard: Option<TokenStandard>,
#[serde(skip_serializing_if = "Option::is_none")]
pub decimals: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub symbol: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub update_date: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub create_date: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Balance {
pub amount: String,
pub token: Token,
pub update_date: String,
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WalletMetadata {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ref_id: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Wallet {
pub id: String,
pub address: String,
pub blockchain: Blockchain,
pub create_date: String,
pub update_date: String,
pub custody_type: CustodyType,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ref_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<WalletState>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wallet_set_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub initial_public_key: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub account_type: Option<AccountType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sca_core: Option<ScaCore>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_balances: Option<Vec<Balance>>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WalletsData {
pub wallets: Vec<Wallet>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Wallets {
pub data: WalletsData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WalletData {
pub wallet: Wallet,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WalletResponse {
pub data: WalletData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WalletsWithBalancesData {
pub wallets: Vec<Wallet>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WalletsWithBalances {
pub data: WalletsWithBalancesData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BalancesData {
pub token_balances: Vec<Balance>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Balances {
pub data: BalancesData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Nft {
pub amount: String,
pub token: Token,
pub update_date: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub nft_token_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<String>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct NftsData {
pub nfts: Vec<Nft>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct Nfts {
pub data: NftsData,
}
#[derive(Debug, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateWalletsRequest {
pub idempotency_key: String,
pub entity_secret_ciphertext: String,
pub wallet_set_id: String,
pub blockchains: Vec<Blockchain>,
#[serde(skip_serializing_if = "Option::is_none")]
pub account_type: Option<AccountType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub count: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Vec<WalletMetadata>>,
}
#[derive(Debug, Clone, Default, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateWalletRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ref_id: Option<String>,
}
#[derive(Debug, Default, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListWalletsParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub blockchain: Option<Blockchain>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wallet_set_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ref_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<WalletState>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custody_type: Option<CustodyType>,
#[serde(flatten)]
pub page: PageParams,
}
#[derive(Debug, Default, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListWalletBalancesParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub include_all: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub blockchain: Option<Blockchain>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wallet_set_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wallet_ids: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub custody_type: Option<CustodyType>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(flatten)]
pub page: PageParams,
}
#[derive(Debug, Default, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WalletNftsParams {
#[serde(flatten)]
pub page: PageParams,
}
#[derive(Debug, Default, Clone, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ListWalletNftsParams {
#[serde(skip_serializing_if = "Option::is_none")]
pub standard: Option<NftStandard>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub token_address: Option<String>,
#[serde(flatten)]
pub page: PageParams,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wallet_response_deserializes() -> Result<(), Box<dyn std::error::Error>> {
let json = r#"{
"data": {
"wallet": {
"id": "wallet-id-1",
"address": "0x1234",
"blockchain": "ETH",
"createDate": "2024-01-01T00:00:00Z",
"updateDate": "2024-01-01T00:00:00Z",
"custodyType": "DEVELOPER",
"state": "LIVE"
}
}
}"#;
let resp: WalletResponse = serde_json::from_str(json)?;
assert_eq!(resp.data.wallet.id, "wallet-id-1");
assert_eq!(resp.data.wallet.blockchain, Blockchain::Eth);
assert_eq!(resp.data.wallet.state, Some(WalletState::Live));
Ok(())
}
#[test]
fn wallets_response_deserializes() -> Result<(), Box<dyn std::error::Error>> {
let json = r#"{
"data": {
"wallets": [
{
"id": "w1",
"address": "0xabc",
"blockchain": "MATIC",
"createDate": "2024-01-01T00:00:00Z",
"updateDate": "2024-01-01T00:00:00Z",
"custodyType": "DEVELOPER"
}
]
}
}"#;
let resp: Wallets = serde_json::from_str(json)?;
assert_eq!(resp.data.wallets.len(), 1);
assert_eq!(resp.data.wallets[0].blockchain, Blockchain::Matic);
Ok(())
}
#[test]
fn nfts_response_deserializes() -> Result<(), Box<dyn std::error::Error>> {
let json = r#"{
"data": {
"nfts": [
{
"amount": "1",
"token": {
"blockchain": "BASE",
"isNative": false
},
"updateDate": "2024-01-01T00:00:00Z",
"nftTokenId": "42"
}
]
}
}"#;
let resp: Nfts = serde_json::from_str(json)?;
assert_eq!(resp.data.nfts.len(), 1);
assert_eq!(resp.data.nfts[0].nft_token_id.as_deref(), Some("42"));
Ok(())
}
#[test]
fn sca_core_serializes() -> Result<(), Box<dyn std::error::Error>> {
let json = serde_json::to_string(&ScaCore::Circle4337V1)?;
assert_eq!(json, "\"circle_4337_v1\"");
let back: ScaCore = serde_json::from_str(&json)?;
assert_eq!(back, ScaCore::Circle4337V1);
Ok(())
}
#[test]
fn create_wallets_request_serializes() -> Result<(), Box<dyn std::error::Error>> {
let req = CreateWalletsRequest {
idempotency_key: "key".to_string(),
entity_secret_ciphertext: "cipher".to_string(),
wallet_set_id: "set-id".to_string(),
blockchains: vec![Blockchain::Eth],
account_type: None,
count: Some(2),
metadata: None,
};
let json = serde_json::to_string(&req)?;
assert!(json.contains("walletSetId"));
assert!(json.contains("\"ETH\""));
Ok(())
}
}