1#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24 config::ConfigurationRestApi,
25 models::{ParamBuildError, RestApiResponse},
26 utils::send_request,
27};
28use crate::vip_loan::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait UserInformationApi: Send + Sync {
34 async fn check_vip_loan_collateral_account(
35 &self,
36 params: CheckVipLoanCollateralAccountParams,
37 ) -> anyhow::Result<RestApiResponse<models::CheckVipLoanCollateralAccountResponse>>;
38 async fn get_vip_loan_accrued_interest(
39 &self,
40 params: GetVipLoanAccruedInterestParams,
41 ) -> anyhow::Result<RestApiResponse<models::GetVipLoanAccruedInterestResponse>>;
42 async fn get_vip_loan_ongoing_orders(
43 &self,
44 params: GetVipLoanOngoingOrdersParams,
45 ) -> anyhow::Result<RestApiResponse<models::GetVipLoanOngoingOrdersResponse>>;
46 async fn query_application_status(
47 &self,
48 params: QueryApplicationStatusParams,
49 ) -> anyhow::Result<RestApiResponse<models::QueryApplicationStatusResponse>>;
50}
51
52#[derive(Debug, Clone)]
53pub struct UserInformationApiClient {
54 configuration: ConfigurationRestApi,
55}
56
57impl UserInformationApiClient {
58 pub fn new(configuration: ConfigurationRestApi) -> Self {
59 Self { configuration }
60 }
61}
62
63#[derive(Clone, Debug, Builder, Default)]
68#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
69pub struct CheckVipLoanCollateralAccountParams {
70 #[builder(setter(into), default)]
75 pub order_id: Option<i64>,
76 #[builder(setter(into), default)]
81 pub collateral_account_id: Option<i64>,
82 #[builder(setter(into), default)]
87 pub recv_window: Option<i64>,
88}
89
90impl CheckVipLoanCollateralAccountParams {
91 #[must_use]
94 pub fn builder() -> CheckVipLoanCollateralAccountParamsBuilder {
95 CheckVipLoanCollateralAccountParamsBuilder::default()
96 }
97}
98#[derive(Clone, Debug, Builder, Default)]
103#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
104pub struct GetVipLoanAccruedInterestParams {
105 #[builder(setter(into), default)]
110 pub order_id: Option<i64>,
111 #[builder(setter(into), default)]
116 pub loan_coin: Option<String>,
117 #[builder(setter(into), default)]
122 pub start_time: Option<i64>,
123 #[builder(setter(into), default)]
128 pub end_time: Option<i64>,
129 #[builder(setter(into), default)]
133 pub current: Option<i64>,
134 #[builder(setter(into), default)]
138 pub limit: Option<i64>,
139 #[builder(setter(into), default)]
144 pub recv_window: Option<i64>,
145}
146
147impl GetVipLoanAccruedInterestParams {
148 #[must_use]
151 pub fn builder() -> GetVipLoanAccruedInterestParamsBuilder {
152 GetVipLoanAccruedInterestParamsBuilder::default()
153 }
154}
155#[derive(Clone, Debug, Builder, Default)]
160#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
161pub struct GetVipLoanOngoingOrdersParams {
162 #[builder(setter(into), default)]
167 pub order_id: Option<i64>,
168 #[builder(setter(into), default)]
173 pub collateral_account_id: Option<i64>,
174 #[builder(setter(into), default)]
179 pub loan_coin: Option<String>,
180 #[builder(setter(into), default)]
185 pub collateral_coin: Option<String>,
186 #[builder(setter(into), default)]
190 pub current: Option<i64>,
191 #[builder(setter(into), default)]
195 pub limit: Option<i64>,
196 #[builder(setter(into), default)]
201 pub recv_window: Option<i64>,
202}
203
204impl GetVipLoanOngoingOrdersParams {
205 #[must_use]
208 pub fn builder() -> GetVipLoanOngoingOrdersParamsBuilder {
209 GetVipLoanOngoingOrdersParamsBuilder::default()
210 }
211}
212#[derive(Clone, Debug, Builder, Default)]
217#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
218pub struct QueryApplicationStatusParams {
219 #[builder(setter(into), default)]
223 pub current: Option<i64>,
224 #[builder(setter(into), default)]
228 pub limit: Option<i64>,
229 #[builder(setter(into), default)]
234 pub recv_window: Option<i64>,
235}
236
237impl QueryApplicationStatusParams {
238 #[must_use]
241 pub fn builder() -> QueryApplicationStatusParamsBuilder {
242 QueryApplicationStatusParamsBuilder::default()
243 }
244}
245
246#[async_trait]
247impl UserInformationApi for UserInformationApiClient {
248 async fn check_vip_loan_collateral_account(
249 &self,
250 params: CheckVipLoanCollateralAccountParams,
251 ) -> anyhow::Result<RestApiResponse<models::CheckVipLoanCollateralAccountResponse>> {
252 let CheckVipLoanCollateralAccountParams {
253 order_id,
254 collateral_account_id,
255 recv_window,
256 } = params;
257
258 let mut query_params = BTreeMap::new();
259 let body_params = BTreeMap::new();
260
261 if let Some(rw) = order_id {
262 query_params.insert("orderId".to_string(), json!(rw));
263 }
264
265 if let Some(rw) = collateral_account_id {
266 query_params.insert("collateralAccountId".to_string(), json!(rw));
267 }
268
269 if let Some(rw) = recv_window {
270 query_params.insert("recvWindow".to_string(), json!(rw));
271 }
272
273 send_request::<models::CheckVipLoanCollateralAccountResponse>(
274 &self.configuration,
275 "/sapi/v1/loan/vip/collateral/account",
276 reqwest::Method::GET,
277 query_params,
278 body_params,
279 if HAS_TIME_UNIT {
280 self.configuration.time_unit
281 } else {
282 None
283 },
284 true,
285 )
286 .await
287 }
288
289 async fn get_vip_loan_accrued_interest(
290 &self,
291 params: GetVipLoanAccruedInterestParams,
292 ) -> anyhow::Result<RestApiResponse<models::GetVipLoanAccruedInterestResponse>> {
293 let GetVipLoanAccruedInterestParams {
294 order_id,
295 loan_coin,
296 start_time,
297 end_time,
298 current,
299 limit,
300 recv_window,
301 } = params;
302
303 let mut query_params = BTreeMap::new();
304 let body_params = BTreeMap::new();
305
306 if let Some(rw) = order_id {
307 query_params.insert("orderId".to_string(), json!(rw));
308 }
309
310 if let Some(rw) = loan_coin {
311 query_params.insert("loanCoin".to_string(), json!(rw));
312 }
313
314 if let Some(rw) = start_time {
315 query_params.insert("startTime".to_string(), json!(rw));
316 }
317
318 if let Some(rw) = end_time {
319 query_params.insert("endTime".to_string(), json!(rw));
320 }
321
322 if let Some(rw) = current {
323 query_params.insert("current".to_string(), json!(rw));
324 }
325
326 if let Some(rw) = limit {
327 query_params.insert("limit".to_string(), json!(rw));
328 }
329
330 if let Some(rw) = recv_window {
331 query_params.insert("recvWindow".to_string(), json!(rw));
332 }
333
334 send_request::<models::GetVipLoanAccruedInterestResponse>(
335 &self.configuration,
336 "/sapi/v1/loan/vip/accruedInterest",
337 reqwest::Method::GET,
338 query_params,
339 body_params,
340 if HAS_TIME_UNIT {
341 self.configuration.time_unit
342 } else {
343 None
344 },
345 true,
346 )
347 .await
348 }
349
350 async fn get_vip_loan_ongoing_orders(
351 &self,
352 params: GetVipLoanOngoingOrdersParams,
353 ) -> anyhow::Result<RestApiResponse<models::GetVipLoanOngoingOrdersResponse>> {
354 let GetVipLoanOngoingOrdersParams {
355 order_id,
356 collateral_account_id,
357 loan_coin,
358 collateral_coin,
359 current,
360 limit,
361 recv_window,
362 } = params;
363
364 let mut query_params = BTreeMap::new();
365 let body_params = BTreeMap::new();
366
367 if let Some(rw) = order_id {
368 query_params.insert("orderId".to_string(), json!(rw));
369 }
370
371 if let Some(rw) = collateral_account_id {
372 query_params.insert("collateralAccountId".to_string(), json!(rw));
373 }
374
375 if let Some(rw) = loan_coin {
376 query_params.insert("loanCoin".to_string(), json!(rw));
377 }
378
379 if let Some(rw) = collateral_coin {
380 query_params.insert("collateralCoin".to_string(), json!(rw));
381 }
382
383 if let Some(rw) = current {
384 query_params.insert("current".to_string(), json!(rw));
385 }
386
387 if let Some(rw) = limit {
388 query_params.insert("limit".to_string(), json!(rw));
389 }
390
391 if let Some(rw) = recv_window {
392 query_params.insert("recvWindow".to_string(), json!(rw));
393 }
394
395 send_request::<models::GetVipLoanOngoingOrdersResponse>(
396 &self.configuration,
397 "/sapi/v1/loan/vip/ongoing/orders",
398 reqwest::Method::GET,
399 query_params,
400 body_params,
401 if HAS_TIME_UNIT {
402 self.configuration.time_unit
403 } else {
404 None
405 },
406 true,
407 )
408 .await
409 }
410
411 async fn query_application_status(
412 &self,
413 params: QueryApplicationStatusParams,
414 ) -> anyhow::Result<RestApiResponse<models::QueryApplicationStatusResponse>> {
415 let QueryApplicationStatusParams {
416 current,
417 limit,
418 recv_window,
419 } = params;
420
421 let mut query_params = BTreeMap::new();
422 let body_params = BTreeMap::new();
423
424 if let Some(rw) = current {
425 query_params.insert("current".to_string(), json!(rw));
426 }
427
428 if let Some(rw) = limit {
429 query_params.insert("limit".to_string(), json!(rw));
430 }
431
432 if let Some(rw) = recv_window {
433 query_params.insert("recvWindow".to_string(), json!(rw));
434 }
435
436 send_request::<models::QueryApplicationStatusResponse>(
437 &self.configuration,
438 "/sapi/v1/loan/vip/request/data",
439 reqwest::Method::GET,
440 query_params,
441 body_params,
442 if HAS_TIME_UNIT {
443 self.configuration.time_unit
444 } else {
445 None
446 },
447 true,
448 )
449 .await
450 }
451}
452
453#[cfg(all(test, feature = "vip_loan"))]
454mod tests {
455 use super::*;
456 use crate::TOKIO_SHARED_RT;
457 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
458 use async_trait::async_trait;
459 use std::collections::HashMap;
460
461 struct DummyRestApiResponse<T> {
462 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
463 status: u16,
464 headers: HashMap<String, String>,
465 rate_limits: Option<Vec<RestApiRateLimit>>,
466 }
467
468 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
469 fn from(dummy: DummyRestApiResponse<T>) -> Self {
470 Self {
471 data_fn: dummy.inner,
472 status: dummy.status,
473 headers: dummy.headers,
474 rate_limits: dummy.rate_limits,
475 }
476 }
477 }
478
479 struct MockUserInformationApiClient {
480 force_error: bool,
481 }
482
483 #[async_trait]
484 impl UserInformationApi for MockUserInformationApiClient {
485 async fn check_vip_loan_collateral_account(
486 &self,
487 _params: CheckVipLoanCollateralAccountParams,
488 ) -> anyhow::Result<RestApiResponse<models::CheckVipLoanCollateralAccountResponse>>
489 {
490 if self.force_error {
491 return Err(ConnectorError::ConnectorClientError {
492 msg: "ResponseError".to_string(),
493 code: None,
494 }
495 .into());
496 }
497
498 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"collateralAccountId":"12345678","collateralCoin":"BNB,BTC,ETH"},{"collateralAccountId":"23456789","collateralCoin":"BNB,BTC,ETH"}],"total":2}"#).unwrap();
499 let dummy_response: models::CheckVipLoanCollateralAccountResponse =
500 serde_json::from_value(resp_json.clone())
501 .expect("should parse into models::CheckVipLoanCollateralAccountResponse");
502
503 let dummy = DummyRestApiResponse {
504 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
505 status: 200,
506 headers: HashMap::new(),
507 rate_limits: None,
508 };
509
510 Ok(dummy.into())
511 }
512
513 async fn get_vip_loan_accrued_interest(
514 &self,
515 _params: GetVipLoanAccruedInterestParams,
516 ) -> anyhow::Result<RestApiResponse<models::GetVipLoanAccruedInterestResponse>> {
517 if self.force_error {
518 return Err(ConnectorError::ConnectorClientError {
519 msg: "ResponseError".to_string(),
520 code: None,
521 }
522 .into());
523 }
524
525 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"USDT","principalAmount":"10000","interestAmount":"1.2","annualInterestRate":"0.001273","accrualTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap();
526 let dummy_response: models::GetVipLoanAccruedInterestResponse =
527 serde_json::from_value(resp_json.clone())
528 .expect("should parse into models::GetVipLoanAccruedInterestResponse");
529
530 let dummy = DummyRestApiResponse {
531 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
532 status: 200,
533 headers: HashMap::new(),
534 rate_limits: None,
535 };
536
537 Ok(dummy.into())
538 }
539
540 async fn get_vip_loan_ongoing_orders(
541 &self,
542 _params: GetVipLoanOngoingOrdersParams,
543 ) -> anyhow::Result<RestApiResponse<models::GetVipLoanOngoingOrdersResponse>> {
544 if self.force_error {
545 return Err(ConnectorError::ConnectorClientError {
546 msg: "ResponseError".to_string(),
547 code: None,
548 }
549 .into());
550 }
551
552 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"orderId":100000001,"loanCoin":"BUSD","totalDebt":"10000","loanRate":"0.0123","residualInterest":"10.27687923","collateralAccountId":"12345678,23456789","collateralCoin":"BNB,BTC,ETH","totalCollateralValueAfterHaircut":"25000.27565492","lockedCollateralValue":"25000.27565492","currentLTV":"0.57","expirationTime":1575018510000,"loanDate":"1676851200000","loanTerm":"30days"}],"total":1}"#).unwrap();
553 let dummy_response: models::GetVipLoanOngoingOrdersResponse =
554 serde_json::from_value(resp_json.clone())
555 .expect("should parse into models::GetVipLoanOngoingOrdersResponse");
556
557 let dummy = DummyRestApiResponse {
558 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
559 status: 200,
560 headers: HashMap::new(),
561 rate_limits: None,
562 };
563
564 Ok(dummy.into())
565 }
566
567 async fn query_application_status(
568 &self,
569 _params: QueryApplicationStatusParams,
570 ) -> anyhow::Result<RestApiResponse<models::QueryApplicationStatusResponse>> {
571 if self.force_error {
572 return Err(ConnectorError::ConnectorClientError {
573 msg: "ResponseError".to_string(),
574 code: None,
575 }
576 .into());
577 }
578
579 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanAccountId":"12345678","orderId":"12345678","requestId":"12345678","loanCoin":"BTC","loanAmount":"100.55","collateralAccountId":"12345678,12345678,12345678","collateralCoin":"BUSD,USDT,ETH","loanTerm":"30","status":"Repaid","loanDate":"1676851200000"}],"total":1}"#).unwrap();
580 let dummy_response: models::QueryApplicationStatusResponse =
581 serde_json::from_value(resp_json.clone())
582 .expect("should parse into models::QueryApplicationStatusResponse");
583
584 let dummy = DummyRestApiResponse {
585 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
586 status: 200,
587 headers: HashMap::new(),
588 rate_limits: None,
589 };
590
591 Ok(dummy.into())
592 }
593 }
594
595 #[test]
596 fn check_vip_loan_collateral_account_required_params_success() {
597 TOKIO_SHARED_RT.block_on(async {
598 let client = MockUserInformationApiClient { force_error: false };
599
600 let params = CheckVipLoanCollateralAccountParams::builder().build().unwrap();
601
602 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"collateralAccountId":"12345678","collateralCoin":"BNB,BTC,ETH"},{"collateralAccountId":"23456789","collateralCoin":"BNB,BTC,ETH"}],"total":2}"#).unwrap();
603 let expected_response : models::CheckVipLoanCollateralAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::CheckVipLoanCollateralAccountResponse");
604
605 let resp = client.check_vip_loan_collateral_account(params).await.expect("Expected a response");
606 let data_future = resp.data();
607 let actual_response = data_future.await.unwrap();
608 assert_eq!(actual_response, expected_response);
609 });
610 }
611
612 #[test]
613 fn check_vip_loan_collateral_account_optional_params_success() {
614 TOKIO_SHARED_RT.block_on(async {
615 let client = MockUserInformationApiClient { force_error: false };
616
617 let params = CheckVipLoanCollateralAccountParams::builder().order_id(1).collateral_account_id(1).recv_window(5000).build().unwrap();
618
619 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"collateralAccountId":"12345678","collateralCoin":"BNB,BTC,ETH"},{"collateralAccountId":"23456789","collateralCoin":"BNB,BTC,ETH"}],"total":2}"#).unwrap();
620 let expected_response : models::CheckVipLoanCollateralAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::CheckVipLoanCollateralAccountResponse");
621
622 let resp = client.check_vip_loan_collateral_account(params).await.expect("Expected a response");
623 let data_future = resp.data();
624 let actual_response = data_future.await.unwrap();
625 assert_eq!(actual_response, expected_response);
626 });
627 }
628
629 #[test]
630 fn check_vip_loan_collateral_account_response_error() {
631 TOKIO_SHARED_RT.block_on(async {
632 let client = MockUserInformationApiClient { force_error: true };
633
634 let params = CheckVipLoanCollateralAccountParams::builder()
635 .build()
636 .unwrap();
637
638 match client.check_vip_loan_collateral_account(params).await {
639 Ok(_) => panic!("Expected an error"),
640 Err(err) => {
641 assert_eq!(err.to_string(), "Connector client error: ResponseError");
642 }
643 }
644 });
645 }
646
647 #[test]
648 fn get_vip_loan_accrued_interest_required_params_success() {
649 TOKIO_SHARED_RT.block_on(async {
650 let client = MockUserInformationApiClient { force_error: false };
651
652 let params = GetVipLoanAccruedInterestParams::builder().build().unwrap();
653
654 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"USDT","principalAmount":"10000","interestAmount":"1.2","annualInterestRate":"0.001273","accrualTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap();
655 let expected_response : models::GetVipLoanAccruedInterestResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetVipLoanAccruedInterestResponse");
656
657 let resp = client.get_vip_loan_accrued_interest(params).await.expect("Expected a response");
658 let data_future = resp.data();
659 let actual_response = data_future.await.unwrap();
660 assert_eq!(actual_response, expected_response);
661 });
662 }
663
664 #[test]
665 fn get_vip_loan_accrued_interest_optional_params_success() {
666 TOKIO_SHARED_RT.block_on(async {
667 let client = MockUserInformationApiClient { force_error: false };
668
669 let params = GetVipLoanAccruedInterestParams::builder().order_id(1).loan_coin("loan_coin_example".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).limit(10).recv_window(5000).build().unwrap();
670
671 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"USDT","principalAmount":"10000","interestAmount":"1.2","annualInterestRate":"0.001273","accrualTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap();
672 let expected_response : models::GetVipLoanAccruedInterestResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetVipLoanAccruedInterestResponse");
673
674 let resp = client.get_vip_loan_accrued_interest(params).await.expect("Expected a response");
675 let data_future = resp.data();
676 let actual_response = data_future.await.unwrap();
677 assert_eq!(actual_response, expected_response);
678 });
679 }
680
681 #[test]
682 fn get_vip_loan_accrued_interest_response_error() {
683 TOKIO_SHARED_RT.block_on(async {
684 let client = MockUserInformationApiClient { force_error: true };
685
686 let params = GetVipLoanAccruedInterestParams::builder().build().unwrap();
687
688 match client.get_vip_loan_accrued_interest(params).await {
689 Ok(_) => panic!("Expected an error"),
690 Err(err) => {
691 assert_eq!(err.to_string(), "Connector client error: ResponseError");
692 }
693 }
694 });
695 }
696
697 #[test]
698 fn get_vip_loan_ongoing_orders_required_params_success() {
699 TOKIO_SHARED_RT.block_on(async {
700 let client = MockUserInformationApiClient { force_error: false };
701
702 let params = GetVipLoanOngoingOrdersParams::builder().build().unwrap();
703
704 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"orderId":100000001,"loanCoin":"BUSD","totalDebt":"10000","loanRate":"0.0123","residualInterest":"10.27687923","collateralAccountId":"12345678,23456789","collateralCoin":"BNB,BTC,ETH","totalCollateralValueAfterHaircut":"25000.27565492","lockedCollateralValue":"25000.27565492","currentLTV":"0.57","expirationTime":1575018510000,"loanDate":"1676851200000","loanTerm":"30days"}],"total":1}"#).unwrap();
705 let expected_response : models::GetVipLoanOngoingOrdersResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetVipLoanOngoingOrdersResponse");
706
707 let resp = client.get_vip_loan_ongoing_orders(params).await.expect("Expected a response");
708 let data_future = resp.data();
709 let actual_response = data_future.await.unwrap();
710 assert_eq!(actual_response, expected_response);
711 });
712 }
713
714 #[test]
715 fn get_vip_loan_ongoing_orders_optional_params_success() {
716 TOKIO_SHARED_RT.block_on(async {
717 let client = MockUserInformationApiClient { force_error: false };
718
719 let params = GetVipLoanOngoingOrdersParams::builder().order_id(1).collateral_account_id(1).loan_coin("loan_coin_example".to_string()).collateral_coin("collateral_coin_example".to_string()).current(1).limit(10).recv_window(5000).build().unwrap();
720
721 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"orderId":100000001,"loanCoin":"BUSD","totalDebt":"10000","loanRate":"0.0123","residualInterest":"10.27687923","collateralAccountId":"12345678,23456789","collateralCoin":"BNB,BTC,ETH","totalCollateralValueAfterHaircut":"25000.27565492","lockedCollateralValue":"25000.27565492","currentLTV":"0.57","expirationTime":1575018510000,"loanDate":"1676851200000","loanTerm":"30days"}],"total":1}"#).unwrap();
722 let expected_response : models::GetVipLoanOngoingOrdersResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetVipLoanOngoingOrdersResponse");
723
724 let resp = client.get_vip_loan_ongoing_orders(params).await.expect("Expected a response");
725 let data_future = resp.data();
726 let actual_response = data_future.await.unwrap();
727 assert_eq!(actual_response, expected_response);
728 });
729 }
730
731 #[test]
732 fn get_vip_loan_ongoing_orders_response_error() {
733 TOKIO_SHARED_RT.block_on(async {
734 let client = MockUserInformationApiClient { force_error: true };
735
736 let params = GetVipLoanOngoingOrdersParams::builder().build().unwrap();
737
738 match client.get_vip_loan_ongoing_orders(params).await {
739 Ok(_) => panic!("Expected an error"),
740 Err(err) => {
741 assert_eq!(err.to_string(), "Connector client error: ResponseError");
742 }
743 }
744 });
745 }
746
747 #[test]
748 fn query_application_status_required_params_success() {
749 TOKIO_SHARED_RT.block_on(async {
750 let client = MockUserInformationApiClient { force_error: false };
751
752 let params = QueryApplicationStatusParams::builder().build().unwrap();
753
754 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanAccountId":"12345678","orderId":"12345678","requestId":"12345678","loanCoin":"BTC","loanAmount":"100.55","collateralAccountId":"12345678,12345678,12345678","collateralCoin":"BUSD,USDT,ETH","loanTerm":"30","status":"Repaid","loanDate":"1676851200000"}],"total":1}"#).unwrap();
755 let expected_response : models::QueryApplicationStatusResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryApplicationStatusResponse");
756
757 let resp = client.query_application_status(params).await.expect("Expected a response");
758 let data_future = resp.data();
759 let actual_response = data_future.await.unwrap();
760 assert_eq!(actual_response, expected_response);
761 });
762 }
763
764 #[test]
765 fn query_application_status_optional_params_success() {
766 TOKIO_SHARED_RT.block_on(async {
767 let client = MockUserInformationApiClient { force_error: false };
768
769 let params = QueryApplicationStatusParams::builder().current(1).limit(10).recv_window(5000).build().unwrap();
770
771 let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanAccountId":"12345678","orderId":"12345678","requestId":"12345678","loanCoin":"BTC","loanAmount":"100.55","collateralAccountId":"12345678,12345678,12345678","collateralCoin":"BUSD,USDT,ETH","loanTerm":"30","status":"Repaid","loanDate":"1676851200000"}],"total":1}"#).unwrap();
772 let expected_response : models::QueryApplicationStatusResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryApplicationStatusResponse");
773
774 let resp = client.query_application_status(params).await.expect("Expected a response");
775 let data_future = resp.data();
776 let actual_response = data_future.await.unwrap();
777 assert_eq!(actual_response, expected_response);
778 });
779 }
780
781 #[test]
782 fn query_application_status_response_error() {
783 TOKIO_SHARED_RT.block_on(async {
784 let client = MockUserInformationApiClient { force_error: true };
785
786 let params = QueryApplicationStatusParams::builder().build().unwrap();
787
788 match client.query_application_status(params).await {
789 Ok(_) => panic!("Expected an error"),
790 Err(err) => {
791 assert_eq!(err.to_string(), "Connector client error: ResponseError");
792 }
793 }
794 });
795 }
796}