Skip to main content

bybit_rust_api/ws/private/
wallet.rs

1//! Wallet stream — real-time wallet balance updates.
2//!
3//! # Topics
4//! - `wallet` (all categories)
5//! - `wallet.linear`, `wallet.inverse`, `wallet.spot`, `wallet.option`
6
7use serde::Deserialize;
8
9/// Coin balance within the wallet.
10#[derive(Debug, Clone, Deserialize)]
11pub struct CoinBalance {
12    /// Coin name (e.g. "USDT", "BTC")
13    #[serde(rename = "coin")]
14    #[serde(default)]
15    pub coin: Option<String>,
16    /// Equity (total value in this coin)
17    #[serde(rename = "equity")]
18    #[serde(default)]
19    pub equity: Option<String>,
20    /// Wallet balance
21    #[serde(rename = "walletBalance")]
22    #[serde(default)]
23    pub wallet_balance: Option<String>,
24    /// Position margin
25    #[serde(rename = "positionMargin")]
26    #[serde(default)]
27    pub position_margin: Option<String>,
28    /// Available balance
29    #[serde(rename = "availableToWithdraw")]
30    #[serde(default)]
31    pub available_to_withdraw: Option<String>,
32    /// Available to trade (order margin)
33    #[serde(rename = "availableToTrade")]
34    #[serde(default)]
35    pub available_to_trade: Option<String>,
36    /// Unrealised PnL
37    #[serde(rename = "unrealisedPnl")]
38    #[serde(default)]
39    pub unrealised_pnl: Option<String>,
40    /// Cumulative realised PnL
41    #[serde(rename = "cumRealisedPnl")]
42    #[serde(default)]
43    pub cum_realised_pnl: Option<String>,
44    /// Bonus
45    #[serde(rename = "bonus")]
46    #[serde(default)]
47    pub bonus: Option<String>,
48    /// Whether this is a borrow coin (margin)
49    #[serde(rename = "borrowAmount")]
50    #[serde(default)]
51    pub borrow_amount: Option<String>,
52}
53
54/// Wallet data from private WebSocket.
55#[derive(Debug, Clone, Deserialize)]
56pub struct WalletData {
57    /// Account type
58    #[serde(rename = "accountType")]
59    #[serde(default)]
60    pub account_type: Option<String>,
61    /// Account LTV (Loan-to-Value)
62    #[serde(rename = "accountLTV")]
63    #[serde(default)]
64    pub account_ltv: Option<String>,
65    /// Account IM rate
66    #[serde(rename = "accountIMRate")]
67    #[serde(default)]
68    pub account_im_rate: Option<String>,
69    /// Account MM rate
70    #[serde(rename = "accountMMRate")]
71    #[serde(default)]
72    pub account_mm_rate: Option<String>,
73    /// Total equity (USD value)
74    #[serde(rename = "totalEquity")]
75    #[serde(default)]
76    pub total_equity: Option<String>,
77    /// Total wallet balance
78    #[serde(rename = "totalWalletBalance")]
79    #[serde(default)]
80    pub total_wallet_balance: Option<String>,
81    /// Total margin balance
82    #[serde(rename = "totalMarginBalance")]
83    #[serde(default)]
84    pub total_margin_balance: Option<String>,
85    /// Total available balance
86    #[serde(rename = "totalAvailableBalance")]
87    #[serde(default)]
88    pub total_available_balance: Option<String>,
89    /// Total perpetual PnL (Unified account)
90    #[serde(rename = "totalPerpUPL")]
91    #[serde(default)]
92    pub total_perp_upl: Option<String>,
93    /// Total initial margin
94    #[serde(rename = "totalInitialMargin")]
95    #[serde(default)]
96    pub total_initial_margin: Option<String>,
97    /// Total maintenance margin
98    #[serde(rename = "totalMaintenanceMargin")]
99    #[serde(default)]
100    pub total_maintenance_margin: Option<String>,
101    /// Coin balances per asset
102    #[serde(rename = "coin")]
103    #[serde(default)]
104    pub coins: Vec<CoinBalance>,
105    /// Timestamp
106    #[serde(rename = "time")]
107    #[serde(default)]
108    pub time: Option<String>,
109    /// Category
110    #[serde(rename = "category")]
111    #[serde(default)]
112    pub category: Option<String>,
113}
114
115#[cfg(test)]
116mod tests {
117    use super::*;
118
119    #[test]
120    fn test_parse_wallet() {
121        let json = serde_json::json!({
122            "accountType": "UNIFIED",
123            "totalEquity": "10000.00",
124            "totalWalletBalance": "10000.00",
125            "coin": [
126                {
127                    "coin": "USDT",
128                    "equity": "10000.00",
129                    "walletBalance": "10000.00",
130                    "availableToWithdraw": "8000.00",
131                    "availableToTrade": "9000.00"
132                }
133            ],
134            "category": "linear"
135        });
136
137        let wallet: WalletData = serde_json::from_value(json).unwrap();
138        assert_eq!(wallet.account_type.as_deref(), Some("UNIFIED"));
139        assert_eq!(wallet.coins.len(), 1);
140        assert_eq!(wallet.coins[0].coin.as_deref(), Some("USDT"));
141    }
142}