@rabbitio/ui-kit 1.0.0-beta.2 → 1.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/README.md +23 -16
  3. package/dist/index.cjs +4404 -1
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +8757 -1
  6. package/dist/index.css.map +1 -1
  7. package/dist/index.modern.js +3692 -1
  8. package/dist/index.modern.js.map +1 -1
  9. package/dist/index.module.js +4375 -1
  10. package/dist/index.module.js.map +1 -1
  11. package/dist/index.umd.js +4406 -1
  12. package/dist/index.umd.js.map +1 -1
  13. package/index.js +1 -1
  14. package/package.json +17 -24
  15. package/src/common/amountUtils.js +423 -0
  16. package/src/common/errorUtils.js +27 -0
  17. package/src/common/fiatCurrenciesService.js +161 -0
  18. package/src/common/models/blockchain.js +10 -0
  19. package/src/common/models/coin.js +157 -0
  20. package/src/common/models/protocol.js +5 -0
  21. package/src/common/utils/cache.js +268 -0
  22. package/src/common/utils/emailAPI.js +18 -0
  23. package/src/common/utils/logging/logger.js +48 -0
  24. package/src/common/utils/logging/logsStorage.js +61 -0
  25. package/src/common/utils/safeStringify.js +50 -0
  26. package/src/components/atoms/AssetIcon/AssetIcon.jsx +55 -0
  27. package/src/components/atoms/AssetIcon/asset-icon.module.scss +42 -0
  28. package/{stories → src/components}/atoms/LoadingDots/LoadingDots.module.scss +1 -1
  29. package/src/components/atoms/SupportChat/SupportChat.jsx +40 -0
  30. package/{stories → src/components}/atoms/buttons/Button/Button.jsx +6 -6
  31. package/{stories → src/components}/atoms/buttons/Button/Button.module.scss +6 -1
  32. package/src/components/hooks/useCallHandlingErrors.js +26 -0
  33. package/src/components/hooks/useReferredState.js +24 -0
  34. package/src/index.js +33 -0
  35. package/src/swaps-lib/external-apis/swapProvider.js +169 -0
  36. package/src/swaps-lib/external-apis/swapspaceSwapProvider.js +812 -0
  37. package/src/swaps-lib/models/baseSwapCreationInfo.js +40 -0
  38. package/src/swaps-lib/models/existingSwap.js +58 -0
  39. package/src/swaps-lib/models/existingSwapWithFiatData.js +115 -0
  40. package/src/swaps-lib/services/publicSwapService.js +602 -0
  41. package/src/swaps-lib/utils/swapUtils.js +209 -0
  42. package/stories/index.js +0 -2
  43. /package/{stories → src/components}/atoms/LoadingDots/LoadingDots.jsx +0 -0
