use pretty_simple_display::{DebugPretty, DisplaySimple};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[repr(u8)]
pub enum AddressBookType {
Transfer = 0,
Withdrawal = 1,
DepositSource = 2,
}
impl AddressBookType {
#[must_use]
#[inline]
pub fn as_str(&self) -> &'static str {
match self {
AddressBookType::Transfer => "transfer",
AddressBookType::Withdrawal => "withdrawal",
AddressBookType::DepositSource => "deposit_source",
}
}
}
impl std::fmt::Display for AddressBookType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[repr(u8)]
#[derive(Default)]
pub enum WithdrawalPriorityLevel {
VeryLow = 0,
Low = 1,
Mid = 2,
#[default]
High = 3,
VeryHigh = 4,
ExtremeHigh = 5,
Insane = 6,
}
impl WithdrawalPriorityLevel {
#[must_use]
#[inline]
pub fn as_str(&self) -> &'static str {
match self {
WithdrawalPriorityLevel::VeryLow => "very_low",
WithdrawalPriorityLevel::Low => "low",
WithdrawalPriorityLevel::Mid => "mid",
WithdrawalPriorityLevel::High => "high",
WithdrawalPriorityLevel::VeryHigh => "very_high",
WithdrawalPriorityLevel::ExtremeHigh => "extreme_high",
WithdrawalPriorityLevel::Insane => "insane",
}
}
}
impl std::fmt::Display for WithdrawalPriorityLevel {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[skip_serializing_none]
#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
pub struct DepositAddress {
pub address: String,
pub currency: String,
#[serde(rename = "type")]
pub address_type: Option<String>,
pub creation_timestamp: Option<u64>,
pub status: Option<String>,
}
impl DepositAddress {
#[must_use]
pub fn new(address: String, currency: String) -> Self {
Self {
address,
currency,
address_type: None,
creation_timestamp: None,
status: None,
}
}
}
#[skip_serializing_none]
#[derive(DebugPretty, DisplaySimple, Clone, Serialize, Deserialize)]
pub struct AddressBookEntry {
pub address: String,
pub currency: String,
#[serde(rename = "type")]
pub entry_type: Option<String>,
pub label: Option<String>,
pub creation_timestamp: Option<u64>,
pub update_timestamp: Option<u64>,
pub agreed: Option<bool>,
pub personal: Option<bool>,
pub unhosted: Option<bool>,
pub tag: Option<String>,
pub beneficiary_vasp_name: Option<String>,
pub beneficiary_vasp_did: Option<String>,
pub beneficiary_vasp_website: Option<String>,
pub beneficiary_first_name: Option<String>,
pub beneficiary_last_name: Option<String>,
pub beneficiary_company_name: Option<String>,
pub beneficiary_address: Option<String>,
}
impl AddressBookEntry {
#[must_use]
pub fn new(address: String, currency: String) -> Self {
Self {
address,
currency,
entry_type: None,
label: None,
creation_timestamp: None,
update_timestamp: None,
agreed: None,
personal: None,
unhosted: None,
tag: None,
beneficiary_vasp_name: None,
beneficiary_vasp_did: None,
beneficiary_vasp_website: None,
beneficiary_first_name: None,
beneficiary_last_name: None,
beneficiary_company_name: None,
beneficiary_address: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_address_book_type_as_str() {
assert_eq!(AddressBookType::Transfer.as_str(), "transfer");
assert_eq!(AddressBookType::Withdrawal.as_str(), "withdrawal");
assert_eq!(AddressBookType::DepositSource.as_str(), "deposit_source");
}
#[test]
fn test_address_book_type_display() {
assert_eq!(format!("{}", AddressBookType::Transfer), "transfer");
assert_eq!(format!("{}", AddressBookType::Withdrawal), "withdrawal");
}
#[test]
fn test_address_book_type_serialization() {
let json = serde_json::to_string(&AddressBookType::Withdrawal).unwrap();
assert_eq!(json, "\"withdrawal\"");
let deserialized: AddressBookType = serde_json::from_str("\"transfer\"").unwrap();
assert_eq!(deserialized, AddressBookType::Transfer);
}
#[test]
fn test_withdrawal_priority_level_as_str() {
assert_eq!(WithdrawalPriorityLevel::VeryLow.as_str(), "very_low");
assert_eq!(WithdrawalPriorityLevel::Low.as_str(), "low");
assert_eq!(WithdrawalPriorityLevel::Mid.as_str(), "mid");
assert_eq!(WithdrawalPriorityLevel::High.as_str(), "high");
assert_eq!(WithdrawalPriorityLevel::VeryHigh.as_str(), "very_high");
assert_eq!(
WithdrawalPriorityLevel::ExtremeHigh.as_str(),
"extreme_high"
);
assert_eq!(WithdrawalPriorityLevel::Insane.as_str(), "insane");
}
#[test]
fn test_withdrawal_priority_level_default() {
assert_eq!(
WithdrawalPriorityLevel::default(),
WithdrawalPriorityLevel::High
);
}
#[test]
fn test_withdrawal_priority_level_serialization() {
let json = serde_json::to_string(&WithdrawalPriorityLevel::Mid).unwrap();
assert_eq!(json, "\"mid\"");
let deserialized: WithdrawalPriorityLevel = serde_json::from_str("\"high\"").unwrap();
assert_eq!(deserialized, WithdrawalPriorityLevel::High);
}
#[test]
fn test_deposit_address_new() {
let addr = DepositAddress::new("bc1qtest123".to_string(), "BTC".to_string());
assert_eq!(addr.address, "bc1qtest123");
assert_eq!(addr.currency, "BTC");
assert!(addr.address_type.is_none());
}
#[test]
fn test_deposit_address_serialization() {
let addr = DepositAddress {
address: "0xtest123".to_string(),
currency: "ETH".to_string(),
address_type: Some("deposit".to_string()),
creation_timestamp: Some(1234567890000),
status: Some("active".to_string()),
};
let json = serde_json::to_string(&addr).unwrap();
assert!(json.contains("\"address\":\"0xtest123\""));
assert!(json.contains("\"currency\":\"ETH\""));
assert!(json.contains("\"type\":\"deposit\""));
}
#[test]
fn test_address_book_entry_new() {
let entry = AddressBookEntry::new("bc1qtest456".to_string(), "BTC".to_string());
assert_eq!(entry.address, "bc1qtest456");
assert_eq!(entry.currency, "BTC");
assert!(entry.label.is_none());
assert!(entry.agreed.is_none());
}
#[test]
fn test_address_book_entry_serialization() {
let entry = AddressBookEntry {
address: "bc1qtest789".to_string(),
currency: "BTC".to_string(),
entry_type: Some("withdrawal".to_string()),
label: Some("Main wallet".to_string()),
creation_timestamp: Some(1234567890000),
update_timestamp: None,
agreed: Some(true),
personal: Some(false),
unhosted: None,
tag: None,
beneficiary_vasp_name: Some("Test VASP".to_string()),
beneficiary_vasp_did: None,
beneficiary_vasp_website: None,
beneficiary_first_name: Some("John".to_string()),
beneficiary_last_name: Some("Doe".to_string()),
beneficiary_company_name: None,
beneficiary_address: Some("123 Main St".to_string()),
};
let json = serde_json::to_string(&entry).unwrap();
assert!(json.contains("\"address\":\"bc1qtest789\""));
assert!(json.contains("\"type\":\"withdrawal\""));
assert!(json.contains("\"label\":\"Main wallet\""));
assert!(json.contains("\"agreed\":true"));
}
#[test]
fn test_address_book_entry_deserialization() {
let json = r#"{
"address": "bc1qtest",
"currency": "BTC",
"type": "transfer",
"label": "Test",
"creation_timestamp": 1234567890000,
"agreed": true,
"personal": false,
"beneficiary_first_name": "Jane",
"beneficiary_last_name": "Smith"
}"#;
let entry: AddressBookEntry = serde_json::from_str(json).unwrap();
assert_eq!(entry.address, "bc1qtest");
assert_eq!(entry.currency, "BTC");
assert_eq!(entry.entry_type, Some("transfer".to_string()));
assert_eq!(entry.label, Some("Test".to_string()));
assert_eq!(entry.agreed, Some(true));
assert_eq!(entry.personal, Some(false));
assert_eq!(entry.beneficiary_first_name, Some("Jane".to_string()));
}
}