Skip to main content

alat/modules/
account.rs

1//! Account maintenance — wallet balance/details and transaction history.
2//!
3//! These endpoints belong to the **Wallet Services – Account Management** product
4//! (`/ws-acct-mgt`) and let you inspect wallets your channel manages: their
5//! current balance/status, and a list of past transactions over a date range.
6//!
7//! # Ecosystem concepts
8//! - **NUBAN**: the standard 10-digit Nigerian account number identifying a wallet.
9//! - **Available vs. ledger balance**: the API exposes a single
10//!   `availableBalance` here (the spendable amount). Note it is returned as a
11//!   **string**, not a number — see [`WalletAccountDetails::available_balance`].
12
13use crate::client::Client;
14use crate::envelope::ServiceResponse;
15use crate::error::Result;
16use serde::{Deserialize, Serialize};
17
18/// A wallet's identity, balance, and status.
19///
20/// This is the `result` object of `B2BGetAccountV2ReponseServiceResponse`.
21#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct WalletAccountDetails {
24    /// The 10-digit NUBAN of the wallet (the API names this `walletNumber`).
25    pub wallet_number: String,
26    /// The spendable balance. **Returned as a string by the API** (e.g.
27    /// `"1500.00"`); parse it yourself if you need arithmetic, to avoid the
28    /// rounding hazards of binary floating point on money.
29    pub available_balance: String,
30    /// The wallet's status (e.g. `"Active"`, `"Dormant"`, `"PND"`).
31    pub wallet_status: String,
32    /// The account/product type (e.g. `"Wallet"`).
33    pub account_type: String,
34}
35
36/// Request body for the transaction-history lookup.
37///
38/// Server type: `TransactionhistoryV2Request`. The window is expressed with
39/// `from`/`to` (the API does **not** offer page-number/page-size paging here).
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct TransactionHistoryRequest {
43    /// The 10-digit NUBAN whose history to fetch.
44    pub account_number: String,
45    /// Start of the date range. The API accepts a date/date-time string; use the
46    /// format your channel was onboarded with (commonly `YYYY-MM-DD`).
47    pub from: String,
48    /// End of the date range (same format as [`from`](Self::from)).
49    pub to: String,
50    /// Optional free-text filter applied to the transactions (narration, etc.).
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub key_word: Option<String>,
53}
54
55/// A single transaction row.
56///
57/// Shared by both the account-history (`transhistoryV2`) and statement
58/// (`GetCustomerTransactions`) endpoints; fields absent from one of them are
59/// modeled as `Option`. Several JSON keys carry the API's own spellings
60/// (`recieverName`, etc.) and are mapped to clean Rust names via `serde(rename)`.
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(rename_all = "camelCase")]
63pub struct Transaction {
64    /// Short title/label for the transaction.
65    pub title: Option<String>,
66    /// Transaction amount.
67    pub amount: f64,
68    /// Channel/route of the transaction (e.g. `"InterBank"`, `"IntraBank"`).
69    #[serde(rename = "type")]
70    pub transaction_type: Option<String>,
71    /// Display date string.
72    pub date: Option<String>,
73    /// Posting date/time (present on account history; absent on statements).
74    pub transaction_date: Option<String>,
75    /// Human-readable narration.
76    pub narration: Option<String>,
77    /// Transaction status (e.g. `"Default"`, `"Successful"`).
78    pub status: Option<String>,
79    /// Credit type classification (e.g. `"Default"`).
80    pub credit_type: Option<String>,
81    /// Sender's display name.
82    pub sender: Option<String>,
83    /// Sender's account number.
84    pub sender_account_number: Option<String>,
85    /// Destination bank name.
86    pub destination_bank: Option<String>,
87    /// Destination account number.
88    pub destination_account_number: Option<String>,
89    /// Receiver's display name (API key is the misspelled `recieverName`).
90    #[serde(rename = "recieverName")]
91    pub receiver_name: Option<String>,
92    /// Reference id for the transaction.
93    pub reference_id: Option<String>,
94    /// Whether a receipt can be viewed for this transaction.
95    pub is_view_receipt_enabled: Option<bool>,
96    /// Core-banking transaction id.
97    pub tran_id: Option<String>,
98}
99
100impl Client {
101    /// Fetches a wallet's balance, status, and type by NUBAN.
102    ///
103    /// `GET /ws-acct-mgt/api/AccountMaintenance/CustomerAccount/GetAccountV2/accountNumber/{accountNumber}`
104    pub async fn get_wallet_details(&self, account_number: &str) -> Result<WalletAccountDetails> {
105        let path = format!(
106            "ws-acct-mgt/api/AccountMaintenance/CustomerAccount/GetAccountV2/accountNumber/{}",
107            account_number
108        );
109        self.get_json::<ServiceResponse<WalletAccountDetails>>(&path, &[], &[])
110            .await?
111            .into_result()
112    }
113
114    /// Fetches a wallet's transaction history over a date range.
115    ///
116    /// `POST /ws-acct-mgt/api/AccountMaintenance/CustomerAccount/transhistoryV2`
117    pub async fn get_transaction_history(
118        &self,
119        request: &TransactionHistoryRequest,
120    ) -> Result<Vec<Transaction>> {
121        self.post_json::<_, ServiceResponse<Vec<Transaction>>>(
122            "ws-acct-mgt/api/AccountMaintenance/CustomerAccount/transhistoryV2",
123            request,
124            &[],
125        )
126        .await?
127        .into_result()
128    }
129}