@@ -0,0 +1,602 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import EventBusInstance from "eventbusjs";
3
+
4
+ import { FiatCurrenciesService } from "../../common/fiatCurrenciesService.js";
5
+ import { improveAndRethrow } from "../../common/errorUtils.js";
6
+ import { safeStringify } from "../../common/utils/safeStringify.js";
7
+ import { Logger } from "../../common/utils/logging/logger.js";
8
+ import { Coin } from "../../common/models/coin.js";
9
+ import { AmountUtils } from "../../common/amountUtils.js";
10
+ import { BaseSwapCreationInfo } from "../models/baseSwapCreationInfo.js";
11
+ import { SwapUtils } from "../utils/swapUtils.js";
12
+ import { SwapspaceSwapProvider } from "../external-apis/swapspaceSwapProvider.js";
13
+ import { SwapProvider } from "../external-apis/swapProvider.js";
14
+
15
+ export class PublicSwapService {
16
+ static PUBLIC_SWAP_CREATED_EVENT = "publicSwapCreatedEvent";
17
+
18
+ static PUBLIC_SWAPS_COMMON_ERRORS = {
19
+ REQUESTS_LIMIT_EXCEEDED: "requestsLimitExceeded",
20
+ };
21
+
22
+ static PUBLIC_SWAP_DETAILS_FAIL_REASONS = {
23
+ AMOUNT_LESS_THAN_MIN_SWAPPABLE: "amountLessThanMinSwappable",
24
+ AMOUNT_HIGHER_THAN_MAX_SWAPPABLE: "amountHigherThanMaxSwappable",
25
+ PAIR_NOT_SUPPORTED: "pairNotSupported",
26
+ };
27
+
28
+ static _fiatDecimalsCount =
29
+ FiatCurrenciesService.getCurrencyDecimalCountByCode("USD");
30
+
31
+ constructor(API_KEYS_PROXY_URL, cache) {
32
+ this._swapProvider = new SwapspaceSwapProvider(
33
+ API_KEYS_PROXY_URL,
34
+ cache,
35
+ () => null,
36
+ false
37
+ );
38
+ }
39
+
40
+ async initialize() {
41
+ try {
42
+ await this._swapProvider.initialize();
43
+ } catch (e) {
44
+ Logger.logError(e, "PublicSwapService.initialize");
45
+ }
46
+ }
47
+
48
+ async getDepositCurrenciesListForPublicSwap() {
49
+ try {
50
+ return await this._getCurrenciesListForPublicSwap(false);
51
+ } catch (e) {
52
+ improveAndRethrow(e, "getDepositCurrenciesListForPublicSwap");
53
+ }
54
+ }
55
+
56
+ async getWithdrawCurrenciesListForPublicSwap() {
57
+ try {
58
+ return await this._getCurrenciesListForPublicSwap(true);
59
+ } catch (e) {
60
+ improveAndRethrow(e, "getWithdrawCurrenciesListForPublicSwap");
61
+ }
62
+ }
63
+
64
+ async _getCurrenciesListForPublicSwap(withdraw = false) {
65
+ const loggerSource = "getCurrenciesListForPublicSwap";
66
+ try {
67
+ const result = withdraw
68
+ ? await this._swapProvider.getWithdrawalCurrencies()
69
+ : await this._swapProvider.getDepositCurrencies();
70
+ if (
71
+ result.reason ===
72
+ SwapProvider.COMMON_ERRORS.REQUESTS_LIMIT_EXCEEDED
73
+ ) {
74
+ SwapUtils.safeHandleRequestsLimitExceeding();
75
+ return {
76
+ result: false,
77
+ reason: PublicSwapService.PUBLIC_SWAPS_COMMON_ERRORS
78
+ .REQUESTS_LIMIT_EXCEEDED,
79
+ };
80
+ }
81
+ Logger.log(
82
+ `Retrieved ${result?.coins?.length} supported currencies for swap`,
83
+ loggerSource
84
+ );
85
+ if (result.coins.length > 1) {
86
+ let temp = result.coins[0];
87
+ result.coins[0] = result.coins[1];
88
+ result.coins[1] = temp;
89
+ }
90
+ return { result: true, coins: result.coins };
91
+ } catch (e) {
92
+ improveAndRethrow(e, loggerSource);
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Retrieves initial data for swapping two coins.
98
+ *
99
+ * @param fromCoin {Coin}
100
+ * @param toCoin {Coin}
101
+ * @return {Promise<{
102
+ * result: true,
103
+ * min: string,
104
+ * fiatMin: (number|null),
105
+ * max: string,
106
+ * fiatMax: (number|null),
107
+ * rate: (string|null)
108
+ * }|{
109
+ * result: false,
110
+ * reason: string
111
+ * }>}
112
+ */
113
+ async getInitialPublicSwapData(fromCoin, toCoin) {
114
+ try {
115
+ const result = await SwapUtils.getInitialSwapData(
116
+ this._swapProvider,
117
+ fromCoin,
118
+ toCoin
119
+ );
120
+ if (!result.result) {
121
+ if (
122
+ result.reason ===
123
+ SwapProvider.COMMON_ERRORS.REQUESTS_LIMIT_EXCEEDED
124
+ ) {
125
+ SwapUtils.safeHandleRequestsLimitExceeding();
126
+ return {
127
+ result: false,
128
+ reason: PublicSwapService.PUBLIC_SWAPS_COMMON_ERRORS
129
+ .REQUESTS_LIMIT_EXCEEDED,
130
+ };
131
+ }
132
+ if (
133
+ result.reason ===
134
+ SwapProvider.NO_SWAPS_REASONS.NOT_SUPPORTED
135
+ ) {
136
+ return {
137
+ result: false,
138
+ reason: PublicSwapService
139
+ .PUBLIC_SWAP_DETAILS_FAIL_REASONS
140
+ .PAIR_NOT_SUPPORTED,
141
+ };
142
+ }
143
+ }
144
+ return result;
145
+ } catch (e) {
146
+ improveAndRethrow(e, "getInitialPublicSwapData");
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Retrieves swap details that can be used to create swap.
152
+ *
153
+ * @param fromCoin {Coin}
154
+ * @param toCoin {Coin}
155
+ * @param fromAmountCoins {string}
156
+ * @return {Promise<{
157
+ * result: false,
158
+ * reason: string,
159
+ * min: (string|null),
160
+ * max: (string|null),
161
+ * rate: (string|undefined),
162
+ * fiatMin: (number|null),
163
+ * fiatMax: (number|null)
164
+ * }|{
165
+ * result: true,
166
+ * swapCreationInfo: BaseSwapCreationInfo
167
+ * }>}
168
+ */
169
+ async getPublicSwapDetails(fromCoin, toCoin, fromAmountCoins) {
170
+ const loggerSource = "getPublicSwapDetails";
171
+ try {
172
+ const coinUsdtRate =
173
+ (await this._swapProvider.getCoinToUSDTRate(fromCoin))?.rate ??
174
+ null;
175
+ const details = await this._swapProvider.getSwapInfo(
176
+ fromCoin,
177
+ toCoin,
178
+ fromAmountCoins,
179
+ coinUsdtRate
180
+ );
181
+ const min = details.result ? details.min : details.smallestMin;
182
+ const max = details.result ? details.max : details.greatestMax;
183
+ let fiatMin = null,
184
+ fiatMax = null;
185
+ if (coinUsdtRate != null) {
186
+ if (min != null) {
187
+ fiatMin = BigNumber(min)
188
+ .times(coinUsdtRate)
189
+ .toFixed(PublicSwapService._fiatDecimalsCount);
190
+ }
191
+ if (max != null) {
192
+ fiatMax = BigNumber(max)
193
+ .times(coinUsdtRate)
194
+ .toFixed(PublicSwapService._fiatDecimalsCount);
195
+ }
196
+ }
197
+
198
+ const composeFailResult = (reason) => ({
199
+ result: false,
200
+ reason: reason,
201
+ min: min ?? null,
202
+ fiatMin: fiatMin,
203
+ max: max ?? null,
204
+ fiatMax: fiatMax,
205
+ rate: details.rate ?? null,
206
+ });
207
+
208
+ if (!details.result) {
209
+ if (
210
+ details?.reason ===
211
+ SwapProvider.NO_SWAPS_REASONS.NOT_SUPPORTED
212
+ )
213
+ return composeFailResult(
214
+ PublicSwapService.PUBLIC_SWAP_DETAILS_FAIL_REASONS
215
+ .PAIR_NOT_SUPPORTED
216
+ );
217
+ else if (
218
+ details?.reason ===
219
+ SwapProvider.COMMON_ERRORS.REQUESTS_LIMIT_EXCEEDED
220
+ ) {
221
+ SwapUtils.safeHandleRequestsLimitExceeding();
222
+ return composeFailResult(
223
+ PublicSwapService.PUBLIC_SWAPS_COMMON_ERRORS
224
+ .REQUESTS_LIMIT_EXCEEDED
225
+ );
226
+ }
227
+ }
228
+
229
+ const fromAmountBigNumber = BigNumber(fromAmountCoins);
230
+ if (typeof min === "string" && fromAmountBigNumber.lt(min)) {
231
+ return composeFailResult(
232
+ PublicSwapService.PUBLIC_SWAP_DETAILS_FAIL_REASONS
233
+ .AMOUNT_LESS_THAN_MIN_SWAPPABLE
234
+ );
235
+ } else if (typeof max === "string" && fromAmountBigNumber.gt(max)) {
236
+ return composeFailResult(
237
+ PublicSwapService.PUBLIC_SWAP_DETAILS_FAIL_REASONS
238
+ .AMOUNT_HIGHER_THAN_MAX_SWAPPABLE
239
+ );
240
+ }
241
+
242
+ const toAmountCoins = AmountUtils.trim(
243
+ fromAmountBigNumber.times(details.rate),
244
+ fromCoin.digits
245
+ );
246
+ const result = {
247
+ result: true,
248
+ swapCreationInfo: new BaseSwapCreationInfo(
249
+ fromCoin,
250
+ toCoin,
251
+ fromAmountCoins,
252
+ toAmountCoins,
253
+ details.rate,
254
+ details.rawSwapData,
255
+ min,
256
+ fiatMin,
257
+ max,
258
+ fiatMax,
259
+ details.durationMinutesRange
260
+ ),
261
+ };
262
+ Logger.log(
263
+ `Result: ${safeStringify({
264
+ result: result.result,
265
+ swapCreationInfo: {
266
+ ...result.swapCreationInfo,
267
+ fromCoin: result?.swapCreationInfo?.fromCoin?.ticker,
268
+ toCoin: result?.swapCreationInfo?.toCoin?.ticker,
269
+ },
270
+ })}`,
271
+ loggerSource
272
+ );
273
+
274
+ return result;
275
+ } catch (e) {
276
+ improveAndRethrow(e, loggerSource);
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Creates swap by given params.
282
+ *
283
+ * @param fromCoin {Coin}
284
+ * @param toCoin {Coin}
285
+ * @param fromAmount {string}
286
+ * @param swapCreationInfo {BaseSwapCreationInfo}
287
+ * @param toAddress {string}
288
+ * @param refundAddress {string}
289
+ * @param clientIp {string}
290
+ * @return {Promise<{
291
+ * result: true,
292
+ * fiatCurrencyCode: string,
293
+ * toCoin: Coin,
294
+ * fromAmountFiat: (number|null),
295
+ * address: string,
296
+ * durationMinutesRange: string,
297
+ * fromAmount: string,
298
+ * toAmount: string,
299
+ * toAmountFiat: (number|null),
300
+ * fiatCurrencyDecimals: number,
301
+ * fromCoin: Coin,
302
+ * rate: string,
303
+ * swapId: string
304
+ * }|{
305
+ * result: false,
306
+ * reason: string
307
+ * }>}
308
+ */
309
+ async createPublicSwap(
310
+ fromCoin,
311
+ toCoin,
312
+ fromAmount,
313
+ swapCreationInfo,
314
+ toAddress,
315
+ refundAddress,
316
+ clientIp
317
+ ) {
318
+ const loggerSource = "createPublicSwap";
319
+ try {
320
+ if (
321
+ !(fromCoin instanceof Coin) ||
322
+ !(toCoin instanceof Coin) ||
323
+ typeof fromAmount !== "string" ||
324
+ typeof toAddress !== "string" ||
325
+ typeof refundAddress !== "string" ||
326
+ !(swapCreationInfo instanceof BaseSwapCreationInfo)
327
+ ) {
328
+ throw new Error(
329
+ `Wrong input: ${fromCoin.ticker} ${toCoin.ticker} ${fromAmount} ${swapCreationInfo}`
330
+ );
331
+ }
332
+ Logger.log(
333
+ `Start: ${fromAmount} ${fromCoin.ticker} -> ${
334
+ toCoin.ticker
335
+ }. Details: ${safeStringify({
336
+ ...swapCreationInfo,
337
+ fromCoin: swapCreationInfo?.fromCoin?.ticker,
338
+ toCoin: swapCreationInfo?.toCoin?.ticker,
339
+ })}`,
340
+ loggerSource
341
+ );
342
+
343
+ const result = await this._swapProvider.createSwap(
344
+ fromCoin,
345
+ toCoin,
346
+ fromAmount,
347
+ toAddress,
348
+ refundAddress,
349
+ swapCreationInfo.rawSwapData,
350
+ clientIp
351
+ );
352
+ Logger.log(
353
+ `Created:${safeStringify({
354
+ ...result,
355
+ fromCoin: fromCoin?.ticker,
356
+ toCoin: toCoin?.ticker,
357
+ })}`,
358
+ loggerSource
359
+ );
360
+ if (!result?.result) {
361
+ if (
362
+ result?.reason ===
363
+ SwapProvider.COMMON_ERRORS.REQUESTS_LIMIT_EXCEEDED
364
+ ) {
365
+ SwapUtils.safeHandleRequestsLimitExceeding();
366
+ return {
367
+ result: false,
368
+ reason: PublicSwapService.PUBLIC_SWAPS_COMMON_ERRORS
369
+ .REQUESTS_LIMIT_EXCEEDED,
370
+ };
371
+ }
372
+ if (
373
+ result?.reason ===
374
+ SwapProvider.CREATION_FAIL_REASONS.RETRIABLE_FAIL
375
+ ) {
376
+ // TODO: [feature, high] implement retrying if one partner fail and we have another partners task_id=a07e367e488f4a4899613ac9056fa359
377
+ // return {
378
+ // result: false,
379
+ // reason: PublicSwapService.SWAP_CREATION_FAIL_REASONS.RETRIABLE_FAIL,
380
+ // };
381
+ }
382
+ }
383
+ if (result.result && result?.swapId) {
384
+ let fromAmountFiat = null,
385
+ toAmountFiat = null;
386
+ try {
387
+ const fromCoinUsdtRate =
388
+ (await this._swapProvider.getCoinToUSDTRate(fromCoin))
389
+ ?.rate ?? null;
390
+ const toCoinUsdtRate =
391
+ (await this._swapProvider.getCoinToUSDTRate(fromCoin))
392
+ ?.rate ?? null;
393
+ if (fromCoinUsdtRate != null && result.fromAmount != null) {
394
+ fromAmountFiat = BigNumber(result.fromAmount)
395
+ .times(fromCoinUsdtRate)
396
+ .toFixed(PublicSwapService._fiatDecimalsCount);
397
+ }
398
+ if (toCoinUsdtRate != null && result.toAmount != null) {
399
+ toAmountFiat = BigNumber(result.toAmount)
400
+ .times(toCoinUsdtRate)
401
+ .toFixed(PublicSwapService._fiatDecimalsCount);
402
+ }
403
+ } catch (e) {
404
+ Logger.logError(
405
+ e,
406
+ loggerSource,
407
+ "Failed to calculate fiat amounts for result"
408
+ );
409
+ }
410
+
411
+ EventBusInstance.dispatch(
412
+ PublicSwapService.PUBLIC_SWAP_CREATED_EVENT,
413
+ null,
414
+ fromCoin.ticker,
415
+ toCoin.ticker,
416
+ fromAmountFiat
417
+ );
418
+
419
+ const toReturn = {
420
+ result: true,
421
+ swapId: result.swapId,
422
+ fromCoin: fromCoin,
423
+ toCoin: toCoin,
424
+ fromAmount: result.fromAmount,
425
+ toAmount: result.toAmount,
426
+ fromAmountFiat: fromAmountFiat,
427
+ toAmountFiat: toAmountFiat,
428
+ fiatCurrencyCode: "USD",
429
+ fiatCurrencyDecimals: PublicSwapService._fiatDecimalsCount,
430
+ rate: result.rate,
431
+ durationMinutesRange: swapCreationInfo.durationMinutesRange,
432
+ address: result.fromAddress, // CRITICAL: this is the address to send coins to swaps provider
433
+ };
434
+
435
+ this._savePublicSwapIdLocally(result.swapId);
436
+
437
+ Logger.log(
438
+ `Returning: ${safeStringify({
439
+ ...toReturn,
440
+ fromCoin: fromCoin?.ticker,
441
+ toCoin: toCoin?.ticker,
442
+ })}`,
443
+ loggerSource
444
+ );
445
+ return toReturn;
446
+ }
447
+
448
+ throw new Error(
449
+ `Unexpected result from provider ${safeStringify(result)}`
450
+ );
451
+ } catch (e) {
452
+ improveAndRethrow(e, loggerSource);
453
+ }
454
+ }
455
+
456
+ /**
457
+ * Retrieves swap details and status for existing swaps by their ids.
458
+ *
459
+ * @param swapIds {string[]}
460
+ * @return {Promise<{
461
+ * result: true,
462
+ * swaps: ExistingSwapWithFiatData[]
463
+ * }|{
464
+ * result: false,
465
+ * reason: string
466
+ * }>}
467
+ * error reason is one of PUBLIC_SWAPS_COMMON_ERRORS
468
+ */
469
+ async getPublicExistingSwapDetailsAndStatus(swapIds) {
470
+ const loggerSource = "getPublicExistingSwapDetailsAndStatus";
471
+ try {
472
+ const result =
473
+ await SwapUtils.getExistingSwapsDetailsWithFiatAmounts(
474
+ this._swapProvider,
475
+ swapIds
476
+ );
477
+ if (!result?.result) {
478
+ if (
479
+ result.reason ===
480
+ SwapProvider.COMMON_ERRORS.REQUESTS_LIMIT_EXCEEDED
481
+ ) {
482
+ SwapUtils.safeHandleRequestsLimitExceeding();
483
+ return {
484
+ result: false,
485
+ reason: PublicSwapService.PUBLIC_SWAPS_COMMON_ERRORS
486
+ .REQUESTS_LIMIT_EXCEEDED,
487
+ };
488
+ }
489
+ throw new Error("Unknown reason: " + result?.reason);
490
+ }
491
+
492
+ return result;
493
+ } catch (e) {
494
+ improveAndRethrow(e, loggerSource);
495
+ }
496
+ }
497
+
498
+ /**
499
+ * Retrieves the whole available swaps history by ids saved locally.
500
+ *
501
+ * @return {Promise<{
502
+ * result: true,
503
+ * swaps: ExistingSwapWithFiatData[]
504
+ * }|{
505
+ * result: false,
506
+ * reason: string
507
+ * }>}
508
+ */
509
+ async getPublicSwapsHistory() {
510
+ try {
511
+ const swapIds = this._getPublicSwapIdsSavedLocally();
512
+ if (swapIds.length) {
513
+ return await this.getPublicExistingSwapDetailsAndStatus(
514
+ swapIds
515
+ );
516
+ }
517
+ return { result: true, swaps: [] };
518
+ } catch (e) {
519
+ improveAndRethrow(e, "getPublicSwapsHistory");
520
+ }
521
+ }
522
+
523
+ /**
524
+ * @param swapId {string}
525
+ * @private
526
+ */
527
+ _savePublicSwapIdLocally(swapId) {
528
+ if (typeof window !== "undefined") {
529
+ try {
530
+ const saved = localStorage.getItem("publicSwapIds");
531
+ const ids =
532
+ typeof saved === "string" && saved.length > 0
533
+ ? saved.split(",")
534
+ : [];
535
+ ids.push(swapId);
536
+ localStorage.setItem("publicSwapIds", ids.join(","));
537
+ } catch (e) {
538
+ improveAndRethrow(e, "_savePublicSwapIdLocally");
539
+ }
540
+ }
541
+ }
542
+
543
+ /**
544
+ * @private
545
+ * @return {string[]}
546
+ */
547
+ _getPublicSwapIdsSavedLocally() {
548
+ if (typeof window !== "undefined") {
549
+ try {
550
+ const saved = localStorage.getItem("publicSwapIds");
551
+ return typeof saved === "string" && saved.length > 0
552
+ ? saved.split(",")
553
+ : [];
554
+ } catch (e) {
555
+ improveAndRethrow(e, "_getPublicSwapIdsSavedLocally");
556
+ }
557
+ }
558
+ }
559
+
560
+ /**
561
+ * @param coinOrTicker {Coin|string}
562
+ * @return {string} icon URL (ready to use)
563
+ */
564
+ getAssetIconUrl(coinOrTicker) {
565
+ return this._swapProvider.getIconUrl(coinOrTicker);
566
+ }
567
+
568
+ /**
569
+ * @param ticker {string}
570
+ * @return {Coin|null}
571
+ */
572
+ getCoinByTickerIfPresent(ticker) {
573
+ return this._swapProvider.getCoinByTickerIfPresent(ticker);
574
+ }
575
+
576
+ /**
577
+ * TODO: [feature, moderate] add other fiat currencies support. task_id=5490e21b8b9c4f89a2247b28db3c9e0a
578
+ * @param asset {Coin}
579
+ * @return {Promise<string|null>}
580
+ */
581
+ async getAssetToUsdtRate(asset) {
582
+ try {
583
+ const result = await this._swapProvider.getCoinToUSDTRate(asset);
584
+ return result?.rate ?? null;
585
+ } catch (e) {
586
+ improveAndRethrow(e, "getAssetToUsdtRate");
587
+ }
588
+ }
589
+
590
+ /**
591
+ * @param asset {Coin}
592
+ * @param address {string}
593
+ * @return {boolean}
594
+ */
595
+ isAddressValidForAsset(asset, address) {
596
+ try {
597
+ return this._swapProvider.isAddressValidForAsset(asset, address);
598
+ } catch (e) {
599
+ improveAndRethrow(e, "isAddressValidForAsset");
600
+ }
601
+ }
602
+ }