bybit_rust_api/rest/broker/
broker_client.rs

1use crate::rest::client::{RestClient, SecType, ServerResponse};
2use anyhow::Result;
3use serde_json::json;
4
5pub struct BrokerClient {
6    client: RestClient,
7}
8
9impl BrokerClient {
10    pub fn new(client: RestClient) -> Self {
11        BrokerClient { client }
12    }
13
14    /// Get broker account info
15    /// https://bybit-exchange.github.io/docs/v5/broker/account-info
16    pub async fn get_account_info(&self) -> Result<ServerResponse<serde_json::Value>> {
17        let endpoint = "v5/broker/account-info";
18        let response = self
19            .client
20            .get(endpoint, json!({}), SecType::Signed)
21            .await?;
22        Ok(response)
23    }
24
25    /// Get sub account deposit records
26    /// https://bybit-exchange.github.io/docs/v5/broker/sub-deposit-record
27    pub async fn get_sub_member_deposit_record(
28        &self,
29        sub_member_id: Option<&str>,
30        coin: Option<&str>,
31        start_time: Option<i64>,
32        end_time: Option<i64>,
33        limit: Option<i32>,
34        cursor: Option<&str>,
35    ) -> Result<ServerResponse<serde_json::Value>> {
36        let endpoint = "v5/broker/asset/query-sub-member-deposit-record";
37        let mut params = json!({});
38
39        if let Some(sub_member_id) = sub_member_id {
40            params["subMemberId"] = json!(sub_member_id);
41        }
42        if let Some(coin) = coin {
43            params["coin"] = json!(coin);
44        }
45        if let Some(start_time) = start_time {
46            params["startTime"] = json!(start_time);
47        }
48        if let Some(end_time) = end_time {
49            params["endTime"] = json!(end_time);
50        }
51        if let Some(limit) = limit {
52            params["limit"] = json!(limit);
53        }
54        if let Some(cursor) = cursor {
55            params["cursor"] = json!(cursor);
56        }
57
58        let response = self.client.get(endpoint, params, SecType::Signed).await?;
59        Ok(response)
60    }
61
62    /// Get broker earning
63    /// https://bybit-exchange.github.io/docs/v5/broker/earning
64    pub async fn get_earning_record(
65        &self,
66        biz_type: Option<&str>,
67        begin: Option<&str>,
68        end: Option<&str>,
69        uid: Option<&str>,
70        limit: Option<i32>,
71        cursor: Option<&str>,
72    ) -> Result<ServerResponse<serde_json::Value>> {
73        let endpoint = "v5/broker/earning-record";
74        let mut params = json!({});
75
76        if let Some(biz_type) = biz_type {
77            params["bizType"] = json!(biz_type);
78        }
79        if let Some(begin) = begin {
80            params["begin"] = json!(begin);
81        }
82        if let Some(end) = end {
83            params["end"] = json!(end);
84        }
85        if let Some(uid) = uid {
86            params["uid"] = json!(uid);
87        }
88        if let Some(limit) = limit {
89            params["limit"] = json!(limit);
90        }
91        if let Some(cursor) = cursor {
92            params["cursor"] = json!(cursor);
93        }
94
95        let response = self.client.get(endpoint, params, SecType::Signed).await?;
96        Ok(response)
97    }
98
99    /// Get award info
100    /// https://bybit-exchange.github.io/docs/v5/broker/award-info
101    pub async fn get_award_info(
102        &self,
103        coin: Option<&str>,
104        record_type: Option<&str>,
105        page: Option<i32>,
106        limit: Option<i32>,
107        start_date: Option<&str>,
108        end_date: Option<&str>,
109    ) -> Result<ServerResponse<serde_json::Value>> {
110        let endpoint = "v5/broker/award/info";
111        let mut params = json!({});
112
113        if let Some(coin) = coin {
114            params["coin"] = json!(coin);
115        }
116        if let Some(record_type) = record_type {
117            params["recordType"] = json!(record_type);
118        }
119        if let Some(page) = page {
120            params["page"] = json!(page);
121        }
122        if let Some(limit) = limit {
123            params["limit"] = json!(limit);
124        }
125        if let Some(start_date) = start_date {
126            params["startDate"] = json!(start_date);
127        }
128        if let Some(end_date) = end_date {
129            params["endDate"] = json!(end_date);
130        }
131
132        let response = self.client.get(endpoint, params, SecType::Signed).await?;
133        Ok(response)
134    }
135
136    /// Distribute award
137    /// https://bybit-exchange.github.io/docs/v5/broker/distribute-award
138    pub async fn distribute_award(
139        &self,
140        coin: &str,
141        amount: &str,
142        to_uid: &str,
143        record_type: &str,
144        from_memo: Option<&str>,
145        to_memo: Option<&str>,
146    ) -> Result<ServerResponse<serde_json::Value>> {
147        let endpoint = "v5/broker/award/distribute-award";
148        let mut body = json!({
149            "coin": coin,
150            "amount": amount,
151            "toUid": to_uid,
152            "recordType": record_type,
153        });
154
155        if let Some(from_memo) = from_memo {
156            body["fromMemo"] = json!(from_memo);
157        }
158        if let Some(to_memo) = to_memo {
159            body["toMemo"] = json!(to_memo);
160        }
161
162        let response = self.client.post(endpoint, body, SecType::Signed).await?;
163        Ok(response)
164    }
165
166    /// Get distribution record
167    /// https://bybit-exchange.github.io/docs/v5/broker/distribution-record
168    pub async fn get_distribution_record(
169        &self,
170        coin: Option<&str>,
171        page: Option<i32>,
172        limit: Option<i32>,
173        start_date: Option<&str>,
174        end_date: Option<&str>,
175    ) -> Result<ServerResponse<serde_json::Value>> {
176        let endpoint = "v5/broker/award/distribution-record";
177        let mut params = json!({});
178
179        if let Some(coin) = coin {
180            params["coin"] = json!(coin);
181        }
182        if let Some(page) = page {
183            params["page"] = json!(page);
184        }
185        if let Some(limit) = limit {
186            params["limit"] = json!(limit);
187        }
188        if let Some(start_date) = start_date {
189            params["startDate"] = json!(start_date);
190        }
191        if let Some(end_date) = end_date {
192            params["endDate"] = json!(end_date);
193        }
194
195        let response = self.client.get(endpoint, params, SecType::Signed).await?;
196        Ok(response)
197    }
198}
199
200#[cfg(test)]
201mod tests {
202    use super::*;
203    use crate::rest::ApiKeyPair;
204
205    fn create_test_client() -> BrokerClient {
206        let api_key_pair = ApiKeyPair::new(
207            "test_key".to_string(),
208            "test_secret".to_string(),
209            "".to_string(),
210        );
211        let rest_client =
212            RestClient::new(api_key_pair, "https://api-testnet.bybit.com".to_string());
213        BrokerClient::new(rest_client)
214    }
215
216    #[test]
217    fn test_client_creation() {
218        let client = create_test_client();
219        // Test that client was created successfully
220        assert_eq!(
221            std::mem::size_of_val(&client),
222            std::mem::size_of::<BrokerClient>()
223        );
224    }
225
226    #[tokio::test]
227    async fn test_distribute_award_required_params() {
228        let client = create_test_client();
229        let result = client
230            .distribute_award("USDT", "100.0", "12345", "reward", None, None)
231            .await;
232        // Should not panic with valid required parameters
233        assert!(result.is_err() || result.is_ok());
234    }
235
236    #[tokio::test]
237    async fn test_get_sub_member_deposit_record_params() {
238        let client = create_test_client();
239        let result = client
240            .get_sub_member_deposit_record(Some("sub123"), Some("USDT"), None, None, Some(10), None)
241            .await;
242        // Should handle optional parameters correctly
243        assert!(result.is_err() || result.is_ok());
244    }
245
246    #[tokio::test]
247    async fn test_get_earning_record_params() {
248        let client = create_test_client();
249        let result = client
250            .get_earning_record(
251                Some("trading"),
252                Some("2023-01-01"),
253                Some("2023-12-31"),
254                None,
255                Some(50),
256                None,
257            )
258            .await;
259        // Should handle optional parameters correctly
260        assert!(result.is_err() || result.is_ok());
261    }
262}