bybit_rust_api/rest/broker/
broker_client.rs

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