1use crate::rest::client::{RestClient, SecType, ServerResponse};
2use anyhow::Result;
3use serde_json::json;
4
5pub struct AssetClient {
6 client: RestClient,
7}
8
9impl AssetClient {
10 pub fn new(client: RestClient) -> Self {
11 AssetClient { client }
12 }
13
14 pub async fn get_exchange_order_record(
19 &self,
20 from_coin: Option<&str>,
21 to_coin: Option<&str>,
22 limit: Option<i32>,
23 cursor: Option<&str>,
24 ) -> Result<ServerResponse<serde_json::Value>> {
25 let endpoint = "v5/asset/exchange/order-record";
26 let mut params = json!({});
27
28 if let Some(from_coin) = from_coin {
29 params["fromCoin"] = json!(from_coin);
30 }
31 if let Some(to_coin) = to_coin {
32 params["toCoin"] = json!(to_coin);
33 }
34 if let Some(limit) = limit {
35 params["limit"] = json!(limit);
36 }
37 if let Some(cursor) = cursor {
38 params["cursor"] = json!(cursor);
39 }
40
41 let response = self.client.get(endpoint, params, SecType::Signed).await?;
42 Ok(response)
43 }
44
45 pub async fn get_delivery_record(
50 &self,
51 category: &str,
52 symbol: Option<&str>,
53 exp_date: Option<&str>,
54 limit: Option<i32>,
55 cursor: Option<&str>,
56 ) -> Result<ServerResponse<serde_json::Value>> {
57 let endpoint = "v5/asset/delivery-record";
58 let mut params = json!({
59 "category": category,
60 });
61
62 if let Some(symbol) = symbol {
63 params["symbol"] = json!(symbol);
64 }
65 if let Some(exp_date) = exp_date {
66 params["expDate"] = json!(exp_date);
67 }
68 if let Some(limit) = limit {
69 params["limit"] = json!(limit);
70 }
71 if let Some(cursor) = cursor {
72 params["cursor"] = json!(cursor);
73 }
74
75 let response = self.client.get(endpoint, params, SecType::Signed).await?;
76 Ok(response)
77 }
78
79 pub async fn get_settlement_record(
84 &self,
85 category: &str,
86 symbol: Option<&str>,
87 limit: Option<i32>,
88 cursor: Option<&str>,
89 ) -> Result<ServerResponse<serde_json::Value>> {
90 let endpoint = "v5/asset/settlement-record";
91 let mut params = json!({
92 "category": category,
93 });
94
95 if let Some(symbol) = symbol {
96 params["symbol"] = json!(symbol);
97 }
98 if let Some(limit) = limit {
99 params["limit"] = json!(limit);
100 }
101 if let Some(cursor) = cursor {
102 params["cursor"] = json!(cursor);
103 }
104
105 let response = self.client.get(endpoint, params, SecType::Signed).await?;
106 Ok(response)
107 }
108
109 pub async fn get_coin_info(
114 &self,
115 coin: Option<&str>,
116 ) -> Result<ServerResponse<serde_json::Value>> {
117 let endpoint = "v5/asset/coin/query-info";
118 let mut params = json!({});
119
120 if let Some(coin) = coin {
121 params["coin"] = json!(coin);
122 }
123
124 let response = self.client.get(endpoint, params, SecType::Signed).await?;
125 Ok(response)
126 }
127
128 pub async fn get_asset_info(
133 &self,
134 account_type: &str,
135 coin: Option<&str>,
136 ) -> Result<ServerResponse<serde_json::Value>> {
137 let endpoint = "v5/asset/transfer/query-asset-info";
138 let mut params = json!({
139 "accountType": account_type,
140 });
141
142 if let Some(coin) = coin {
143 params["coin"] = json!(coin);
144 }
145
146 let response = self.client.get(endpoint, params, SecType::Signed).await?;
147 Ok(response)
148 }
149
150 pub async fn get_sub_member_list(&self) -> Result<ServerResponse<serde_json::Value>> {
155 let endpoint = "v5/asset/transfer/query-sub-member-list";
156 let response = self
157 .client
158 .get(endpoint, json!({}), SecType::Signed)
159 .await?;
160 Ok(response)
161 }
162
163 pub async fn get_deposit_records(
168 &self,
169 coin: Option<&str>,
170 start_time: Option<i64>,
171 end_time: Option<i64>,
172 limit: Option<i32>,
173 cursor: Option<&str>,
174 ) -> Result<ServerResponse<serde_json::Value>> {
175 let endpoint = "v5/asset/deposit/query-record";
176 let mut params = json!({});
177
178 if let Some(coin) = coin {
179 params["coin"] = json!(coin);
180 }
181 if let Some(start_time) = start_time {
182 params["startTime"] = json!(start_time);
183 }
184 if let Some(end_time) = end_time {
185 params["endTime"] = json!(end_time);
186 }
187 if let Some(limit) = limit {
188 params["limit"] = json!(limit);
189 }
190 if let Some(cursor) = cursor {
191 params["cursor"] = json!(cursor);
192 }
193
194 let response = self.client.get(endpoint, params, SecType::Signed).await?;
195 Ok(response)
196 }
197
198 pub async fn get_sub_deposit_records(
203 &self,
204 sub_member_id: &str,
205 coin: Option<&str>,
206 start_time: Option<i64>,
207 end_time: Option<i64>,
208 limit: Option<i32>,
209 cursor: Option<&str>,
210 ) -> Result<ServerResponse<serde_json::Value>> {
211 let endpoint = "v5/asset/deposit/query-sub-member-record";
212 let mut params = json!({
213 "subMemberId": sub_member_id,
214 });
215
216 if let Some(coin) = coin {
217 params["coin"] = json!(coin);
218 }
219 if let Some(start_time) = start_time {
220 params["startTime"] = json!(start_time);
221 }
222 if let Some(end_time) = end_time {
223 params["endTime"] = json!(end_time);
224 }
225 if let Some(limit) = limit {
226 params["limit"] = json!(limit);
227 }
228 if let Some(cursor) = cursor {
229 params["cursor"] = json!(cursor);
230 }
231
232 let response = self.client.get(endpoint, params, SecType::Signed).await?;
233 Ok(response)
234 }
235
236 pub async fn get_internal_deposit_records(
241 &self,
242 start_time: Option<i64>,
243 end_time: Option<i64>,
244 coin: Option<&str>,
245 cursor: Option<&str>,
246 limit: Option<i32>,
247 ) -> Result<ServerResponse<serde_json::Value>> {
248 let endpoint = "v5/asset/deposit/query-internal-record";
249 let mut params = json!({});
250
251 if let Some(start_time) = start_time {
252 params["startTime"] = json!(start_time);
253 }
254 if let Some(end_time) = end_time {
255 params["endTime"] = json!(end_time);
256 }
257 if let Some(coin) = coin {
258 params["coin"] = json!(coin);
259 }
260 if let Some(cursor) = cursor {
261 params["cursor"] = json!(cursor);
262 }
263 if let Some(limit) = limit {
264 params["limit"] = json!(limit);
265 }
266
267 let response = self.client.get(endpoint, params, SecType::Signed).await?;
268 Ok(response)
269 }
270
271 pub async fn get_master_deposit_address(
276 &self,
277 coin: &str,
278 chain_type: Option<&str>,
279 ) -> Result<ServerResponse<serde_json::Value>> {
280 let endpoint = "v5/asset/deposit/query-address";
281 let mut params = json!({
282 "coin": coin,
283 });
284
285 if let Some(chain_type) = chain_type {
286 params["chainType"] = json!(chain_type);
287 }
288
289 let response = self.client.get(endpoint, params, SecType::Signed).await?;
290 Ok(response)
291 }
292
293 pub async fn get_sub_deposit_address(
298 &self,
299 coin: &str,
300 chain_type: &str,
301 sub_member_id: &str,
302 ) -> Result<ServerResponse<serde_json::Value>> {
303 let endpoint = "v5/asset/deposit/query-sub-member-address";
304 let params = json!({
305 "coin": coin,
306 "chainType": chain_type,
307 "subMemberId": sub_member_id,
308 });
309
310 let response = self.client.get(endpoint, params, SecType::Signed).await?;
311 Ok(response)
312 }
313
314 pub async fn get_allowed_deposit_list(
319 &self,
320 coin: Option<&str>,
321 chain: Option<&str>,
322 limit: Option<i32>,
323 cursor: Option<&str>,
324 ) -> Result<ServerResponse<serde_json::Value>> {
325 let endpoint = "v5/asset/deposit/query-allowed-list";
326 let mut params = json!({});
327
328 if let Some(coin) = coin {
329 params["coin"] = json!(coin);
330 }
331 if let Some(chain) = chain {
332 params["chain"] = json!(chain);
333 }
334 if let Some(limit) = limit {
335 params["limit"] = json!(limit);
336 }
337 if let Some(cursor) = cursor {
338 params["cursor"] = json!(cursor);
339 }
340
341 let response = self.client.get(endpoint, params, SecType::Signed).await?;
342 Ok(response)
343 }
344
345 pub async fn get_withdrawal_records(
350 &self,
351 withdraw_id: Option<&str>,
352 coin: Option<&str>,
353 withdraw_type: Option<i32>,
354 start_time: Option<i64>,
355 end_time: Option<i64>,
356 limit: Option<i32>,
357 cursor: Option<&str>,
358 ) -> Result<ServerResponse<serde_json::Value>> {
359 let endpoint = "v5/asset/withdraw/query-record";
360 let mut params = json!({});
361
362 if let Some(withdraw_id) = withdraw_id {
363 params["withdrawID"] = json!(withdraw_id);
364 }
365 if let Some(coin) = coin {
366 params["coin"] = json!(coin);
367 }
368 if let Some(withdraw_type) = withdraw_type {
369 params["withdrawType"] = json!(withdraw_type);
370 }
371 if let Some(start_time) = start_time {
372 params["startTime"] = json!(start_time);
373 }
374 if let Some(end_time) = end_time {
375 params["endTime"] = json!(end_time);
376 }
377 if let Some(limit) = limit {
378 params["limit"] = json!(limit);
379 }
380 if let Some(cursor) = cursor {
381 params["cursor"] = json!(cursor);
382 }
383
384 let response = self.client.get(endpoint, params, SecType::Signed).await?;
385 Ok(response)
386 }
387
388 pub async fn get_withdrawable_amount(
393 &self,
394 coin: &str,
395 ) -> Result<ServerResponse<serde_json::Value>> {
396 let endpoint = "v5/asset/withdraw/withdrawable-amount";
397 let params = json!({
398 "coin": coin,
399 });
400
401 let response = self.client.get(endpoint, params, SecType::Signed).await?;
402 Ok(response)
403 }
404
405 pub async fn withdraw(
410 &self,
411 coin: &str,
412 chain: &str,
413 address: &str,
414 tag: Option<&str>,
415 amount: &str,
416 timestamp: i64,
417 for_ce_chain: Option<i32>,
418 account_type: Option<&str>,
419 ) -> Result<ServerResponse<serde_json::Value>> {
420 let endpoint = "v5/asset/withdraw/create";
421 let mut body = json!({
422 "coin": coin,
423 "chain": chain,
424 "address": address,
425 "amount": amount,
426 "timestamp": timestamp,
427 });
428
429 if let Some(tag) = tag {
430 body["tag"] = json!(tag);
431 }
432 if let Some(for_ce_chain) = for_ce_chain {
433 body["forceChain"] = json!(for_ce_chain);
434 }
435 if let Some(account_type) = account_type {
436 body["accountType"] = json!(account_type);
437 }
438
439 let response = self.client.post(endpoint, body, SecType::Signed).await?;
440 Ok(response)
441 }
442
443 pub async fn cancel_withdrawal(&self, id: &str) -> Result<ServerResponse<serde_json::Value>> {
448 let endpoint = "v5/asset/withdraw/cancel";
449 let body = json!({
450 "id": id,
451 });
452
453 let response = self.client.post(endpoint, body, SecType::Signed).await?;
454 Ok(response)
455 }
456
457 pub async fn create_internal_transfer(
462 &self,
463 transfer_id: &str,
464 coin: &str,
465 amount: &str,
466 from_account_type: &str,
467 to_account_type: &str,
468 ) -> Result<ServerResponse<serde_json::Value>> {
469 let endpoint = "v5/asset/transfer/inter-transfer";
470 let body = json!({
471 "transferId": transfer_id,
472 "coin": coin,
473 "amount": amount,
474 "fromAccountType": from_account_type,
475 "toAccountType": to_account_type,
476 });
477
478 let response = self.client.post(endpoint, body, SecType::Signed).await?;
479 Ok(response)
480 }
481
482 pub async fn get_internal_transfer_records(
487 &self,
488 transfer_id: Option<&str>,
489 coin: Option<&str>,
490 status: Option<&str>,
491 start_time: Option<i64>,
492 end_time: Option<i64>,
493 limit: Option<i32>,
494 cursor: Option<&str>,
495 ) -> Result<ServerResponse<serde_json::Value>> {
496 let endpoint = "v5/asset/transfer/query-inter-transfer-list";
497 let mut params = json!({});
498
499 if let Some(transfer_id) = transfer_id {
500 params["transferId"] = json!(transfer_id);
501 }
502 if let Some(coin) = coin {
503 params["coin"] = json!(coin);
504 }
505 if let Some(status) = status {
506 params["status"] = json!(status);
507 }
508 if let Some(start_time) = start_time {
509 params["startTime"] = json!(start_time);
510 }
511 if let Some(end_time) = end_time {
512 params["endTime"] = json!(end_time);
513 }
514 if let Some(limit) = limit {
515 params["limit"] = json!(limit);
516 }
517 if let Some(cursor) = cursor {
518 params["cursor"] = json!(cursor);
519 }
520
521 let response = self.client.get(endpoint, params, SecType::Signed).await?;
522 Ok(response)
523 }
524
525 pub async fn create_universal_transfer(
530 &self,
531 transfer_id: &str,
532 coin: &str,
533 amount: &str,
534 from_member_id: &str,
535 to_member_id: &str,
536 from_account_type: &str,
537 to_account_type: &str,
538 ) -> Result<ServerResponse<serde_json::Value>> {
539 let endpoint = "v5/asset/transfer/universal-transfer";
540 let body = json!({
541 "transferId": transfer_id,
542 "coin": coin,
543 "amount": amount,
544 "fromMemberId": from_member_id,
545 "toMemberId": to_member_id,
546 "fromAccountType": from_account_type,
547 "toAccountType": to_account_type,
548 });
549
550 let response = self.client.post(endpoint, body, SecType::Signed).await?;
551 Ok(response)
552 }
553
554 pub async fn get_universal_transfer_records(
559 &self,
560 transfer_id: Option<&str>,
561 coin: Option<&str>,
562 status: Option<&str>,
563 start_time: Option<i64>,
564 end_time: Option<i64>,
565 limit: Option<i32>,
566 cursor: Option<&str>,
567 ) -> Result<ServerResponse<serde_json::Value>> {
568 let endpoint = "v5/asset/transfer/query-universal-transfer-list";
569 let mut params = json!({});
570
571 if let Some(transfer_id) = transfer_id {
572 params["transferId"] = json!(transfer_id);
573 }
574 if let Some(coin) = coin {
575 params["coin"] = json!(coin);
576 }
577 if let Some(status) = status {
578 params["status"] = json!(status);
579 }
580 if let Some(start_time) = start_time {
581 params["startTime"] = json!(start_time);
582 }
583 if let Some(end_time) = end_time {
584 params["endTime"] = json!(end_time);
585 }
586 if let Some(limit) = limit {
587 params["limit"] = json!(limit);
588 }
589 if let Some(cursor) = cursor {
590 params["cursor"] = json!(cursor);
591 }
592
593 let response = self.client.get(endpoint, params, SecType::Signed).await?;
594 Ok(response)
595 }
596
597 pub async fn get_allowed_transfer_coin_list(
602 &self,
603 from_account_type: &str,
604 to_account_type: &str,
605 ) -> Result<ServerResponse<serde_json::Value>> {
606 let endpoint = "v5/asset/transfer/query-transfer-coin-list";
607 let params = json!({
608 "fromAccountType": from_account_type,
609 "toAccountType": to_account_type,
610 });
611
612 let response = self.client.get(endpoint, params, SecType::Signed).await?;
613 Ok(response)
614 }
615
616 pub async fn request_convert_quote(
621 &self,
622 from_coin: &str,
623 to_coin: &str,
624 from_coin_type: Option<&str>,
625 to_coin_type: Option<&str>,
626 request_coin: &str,
627 request_amount: &str,
628 account_type: &str,
629 request_id: Option<&str>,
630 ) -> Result<ServerResponse<serde_json::Value>> {
631 let endpoint = "v5/asset/exchange/quote-apply";
632 let mut body = json!({
633 "fromCoin": from_coin,
634 "toCoin": to_coin,
635 "requestCoin": request_coin,
636 "requestAmount": request_amount,
637 "accountType": account_type,
638 });
639
640 if let Some(from_coin_type) = from_coin_type {
641 body["fromCoinType"] = json!(from_coin_type);
642 }
643 if let Some(to_coin_type) = to_coin_type {
644 body["toCoinType"] = json!(to_coin_type);
645 }
646 if let Some(request_id) = request_id {
647 body["requestId"] = json!(request_id);
648 }
649
650 let response = self.client.post(endpoint, body, SecType::Signed).await?;
651 Ok(response)
652 }
653
654 pub async fn confirm_convert_quote(
659 &self,
660 quote_tx_id: &str,
661 ) -> Result<ServerResponse<serde_json::Value>> {
662 let endpoint = "v5/asset/exchange/convert-execute";
663 let body = json!({
664 "quoteTxId": quote_tx_id,
665 });
666
667 let response = self.client.post(endpoint, body, SecType::Signed).await?;
668 Ok(response)
669 }
670
671 pub async fn get_convert_result(
676 &self,
677 quote_tx_id: Option<&str>,
678 account_type: Option<&str>,
679 ) -> Result<ServerResponse<serde_json::Value>> {
680 let endpoint = "v5/asset/exchange/convert-result-query";
681 let mut params = json!({});
682
683 if let Some(quote_tx_id) = quote_tx_id {
684 params["quoteTxId"] = json!(quote_tx_id);
685 }
686 if let Some(account_type) = account_type {
687 params["accountType"] = json!(account_type);
688 }
689
690 let response = self.client.get(endpoint, params, SecType::Signed).await?;
691 Ok(response)
692 }
693
694 pub async fn get_convert_history(
699 &self,
700 account_type: Option<&str>,
701 index: Option<i32>,
702 limit: Option<i32>,
703 ) -> Result<ServerResponse<serde_json::Value>> {
704 let endpoint = "v5/asset/exchange/query-convert-history";
705 let mut params = json!({});
706
707 if let Some(account_type) = account_type {
708 params["accountType"] = json!(account_type);
709 }
710 if let Some(index) = index {
711 params["index"] = json!(index);
712 }
713 if let Some(limit) = limit {
714 params["limit"] = json!(limit);
715 }
716
717 let response = self.client.get(endpoint, params, SecType::Signed).await?;
718 Ok(response)
719 }
720
721 pub async fn get_convert_coin_list(
726 &self,
727 coin: Option<&str>,
728 side: Option<i32>,
729 account_type: &str,
730 ) -> Result<ServerResponse<serde_json::Value>> {
731 let endpoint = "v5/asset/exchange/query-coin-list";
732 let mut params = json!({
733 "accountType": account_type,
734 });
735
736 if let Some(coin) = coin {
737 params["coin"] = json!(coin);
738 }
739 if let Some(side) = side {
740 params["side"] = json!(side);
741 }
742
743 let response = self.client.get(endpoint, params, SecType::Signed).await?;
744 Ok(response)
745 }
746
747 pub async fn get_coin_greeks(
752 &self,
753 base_coin: Option<&str>,
754 ) -> Result<ServerResponse<serde_json::Value>> {
755 let endpoint = "v5/asset/coin-greeks";
756 let mut params = json!({});
757
758 if let Some(base_coin) = base_coin {
759 params["baseCoin"] = json!(base_coin);
760 }
761
762 let response = self.client.get(endpoint, params, SecType::Signed).await?;
763 Ok(response)
764 }
765
766 pub async fn query_account_coin_balance(
771 &self,
772 member_id: Option<&str>,
773 to_member_id: Option<&str>,
774 account_type: &str,
775 to_account_type: Option<&str>,
776 coin: &str,
777 with_bonus: Option<i32>,
778 with_transfer_safe_amount: Option<i32>,
779 with_ltv_transfer_safe_amount: Option<i32>,
780 ) -> Result<ServerResponse<serde_json::Value>> {
781 let endpoint = "v5/asset/transfer/query-account-coin-balance";
782 let mut params = json!({
783 "accountType": account_type,
784 "coin": coin,
785 });
786
787 if let Some(member_id) = member_id {
788 params["memberId"] = json!(member_id);
789 }
790 if let Some(to_member_id) = to_member_id {
791 params["toMemberId"] = json!(to_member_id);
792 }
793 if let Some(to_account_type) = to_account_type {
794 params["toAccountType"] = json!(to_account_type);
795 }
796 if let Some(with_bonus) = with_bonus {
797 params["withBonus"] = json!(with_bonus);
798 }
799 if let Some(with_transfer_safe_amount) = with_transfer_safe_amount {
800 params["withTransferSafeAmount"] = json!(with_transfer_safe_amount);
801 }
802 if let Some(with_ltv_transfer_safe_amount) = with_ltv_transfer_safe_amount {
803 params["withLtvTransferSafeAmount"] = json!(with_ltv_transfer_safe_amount);
804 }
805
806 let response = self.client.get(endpoint, params, SecType::Signed).await?;
807 Ok(response)
808 }
809
810 pub async fn query_account_coins_balance(
815 &self,
816 member_id: Option<&str>,
817 account_type: &str,
818 coin: Option<&str>,
819 with_bonus: Option<i32>,
820 ) -> Result<ServerResponse<serde_json::Value>> {
821 let endpoint = "v5/asset/transfer/query-account-coins-balance";
822 let mut params = json!({
823 "accountType": account_type,
824 });
825
826 if let Some(member_id) = member_id {
827 params["memberId"] = json!(member_id);
828 }
829 if let Some(coin) = coin {
830 params["coin"] = json!(coin);
831 }
832 if let Some(with_bonus) = with_bonus {
833 params["withBonus"] = json!(with_bonus);
834 }
835
836 let response = self.client.get(endpoint, params, SecType::Signed).await?;
837 Ok(response)
838 }
839
840 pub async fn save_transfer_sub_member(
845 &self,
846 coin: Vec<String>,
847 member_ids: Vec<String>,
848 ) -> Result<ServerResponse<serde_json::Value>> {
849 let endpoint = "v5/asset/transfer/save-transfer-sub-member";
850 let body = json!({
851 "coin": coin,
852 "memberIds": member_ids,
853 });
854
855 let response = self.client.post(endpoint, body, SecType::Signed).await?;
856 Ok(response)
857 }
858}
859
860#[cfg(test)]
861mod tests {
862 use super::*;
863 use crate::rest::ApiKeyPair;
864
865 fn create_test_client() -> AssetClient {
866 let api_key_pair = ApiKeyPair::new(
867 "test".to_string(),
868 "test_key".to_string(),
869 "test_secret".to_string(),
870 );
871 let rest_client = RestClient::new(
872 api_key_pair,
873 "https://api-testnet.bybit.com".to_string(),
874 false,
875 );
876 AssetClient::new(rest_client)
877 }
878
879 #[test]
880 fn test_asset_client_creation() {
881 let _client = create_test_client();
882 }
883
884 #[tokio::test]
885 async fn test_exchange_order_record_params() {
886 let from_coin = Some("BTC");
887 let to_coin = Some("USDT");
888 let limit = Some(50);
889 let cursor: Option<&str> = None;
890
891 assert_eq!(from_coin, Some("BTC"));
892 assert_eq!(to_coin, Some("USDT"));
893 assert_eq!(limit, Some(50));
894 assert!(cursor.is_none());
895 }
896
897 #[tokio::test]
898 async fn test_withdrawal_params() {
899 let coin = "BTC";
900 let chain = "BTC";
901 let address = "bc1qtest123456789";
902 let tag: Option<&str> = None;
903 let amount = "0.001";
904 let timestamp = 1234567890i64;
905 let for_ce_chain: Option<i32> = None;
906 let account_type = Some("UNIFIED");
907
908 assert_eq!(coin, "BTC");
909 assert_eq!(chain, "BTC");
910 assert_eq!(address, "bc1qtest123456789");
911 assert!(tag.is_none());
912 assert_eq!(amount, "0.001");
913 assert_eq!(timestamp, 1234567890);
914 assert!(for_ce_chain.is_none());
915 assert_eq!(account_type, Some("UNIFIED"));
916 }
917
918 #[tokio::test]
919 async fn test_internal_transfer_params() {
920 let transfer_id = "transfer123";
921 let coin = "USDT";
922 let amount = "100";
923 let from_account_type = "UNIFIED";
924 let to_account_type = "CONTRACT";
925
926 assert_eq!(transfer_id, "transfer123");
927 assert_eq!(coin, "USDT");
928 assert_eq!(amount, "100");
929 assert_eq!(from_account_type, "UNIFIED");
930 assert_eq!(to_account_type, "CONTRACT");
931 }
932
933 #[tokio::test]
934 async fn test_universal_transfer_params() {
935 let transfer_id = "transfer456";
936 let coin = "BTC";
937 let amount = "0.5";
938 let from_member_id = "member1";
939 let to_member_id = "member2";
940 let from_account_type = "UNIFIED";
941 let to_account_type = "SPOT";
942
943 assert_eq!(transfer_id, "transfer456");
944 assert_eq!(coin, "BTC");
945 assert_eq!(amount, "0.5");
946 assert_eq!(from_member_id, "member1");
947 assert_eq!(to_member_id, "member2");
948 assert_eq!(from_account_type, "UNIFIED");
949 assert_eq!(to_account_type, "SPOT");
950 }
951
952 #[tokio::test]
953 async fn test_convert_quote_params() {
954 let from_coin = "BTC";
955 let to_coin = "USDT";
956 let from_coin_type: Option<&str> = None;
957 let to_coin_type: Option<&str> = None;
958 let request_coin = "BTC";
959 let request_amount = "0.1";
960 let account_type = "UNIFIED";
961 let request_id = Some("req123");
962
963 assert_eq!(from_coin, "BTC");
964 assert_eq!(to_coin, "USDT");
965 assert!(from_coin_type.is_none());
966 assert!(to_coin_type.is_none());
967 assert_eq!(request_coin, "BTC");
968 assert_eq!(request_amount, "0.1");
969 assert_eq!(account_type, "UNIFIED");
970 assert_eq!(request_id, Some("req123"));
971 }
972
973 #[tokio::test]
974 async fn test_deposit_records_params() {
975 let coin = Some("ETH");
976 let start_time = Some(1234567890i64);
977 let end_time = Some(1234567999i64);
978 let limit = Some(100);
979 let cursor: Option<&str> = None;
980
981 assert_eq!(coin, Some("ETH"));
982 assert_eq!(start_time, Some(1234567890));
983 assert_eq!(end_time, Some(1234567999));
984 assert_eq!(limit, Some(100));
985 assert!(cursor.is_none());
986 }
987
988 #[tokio::test]
989 async fn test_query_account_coin_balance_params() {
990 let member_id = Some("member123");
991 let to_member_id: Option<&str> = None;
992 let account_type = "UNIFIED";
993 let to_account_type: Option<&str> = None;
994 let coin = "USDT";
995 let with_bonus = Some(1);
996 let with_transfer_safe_amount = Some(1);
997 let with_ltv_transfer_safe_amount = Some(0);
998
999 assert_eq!(member_id, Some("member123"));
1000 assert!(to_member_id.is_none());
1001 assert_eq!(account_type, "UNIFIED");
1002 assert!(to_account_type.is_none());
1003 assert_eq!(coin, "USDT");
1004 assert_eq!(with_bonus, Some(1));
1005 assert_eq!(with_transfer_safe_amount, Some(1));
1006 assert_eq!(with_ltv_transfer_safe_amount, Some(0));
1007 }
1008
1009 #[tokio::test]
1010 async fn test_save_transfer_sub_member_params() {
1011 let coin = vec!["BTC".to_string(), "ETH".to_string()];
1012 let member_ids = vec!["member1".to_string(), "member2".to_string()];
1013
1014 assert_eq!(coin.len(), 2);
1015 assert_eq!(coin[0], "BTC");
1016 assert_eq!(coin[1], "ETH");
1017 assert_eq!(member_ids.len(), 2);
1018 assert_eq!(member_ids[0], "member1");
1019 assert_eq!(member_ids[1], "member2");
1020 }
1021}