@rabbitio/ui-kit 1.0.0-beta.42 → 1.0.0-beta.45

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 (67) hide show
  1. package/.gitlab-ci.yml +29 -0
  2. package/.husky/commit-msg +8 -0
  3. package/.husky/pre-push +1 -0
  4. package/README.md +13 -4
  5. package/dist/index.cjs +1545 -148
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.css +23630 -0
  8. package/dist/index.css.map +1 -1
  9. package/dist/index.modern.js +1318 -103
  10. package/dist/index.modern.js.map +1 -1
  11. package/dist/index.module.js +1534 -149
  12. package/dist/index.module.js.map +1 -1
  13. package/dist/index.umd.js +1544 -152
  14. package/dist/index.umd.js.map +1 -1
  15. package/package.json +16 -3
  16. package/src/assets/image/icons/arrow-tosca.svg +3 -0
  17. package/src/assets/image/icons/arrow-white.svg +14 -0
  18. package/src/assets/image/icons/failed-validation-icon.svg +15 -0
  19. package/src/assets/image/icons/successful-validation-icon.svg +10 -0
  20. package/src/common/amountUtils.js +4 -2
  21. package/src/common/tests/integration/external-apis/ipAddressProviders/getClientIpAddress.test.js +14 -0
  22. package/src/common/utils/cache.js +4 -4
  23. package/src/components/atoms/BackgroundTitle/BackgroundTitle.jsx +44 -0
  24. package/src/components/atoms/BackgroundTitle/background-title.module.scss +52 -0
  25. package/src/components/atoms/Validation/Validation.jsx +130 -0
  26. package/src/components/atoms/Validation/validation.module.scss +15 -0
  27. package/src/components/atoms/buttons/Close/Close.jsx +64 -0
  28. package/src/components/atoms/buttons/Close/close.module.scss +75 -0
  29. package/src/components/atoms/buttons/LinkButton/LinkButton.jsx +121 -0
  30. package/src/components/atoms/buttons/LinkButton/link-button.module.scss +45 -0
  31. package/src/components/organisms/Dialog/Dialog.jsx +515 -0
  32. package/src/components/organisms/Dialog/DialogButtons/DialogButtons.jsx +122 -0
  33. package/src/components/organisms/Dialog/DialogButtons/dialog-buttons.module.scss +25 -0
  34. package/src/components/organisms/Dialog/DialogStep/DialogStep.jsx +664 -0
  35. package/src/components/organisms/Dialog/DialogStep/dialog-step.module.scss +362 -0
  36. package/src/components/organisms/Dialog/dialog.module.scss +223 -0
  37. package/src/components/tests/utils/inputValueProviders/provideFormatOfFloatValueByInputString.test.js +139 -0
  38. package/src/components/tests/utils/urlQueryUtils/getQueryParameterValues.test.js +71 -0
  39. package/src/components/tests/utils/urlQueryUtils/saveQueryParameterAndValues.test.js +144 -0
  40. package/src/components/utils/inputValueProviders.js +58 -0
  41. package/src/constants/organisms/dialog/DialogStep/dialogStep.js +1 -0
  42. package/src/constants/organisms/dialog/dialog.js +29 -0
  43. package/src/index.js +11 -0
  44. package/src/robustExteranlApiCallerService/robustExternalAPICallerService.js +3 -1
  45. package/src/robustExteranlApiCallerService/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/_performCallAttempt.test.js +787 -0
  46. package/src/robustExteranlApiCallerService/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/callExternalAPI.test.js +745 -0
  47. package/src/robustExteranlApiCallerService/tests/robustExternalAPICallerService/robustExternalAPICallerService/constructor.test.js +31 -0
  48. package/src/swaps-lib/external-apis/swapProvider.js +17 -4
  49. package/src/swaps-lib/external-apis/swapspaceSwapProvider.js +91 -30
  50. package/src/swaps-lib/models/baseSwapCreationInfo.js +4 -1
  51. package/src/swaps-lib/models/existingSwap.js +3 -0
  52. package/src/swaps-lib/models/existingSwapWithFiatData.js +4 -0
  53. package/src/swaps-lib/services/publicSwapService.js +32 -4
  54. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +506 -0
  55. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/createSwap.test.js +1311 -0
  56. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getAllSupportedCurrencies.test.js +76 -0
  57. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getDepositCurrencies.test.js +82 -0
  58. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getSwapInfo.test.js +1892 -0
  59. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getWithdrawalCurrencies.test.js +111 -0
  60. package/src/swaps-lib/test/utils/swapUtils/safeHandleRequestsLimitExceeding.test.js +88 -0
  61. package/stories/stubs/exampleContent.jsx +20 -0
  62. package/styles/fonts/NunitoSans-Bold.ttf +0 -0
  63. package/styles/fonts/NunitoSans-ExtraBold.ttf +0 -0
  64. package/styles/fonts/NunitoSans-Light.ttf +0 -0
  65. package/styles/fonts/NunitoSans-Regular.ttf +0 -0
  66. package/styles/fonts/NunitoSans-SemiBold.ttf +0 -0
  67. package/styles/index.scss +14 -13
