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::nft::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait NftApi: Send + Sync {
34 async fn get_nft_asset(
35 &self,
36 params: GetNftAssetParams,
37 ) -> anyhow::Result<RestApiResponse<models::GetNftAssetResponse>>;
38 async fn get_nft_deposit_history(
39 &self,
40 params: GetNftDepositHistoryParams,
41 ) -> anyhow::Result<RestApiResponse<models::GetNftDepositHistoryResponse>>;
42 async fn get_nft_transaction_history(
43 &self,
44 params: GetNftTransactionHistoryParams,
45 ) -> anyhow::Result<RestApiResponse<models::GetNftTransactionHistoryResponse>>;
46 async fn get_nft_withdraw_history(
47 &self,
48 params: GetNftWithdrawHistoryParams,
49 ) -> anyhow::Result<RestApiResponse<models::GetNftWithdrawHistoryResponse>>;
50}
51
52#[derive(Debug, Clone)]
53pub struct NftApiClient {
54 configuration: ConfigurationRestApi,
55}
56
57impl NftApiClient {
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 GetNftAssetParams {
70 #[builder(setter(into), default)]
74 pub limit: Option<i64>,
75 #[builder(setter(into), default)]
79 pub page: Option<i64>,
80 #[builder(setter(into), default)]
85 pub recv_window: Option<i64>,
86}
87
88impl GetNftAssetParams {
89 #[must_use]
92 pub fn builder() -> GetNftAssetParamsBuilder {
93 GetNftAssetParamsBuilder::default()
94 }
95}
96#[derive(Clone, Debug, Builder, Default)]
101#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
102pub struct GetNftDepositHistoryParams {
103 #[builder(setter(into), default)]
108 pub start_time: Option<i64>,
109 #[builder(setter(into), default)]
114 pub end_time: Option<i64>,
115 #[builder(setter(into), default)]
119 pub limit: Option<i64>,
120 #[builder(setter(into), default)]
124 pub page: Option<i64>,
125 #[builder(setter(into), default)]
130 pub recv_window: Option<i64>,
131}
132
133impl GetNftDepositHistoryParams {
134 #[must_use]
137 pub fn builder() -> GetNftDepositHistoryParamsBuilder {
138 GetNftDepositHistoryParamsBuilder::default()
139 }
140}
141#[derive(Clone, Debug, Builder)]
146#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
147pub struct GetNftTransactionHistoryParams {
148 #[builder(setter(into))]
152 pub order_type: i64,
153 #[builder(setter(into), default)]
158 pub start_time: Option<i64>,
159 #[builder(setter(into), default)]
164 pub end_time: Option<i64>,
165 #[builder(setter(into), default)]
169 pub limit: Option<i64>,
170 #[builder(setter(into), default)]
174 pub page: Option<i64>,
175 #[builder(setter(into), default)]
180 pub recv_window: Option<i64>,
181}
182
183impl GetNftTransactionHistoryParams {
184 #[must_use]
191 pub fn builder(order_type: i64) -> GetNftTransactionHistoryParamsBuilder {
192 GetNftTransactionHistoryParamsBuilder::default().order_type(order_type)
193 }
194}
195#[derive(Clone, Debug, Builder, Default)]
200#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
201pub struct GetNftWithdrawHistoryParams {
202 #[builder(setter(into), default)]
207 pub start_time: Option<i64>,
208 #[builder(setter(into), default)]
213 pub end_time: Option<i64>,
214 #[builder(setter(into), default)]
218 pub limit: Option<i64>,
219 #[builder(setter(into), default)]
223 pub page: Option<i64>,
224 #[builder(setter(into), default)]
229 pub recv_window: Option<i64>,
230}
231
232impl GetNftWithdrawHistoryParams {
233 #[must_use]
236 pub fn builder() -> GetNftWithdrawHistoryParamsBuilder {
237 GetNftWithdrawHistoryParamsBuilder::default()
238 }
239}
240
241#[async_trait]
242impl NftApi for NftApiClient {
243 async fn get_nft_asset(
244 &self,
245 params: GetNftAssetParams,
246 ) -> anyhow::Result<RestApiResponse<models::GetNftAssetResponse>> {
247 let GetNftAssetParams {
248 limit,
249 page,
250 recv_window,
251 } = params;
252
253 let mut query_params = BTreeMap::new();
254 let body_params = BTreeMap::new();
255
256 if let Some(rw) = limit {
257 query_params.insert("limit".to_string(), json!(rw));
258 }
259
260 if let Some(rw) = page {
261 query_params.insert("page".to_string(), json!(rw));
262 }
263
264 if let Some(rw) = recv_window {
265 query_params.insert("recvWindow".to_string(), json!(rw));
266 }
267
268 send_request::<models::GetNftAssetResponse>(
269 &self.configuration,
270 "/sapi/v1/nft/user/getAsset",
271 reqwest::Method::GET,
272 query_params,
273 body_params,
274 if HAS_TIME_UNIT {
275 self.configuration.time_unit
276 } else {
277 None
278 },
279 true,
280 )
281 .await
282 }
283
284 async fn get_nft_deposit_history(
285 &self,
286 params: GetNftDepositHistoryParams,
287 ) -> anyhow::Result<RestApiResponse<models::GetNftDepositHistoryResponse>> {
288 let GetNftDepositHistoryParams {
289 start_time,
290 end_time,
291 limit,
292 page,
293 recv_window,
294 } = params;
295
296 let mut query_params = BTreeMap::new();
297 let body_params = BTreeMap::new();
298
299 if let Some(rw) = start_time {
300 query_params.insert("startTime".to_string(), json!(rw));
301 }
302
303 if let Some(rw) = end_time {
304 query_params.insert("endTime".to_string(), json!(rw));
305 }
306
307 if let Some(rw) = limit {
308 query_params.insert("limit".to_string(), json!(rw));
309 }
310
311 if let Some(rw) = page {
312 query_params.insert("page".to_string(), json!(rw));
313 }
314
315 if let Some(rw) = recv_window {
316 query_params.insert("recvWindow".to_string(), json!(rw));
317 }
318
319 send_request::<models::GetNftDepositHistoryResponse>(
320 &self.configuration,
321 "/sapi/v1/nft/history/deposit",
322 reqwest::Method::GET,
323 query_params,
324 body_params,
325 if HAS_TIME_UNIT {
326 self.configuration.time_unit
327 } else {
328 None
329 },
330 true,
331 )
332 .await
333 }
334
335 async fn get_nft_transaction_history(
336 &self,
337 params: GetNftTransactionHistoryParams,
338 ) -> anyhow::Result<RestApiResponse<models::GetNftTransactionHistoryResponse>> {
339 let GetNftTransactionHistoryParams {
340 order_type,
341 start_time,
342 end_time,
343 limit,
344 page,
345 recv_window,
346 } = params;
347
348 let mut query_params = BTreeMap::new();
349 let body_params = BTreeMap::new();
350
351 query_params.insert("orderType".to_string(), json!(order_type));
352
353 if let Some(rw) = start_time {
354 query_params.insert("startTime".to_string(), json!(rw));
355 }
356
357 if let Some(rw) = end_time {
358 query_params.insert("endTime".to_string(), json!(rw));
359 }
360
361 if let Some(rw) = limit {
362 query_params.insert("limit".to_string(), json!(rw));
363 }
364
365 if let Some(rw) = page {
366 query_params.insert("page".to_string(), json!(rw));
367 }
368
369 if let Some(rw) = recv_window {
370 query_params.insert("recvWindow".to_string(), json!(rw));
371 }
372
373 send_request::<models::GetNftTransactionHistoryResponse>(
374 &self.configuration,
375 "/sapi/v1/nft/history/transactions",
376 reqwest::Method::GET,
377 query_params,
378 body_params,
379 if HAS_TIME_UNIT {
380 self.configuration.time_unit
381 } else {
382 None
383 },
384 true,
385 )
386 .await
387 }
388
389 async fn get_nft_withdraw_history(
390 &self,
391 params: GetNftWithdrawHistoryParams,
392 ) -> anyhow::Result<RestApiResponse<models::GetNftWithdrawHistoryResponse>> {
393 let GetNftWithdrawHistoryParams {
394 start_time,
395 end_time,
396 limit,
397 page,
398 recv_window,
399 } = params;
400
401 let mut query_params = BTreeMap::new();
402 let body_params = BTreeMap::new();
403
404 if let Some(rw) = start_time {
405 query_params.insert("startTime".to_string(), json!(rw));
406 }
407
408 if let Some(rw) = end_time {
409 query_params.insert("endTime".to_string(), json!(rw));
410 }
411
412 if let Some(rw) = limit {
413 query_params.insert("limit".to_string(), json!(rw));
414 }
415
416 if let Some(rw) = page {
417 query_params.insert("page".to_string(), json!(rw));
418 }
419
420 if let Some(rw) = recv_window {
421 query_params.insert("recvWindow".to_string(), json!(rw));
422 }
423
424 send_request::<models::GetNftWithdrawHistoryResponse>(
425 &self.configuration,
426 "/sapi/v1/nft/history/withdraw",
427 reqwest::Method::GET,
428 query_params,
429 body_params,
430 if HAS_TIME_UNIT {
431 self.configuration.time_unit
432 } else {
433 None
434 },
435 true,
436 )
437 .await
438 }
439}
440
441#[cfg(all(test, feature = "nft"))]
442mod tests {
443 use super::*;
444 use crate::TOKIO_SHARED_RT;
445 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
446 use async_trait::async_trait;
447 use std::collections::HashMap;
448
449 struct DummyRestApiResponse<T> {
450 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
451 status: u16,
452 headers: HashMap<String, String>,
453 rate_limits: Option<Vec<RestApiRateLimit>>,
454 }
455
456 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
457 fn from(dummy: DummyRestApiResponse<T>) -> Self {
458 Self {
459 data_fn: dummy.inner,
460 status: dummy.status,
461 headers: dummy.headers,
462 rate_limits: dummy.rate_limits,
463 }
464 }
465 }
466
467 struct MockNftApiClient {
468 force_error: bool,
469 }
470
471 #[async_trait]
472 impl NftApi for MockNftApiClient {
473 async fn get_nft_asset(
474 &self,
475 _params: GetNftAssetParams,
476 ) -> anyhow::Result<RestApiResponse<models::GetNftAssetResponse>> {
477 if self.force_error {
478 return Err(ConnectorError::ConnectorClientError {
479 msg: "ResponseError".to_string(),
480 code: None,
481 }
482 .into());
483 }
484
485 let resp_json: Value = serde_json::from_str(r#"{"total":347,"list":[{"network":"BSC","contractAddress":"REGULAR11234567891779","tokenId":"100900000017"},{"network":"BSC","contractAddress":"SSMDQ8W59","tokenId":"200500000011"},{"network":"BSC","contractAddress":"SSMDQ8W59","tokenId":"200500000019"}]}"#).unwrap();
486 let dummy_response: models::GetNftAssetResponse =
487 serde_json::from_value(resp_json.clone())
488 .expect("should parse into models::GetNftAssetResponse");
489
490 let dummy = DummyRestApiResponse {
491 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
492 status: 200,
493 headers: HashMap::new(),
494 rate_limits: None,
495 };
496
497 Ok(dummy.into())
498 }
499
500 async fn get_nft_deposit_history(
501 &self,
502 _params: GetNftDepositHistoryParams,
503 ) -> anyhow::Result<RestApiResponse<models::GetNftDepositHistoryResponse>> {
504 if self.force_error {
505 return Err(ConnectorError::ConnectorClientError {
506 msg: "ResponseError".to_string(),
507 code: None,
508 }
509 .into());
510 }
511
512 let resp_json: Value = serde_json::from_str(r#"{"total":2,"list":[{"network":"ETH","txID":null,"contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"10014","timestamp":1629986047000},{"network":"BSC","txID":null,"contractAdrress":"0x058451b463bab04f52c0799d55c4094f507acfa9","tokenId":"10016","timestamp":1630083581000}]}"#).unwrap();
513 let dummy_response: models::GetNftDepositHistoryResponse =
514 serde_json::from_value(resp_json.clone())
515 .expect("should parse into models::GetNftDepositHistoryResponse");
516
517 let dummy = DummyRestApiResponse {
518 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
519 status: 200,
520 headers: HashMap::new(),
521 rate_limits: None,
522 };
523
524 Ok(dummy.into())
525 }
526
527 async fn get_nft_transaction_history(
528 &self,
529 _params: GetNftTransactionHistoryParams,
530 ) -> anyhow::Result<RestApiResponse<models::GetNftTransactionHistoryResponse>> {
531 if self.force_error {
532 return Err(ConnectorError::ConnectorClientError {
533 msg: "ResponseError".to_string(),
534 code: None,
535 }
536 .into());
537 }
538
539 let resp_json: Value = serde_json::from_str(r#"{"total":2,"list":[{"orderNo":"1_470502070600699904","tokens":[{"network":"BSC","tokenId":"216000000496","contractAddress":"MYSTERY_BOX0000087"}],"tradeTime":1626941236000,"tradeAmount":"19.60000000","tradeCurrency":"BNB"},{"orderNo":"1_488306442479116288","tokens":[{"network":"BSC","tokenId":"132900000007","contractAddress":"0xAf12111a592e408DAbC740849fcd5e68629D9fb6"}],"tradeTime":1631186130000,"tradeAmount":"192.00000000","tradeCurrency":"BNB"}]}"#).unwrap();
540 let dummy_response: models::GetNftTransactionHistoryResponse =
541 serde_json::from_value(resp_json.clone())
542 .expect("should parse into models::GetNftTransactionHistoryResponse");
543
544 let dummy = DummyRestApiResponse {
545 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
546 status: 200,
547 headers: HashMap::new(),
548 rate_limits: None,
549 };
550
551 Ok(dummy.into())
552 }
553
554 async fn get_nft_withdraw_history(
555 &self,
556 _params: GetNftWithdrawHistoryParams,
557 ) -> anyhow::Result<RestApiResponse<models::GetNftWithdrawHistoryResponse>> {
558 if self.force_error {
559 return Err(ConnectorError::ConnectorClientError {
560 msg: "ResponseError".to_string(),
561 code: None,
562 }
563 .into());
564 }
565
566 let resp_json: Value = serde_json::from_str(r#"{"total":178,"list":[{"network":"ETH","txID":"0x2be5eed31d787fdb4880bc631c8e76bdfb6150e137f5cf1732e0416ea206f57f","contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"1000001247","timestamp":1633674433000,"fee":0.1,"feeAsset":"ETH"},{"network":"ETH","txID":"0x3b3aea5c0a4faccd6f306641e6deb9713ab229ac233be3be227f580311e4362a","contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"40000030","timestamp":1633677022000,"fee":0.1,"feeAsset":"ETH"}]}"#).unwrap();
567 let dummy_response: models::GetNftWithdrawHistoryResponse =
568 serde_json::from_value(resp_json.clone())
569 .expect("should parse into models::GetNftWithdrawHistoryResponse");
570
571 let dummy = DummyRestApiResponse {
572 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
573 status: 200,
574 headers: HashMap::new(),
575 rate_limits: None,
576 };
577
578 Ok(dummy.into())
579 }
580 }
581
582 #[test]
583 fn get_nft_asset_required_params_success() {
584 TOKIO_SHARED_RT.block_on(async {
585 let client = MockNftApiClient { force_error: false };
586
587 let params = GetNftAssetParams::builder().build().unwrap();
588
589 let resp_json: Value = serde_json::from_str(r#"{"total":347,"list":[{"network":"BSC","contractAddress":"REGULAR11234567891779","tokenId":"100900000017"},{"network":"BSC","contractAddress":"SSMDQ8W59","tokenId":"200500000011"},{"network":"BSC","contractAddress":"SSMDQ8W59","tokenId":"200500000019"}]}"#).unwrap();
590 let expected_response : models::GetNftAssetResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftAssetResponse");
591
592 let resp = client.get_nft_asset(params).await.expect("Expected a response");
593 let data_future = resp.data();
594 let actual_response = data_future.await.unwrap();
595 assert_eq!(actual_response, expected_response);
596 });
597 }
598
599 #[test]
600 fn get_nft_asset_optional_params_success() {
601 TOKIO_SHARED_RT.block_on(async {
602 let client = MockNftApiClient { force_error: false };
603
604 let params = GetNftAssetParams::builder().limit(50).page(1).recv_window(5000).build().unwrap();
605
606 let resp_json: Value = serde_json::from_str(r#"{"total":347,"list":[{"network":"BSC","contractAddress":"REGULAR11234567891779","tokenId":"100900000017"},{"network":"BSC","contractAddress":"SSMDQ8W59","tokenId":"200500000011"},{"network":"BSC","contractAddress":"SSMDQ8W59","tokenId":"200500000019"}]}"#).unwrap();
607 let expected_response : models::GetNftAssetResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftAssetResponse");
608
609 let resp = client.get_nft_asset(params).await.expect("Expected a response");
610 let data_future = resp.data();
611 let actual_response = data_future.await.unwrap();
612 assert_eq!(actual_response, expected_response);
613 });
614 }
615
616 #[test]
617 fn get_nft_asset_response_error() {
618 TOKIO_SHARED_RT.block_on(async {
619 let client = MockNftApiClient { force_error: true };
620
621 let params = GetNftAssetParams::builder().build().unwrap();
622
623 match client.get_nft_asset(params).await {
624 Ok(_) => panic!("Expected an error"),
625 Err(err) => {
626 assert_eq!(err.to_string(), "Connector client error: ResponseError");
627 }
628 }
629 });
630 }
631
632 #[test]
633 fn get_nft_deposit_history_required_params_success() {
634 TOKIO_SHARED_RT.block_on(async {
635 let client = MockNftApiClient { force_error: false };
636
637 let params = GetNftDepositHistoryParams::builder().build().unwrap();
638
639 let resp_json: Value = serde_json::from_str(r#"{"total":2,"list":[{"network":"ETH","txID":null,"contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"10014","timestamp":1629986047000},{"network":"BSC","txID":null,"contractAdrress":"0x058451b463bab04f52c0799d55c4094f507acfa9","tokenId":"10016","timestamp":1630083581000}]}"#).unwrap();
640 let expected_response : models::GetNftDepositHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftDepositHistoryResponse");
641
642 let resp = client.get_nft_deposit_history(params).await.expect("Expected a response");
643 let data_future = resp.data();
644 let actual_response = data_future.await.unwrap();
645 assert_eq!(actual_response, expected_response);
646 });
647 }
648
649 #[test]
650 fn get_nft_deposit_history_optional_params_success() {
651 TOKIO_SHARED_RT.block_on(async {
652 let client = MockNftApiClient { force_error: false };
653
654 let params = GetNftDepositHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).limit(50).page(1).recv_window(5000).build().unwrap();
655
656 let resp_json: Value = serde_json::from_str(r#"{"total":2,"list":[{"network":"ETH","txID":null,"contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"10014","timestamp":1629986047000},{"network":"BSC","txID":null,"contractAdrress":"0x058451b463bab04f52c0799d55c4094f507acfa9","tokenId":"10016","timestamp":1630083581000}]}"#).unwrap();
657 let expected_response : models::GetNftDepositHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftDepositHistoryResponse");
658
659 let resp = client.get_nft_deposit_history(params).await.expect("Expected a response");
660 let data_future = resp.data();
661 let actual_response = data_future.await.unwrap();
662 assert_eq!(actual_response, expected_response);
663 });
664 }
665
666 #[test]
667 fn get_nft_deposit_history_response_error() {
668 TOKIO_SHARED_RT.block_on(async {
669 let client = MockNftApiClient { force_error: true };
670
671 let params = GetNftDepositHistoryParams::builder().build().unwrap();
672
673 match client.get_nft_deposit_history(params).await {
674 Ok(_) => panic!("Expected an error"),
675 Err(err) => {
676 assert_eq!(err.to_string(), "Connector client error: ResponseError");
677 }
678 }
679 });
680 }
681
682 #[test]
683 fn get_nft_transaction_history_required_params_success() {
684 TOKIO_SHARED_RT.block_on(async {
685 let client = MockNftApiClient { force_error: false };
686
687 let params = GetNftTransactionHistoryParams::builder(789,).build().unwrap();
688
689 let resp_json: Value = serde_json::from_str(r#"{"total":2,"list":[{"orderNo":"1_470502070600699904","tokens":[{"network":"BSC","tokenId":"216000000496","contractAddress":"MYSTERY_BOX0000087"}],"tradeTime":1626941236000,"tradeAmount":"19.60000000","tradeCurrency":"BNB"},{"orderNo":"1_488306442479116288","tokens":[{"network":"BSC","tokenId":"132900000007","contractAddress":"0xAf12111a592e408DAbC740849fcd5e68629D9fb6"}],"tradeTime":1631186130000,"tradeAmount":"192.00000000","tradeCurrency":"BNB"}]}"#).unwrap();
690 let expected_response : models::GetNftTransactionHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftTransactionHistoryResponse");
691
692 let resp = client.get_nft_transaction_history(params).await.expect("Expected a response");
693 let data_future = resp.data();
694 let actual_response = data_future.await.unwrap();
695 assert_eq!(actual_response, expected_response);
696 });
697 }
698
699 #[test]
700 fn get_nft_transaction_history_optional_params_success() {
701 TOKIO_SHARED_RT.block_on(async {
702 let client = MockNftApiClient { force_error: false };
703
704 let params = GetNftTransactionHistoryParams::builder(789,).start_time(1623319461670).end_time(1641782889000).limit(50).page(1).recv_window(5000).build().unwrap();
705
706 let resp_json: Value = serde_json::from_str(r#"{"total":2,"list":[{"orderNo":"1_470502070600699904","tokens":[{"network":"BSC","tokenId":"216000000496","contractAddress":"MYSTERY_BOX0000087"}],"tradeTime":1626941236000,"tradeAmount":"19.60000000","tradeCurrency":"BNB"},{"orderNo":"1_488306442479116288","tokens":[{"network":"BSC","tokenId":"132900000007","contractAddress":"0xAf12111a592e408DAbC740849fcd5e68629D9fb6"}],"tradeTime":1631186130000,"tradeAmount":"192.00000000","tradeCurrency":"BNB"}]}"#).unwrap();
707 let expected_response : models::GetNftTransactionHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftTransactionHistoryResponse");
708
709 let resp = client.get_nft_transaction_history(params).await.expect("Expected a response");
710 let data_future = resp.data();
711 let actual_response = data_future.await.unwrap();
712 assert_eq!(actual_response, expected_response);
713 });
714 }
715
716 #[test]
717 fn get_nft_transaction_history_response_error() {
718 TOKIO_SHARED_RT.block_on(async {
719 let client = MockNftApiClient { force_error: true };
720
721 let params = GetNftTransactionHistoryParams::builder(789)
722 .build()
723 .unwrap();
724
725 match client.get_nft_transaction_history(params).await {
726 Ok(_) => panic!("Expected an error"),
727 Err(err) => {
728 assert_eq!(err.to_string(), "Connector client error: ResponseError");
729 }
730 }
731 });
732 }
733
734 #[test]
735 fn get_nft_withdraw_history_required_params_success() {
736 TOKIO_SHARED_RT.block_on(async {
737 let client = MockNftApiClient { force_error: false };
738
739 let params = GetNftWithdrawHistoryParams::builder().build().unwrap();
740
741 let resp_json: Value = serde_json::from_str(r#"{"total":178,"list":[{"network":"ETH","txID":"0x2be5eed31d787fdb4880bc631c8e76bdfb6150e137f5cf1732e0416ea206f57f","contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"1000001247","timestamp":1633674433000,"fee":0.1,"feeAsset":"ETH"},{"network":"ETH","txID":"0x3b3aea5c0a4faccd6f306641e6deb9713ab229ac233be3be227f580311e4362a","contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"40000030","timestamp":1633677022000,"fee":0.1,"feeAsset":"ETH"}]}"#).unwrap();
742 let expected_response : models::GetNftWithdrawHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftWithdrawHistoryResponse");
743
744 let resp = client.get_nft_withdraw_history(params).await.expect("Expected a response");
745 let data_future = resp.data();
746 let actual_response = data_future.await.unwrap();
747 assert_eq!(actual_response, expected_response);
748 });
749 }
750
751 #[test]
752 fn get_nft_withdraw_history_optional_params_success() {
753 TOKIO_SHARED_RT.block_on(async {
754 let client = MockNftApiClient { force_error: false };
755
756 let params = GetNftWithdrawHistoryParams::builder().start_time(1623319461670).end_time(1641782889000).limit(50).page(1).recv_window(5000).build().unwrap();
757
758 let resp_json: Value = serde_json::from_str(r#"{"total":178,"list":[{"network":"ETH","txID":"0x2be5eed31d787fdb4880bc631c8e76bdfb6150e137f5cf1732e0416ea206f57f","contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"1000001247","timestamp":1633674433000,"fee":0.1,"feeAsset":"ETH"},{"network":"ETH","txID":"0x3b3aea5c0a4faccd6f306641e6deb9713ab229ac233be3be227f580311e4362a","contractAdrress":"0xe507c961ee127d4439977a61af39c34eafee0dc6","tokenId":"40000030","timestamp":1633677022000,"fee":0.1,"feeAsset":"ETH"}]}"#).unwrap();
759 let expected_response : models::GetNftWithdrawHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetNftWithdrawHistoryResponse");
760
761 let resp = client.get_nft_withdraw_history(params).await.expect("Expected a response");
762 let data_future = resp.data();
763 let actual_response = data_future.await.unwrap();
764 assert_eq!(actual_response, expected_response);
765 });
766 }
767
768 #[test]
769 fn get_nft_withdraw_history_response_error() {
770 TOKIO_SHARED_RT.block_on(async {
771 let client = MockNftApiClient { force_error: true };
772
773 let params = GetNftWithdrawHistoryParams::builder().build().unwrap();
774
775 match client.get_nft_withdraw_history(params).await {
776 Ok(_) => panic!("Expected an error"),
777 Err(err) => {
778 assert_eq!(err.to_string(), "Connector client error: ResponseError");
779 }
780 }
781 });
782 }
783}