@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,1311 @@
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 { SwapProvider } from "../../../external-apis/swapProvider.js";
8
+ import { SwapspaceSwapProvider } from "../../../external-apis/swapspaceSwapProvider.js";
9
+ import { Coin } from "../../../../common/models/coin.js";
10
+ import { Blockchain } from "../../../../common/models/blockchain.js";
11
+ import { Cache } from "../../../../common/utils/cache.js";
12
+
13
+ describe("swapspaceSwapProvider", function () {
14
+ describe("createSwap", function () {
15
+ const anyReceivingAddress = "any addr";
16
+ const anyRefundAddress = "any refund addr";
17
+ const anyAmount = "100.1319";
18
+ const anyIp = "123.23.21.22";
19
+ const anyValidRawSwapData = {
20
+ fromCurrency: "any currency from",
21
+ fromNetwork: "any network from",
22
+ toCurrency: "any currency to",
23
+ toNetwork: "any network to",
24
+ id: "any id",
25
+ partner: "any partner",
26
+ };
27
+
28
+ const BTC = new Coin(
29
+ "Bitcoin",
30
+ "BTC",
31
+ "BTC",
32
+ 8,
33
+ null,
34
+ "sat",
35
+ null,
36
+ null,
37
+ 1,
38
+ null,
39
+ [],
40
+ null,
41
+ new Blockchain("Bitcoin")
42
+ );
43
+ const ETH = new Coin(
44
+ "Ethereum",
45
+ "ETH",
46
+ "ETH",
47
+ 18,
48
+ null,
49
+ "wei",
50
+ null,
51
+ null,
52
+ 1,
53
+ null,
54
+ [],
55
+ null,
56
+ new Blockchain("Ethereum")
57
+ );
58
+ const USDCTRC20 = new Coin(
59
+ "USDCTRC20",
60
+ "USDCTRC20",
61
+ "USDC",
62
+ 6,
63
+ null,
64
+ "millicents",
65
+ null,
66
+ null,
67
+ 1,
68
+ null,
69
+ [],
70
+ null,
71
+ new Blockchain("Tron")
72
+ );
73
+ let swapspaceSwapProvider;
74
+ let fetchSupportedCurrenciesStub;
75
+ let axiosPostStub;
76
+
77
+ beforeEach(() => {
78
+ swapspaceSwapProvider = new SwapspaceSwapProvider("/", new Cache());
79
+ swapspaceSwapProvider._supportedCoins = [
80
+ { coin: BTC, extraId: "" },
81
+ { coin: ETH, extraId: "" },
82
+ ];
83
+
84
+ fetchSupportedCurrenciesStub = sinon.stub(
85
+ swapspaceSwapProvider,
86
+ "_fetchSupportedCurrenciesIfNeeded"
87
+ );
88
+ fetchSupportedCurrenciesStub.resolves();
89
+
90
+ axiosPostStub = sinon.stub(axios, "post");
91
+ axiosPostStub.resolves({
92
+ data: {
93
+ id: "test-id",
94
+ from: { amount: 1, address: "from-address" },
95
+ to: { amount: 2, address: "to-address" },
96
+ rate: 2,
97
+ fixed: false,
98
+ },
99
+ });
100
+ });
101
+
102
+ afterEach(() => {
103
+ fetchSupportedCurrenciesStub.restore();
104
+ axiosPostStub.restore();
105
+ });
106
+
107
+ it("Should fetch supported currencies", async () => {
108
+ await swapspaceSwapProvider.createSwap(
109
+ USDCTRC20,
110
+ ETH,
111
+ anyAmount,
112
+ anyReceivingAddress,
113
+ anyRefundAddress,
114
+ anyValidRawSwapData,
115
+ anyIp,
116
+ false
117
+ );
118
+ fetchSupportedCurrenciesStub.calledOnce.should.be.true();
119
+ });
120
+
121
+ it("Should send an axios POST request", async () => {
122
+ await swapspaceSwapProvider.createSwap(
123
+ USDCTRC20,
124
+ ETH,
125
+ anyAmount,
126
+ anyReceivingAddress,
127
+ anyRefundAddress,
128
+ anyValidRawSwapData,
129
+ anyIp,
130
+ false
131
+ );
132
+ axiosPostStub.calledOnce.should.be.true();
133
+ });
134
+
135
+ it("Should send the request to the correct URL", async () => {
136
+ await swapspaceSwapProvider.createSwap(
137
+ USDCTRC20,
138
+ ETH,
139
+ anyAmount,
140
+ anyReceivingAddress,
141
+ anyRefundAddress,
142
+ anyValidRawSwapData,
143
+ anyIp,
144
+ false
145
+ );
146
+ axiosPostStub.args[0][0].should.equal(
147
+ `${swapspaceSwapProvider._URL}/api/v2/exchange`
148
+ );
149
+ });
150
+
151
+ it("Should pass client IP address in request data", async () => {
152
+ await swapspaceSwapProvider.createSwap(
153
+ USDCTRC20,
154
+ ETH,
155
+ anyAmount,
156
+ anyReceivingAddress,
157
+ anyRefundAddress,
158
+ anyValidRawSwapData,
159
+ "123.123.123.123",
160
+ false
161
+ );
162
+
163
+ axiosPostStub.args[0][1].should.have.property(
164
+ "userIp",
165
+ "123.123.123.123"
166
+ );
167
+ });
168
+
169
+ it("Should pass provided refund address in request data", async () => {
170
+ await swapspaceSwapProvider.createSwap(
171
+ USDCTRC20,
172
+ ETH,
173
+ anyAmount,
174
+ anyReceivingAddress,
175
+ anyRefundAddress,
176
+ anyValidRawSwapData,
177
+ anyIp,
178
+ false
179
+ );
180
+
181
+ axiosPostStub.args[0][1].should.have.property(
182
+ "refund",
183
+ anyRefundAddress
184
+ );
185
+ });
186
+
187
+ it("Should use rateId from rawSwapData in request data", async () => {
188
+ await swapspaceSwapProvider.createSwap(
189
+ USDCTRC20,
190
+ ETH,
191
+ anyAmount,
192
+ anyReceivingAddress,
193
+ anyRefundAddress,
194
+ { ...anyValidRawSwapData, id: "test-rateId" },
195
+ anyIp,
196
+ false
197
+ );
198
+
199
+ axiosPostStub.args[0][1].should.have.property(
200
+ "rateId",
201
+ "test-rateId"
202
+ );
203
+ });
204
+
205
+ it('Should send the correct "extraId" passed if toCoin has hasExtraId===true', async () => {
206
+ const someExtraId = "extra123";
207
+ swapspaceSwapProvider._supportedCoins = [
208
+ { coin: USDCTRC20 },
209
+ { coin: ETH, hasExtraId: true },
210
+ ];
211
+
212
+ await swapspaceSwapProvider.createSwap(
213
+ USDCTRC20,
214
+ ETH,
215
+ anyAmount,
216
+ anyReceivingAddress,
217
+ anyRefundAddress,
218
+ anyValidRawSwapData,
219
+ anyIp,
220
+ false,
221
+ someExtraId
222
+ );
223
+
224
+ axiosPostStub.args[0][1].should.have.property(
225
+ "extraId",
226
+ someExtraId
227
+ );
228
+ });
229
+
230
+ it('Should send the correct "refundExtraId" when refund extraId passed and fromCoin has hasExtraId===true ', async () => {
231
+ const someExtraId = "extra123";
232
+ swapspaceSwapProvider._supportedCoins = [
233
+ {
234
+ coin: USDCTRC20,
235
+ hasExtraId: true,
236
+ code: "usdt",
237
+ network: "trc20",
238
+ },
239
+ { coin: ETH },
240
+ ];
241
+
242
+ await swapspaceSwapProvider.createSwap(
243
+ USDCTRC20,
244
+ ETH,
245
+ anyAmount,
246
+ anyReceivingAddress,
247
+ anyRefundAddress,
248
+ anyValidRawSwapData,
249
+ anyIp,
250
+ false,
251
+ null,
252
+ someExtraId
253
+ );
254
+
255
+ axiosPostStub.args[0][1].should.have.property(
256
+ "refundExtraId",
257
+ someExtraId
258
+ );
259
+ });
260
+
261
+ it('Should omit passed "extraId" or "refundExtraId" when matching coins have hasExtraId false', async () => {
262
+ const someExtraId = "extra123";
263
+ swapspaceSwapProvider._supportedCoins = [
264
+ { coin: USDCTRC20, hasExtraId: false },
265
+ { coin: ETH, hasExtraId: false },
266
+ ];
267
+
268
+ await swapspaceSwapProvider.createSwap(
269
+ USDCTRC20,
270
+ ETH,
271
+ anyAmount,
272
+ anyReceivingAddress,
273
+ anyRefundAddress,
274
+ anyValidRawSwapData,
275
+ anyIp,
276
+ false,
277
+ someExtraId,
278
+ someExtraId
279
+ );
280
+
281
+ axiosPostStub.args[0][1].extraId.should.be.equal("");
282
+ axiosPostStub.args[0][1].refundExtraId.should.be.equal("");
283
+ });
284
+
285
+ it("Should use rawSwapData to form requestData currencies and networks", async () => {
286
+ await swapspaceSwapProvider.createSwap(
287
+ USDCTRC20,
288
+ ETH,
289
+ anyAmount,
290
+ anyReceivingAddress,
291
+ anyRefundAddress,
292
+ {
293
+ ...anyValidRawSwapData,
294
+ fromCurrency: "from-test",
295
+ fromNetwork: "from-network-test",
296
+ toCurrency: "to-test",
297
+ toNetwork: "to-network-test",
298
+ },
299
+ anyIp,
300
+ false
301
+ );
302
+
303
+ axiosPostStub.args[0][1].should.have.property(
304
+ "fromCurrency",
305
+ "from-test"
306
+ );
307
+ axiosPostStub.args[0][1].should.have.property(
308
+ "fromNetwork",
309
+ "from-network-test"
310
+ );
311
+ axiosPostStub.args[0][1].should.have.property(
312
+ "toCurrency",
313
+ "to-test"
314
+ );
315
+ axiosPostStub.args[0][1].should.have.property(
316
+ "toNetwork",
317
+ "to-network-test"
318
+ );
319
+ });
320
+
321
+ [
322
+ "fromCurrency",
323
+ "fromNetwork",
324
+ "toCurrency",
325
+ "toNetwork",
326
+ "id",
327
+ "partner",
328
+ ].forEach((rawSwapDataProperty) => {
329
+ it(`Should reject if raw swap data contains wrong ${rawSwapDataProperty}`, async () => {
330
+ const rawSwapData = {
331
+ ...anyValidRawSwapData,
332
+ [rawSwapDataProperty]: null,
333
+ };
334
+
335
+ await swapspaceSwapProvider
336
+ .createSwap(
337
+ USDCTRC20,
338
+ ETH,
339
+ anyAmount,
340
+ anyReceivingAddress,
341
+ anyRefundAddress,
342
+ rawSwapData,
343
+ anyIp,
344
+ false
345
+ )
346
+ .should.be.rejectedWith(/.*Invalid raw swap data.*/);
347
+ });
348
+ });
349
+
350
+ it("Should send partner from rawSwapData when provided", async () => {
351
+ await swapspaceSwapProvider.createSwap(
352
+ USDCTRC20,
353
+ ETH,
354
+ anyAmount,
355
+ anyReceivingAddress,
356
+ anyRefundAddress,
357
+ { ...anyValidRawSwapData, partner: "testPartner" },
358
+ anyIp,
359
+ false
360
+ );
361
+
362
+ axiosPostStub.args[0][1].should.have.property(
363
+ "partner",
364
+ "testPartner"
365
+ );
366
+ });
367
+
368
+ [false, true].forEach((fixed) => {
369
+ it("Should ensure that fixed is always set to passed fixed value in the request data", async () => {
370
+ await swapspaceSwapProvider.createSwap(
371
+ USDCTRC20,
372
+ ETH,
373
+ anyAmount,
374
+ anyReceivingAddress,
375
+ anyRefundAddress,
376
+ anyValidRawSwapData,
377
+ anyIp,
378
+ fixed
379
+ );
380
+
381
+ axiosPostStub.args[0][1].fixed.should.equal(fixed);
382
+ });
383
+ });
384
+
385
+ it("Should ensure all required parameters are passed to axios", async () => {
386
+ await swapspaceSwapProvider.createSwap(
387
+ USDCTRC20,
388
+ ETH,
389
+ anyAmount,
390
+ anyReceivingAddress,
391
+ anyRefundAddress,
392
+ anyValidRawSwapData,
393
+ anyIp,
394
+ false
395
+ );
396
+
397
+ const requestData = axiosPostStub.args[0][1];
398
+ requestData.should.have.properties([
399
+ "partner",
400
+ "fromCurrency",
401
+ "fromNetwork",
402
+ "toCurrency",
403
+ "toNetwork",
404
+ "address",
405
+ "amount",
406
+ "fixed",
407
+ "extraId",
408
+ "refundExtraId",
409
+ "rateId",
410
+ "userIp",
411
+ "refund",
412
+ ]);
413
+ });
414
+
415
+ it("Should handle cases where toCurrencyExtraId is not found for the coin", async () => {
416
+ swapspaceSwapProvider._supportedCoins = [
417
+ { coin: USDCTRC20, extraId: "" },
418
+ { coin: ETH },
419
+ ];
420
+ await swapspaceSwapProvider.createSwap(
421
+ USDCTRC20,
422
+ ETH,
423
+ anyAmount,
424
+ anyReceivingAddress,
425
+ anyRefundAddress,
426
+ anyValidRawSwapData,
427
+ anyIp,
428
+ false
429
+ );
430
+ axiosPostStub.args[0][1].extraId.should.be.equal("");
431
+ });
432
+
433
+ it("Should throw an error if swap creation response is invalid", async () => {
434
+ axiosPostStub.resolves({ data: {} });
435
+
436
+ await swapspaceSwapProvider
437
+ .createSwap(
438
+ USDCTRC20,
439
+ ETH,
440
+ anyAmount,
441
+ anyReceivingAddress,
442
+ anyRefundAddress,
443
+ anyValidRawSwapData,
444
+ anyIp,
445
+ false
446
+ )
447
+ .should.be.rejected();
448
+ });
449
+
450
+ it("Should handle status 429 and return requests limit exceeded", async () => {
451
+ axiosPostStub.rejects({ response: { status: 429 } });
452
+
453
+ const result = await swapspaceSwapProvider.createSwap(
454
+ USDCTRC20,
455
+ ETH,
456
+ anyAmount,
457
+ anyReceivingAddress,
458
+ anyRefundAddress,
459
+ anyValidRawSwapData,
460
+ anyIp,
461
+ false
462
+ );
463
+
464
+ result.reason.should.equal(
465
+ SwapProvider.COMMON_ERRORS.REQUESTS_LIMIT_EXCEEDED
466
+ );
467
+ });
468
+
469
+ it("Should return retriable fail for status 422 and specific 'Pair cannot be processed by' error text", async () => {
470
+ axiosPostStub.rejects({
471
+ response: { status: 422, data: "Pair cannot be processed by" },
472
+ });
473
+
474
+ const result = await swapspaceSwapProvider.createSwap(
475
+ USDCTRC20,
476
+ ETH,
477
+ anyAmount,
478
+ anyReceivingAddress,
479
+ anyRefundAddress,
480
+ anyValidRawSwapData,
481
+ anyIp,
482
+ false
483
+ );
484
+
485
+ result.reason.should.equal(
486
+ SwapProvider.CREATION_FAIL_REASONS.RETRIABLE_FAIL
487
+ );
488
+ });
489
+
490
+ it("Should return retriable fail for status 403 and specific 'IP address is forbidden' error text", async () => {
491
+ axiosPostStub.rejects({
492
+ response: { status: 403, data: "IP address is forbidden" },
493
+ });
494
+
495
+ const result = await swapspaceSwapProvider.createSwap(
496
+ USDCTRC20,
497
+ ETH,
498
+ anyAmount,
499
+ anyReceivingAddress,
500
+ anyRefundAddress,
501
+ anyValidRawSwapData,
502
+ anyIp,
503
+ false
504
+ );
505
+
506
+ result.reason.should.equal(
507
+ SwapProvider.CREATION_FAIL_REASONS.RETRIABLE_FAIL
508
+ );
509
+ });
510
+
511
+ it('Should return retriable fail for status 422 and specific "Amount maximum is" error text', async () => {
512
+ axiosPostStub.rejects({
513
+ response: { status: 422, data: "Amount maximum is" },
514
+ });
515
+
516
+ const result = await swapspaceSwapProvider.createSwap(
517
+ USDCTRC20,
518
+ ETH,
519
+ anyAmount,
520
+ anyReceivingAddress,
521
+ anyRefundAddress,
522
+ anyValidRawSwapData,
523
+ anyIp,
524
+ false
525
+ );
526
+
527
+ result.reason.should.equal(
528
+ SwapProvider.CREATION_FAIL_REASONS.RETRIABLE_FAIL
529
+ );
530
+ });
531
+
532
+ it('Should return retriable fail for status 422 and specific "Amount minimum is" error text', async () => {
533
+ axiosPostStub.rejects({
534
+ response: { status: 422, data: "Amount minimum is" },
535
+ });
536
+
537
+ const result = await swapspaceSwapProvider.createSwap(
538
+ USDCTRC20,
539
+ ETH,
540
+ anyAmount,
541
+ anyReceivingAddress,
542
+ anyRefundAddress,
543
+ anyValidRawSwapData,
544
+ anyIp,
545
+ false
546
+ );
547
+
548
+ result.reason.should.equal(
549
+ SwapProvider.CREATION_FAIL_REASONS.RETRIABLE_FAIL
550
+ );
551
+ });
552
+
553
+ it('Should return retriable fail for status 422 and specific "Currency not found" error text', async () => {
554
+ axiosPostStub.rejects({
555
+ response: { status: 422, data: "Currency not found" },
556
+ });
557
+
558
+ const result = await swapspaceSwapProvider.createSwap(
559
+ USDCTRC20,
560
+ ETH,
561
+ anyAmount,
562
+ anyReceivingAddress,
563
+ anyRefundAddress,
564
+ anyValidRawSwapData,
565
+ anyIp,
566
+ false
567
+ );
568
+
569
+ result.reason.should.equal(
570
+ SwapProvider.CREATION_FAIL_REASONS.RETRIABLE_FAIL
571
+ );
572
+ });
573
+
574
+ it("Should return the correct swap details if response is valid", async () => {
575
+ axiosPostStub.resolves({
576
+ data: {
577
+ id: "test-id",
578
+ from: { amount: 1, address: "from-address" },
579
+ to: { amount: 2, address: "to-address" },
580
+ rate: 2,
581
+ fixed: false,
582
+ },
583
+ });
584
+
585
+ const result = await swapspaceSwapProvider.createSwap(
586
+ USDCTRC20,
587
+ ETH,
588
+ anyAmount,
589
+ anyReceivingAddress,
590
+ anyRefundAddress,
591
+ anyValidRawSwapData,
592
+ anyIp,
593
+ false
594
+ );
595
+
596
+ result.should.have.property("swapId", "test-id");
597
+ });
598
+
599
+ it("Should return true in the result property when successful", async () => {
600
+ axiosPostStub.resolves({
601
+ data: {
602
+ id: "test-id",
603
+ from: { amount: 1, address: "any" },
604
+ to: { amount: 2, address: "any" },
605
+ rate: 0.5,
606
+ fixed: false,
607
+ },
608
+ });
609
+
610
+ const result = await swapspaceSwapProvider.createSwap(
611
+ USDCTRC20,
612
+ ETH,
613
+ anyAmount,
614
+ anyReceivingAddress,
615
+ anyRefundAddress,
616
+ anyValidRawSwapData,
617
+ anyIp,
618
+ false
619
+ );
620
+
621
+ result.should.have.property("result", true);
622
+ });
623
+
624
+ it("Should return a proper structure for a successful swap creation", async () => {
625
+ axiosPostStub.resolves({
626
+ data: {
627
+ id: "test-id",
628
+ from: { amount: 1, address: "from-address" },
629
+ to: { amount: 2, address: "to-address" },
630
+ rate: 2,
631
+ fixed: false,
632
+ },
633
+ });
634
+
635
+ const result = await swapspaceSwapProvider.createSwap(
636
+ USDCTRC20,
637
+ ETH,
638
+ anyAmount,
639
+ anyReceivingAddress,
640
+ anyRefundAddress,
641
+ anyValidRawSwapData,
642
+ anyIp,
643
+ false
644
+ );
645
+
646
+ result.result.should.be.Boolean();
647
+ result.swapId.should.be.String();
648
+ result.fromCoin.should.be.instanceOf(Coin);
649
+ result.fromAmount.should.be.String();
650
+ result.fromAddress.should.be.String();
651
+ result.toCoin.should.be.instanceOf(Coin);
652
+ result.toAmount.should.be.String();
653
+ result.toAddress.should.be.String();
654
+ result.rate.should.be.String();
655
+ result.fixed.should.be.Boolean();
656
+ });
657
+
658
+ it("Should calculate rate if not provided in the response", async () => {
659
+ axiosPostStub.resolves({
660
+ data: {
661
+ id: "test-id",
662
+ from: { amount: 1, address: "any" },
663
+ to: { amount: 2, address: "any" },
664
+ fixed: false,
665
+ },
666
+ });
667
+
668
+ const result = await swapspaceSwapProvider.createSwap(
669
+ USDCTRC20,
670
+ ETH,
671
+ anyAmount,
672
+ anyReceivingAddress,
673
+ anyRefundAddress,
674
+ anyValidRawSwapData,
675
+ anyIp,
676
+ false
677
+ );
678
+
679
+ result.rate.should.equal("2.00000000000000000000");
680
+ });
681
+
682
+ it("Should calculate rate if the provided in the response is 0", async () => {
683
+ axiosPostStub.resolves({
684
+ data: {
685
+ id: "test-id",
686
+ from: { amount: 1, address: "any" },
687
+ to: { amount: 2, address: "any" },
688
+ rate: 0,
689
+ fixed: false,
690
+ },
691
+ });
692
+
693
+ const result = await swapspaceSwapProvider.createSwap(
694
+ USDCTRC20,
695
+ ETH,
696
+ anyAmount,
697
+ anyReceivingAddress,
698
+ anyRefundAddress,
699
+ anyValidRawSwapData,
700
+ anyIp,
701
+ false
702
+ );
703
+
704
+ result.rate.should.equal("2.00000000000000000000");
705
+ });
706
+
707
+ it("Should return address details correctly as returned by swapspace", async () => {
708
+ axiosPostStub.resolves({
709
+ data: {
710
+ id: "test-id",
711
+ from: { amount: 4, address: "from-addr" },
712
+ to: { amount: 2, address: "to-addr" },
713
+ rate: 0.5,
714
+ fixed: false,
715
+ },
716
+ });
717
+
718
+ const result = await swapspaceSwapProvider.createSwap(
719
+ USDCTRC20,
720
+ ETH,
721
+ anyAmount,
722
+ anyReceivingAddress,
723
+ anyRefundAddress,
724
+ anyValidRawSwapData,
725
+ anyIp,
726
+ false
727
+ );
728
+
729
+ result.should.have.property("fromAddress", "from-addr");
730
+ result.should.have.property("toAddress", "to-addr");
731
+ });
732
+
733
+ it("Should return proper fromAmount from the response", async () => {
734
+ axiosPostStub.resolves({
735
+ data: {
736
+ id: "test-id",
737
+ from: { amount: 1131.0931, address: "any" },
738
+ to: { amount: 2, address: "any" },
739
+ rate: 0.5,
740
+ fixed: false,
741
+ },
742
+ });
743
+
744
+ const result = await swapspaceSwapProvider.createSwap(
745
+ USDCTRC20,
746
+ ETH,
747
+ anyAmount,
748
+ anyReceivingAddress,
749
+ anyRefundAddress,
750
+ anyValidRawSwapData,
751
+ anyIp,
752
+ false
753
+ );
754
+
755
+ result.should.have.property("fromAmount", "1131.093100");
756
+ });
757
+
758
+ it("Should throw an error if from coin is not Coin", async () => {
759
+ let error;
760
+ try {
761
+ await swapspaceSwapProvider.createSwap(
762
+ {},
763
+ ETH,
764
+ anyAmount,
765
+ anyReceivingAddress,
766
+ anyRefundAddress,
767
+ anyValidRawSwapData,
768
+ anyIp,
769
+ false
770
+ );
771
+ } catch (e) {
772
+ error = e;
773
+ }
774
+
775
+ error.message.should.match(/.*Invalid input: .*/);
776
+ });
777
+
778
+ it("Should throw an error if to coin is not Coin", async () => {
779
+ let error;
780
+ try {
781
+ await swapspaceSwapProvider.createSwap(
782
+ ETH,
783
+ {},
784
+ anyAmount,
785
+ anyReceivingAddress,
786
+ anyRefundAddress,
787
+ anyValidRawSwapData,
788
+ anyIp,
789
+ false
790
+ );
791
+ } catch (e) {
792
+ error = e;
793
+ }
794
+
795
+ error.message.should.match(/.*Invalid input: .*/);
796
+ });
797
+
798
+ it("Should throw an error if amount is not string", async () => {
799
+ let error;
800
+ try {
801
+ await swapspaceSwapProvider.createSwap(
802
+ BTC,
803
+ ETH,
804
+ 1,
805
+ anyReceivingAddress,
806
+ anyRefundAddress,
807
+ anyValidRawSwapData,
808
+ anyIp,
809
+ false
810
+ );
811
+ } catch (e) {
812
+ error = e;
813
+ }
814
+
815
+ error.message.should.match(/.*Invalid input: .*/);
816
+ });
817
+
818
+ it("Should throw an error if address is not string", async () => {
819
+ let error;
820
+ try {
821
+ await swapspaceSwapProvider.createSwap(
822
+ BTC,
823
+ ETH,
824
+ anyAmount,
825
+ 1,
826
+ anyRefundAddress,
827
+ anyValidRawSwapData,
828
+ anyIp,
829
+ false
830
+ );
831
+ } catch (e) {
832
+ error = e;
833
+ }
834
+
835
+ error.message.should.match(/.*Invalid input: .*/);
836
+ });
837
+
838
+ it("Should throw an error if refund address is not string", async () => {
839
+ let error;
840
+ try {
841
+ await swapspaceSwapProvider.createSwap(
842
+ BTC,
843
+ ETH,
844
+ anyAmount,
845
+ anyReceivingAddress,
846
+ null,
847
+ anyValidRawSwapData,
848
+ anyIp,
849
+ false
850
+ );
851
+ } catch (e) {
852
+ error = e;
853
+ }
854
+
855
+ error.message.should.match(/.*Invalid input: .*/);
856
+ });
857
+
858
+ it("Should throw an error if IP address is not string", async () => {
859
+ let error;
860
+ try {
861
+ await swapspaceSwapProvider.createSwap(
862
+ BTC,
863
+ ETH,
864
+ anyAmount,
865
+ anyReceivingAddress,
866
+ anyRefundAddress,
867
+ anyValidRawSwapData,
868
+ null,
869
+ false
870
+ );
871
+ } catch (e) {
872
+ error = e;
873
+ }
874
+
875
+ error.message.should.match(/.*Invalid input: .*/);
876
+ });
877
+
878
+ it("Should throw an error if IP address is empty string", async () => {
879
+ let error;
880
+ try {
881
+ await swapspaceSwapProvider.createSwap(
882
+ BTC,
883
+ ETH,
884
+ anyAmount,
885
+ anyReceivingAddress,
886
+ anyRefundAddress,
887
+ anyValidRawSwapData,
888
+ "",
889
+ false
890
+ );
891
+ } catch (e) {
892
+ error = e;
893
+ }
894
+
895
+ error.message.should.match(/.*Invalid input: .*/);
896
+ });
897
+
898
+ it("Should throw an error if fixed is not boolean", async () => {
899
+ let error;
900
+ try {
901
+ await swapspaceSwapProvider.createSwap(
902
+ BTC,
903
+ ETH,
904
+ anyAmount,
905
+ anyReceivingAddress,
906
+ anyRefundAddress,
907
+ anyValidRawSwapData,
908
+ anyIp
909
+ );
910
+ } catch (e) {
911
+ error = e;
912
+ }
913
+
914
+ error.message.should.match(/.*Invalid input: .*/);
915
+ });
916
+
917
+ it("Should throw an error if swap data has not string fromCurrency", async () => {
918
+ let error;
919
+ try {
920
+ await swapspaceSwapProvider.createSwap(
921
+ BTC,
922
+ ETH,
923
+ anyAmount,
924
+ anyReceivingAddress,
925
+ anyRefundAddress,
926
+ { ...anyValidRawSwapData, fromCurrency: undefined },
927
+ anyIp,
928
+ false
929
+ );
930
+ } catch (e) {
931
+ error = e;
932
+ }
933
+
934
+ error.message.should.match(/.*Invalid raw swap data: .*/);
935
+ });
936
+
937
+ it("Should throw an error if swap data has not string fromNetwork", async () => {
938
+ let error;
939
+ try {
940
+ await swapspaceSwapProvider.createSwap(
941
+ BTC,
942
+ ETH,
943
+ anyAmount,
944
+ anyReceivingAddress,
945
+ anyRefundAddress,
946
+ { ...anyValidRawSwapData, fromNetwork: undefined },
947
+ anyIp,
948
+ false
949
+ );
950
+ } catch (e) {
951
+ error = e;
952
+ }
953
+
954
+ error.message.should.match(/.*Invalid raw swap data: .*/);
955
+ });
956
+
957
+ it("Should throw an error if swap data has not string toCurrency", async () => {
958
+ let error;
959
+ try {
960
+ await swapspaceSwapProvider.createSwap(
961
+ BTC,
962
+ ETH,
963
+ anyAmount,
964
+ anyReceivingAddress,
965
+ anyRefundAddress,
966
+ { ...anyValidRawSwapData, toCurrency: undefined },
967
+ anyIp,
968
+ false
969
+ );
970
+ } catch (e) {
971
+ error = e;
972
+ }
973
+
974
+ error.message.should.match(/.*Invalid raw swap data: .*/);
975
+ });
976
+
977
+ it("Should throw an error if swap data has not string toNetwork", async () => {
978
+ let error;
979
+ try {
980
+ await swapspaceSwapProvider.createSwap(
981
+ BTC,
982
+ ETH,
983
+ anyAmount,
984
+ anyReceivingAddress,
985
+ anyRefundAddress,
986
+ { ...anyValidRawSwapData, toNetwork: undefined },
987
+ anyIp,
988
+ false
989
+ );
990
+ } catch (e) {
991
+ error = e;
992
+ }
993
+
994
+ error.message.should.match(/.*Invalid raw swap data: .*/);
995
+ });
996
+
997
+ it("Should throw an error if swap data has not string id", async () => {
998
+ let error;
999
+ try {
1000
+ await swapspaceSwapProvider.createSwap(
1001
+ BTC,
1002
+ ETH,
1003
+ anyAmount,
1004
+ anyReceivingAddress,
1005
+ anyRefundAddress,
1006
+ { ...anyValidRawSwapData, id: undefined },
1007
+ anyIp,
1008
+ false
1009
+ );
1010
+ } catch (e) {
1011
+ error = e;
1012
+ }
1013
+
1014
+ error.message.should.match(/.*Invalid raw swap data: .*/);
1015
+ });
1016
+
1017
+ it("Should return proper toAmount from the response", async () => {
1018
+ axiosPostStub.resolves({
1019
+ data: {
1020
+ id: "test-id",
1021
+ from: { amount: 1131.0931, address: "any" },
1022
+ to: { amount: 2091.92301, address: "any" },
1023
+ rate: 0.5,
1024
+ fixed: false,
1025
+ },
1026
+ });
1027
+
1028
+ const result = await swapspaceSwapProvider.createSwap(
1029
+ USDCTRC20,
1030
+ ETH,
1031
+ anyAmount,
1032
+ anyReceivingAddress,
1033
+ anyRefundAddress,
1034
+ anyValidRawSwapData,
1035
+ anyIp,
1036
+ false
1037
+ );
1038
+
1039
+ result.should.have.property("toAmount", "2091.923010000000000000");
1040
+ });
1041
+
1042
+ it("Should handle scenario when amounts or addresses in the response are null", async () => {
1043
+ axiosPostStub.resolves({
1044
+ data: {
1045
+ id: "test-id",
1046
+ from: { amount: null, address: null },
1047
+ to: { amount: null, address: null },
1048
+ fixed: false,
1049
+ },
1050
+ });
1051
+
1052
+ await swapspaceSwapProvider
1053
+ .createSwap(
1054
+ USDCTRC20,
1055
+ ETH,
1056
+ anyAmount,
1057
+ anyReceivingAddress,
1058
+ anyRefundAddress,
1059
+ anyValidRawSwapData,
1060
+ anyIp,
1061
+ false
1062
+ )
1063
+ .should.be.rejectedWith(/.*Wrong swap creation result.*/);
1064
+ });
1065
+
1066
+ it("Should handle non-200 HTTP status codes", async () => {
1067
+ axiosPostStub.rejects({
1068
+ response: { status: 500, data: "Server Error" },
1069
+ });
1070
+
1071
+ let error;
1072
+ try {
1073
+ await swapspaceSwapProvider.createSwap(
1074
+ USDCTRC20,
1075
+ ETH,
1076
+ anyAmount,
1077
+ anyReceivingAddress,
1078
+ anyRefundAddress,
1079
+ anyValidRawSwapData,
1080
+ anyIp,
1081
+ false
1082
+ );
1083
+ } catch (e) {
1084
+ error = e;
1085
+ }
1086
+
1087
+ error.response.status.should.be.equal(500);
1088
+ error.response.data.should.be.equal("Server Error");
1089
+ });
1090
+
1091
+ it("Should handle network errors without response data", async () => {
1092
+ axiosPostStub.rejects(new Error("Network Error"));
1093
+
1094
+ await swapspaceSwapProvider
1095
+ .createSwap(
1096
+ USDCTRC20,
1097
+ ETH,
1098
+ anyAmount,
1099
+ anyReceivingAddress,
1100
+ anyRefundAddress,
1101
+ anyValidRawSwapData,
1102
+ anyIp,
1103
+ false
1104
+ )
1105
+ .should.be.rejectedWith(/.*Network Error.*/);
1106
+ });
1107
+
1108
+ it("Should handle cases when provided rate in the response is non-numeric", async () => {
1109
+ axiosPostStub.resolves({
1110
+ data: {
1111
+ id: "test-id",
1112
+ from: { amount: 1, address: "from-address" },
1113
+ to: { amount: 2, address: "to-address" },
1114
+ rate: "invalid",
1115
+ fixed: false,
1116
+ },
1117
+ });
1118
+
1119
+ const result = await swapspaceSwapProvider.createSwap(
1120
+ USDCTRC20,
1121
+ ETH,
1122
+ anyAmount,
1123
+ anyReceivingAddress,
1124
+ anyRefundAddress,
1125
+ anyValidRawSwapData,
1126
+ anyIp,
1127
+ false
1128
+ );
1129
+
1130
+ result.rate.should.equal("2.00000000000000000000");
1131
+ });
1132
+
1133
+ it("Should reject when _fetchSupportedCurrenciesIfNeeded throws an error", async () => {
1134
+ fetchSupportedCurrenciesStub.rejects(new Error("Fetching Error"));
1135
+
1136
+ await swapspaceSwapProvider
1137
+ .createSwap(
1138
+ USDCTRC20,
1139
+ ETH,
1140
+ anyAmount,
1141
+ anyReceivingAddress,
1142
+ anyRefundAddress,
1143
+ anyValidRawSwapData,
1144
+ anyIp,
1145
+ false
1146
+ )
1147
+ .should.be.rejectedWith(/.*Fetching Error.*/);
1148
+ });
1149
+
1150
+ it("Should handle the scenario when axios.post throws an error with no response object", async () => {
1151
+ axiosPostStub.rejects(new Error("Network Error"));
1152
+
1153
+ await swapspaceSwapProvider
1154
+ .createSwap(
1155
+ USDCTRC20,
1156
+ ETH,
1157
+ anyAmount,
1158
+ anyReceivingAddress,
1159
+ anyRefundAddress,
1160
+ anyValidRawSwapData,
1161
+ anyIp,
1162
+ false
1163
+ )
1164
+ .should.be.rejectedWith(/.*Network Error.*/);
1165
+ });
1166
+
1167
+ it('Should handle axios.post returning a response with no "id"', async () => {
1168
+ axiosPostStub.resolves({ data: {} });
1169
+
1170
+ await swapspaceSwapProvider
1171
+ .createSwap(
1172
+ USDCTRC20,
1173
+ ETH,
1174
+ anyAmount,
1175
+ anyReceivingAddress,
1176
+ anyRefundAddress,
1177
+ anyValidRawSwapData,
1178
+ anyIp,
1179
+ false
1180
+ )
1181
+ .should.be.rejectedWith(
1182
+ /.*Swap creation succeeded but the response is wrong:.*/
1183
+ );
1184
+ });
1185
+
1186
+ it("Should handle axios.post returning a response with no from amount or invalid", async () => {
1187
+ axiosPostStub.resolves({
1188
+ data: {
1189
+ id: "test-id",
1190
+ from: { amount: "1", address: "from-address" },
1191
+ to: { amount: 2, address: "to-address" },
1192
+ rate: 2,
1193
+ fixed: false,
1194
+ },
1195
+ });
1196
+
1197
+ await swapspaceSwapProvider
1198
+ .createSwap(
1199
+ USDCTRC20,
1200
+ ETH,
1201
+ anyAmount,
1202
+ anyReceivingAddress,
1203
+ anyRefundAddress,
1204
+ anyValidRawSwapData,
1205
+ anyIp,
1206
+ false
1207
+ )
1208
+ .should.be.rejectedWith(/.*Wrong swap creation result.*/);
1209
+ });
1210
+
1211
+ it("Should handle axios.post returning a response with no to amount or invalid", async () => {
1212
+ axiosPostStub.resolves({
1213
+ data: {
1214
+ id: "test-id",
1215
+ from: { amount: 1, address: "from-address" },
1216
+ to: { amount: "2", address: "to-address" },
1217
+ rate: 2,
1218
+ fixed: false,
1219
+ },
1220
+ });
1221
+
1222
+ await swapspaceSwapProvider
1223
+ .createSwap(
1224
+ USDCTRC20,
1225
+ ETH,
1226
+ anyAmount,
1227
+ anyReceivingAddress,
1228
+ anyRefundAddress,
1229
+ anyValidRawSwapData,
1230
+ anyIp,
1231
+ false
1232
+ )
1233
+ .should.be.rejectedWith(/.*Wrong swap creation result.*/);
1234
+ });
1235
+
1236
+ it("Should handle axios.post returning a response with no from address or invalid", async () => {
1237
+ axiosPostStub.resolves({
1238
+ data: {
1239
+ id: "test-id",
1240
+ from: { amount: 1, address: null },
1241
+ to: { amount: 2, address: "to-address" },
1242
+ rate: 2,
1243
+ fixed: false,
1244
+ },
1245
+ });
1246
+
1247
+ await swapspaceSwapProvider
1248
+ .createSwap(
1249
+ USDCTRC20,
1250
+ ETH,
1251
+ anyAmount,
1252
+ anyReceivingAddress,
1253
+ anyRefundAddress,
1254
+ anyValidRawSwapData,
1255
+ anyIp,
1256
+ false
1257
+ )
1258
+ .should.be.rejectedWith(/.*Wrong swap creation result.*/);
1259
+ });
1260
+
1261
+ it("Should handle axios.post returning a response with no to address or invalid", async () => {
1262
+ axiosPostStub.resolves({
1263
+ data: {
1264
+ id: "test-id",
1265
+ from: { amount: 1, address: "from-address" },
1266
+ to: { amount: 2, address: null },
1267
+ rate: 2,
1268
+ fixed: false,
1269
+ },
1270
+ });
1271
+
1272
+ await swapspaceSwapProvider
1273
+ .createSwap(
1274
+ USDCTRC20,
1275
+ ETH,
1276
+ anyAmount,
1277
+ anyReceivingAddress,
1278
+ anyRefundAddress,
1279
+ anyValidRawSwapData,
1280
+ anyIp,
1281
+ false
1282
+ )
1283
+ .should.be.rejectedWith(/.*Wrong swap creation result.*/);
1284
+ });
1285
+
1286
+ it("Should handle axios.post returning a response with non-boolean fixed", async () => {
1287
+ axiosPostStub.resolves({
1288
+ data: {
1289
+ id: "test-id",
1290
+ from: { amount: 1, address: "from-address" },
1291
+ to: { amount: 2, address: null },
1292
+ rate: 2,
1293
+ fixed: 1,
1294
+ },
1295
+ });
1296
+
1297
+ await swapspaceSwapProvider
1298
+ .createSwap(
1299
+ USDCTRC20,
1300
+ ETH,
1301
+ anyAmount,
1302
+ anyReceivingAddress,
1303
+ anyRefundAddress,
1304
+ anyValidRawSwapData,
1305
+ anyIp,
1306
+ false
1307
+ )
1308
+ .should.be.rejectedWith(/.*Wrong swap creation result.*/);
1309
+ });
1310
+ });
1311
+ });