@@ -0,0 +1,506 @@
1
+ import sinon from "sinon";
2
+ import axios from "axios";
3
+ import should from "should";
4
+
5
+ import { beforeEach, afterEach, describe, it } from "vitest";
6
+
7
+ import { SwapspaceSwapProvider } from "../../../external-apis/swapspaceSwapProvider.js";
8
+ import { Coin } from "../../../../common/models/coin.js";
9
+ import { Cache } from "../../../../common/utils/cache.js";
10
+ import { Protocol } from "../../../../common/models/protocol.js";
11
+
12
+ describe("swapspaceSwapProvider", function () {
13
+ describe("_fetchSupportedCurrenciesIfNeeded", function () {
14
+ const swapspaceProvider = new SwapspaceSwapProvider("/", new Cache());
15
+ const anyError = new Error("Any error");
16
+
17
+ let axiosGetStub;
18
+ beforeEach(() => {
19
+ axiosGetStub = sinon.stub(axios, "get");
20
+ });
21
+
22
+ afterEach(() => {
23
+ axiosGetStub.restore();
24
+ swapspaceProvider._supportedCoins = [];
25
+ });
26
+
27
+ it("Should throw an error if axios throws error", async () => {
28
+ axiosGetStub.resetBehavior();
29
+ axiosGetStub.rejects(anyError);
30
+
31
+ const swapProvider = new SwapspaceSwapProvider("/", new Cache());
32
+
33
+ return swapProvider
34
+ ._fetchSupportedCurrenciesIfNeeded()
35
+ .should.be.rejectedWith(anyError);
36
+ });
37
+
38
+ it("Should not call axios if there is _supportedCoins", async () => {
39
+ swapspaceProvider._supportedCoins = [{ coin: {}, extraId: "" }];
40
+ await swapspaceProvider._fetchSupportedCurrenciesIfNeeded();
41
+
42
+ axiosGetStub.callCount.should.be.equal(0);
43
+ });
44
+
45
+ it("should make a network call if coins are not cached", async () => {
46
+ swapspaceProvider._supportedCoins = [];
47
+ const fakeResponse = { data: [] };
48
+ axiosGetStub.returns(Promise.resolve(fakeResponse));
49
+
50
+ await swapspaceProvider._fetchSupportedCurrenciesIfNeeded();
51
+
52
+ axiosGetStub.calledOnce.should.be.true();
53
+ });
54
+
55
+ it("Should call _customCoinBuilder number of times equal to returned coins count", async () => {
56
+ const _customCoinBuilderStub = sinon.stub();
57
+ const someResp = {
58
+ data: [
59
+ { code: "1", network: "n1" },
60
+ { code: "2", network: "n2" },
61
+ { code: "3", network: "n3" },
62
+ { code: "4", network: "n4" },
63
+ ],
64
+ };
65
+ axiosGetStub.resetBehavior();
66
+ axiosGetStub.resolves(someResp);
67
+ const p = new SwapspaceSwapProvider(
68
+ "/",
69
+ new Cache(),
70
+ _customCoinBuilderStub
71
+ );
72
+
73
+ await p._fetchSupportedCurrenciesIfNeeded();
74
+
75
+ _customCoinBuilderStub.callCount.should.be.equal(
76
+ someResp.data.length
77
+ );
78
+ });
79
+
80
+ it("Should call _customCoinBuilder with proper params", async () => {
81
+ const _customCoinBuilderStub = sinon.stub();
82
+ const someResp = {
83
+ data: [
84
+ { code: "1", network: "n1" },
85
+ { code: "2", network: "n2" },
86
+ { code: "3", network: "n3" },
87
+ { code: "4", network: "n4" },
88
+ ],
89
+ };
90
+ axiosGetStub.resetBehavior();
91
+ axiosGetStub.resolves(someResp);
92
+ const p = new SwapspaceSwapProvider(
93
+ "/",
94
+ new Cache(),
95
+ _customCoinBuilderStub
96
+ );
97
+
98
+ await p._fetchSupportedCurrenciesIfNeeded();
99
+
100
+ _customCoinBuilderStub.args.forEach((args, i) =>
101
+ args.should.be.deepEqual([
102
+ someResp.data[i].code,
103
+ someResp.data[i].network,
104
+ ])
105
+ );
106
+ });
107
+
108
+ it("Should ignore coins that _customCoinBuilder returned null for if useRestrictedCoinsSet is true", async () => {
109
+ const someResp = {
110
+ data: [
111
+ { code: "1", network: "n1" },
112
+ { code: "2", network: "n2" },
113
+ { code: "3", network: "n3" },
114
+ ],
115
+ };
116
+ const _customCoinBuilderStub = sinon.stub();
117
+ _customCoinBuilderStub.onFirstCall().returns({ ticker: "1" });
118
+ _customCoinBuilderStub.onSecondCall().returns(null);
119
+ _customCoinBuilderStub.onThirdCall().returns({ ticker: "3" });
120
+
121
+ axiosGetStub.resetBehavior();
122
+ axiosGetStub.resolves(someResp);
123
+ const p = new SwapspaceSwapProvider(
124
+ "/",
125
+ new Cache(),
126
+ _customCoinBuilderStub,
127
+ true
128
+ );
129
+
130
+ await p._fetchSupportedCurrenciesIfNeeded();
131
+
132
+ p._supportedCoins.length.should.be.equal(2);
133
+ (
134
+ p._supportedCoins.find((i) => i.coin.ticker === "1") != null
135
+ ).should.be.true();
136
+ (
137
+ p._supportedCoins.find((i) => i.coin.ticker === "3") != null
138
+ ).should.be.true();
139
+ });
140
+
141
+ it("Should construct coins with default params if _customCoinBuilder return null for some and useRestrictedCoinsSet is false", async () => {
142
+ const someResp = {
143
+ data: [
144
+ { code: "aaa", network: "n1" },
145
+ {
146
+ code: "bbb",
147
+ network: "n2",
148
+ name: "some",
149
+ contractAddress: "addr",
150
+ },
151
+ { code: "ccc", network: "n3" },
152
+ ],
153
+ };
154
+ const _customCoinBuilderStub = sinon.stub();
155
+ _customCoinBuilderStub.onFirstCall().returns({ ticker: "AAAN1" });
156
+ _customCoinBuilderStub.onSecondCall().returns(null);
157
+ _customCoinBuilderStub.onThirdCall().returns({ ticker: "CCCN3" });
158
+
159
+ axiosGetStub.resetBehavior();
160
+ axiosGetStub.resolves(someResp);
161
+ const p = new SwapspaceSwapProvider(
162
+ "/",
163
+ new Cache(),
164
+ _customCoinBuilderStub,
165
+ false
166
+ );
167
+
168
+ await p._fetchSupportedCurrenciesIfNeeded();
169
+
170
+ p._supportedCoins.length.should.be.equal(3);
171
+
172
+ const newCoin = p._supportedCoins.find(
173
+ (i) => i.coin.ticker === "BBBN2"
174
+ )?.coin;
175
+ (newCoin instanceof Coin).should.be.true();
176
+ newCoin.tickerPrintable.should.be.equal("BBB");
177
+ newCoin.latinName.should.be.equal("some");
178
+ newCoin.digits.should.be.equal(8);
179
+ (newCoin.maxValue === null).should.be.true();
180
+ newCoin.atomName.should.be.equal("");
181
+ (newCoin.mainnet === null).should.be.true();
182
+ (newCoin.testnet === null).should.be.true();
183
+ newCoin.minConfirmations.should.be.equal(1);
184
+ (newCoin.payableEntityStringForFeeRate === null).should.be.true();
185
+ newCoin.feeOptionsTimeStringsSortedDesc.should.be.deepEqual([]);
186
+ newCoin.feeRatesExpirationTimeMs.should.be.equal(60000);
187
+ newCoin.protocol.should.be.deepEqual(new Protocol("N2"));
188
+ (newCoin.blockchain === null).should.be.true();
189
+ newCoin.tokenAddress.should.be.equal("addr");
190
+ newCoin.feeCoin.should.be.equal(newCoin);
191
+ newCoin.doesUseLowerCaseAddresses.should.be.equal(false);
192
+ newCoin.doesUseOutputs.should.be.equal(false);
193
+ });
194
+
195
+ it("Should construct coins with null protocol and ticker===<uppercase code> if _customCoinBuilder return null for item and useRestrictedCoinsSet is false and code and network are equal for item", async () => {
196
+ const someResp = {
197
+ data: [
198
+ {
199
+ code: "bbb",
200
+ network: "bbb",
201
+ },
202
+ ],
203
+ };
204
+ const _customCoinBuilderStub = sinon.stub();
205
+ _customCoinBuilderStub.onFirstCall().returns(null);
206
+
207
+ axiosGetStub.resetBehavior();
208
+ axiosGetStub.resolves(someResp);
209
+ const p = new SwapspaceSwapProvider(
210
+ "/",
211
+ new Cache(),
212
+ _customCoinBuilderStub,
213
+ false
214
+ );
215
+
216
+ await p._fetchSupportedCurrenciesIfNeeded();
217
+
218
+ p._supportedCoins[0].coin.ticker.should.be.equal("BBB");
219
+ (p._supportedCoins[0].coin.protocol === null).should.be.true();
220
+ });
221
+
222
+ it("Should construct coins ticker===<uppercasecodeProtocol> and protocol with name===<uppercasenetwork> if _customCoinBuilder return null for item and useRestrictedCoinsSet is false and code and network are nopt equal for item", async () => {
223
+ const someResp = {
224
+ data: [
225
+ {
226
+ code: "bbb",
227
+ network: "bbb1",
228
+ },
229
+ ],
230
+ };
231
+ const _customCoinBuilderStub = sinon.stub();
232
+ _customCoinBuilderStub.onFirstCall().returns(null);
233
+
234
+ axiosGetStub.resetBehavior();
235
+ axiosGetStub.resolves(someResp);
236
+ const p = new SwapspaceSwapProvider(
237
+ "/",
238
+ new Cache(),
239
+ _customCoinBuilderStub,
240
+ false
241
+ );
242
+
243
+ await p._fetchSupportedCurrenciesIfNeeded();
244
+
245
+ p._supportedCoins[0].coin.ticker.should.be.equal("BBBBBB1");
246
+ p._supportedCoins[0].coin.protocol.should.be.deepEqual(
247
+ new Protocol("BBB1")
248
+ );
249
+ });
250
+
251
+ it("Should construct coins with tokenAddress === null if _customCoinBuilder return null for item and useRestrictedCoinsSet is false and contractAddress is nullish for item", async () => {
252
+ const someResp = {
253
+ data: [
254
+ {
255
+ code: "bbb",
256
+ network: "bbb1",
257
+ },
258
+ ],
259
+ };
260
+ const _customCoinBuilderStub = sinon.stub();
261
+ _customCoinBuilderStub.onFirstCall().returns(null);
262
+
263
+ axiosGetStub.resetBehavior();
264
+ axiosGetStub.resolves(someResp);
265
+ const p = new SwapspaceSwapProvider(
266
+ "/",
267
+ new Cache(),
268
+ _customCoinBuilderStub,
269
+ false
270
+ );
271
+
272
+ await p._fetchSupportedCurrenciesIfNeeded();
273
+
274
+ (p._supportedCoins[0].coin.tokenAddress === null).should.be.true();
275
+ });
276
+
277
+ const setupAndExecstoreCoinDataFormatTest = async (attribute) => {
278
+ const someResp = {
279
+ data: [
280
+ {
281
+ code: "aaa",
282
+ network: "aaa",
283
+ hasExtraId: false,
284
+ extraIdName: "",
285
+ popular: false,
286
+ iconURL: "/aaa",
287
+ deposit: true,
288
+ withdrawal: true,
289
+ validationRegexp: "any",
290
+ },
291
+ {
292
+ code: "bbb",
293
+ network: "bbb1",
294
+ hasExtraId: false,
295
+ extraIdName: "",
296
+ iconURL: "/bbb/bbb1.svg",
297
+ deposit: false,
298
+ withdrawal: false,
299
+ validationRegexp: "any",
300
+ },
301
+ {
302
+ code: "ccc",
303
+ network: "n3",
304
+ hasExtraId: true,
305
+ extraIdName: "",
306
+ popular: false,
307
+ iconURL: "/1/ccc.jpg",
308
+ deposit: true,
309
+ withdrawal: false,
310
+ },
311
+ {
312
+ code: "ddd",
313
+ network: "n4",
314
+ hasExtraId: true,
315
+ extraIdName: "MEMO",
316
+ popular: false,
317
+ deposit: false,
318
+ withdrawal: true,
319
+ validationRegexp: "any",
320
+ },
321
+ ],
322
+ };
323
+
324
+ const _customCoinBuilderStub = sinon.stub();
325
+ _customCoinBuilderStub.returns(null);
326
+ // _customCoinBuilderStub.onCall(1).returns({ ticker: "CCCN3" });
327
+
328
+ axiosGetStub.resetBehavior();
329
+ axiosGetStub.resolves(someResp);
330
+ const p = new SwapspaceSwapProvider(
331
+ "/",
332
+ new Cache(),
333
+ _customCoinBuilderStub,
334
+ false
335
+ );
336
+
337
+ await p._fetchSupportedCurrenciesIfNeeded();
338
+
339
+ return { provider: p, data: someResp.data };
340
+ };
341
+
342
+ it("Should save constructed coin as a coin list item", async () => {
343
+ const { provider } = await setupAndExecstoreCoinDataFormatTest();
344
+
345
+ provider._supportedCoins.forEach((i) =>
346
+ i.coin.should.be.instanceof(Coin)
347
+ );
348
+ });
349
+
350
+ it("Should save code as is", async () => {
351
+ const { provider, data } =
352
+ await setupAndExecstoreCoinDataFormatTest();
353
+
354
+ provider._supportedCoins.forEach((dataItem, i) => {
355
+ dataItem.code.should.be.equal(data[i].code);
356
+ });
357
+ });
358
+
359
+ it("Should save network as is", async () => {
360
+ const { provider, data } =
361
+ await setupAndExecstoreCoinDataFormatTest();
362
+
363
+ provider._supportedCoins.forEach((dataItem, i) => {
364
+ dataItem.network.should.be.equal(data[i].network);
365
+ });
366
+ });
367
+
368
+ it("Should save hasExtraId as is", async () => {
369
+ const { provider, data } =
370
+ await setupAndExecstoreCoinDataFormatTest();
371
+
372
+ provider._supportedCoins.forEach((dataItem, i) => {
373
+ dataItem.hasExtraId.should.be.equal(data[i].hasExtraId);
374
+ });
375
+ });
376
+
377
+ it("Should save extraIdName as is", async () => {
378
+ const { provider, data } =
379
+ await setupAndExecstoreCoinDataFormatTest();
380
+
381
+ provider._supportedCoins.forEach((dataItem, i) => {
382
+ dataItem.extraIdName.should.be.equal(data[i].extraIdName);
383
+ });
384
+ });
385
+
386
+ it("Should save popular to isPopular as boolean", async () => {
387
+ const { provider, data } =
388
+ await setupAndExecstoreCoinDataFormatTest();
389
+
390
+ provider._supportedCoins.forEach((dataItem, i) => {
391
+ dataItem.isPopular.should.be.equal(!!data[i].popular);
392
+ });
393
+ });
394
+
395
+ it("Should save icon or default URL to iconURL", async () => {
396
+ const { provider, data } =
397
+ await setupAndExecstoreCoinDataFormatTest();
398
+
399
+ provider._supportedCoins.forEach((dataItem, i) => {
400
+ dataItem.iconURL.should.be.equal(
401
+ data[i].icon
402
+ ? `https://storage.swapspace.co${data[i].iconURL}`
403
+ : "https://rabbit.io/asset-icons/fallback.svg"
404
+ );
405
+ });
406
+ });
407
+
408
+ it("Should save deposit as is", async () => {
409
+ const { provider, data } =
410
+ await setupAndExecstoreCoinDataFormatTest();
411
+
412
+ provider._supportedCoins.forEach((dataItem, i) => {
413
+ dataItem.deposit.should.be.equal(data[i].deposit);
414
+ });
415
+ });
416
+
417
+ it("Should save withdrawal as is", async () => {
418
+ const { provider, data } =
419
+ await setupAndExecstoreCoinDataFormatTest();
420
+
421
+ provider._supportedCoins.forEach((dataItem, i) => {
422
+ dataItem.withdrawal.should.be.equal(data[i].withdrawal);
423
+ });
424
+ });
425
+
426
+ it("Should save validationRegexp or null if it is nullish", async () => {
427
+ const { provider, data } =
428
+ await setupAndExecstoreCoinDataFormatTest();
429
+
430
+ provider._supportedCoins.forEach((dataItem, i) => {
431
+ (
432
+ dataItem.validationRegexp ===
433
+ (data[i].validationRegexp ?? null)
434
+ ).should.be.true();
435
+ });
436
+ });
437
+
438
+ it("should sort list by isPopular and alphabetically by ticker", async () => {
439
+ const swapspaceProvider = new SwapspaceSwapProvider(
440
+ "/",
441
+ new Cache(),
442
+ () => null,
443
+ false
444
+ );
445
+ const fakeResponse = {
446
+ data: [
447
+ {
448
+ network: "eth",
449
+ code: "eth",
450
+ popular: true,
451
+ },
452
+ {
453
+ network: "bac",
454
+ code: "bac",
455
+ popular: false,
456
+ },
457
+ {
458
+ network: "bbb",
459
+ code: "btc",
460
+ popular: false,
461
+ },
462
+ {
463
+ network: "eee",
464
+ code: "aaa",
465
+ popular: false,
466
+ },
467
+ {
468
+ network: "xxx",
469
+ code: "aaa",
470
+ popular: true,
471
+ },
472
+ ],
473
+ };
474
+ axiosGetStub.returns(Promise.resolve(fakeResponse));
475
+
476
+ await swapspaceProvider._fetchSupportedCurrenciesIfNeeded();
477
+
478
+ swapspaceProvider._supportedCoins
479
+ .map((coin) => coin.coin.ticker)
480
+ .should.be.deepEqual([
481
+ "AAAXXX",
482
+ "ETH",
483
+ "AAAEEE",
484
+ "BAC",
485
+ "BTCBBB",
486
+ ]);
487
+ });
488
+
489
+ it("should handle empty response data", async () => {
490
+ const fakeResponse = { data: null };
491
+ axiosGetStub.returns(Promise.resolve(fakeResponse));
492
+
493
+ await swapspaceProvider._fetchSupportedCurrenciesIfNeeded();
494
+
495
+ swapspaceProvider._supportedCoins.should.deepEqual([]);
496
+ });
497
+
498
+ it("should handle absence of data field in response", async () => {
499
+ const fakeResponse = {};
500
+ axiosGetStub.returns(Promise.resolve(fakeResponse));
501
+
502
+ await swapspaceProvider._fetchSupportedCurrenciesIfNeeded();
503
+ swapspaceProvider._supportedCoins.should.deepEqual([]);
504
+ });
505
+ });
506
+ });