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