namecheap_client/
users.rs1use serde::Deserialize;
4
5use crate::client::Client;
6use crate::error::Result;
7
8#[derive(Debug, Clone, Copy)]
11pub struct Users<'a> {
12 client: &'a Client,
13}
14
15impl<'a> Users<'a> {
16 pub(crate) fn new(client: &'a Client) -> Self {
17 Self { client }
18 }
19
20 pub async fn get_balances(&self) -> Result<Balances> {
37 let payload: BalancesPayload = self
38 .client
39 .send("namecheap.users.getBalances", Vec::new())
40 .await?;
41 Ok(payload.result)
42 }
43}
44
45#[derive(Debug, Deserialize)]
46struct BalancesPayload {
47 #[serde(rename = "UserGetBalancesResult")]
48 result: Balances,
49}
50
51#[derive(Debug, Clone, Deserialize)]
57#[non_exhaustive]
58pub struct Balances {
59 #[serde(rename = "@Currency")]
61 pub currency: String,
62 #[serde(rename = "@AvailableBalance")]
64 pub available_balance: f64,
65 #[serde(rename = "@AccountBalance")]
67 pub account_balance: f64,
68 #[serde(rename = "@EarnedAmount")]
70 pub earned_amount: f64,
71 #[serde(rename = "@WithdrawableAmount")]
73 pub withdrawable_amount: f64,
74 #[serde(rename = "@FundsRequiredForAutoRenew")]
76 pub funds_required_for_auto_renew: f64,
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use reqwest::StatusCode;
83
84 #[test]
85 fn parses_balances_response() {
86 let body = r#"<?xml version="1.0" encoding="utf-8"?>
87 <ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
88 <Errors />
89 <CommandResponse Type="namecheap.users.getBalances">
90 <UserGetBalancesResult Currency="USD" AvailableBalance="4932.96" AccountBalance="4932.96" EarnedAmount="381.30" WithdrawableAmount="1500.00" FundsRequiredForAutoRenew="0.00" />
91 </CommandResponse>
92 </ApiResponse>"#;
93
94 let payload: BalancesPayload = crate::response::parse(StatusCode::OK, body).unwrap();
95 let balances = payload.result;
96 assert_eq!(balances.currency, "USD");
97 assert_eq!(balances.available_balance, 4932.96);
98 assert_eq!(balances.earned_amount, 381.30);
99 assert_eq!(balances.funds_required_for_auto_renew, 0.0);
100 }
101}