use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AddressBeneficiary {
pub currency: String,
pub address: String,
#[serde(default)]
pub user_id: Option<u64>,
pub agreed: bool,
pub personal: bool,
pub unhosted: bool,
#[serde(default)]
pub beneficiary_vasp_name: Option<String>,
#[serde(default)]
pub beneficiary_vasp_did: Option<String>,
#[serde(default)]
pub beneficiary_vasp_website: Option<String>,
#[serde(default)]
pub beneficiary_first_name: Option<String>,
#[serde(default)]
pub beneficiary_last_name: Option<String>,
#[serde(default)]
pub beneficiary_company_name: Option<String>,
#[serde(default)]
pub beneficiary_address: Option<String>,
#[serde(default)]
pub tag: Option<String>,
#[serde(default, alias = "created")]
pub creation_timestamp: Option<u64>,
#[serde(default, alias = "updated")]
pub update_timestamp: Option<u64>,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct SaveAddressBeneficiaryRequest {
pub currency: String,
pub address: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<String>,
pub agreed: bool,
pub personal: bool,
pub unhosted: bool,
pub beneficiary_vasp_name: String,
pub beneficiary_vasp_did: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_vasp_website: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_first_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_last_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_company_name: Option<String>,
pub beneficiary_address: String,
}
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct ListAddressBeneficiariesRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub currency: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_before: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_after: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_before: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_after: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub personal: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub unhosted: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_vasp_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_vasp_did: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub beneficiary_vasp_website: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub continuation: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ListAddressBeneficiariesResponse {
pub data: Vec<AddressBeneficiary>,
#[serde(default)]
pub count: Option<u64>,
#[serde(default)]
pub continuation: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct DepositId {
pub currency: String,
pub user_id: u64,
pub address: String,
pub tx_hash: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Originator {
pub is_personal: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub company_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub first_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub last_name: Option<String>,
pub address: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClearanceDepositResult {
pub currency: String,
#[serde(default)]
pub user_id: Option<u64>,
pub address: String,
pub amount: f64,
pub state: String,
#[serde(default)]
pub transaction_id: Option<String>,
#[serde(default)]
pub source_address: Option<String>,
#[serde(default)]
pub received_timestamp: Option<u64>,
#[serde(default)]
pub updated_timestamp: Option<u64>,
#[serde(default)]
pub note: Option<String>,
#[serde(default)]
pub clearance_state: Option<String>,
#[serde(default)]
pub refund_transaction_id: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_address_beneficiary_deserialize() {
let json = r#"{
"currency": "BTC",
"address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf0uyj",
"user_id": 1016,
"agreed": true,
"personal": false,
"unhosted": false,
"beneficiary_vasp_name": "Money's Gone",
"beneficiary_vasp_did": "did:example:123456789abcdefghi",
"beneficiary_vasp_website": "https://example.com",
"beneficiary_first_name": "John",
"beneficiary_last_name": "Doe",
"beneficiary_company_name": "Example Corp",
"beneficiary_address": "NL, Amsterdam, Street, 1",
"created": 1536569522277,
"updated": 1536569522277
}"#;
let beneficiary: AddressBeneficiary = serde_json::from_str(json).unwrap();
assert_eq!(beneficiary.currency, "BTC");
assert_eq!(
beneficiary.address,
"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf0uyj"
);
assert!(beneficiary.agreed);
assert!(!beneficiary.personal);
assert!(!beneficiary.unhosted);
assert_eq!(
beneficiary.beneficiary_vasp_name,
Some("Money's Gone".to_string())
);
assert_eq!(beneficiary.beneficiary_first_name, Some("John".to_string()));
assert_eq!(beneficiary.creation_timestamp, Some(1536569522277));
}
#[test]
fn test_save_request_serialize() {
let request = SaveAddressBeneficiaryRequest {
currency: "BTC".to_string(),
address: "bc1qtest".to_string(),
tag: None,
agreed: true,
personal: false,
unhosted: false,
beneficiary_vasp_name: "Test VASP".to_string(),
beneficiary_vasp_did: "did:test:123".to_string(),
beneficiary_vasp_website: Some("https://test.com".to_string()),
beneficiary_first_name: Some("John".to_string()),
beneficiary_last_name: Some("Doe".to_string()),
beneficiary_company_name: None,
beneficiary_address: "Test Address".to_string(),
};
let json = serde_json::to_string(&request).unwrap();
assert!(json.contains("\"currency\":\"BTC\""));
assert!(json.contains("\"agreed\":true"));
assert!(!json.contains("\"tag\"")); assert!(!json.contains("beneficiary_company_name")); }
#[test]
fn test_list_response_deserialize() {
let json = r#"{
"data": [
{
"currency": "BTC",
"address": "bc1qtest",
"agreed": true,
"personal": false,
"unhosted": false
}
],
"continuation": "xY7T6cutS3t2B9YtaDkE6TS379oKnkzTvmEDUnEUP2Msa9xKWNNaT",
"count": 1
}"#;
let response: ListAddressBeneficiariesResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.data.len(), 1);
assert_eq!(response.count, Some(1));
assert!(response.continuation.is_some());
}
#[test]
fn test_clearance_deposit_result_deserialize() {
let json = r#"{
"currency": "BTC",
"user_id": 123,
"address": "2NBqqD5GRJ8wHy1PYyCXTe9ke5226FhavBz",
"amount": 0.4,
"state": "completed",
"transaction_id": "230669110fdaf0a0dbcdc079b6b8b43d5af29cc73683835b9bc6b3406c065fda",
"source_address": "A3BqqD5GRJ8wHy1PYyCXTe9ke5226Fha123",
"received_timestamp": 1550574558607,
"updated_timestamp": 1550574558807,
"note": "Note",
"clearance_state": "in_progress"
}"#;
let result: ClearanceDepositResult = serde_json::from_str(json).unwrap();
assert_eq!(result.currency, "BTC");
assert_eq!(result.user_id, Some(123));
let amount_diff = (result.amount - 0.4).abs();
assert!(amount_diff < f64::EPSILON);
assert_eq!(result.state, "completed");
assert_eq!(result.clearance_state, Some("in_progress".to_string()));
}
#[test]
fn test_deposit_id_serialize() {
let deposit_id = DepositId {
currency: "BTC".to_string(),
user_id: 123,
address: "2NBqqD5GRJ8wHy1PYyCXTe9ke5226FhavBz".to_string(),
tx_hash: "230669110fdaf0a0dbcdc079b6b8b43d5af29cc73683835b9bc6b3406c065fda".to_string(),
};
let json = serde_json::to_string(&deposit_id).unwrap();
assert!(json.contains("\"currency\":\"BTC\""));
assert!(json.contains("\"user_id\":123"));
assert!(json.contains("\"tx_hash\":"));
}
#[test]
fn test_originator_serialize() {
let originator = Originator {
is_personal: false,
company_name: Some("Company Name".to_string()),
first_name: Some("First".to_string()),
last_name: Some("Last".to_string()),
address: "NL, Amsterdam, Street, 1".to_string(),
};
let json = serde_json::to_string(&originator).unwrap();
assert!(json.contains("\"is_personal\":false"));
assert!(json.contains("\"company_name\":\"Company Name\""));
assert!(json.contains("\"address\":\"NL, Amsterdam, Street, 1\""));
}
#[test]
fn test_list_request_default() {
let request = ListAddressBeneficiariesRequest::default();
assert!(request.currency.is_none());
assert!(request.limit.is_none());
assert!(request.continuation.is_none());
}
}