@rabbitio/ui-kit 1.0.0-beta.110 → 1.0.0-beta.112

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 (212) hide show
  1. package/.env +1 -1
  2. package/.env.example +1 -1
  3. package/coverage/clover.xml +1411 -1410
  4. package/coverage/coverage-final.json +18 -18
  5. package/coverage/index.html +17 -17
  6. package/coverage/ui-kit/index.html +1 -1
  7. package/coverage/ui-kit/index.js.html +1 -1
  8. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/googleAnalyticsAdapter.js.html +1 -1
  9. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/index.html +1 -1
  10. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/metrikaAdapter.js.html +1 -1
  11. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/mixpanelAdapter.js.html +1 -1
  12. package/coverage/ui-kit/src/common-apis/adapters/axiosAdapter.js.html +1 -1
  13. package/coverage/ui-kit/src/common-apis/adapters/index.html +1 -1
  14. package/coverage/ui-kit/src/common-apis/adapters/qrUtils.js.html +1 -1
  15. package/coverage/ui-kit/src/common-apis/external-apis/apiGroups.js.html +1 -1
  16. package/coverage/ui-kit/src/common-apis/external-apis/emailAPI.js.html +1 -1
  17. package/coverage/ui-kit/src/common-apis/external-apis/index.html +1 -1
  18. package/coverage/ui-kit/src/common-apis/external-apis/ipAddressProviders.js.html +1 -1
  19. package/coverage/ui-kit/src/common-apis/globalConstants.jsx.html +1 -1
  20. package/coverage/ui-kit/src/common-apis/index.html +1 -1
  21. package/coverage/ui-kit/src/common-apis/models/blockchain.js.html +4 -4
  22. package/coverage/ui-kit/src/common-apis/models/coin.js.html +221 -221
  23. package/coverage/ui-kit/src/common-apis/models/index.html +1 -1
  24. package/coverage/ui-kit/src/common-apis/models/protocol.js.html +3 -3
  25. package/coverage/ui-kit/src/common-apis/services/fiatCurrenciesService.js.html +1 -1
  26. package/coverage/ui-kit/src/common-apis/services/index.html +1 -1
  27. package/coverage/ui-kit/src/common-apis/utils/amountUtils.js.html +21 -21
  28. package/coverage/ui-kit/src/common-apis/utils/cache.js.html +6 -6
  29. package/coverage/ui-kit/src/common-apis/utils/errorUtils.js.html +13 -13
  30. package/coverage/ui-kit/src/common-apis/utils/index.html +1 -1
  31. package/coverage/ui-kit/src/common-apis/utils/logging/index.html +1 -1
  32. package/coverage/ui-kit/src/common-apis/utils/logging/logger.js.html +22 -22
  33. package/coverage/ui-kit/src/common-apis/utils/logging/logsStorage.js.html +3 -3
  34. package/coverage/ui-kit/src/common-apis/utils/postponeExecution.js.html +1 -1
  35. package/coverage/ui-kit/src/common-apis/utils/rabbitTicker.js.html +10 -10
  36. package/coverage/ui-kit/src/common-apis/utils/safeStringify.js.html +27 -27
  37. package/coverage/ui-kit/src/index.html +1 -1
  38. package/coverage/ui-kit/src/index.js.html +1 -1
  39. package/coverage/ui-kit/src/robust-api-caller/cacheAndConcurrentRequestsResolver.js.html +1 -1
  40. package/coverage/ui-kit/src/robust-api-caller/cachedRobustExternalApiCallerService.js.html +1 -1
  41. package/coverage/ui-kit/src/robust-api-caller/cancelProcessing.js.html +1 -1
  42. package/coverage/ui-kit/src/robust-api-caller/concurrentCalculationsMetadataHolder.js.html +1 -1
  43. package/coverage/ui-kit/src/robust-api-caller/externalApiProvider.js.html +1 -1
  44. package/coverage/ui-kit/src/robust-api-caller/externalServicesStatsCollector.js.html +1 -1
  45. package/coverage/ui-kit/src/robust-api-caller/index.html +1 -1
  46. package/coverage/ui-kit/src/robust-api-caller/robustExternalAPICallerService.js.html +1 -1
  47. package/coverage/ui-kit/src/swaps-lib/external-apis/exolixSwapProvider.js.html +66 -45
  48. package/coverage/ui-kit/src/swaps-lib/external-apis/goexmeSwapProvider.js.html +521 -545
  49. package/coverage/ui-kit/src/swaps-lib/external-apis/index.html +27 -27
  50. package/coverage/ui-kit/src/swaps-lib/external-apis/letsExchangeSwapProvider.js.html +1 -1
  51. package/coverage/ui-kit/src/swaps-lib/external-apis/swapProvider.js.html +328 -328
  52. package/coverage/ui-kit/src/swaps-lib/external-apis/swapspaceSwapProvider.js.html +76 -52
  53. package/coverage/ui-kit/src/swaps-lib/external-apis/utils.js.html +14 -14
  54. package/coverage/ui-kit/src/swaps-lib/models/baseSwapCreationInfo.js.html +1 -1
  55. package/coverage/ui-kit/src/swaps-lib/models/existingSwap.js.html +141 -141
  56. package/coverage/ui-kit/src/swaps-lib/models/existingSwapWithFiatData.js.html +1 -1
  57. package/coverage/ui-kit/src/swaps-lib/models/index.html +1 -1
  58. package/coverage/ui-kit/src/swaps-lib/models/partner.js.html +1 -1
  59. package/coverage/ui-kit/src/swaps-lib/models/swapProviderCoinInfo.js.html +73 -73
  60. package/coverage/ui-kit/src/swaps-lib/services/index.html +1 -1
  61. package/coverage/ui-kit/src/swaps-lib/services/publicSwapService.js.html +1 -1
  62. package/coverage/ui-kit/src/swaps-lib/utils/index.html +1 -1
  63. package/coverage/ui-kit/src/swaps-lib/utils/swapUtils.js.html +1 -1
  64. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/arrowIcon.jsx.html +1 -1
  65. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/arrowTosca.jsx.html +1 -1
  66. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/arrowWhite.jsx.html +1 -1
  67. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/darkRectangle.jsx.html +1 -1
  68. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/determinedError.jsx.html +1 -1
  69. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/failedValidationIcon.jsx.html +1 -1
  70. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/index.html +1 -1
  71. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/infoIcon.jsx.html +1 -1
  72. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/messageIcon.jsx.html +1 -1
  73. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/noticeQuestionIcon.jsx.html +1 -1
  74. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/successfulValidationIcon.jsx.html +1 -1
  75. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/supportDialogImage.jsx.html +1 -1
  76. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/walletIcon.jsx.html +1 -1
  77. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetIcon/AssetIcon.jsx.html +1 -1
  78. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetIcon/index.html +1 -1
  79. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetSelection/AssetSelection.jsx.html +1 -1
  80. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetSelection/index.html +1 -1
  81. package/coverage/ui-kit/src/ui-kit/components/atoms/BackgroundTitle/BackgroundTitle.jsx.html +1 -1
  82. package/coverage/ui-kit/src/ui-kit/components/atoms/BackgroundTitle/index.html +1 -1
  83. package/coverage/ui-kit/src/ui-kit/components/atoms/InformationMessage/InformationMessage.jsx.html +1 -1
  84. package/coverage/ui-kit/src/ui-kit/components/atoms/InformationMessage/index.html +1 -1
  85. package/coverage/ui-kit/src/ui-kit/components/atoms/Input/Input.jsx.html +1 -1
  86. package/coverage/ui-kit/src/ui-kit/components/atoms/Input/index.html +1 -1
  87. package/coverage/ui-kit/src/ui-kit/components/atoms/LoadingDots/LoadingDots.jsx.html +1 -1
  88. package/coverage/ui-kit/src/ui-kit/components/atoms/LoadingDots/index.html +1 -1
  89. package/coverage/ui-kit/src/ui-kit/components/atoms/NoticeIcon/NoticeIcon.jsx.html +1 -1
  90. package/coverage/ui-kit/src/ui-kit/components/atoms/NoticeIcon/index.html +1 -1
  91. package/coverage/ui-kit/src/ui-kit/components/atoms/QrCode/QrCode.jsx.html +7 -25
  92. package/coverage/ui-kit/src/ui-kit/components/atoms/QrCode/index.html +5 -5
  93. package/coverage/ui-kit/src/ui-kit/components/atoms/RateSelector/RateSelector.jsx.html +1 -1
  94. package/coverage/ui-kit/src/ui-kit/components/atoms/RateSelector/index.html +1 -1
  95. package/coverage/ui-kit/src/ui-kit/components/atoms/SupportChat/SupportChat.jsx.html +1 -1
  96. package/coverage/ui-kit/src/ui-kit/components/atoms/SupportChat/index.html +1 -1
  97. package/coverage/ui-kit/src/ui-kit/components/atoms/Textarea/Textarea.jsx.html +1 -1
  98. package/coverage/ui-kit/src/ui-kit/components/atoms/Textarea/index.html +1 -1
  99. package/coverage/ui-kit/src/ui-kit/components/atoms/TitleBox/TitleBox.jsx.html +1 -1
  100. package/coverage/ui-kit/src/ui-kit/components/atoms/TitleBox/index.html +1 -1
  101. package/coverage/ui-kit/src/ui-kit/components/atoms/Tooltip/Tooltip.jsx.html +1 -1
  102. package/coverage/ui-kit/src/ui-kit/components/atoms/Tooltip/index.html +1 -1
  103. package/coverage/ui-kit/src/ui-kit/components/atoms/TwoLinesOfText/LinesOfText.jsx.html +1 -1
  104. package/coverage/ui-kit/src/ui-kit/components/atoms/TwoLinesOfText/index.html +1 -1
  105. package/coverage/ui-kit/src/ui-kit/components/atoms/Validation/Validation.jsx.html +1 -1
  106. package/coverage/ui-kit/src/ui-kit/components/atoms/Validation/index.html +1 -1
  107. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Button/Button.jsx.html +1 -1
  108. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Button/index.html +1 -1
  109. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Close/Close.jsx.html +1 -1
  110. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Close/index.html +1 -1
  111. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/LinkButton/LinkButton.jsx.html +1 -1
  112. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/LinkButton/index.html +1 -1
  113. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/RadioButtonWithText/RadioButtonWithText.jsx.html +1 -1
  114. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/RadioButtonWithText/index.html +1 -1
  115. package/coverage/ui-kit/src/ui-kit/components/molecules/AmountInput/AmountInput.jsx.html +1 -1
  116. package/coverage/ui-kit/src/ui-kit/components/molecules/AmountInput/index.html +1 -1
  117. package/coverage/ui-kit/src/ui-kit/components/molecules/CoinPicker/CoinPicker.jsx.html +1 -1
  118. package/coverage/ui-kit/src/ui-kit/components/molecules/CoinPicker/index.html +1 -1
  119. package/coverage/ui-kit/src/ui-kit/components/molecules/ColoredNotice/ColoredNotice.jsx.html +1 -1
  120. package/coverage/ui-kit/src/ui-kit/components/molecules/ColoredNotice/index.html +1 -1
  121. package/coverage/ui-kit/src/ui-kit/components/molecules/LineWithIconLink/LineWithIconLink.jsx.html +1 -1
  122. package/coverage/ui-kit/src/ui-kit/components/molecules/LineWithIconLink/index.html +1 -1
  123. package/coverage/ui-kit/src/ui-kit/components/molecules/LogoCarousel/LogoCarousel.jsx.html +1 -1
  124. package/coverage/ui-kit/src/ui-kit/components/molecules/LogoCarousel/index.html +1 -1
  125. package/coverage/ui-kit/src/ui-kit/components/molecules/SearchableCoinsList/SearchableCoinsList.jsx.html +1 -1
  126. package/coverage/ui-kit/src/ui-kit/components/molecules/SearchableCoinsList/index.html +1 -1
  127. package/coverage/ui-kit/src/ui-kit/components/molecules/TitledLineWithIconLink/TitledLineWithIconLink.jsx.html +1 -1
  128. package/coverage/ui-kit/src/ui-kit/components/molecules/TitledLineWithIconLink/index.html +1 -1
  129. package/coverage/ui-kit/src/ui-kit/components/organisms/CoinPickerDialogStep/CoinPickerDialogStep.jsx.html +1 -1
  130. package/coverage/ui-kit/src/ui-kit/components/organisms/CoinPickerDialogStep/index.html +1 -1
  131. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/Dialog.jsx.html +1 -1
  132. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogButtons/DialogButtons.jsx.html +1 -1
  133. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogButtons/index.html +1 -1
  134. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogStep/DialogStep.jsx.html +1 -1
  135. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogStep/index.html +1 -1
  136. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/index.html +1 -1
  137. package/coverage/ui-kit/src/ui-kit/components/organisms/SwapForm/SwapForm.jsx.html +1 -1
  138. package/coverage/ui-kit/src/ui-kit/components/organisms/SwapForm/index.html +1 -1
  139. package/coverage/ui-kit/src/ui-kit/components/organisms/WaitlistSubscription/WaitlistSubscription.jsx.html +1 -1
  140. package/coverage/ui-kit/src/ui-kit/components/organisms/WaitlistSubscription/index.html +1 -1
  141. package/coverage/ui-kit/src/ui-kit/components/templates/DeterminedErrorDialogStep/DeterminedErrorDialogStep.jsx.html +1 -1
  142. package/coverage/ui-kit/src/ui-kit/components/templates/DeterminedErrorDialogStep/index.html +1 -1
  143. package/coverage/ui-kit/src/ui-kit/hooks/index.html +1 -1
  144. package/coverage/ui-kit/src/ui-kit/hooks/useCallHandlingErrors.js.html +1 -1
  145. package/coverage/ui-kit/src/ui-kit/hooks/useIsHydrated.js.html +1 -1
  146. package/coverage/ui-kit/src/ui-kit/hooks/useReferredState.js.html +1 -1
  147. package/coverage/ui-kit/src/ui-kit/utils/index.html +1 -1
  148. package/coverage/ui-kit/src/ui-kit/utils/inputValueProviders.js.html +1 -1
  149. package/coverage/ui-kit/src/ui-kit/utils/searchCoins.js.html +1 -1
  150. package/coverage/ui-kit/src/ui-kit/utils/textUtils.js.html +1 -1
  151. package/coverage/ui-kit/src/ui-kit/utils/uiUtils.js.html +1 -1
  152. package/coverage/ui-kit/src/ui-kit/utils/urlQueryUtils.js.html +1 -1
  153. package/coverage/ui-kit/stories/atoms/BackgroundTitle.stories.jsx.html +1 -1
  154. package/coverage/ui-kit/stories/atoms/LinesOfText.stories.jsx.html +1 -1
  155. package/coverage/ui-kit/stories/atoms/LoadingDots.stories.jsx.html +1 -1
  156. package/coverage/ui-kit/stories/atoms/QrCode.stories.jsx.html +1 -1
  157. package/coverage/ui-kit/stories/atoms/RateSelector.stories.jsx.html +1 -1
  158. package/coverage/ui-kit/stories/atoms/Validation.stories.jsx.html +1 -1
  159. package/coverage/ui-kit/stories/atoms/buttons/Button.stories.jsx.html +1 -1
  160. package/coverage/ui-kit/stories/atoms/buttons/Close.stories.jsx.html +1 -1
  161. package/coverage/ui-kit/stories/atoms/buttons/LinkButton.stories.jsx.html +1 -1
  162. package/coverage/ui-kit/stories/atoms/buttons/index.html +1 -1
  163. package/coverage/ui-kit/stories/atoms/index.html +1 -1
  164. package/coverage/ui-kit/stories/molecules/AmountInput.stories.jsx.html +1 -1
  165. package/coverage/ui-kit/stories/molecules/CoinPicker.stories.jsx.html +1 -1
  166. package/coverage/ui-kit/stories/molecules/ColoredNotice.stories.jsx.html +1 -1
  167. package/coverage/ui-kit/stories/molecules/LineWithIconLink.stories.jsx.html +1 -1
  168. package/coverage/ui-kit/stories/molecules/LogoCarousel.stories.jsx.html +1 -1
  169. package/coverage/ui-kit/stories/molecules/TitledLineWithIconLink.stories.jsx.html +1 -1
  170. package/coverage/ui-kit/stories/molecules/index.html +1 -1
  171. package/coverage/ui-kit/stories/organisms/Dialog/Dialog.stories.jsx.html +1 -1
  172. package/coverage/ui-kit/stories/organisms/Dialog/DialogButtons/DialogButtons.stories.jsx.html +1 -1
  173. package/coverage/ui-kit/stories/organisms/Dialog/DialogButtons/index.html +1 -1
  174. package/coverage/ui-kit/stories/organisms/Dialog/DialogStep/DialogStep.stories.jsx.html +1 -1
  175. package/coverage/ui-kit/stories/organisms/Dialog/DialogStep/index.html +1 -1
  176. package/coverage/ui-kit/stories/organisms/Dialog/index.html +1 -1
  177. package/coverage/ui-kit/stories/organisms/WaitlistSubscription.stories.jsx.html +1 -1
  178. package/coverage/ui-kit/stories/organisms/index.html +1 -1
  179. package/coverage/ui-kit/stories/stubs/coins.jsx.html +1 -1
  180. package/coverage/ui-kit/stories/stubs/exampleContent.jsx.html +1 -1
  181. package/coverage/ui-kit/stories/stubs/index.html +1 -1
  182. package/coverage/ui-kit/stories/templates/DeterminedErrorDialogStep.stories.jsx.html +1 -1
  183. package/coverage/ui-kit/stories/templates/index.html +1 -1
  184. package/dist/index.cjs +94 -92
  185. package/dist/index.cjs.map +1 -1
  186. package/dist/index.css +4 -12
  187. package/dist/index.css.map +1 -1
  188. package/dist/index.modern.js +82 -78
  189. package/dist/index.modern.js.map +1 -1
  190. package/dist/index.module.js +94 -92
  191. package/dist/index.module.js.map +1 -1
  192. package/dist/index.umd.js +94 -92
  193. package/dist/index.umd.js.map +1 -1
  194. package/package.json +1 -1
  195. package/src/common-apis/tests/integration/external-apis/ipAddressProviders/getClientIpAddress.test.js +9 -5
  196. package/src/swaps-lib/external-apis/exolixSwapProvider.js +46 -39
  197. package/src/swaps-lib/external-apis/goexmeSwapProvider.js +29 -37
  198. package/src/swaps-lib/external-apis/swapspaceSwapProvider.js +54 -46
  199. package/src/swaps-lib/models/existingSwap.js +1 -1
  200. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/_convertCurrencyMeta.test.js +80 -0
  201. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/_ensurePairsLoaded.test.js +77 -0
  202. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +50 -123
  203. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/createSwap.test.js +184 -72
  204. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/getExistingSwapsDetailsAndStatus.test.js +151 -0
  205. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/getSwapInfo.test.js +155 -104
  206. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/helpers.test.js +26 -0
  207. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/integration/PairSupport.int.test.js +57 -57
  208. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/integration/_fetchSupportedCurrenciesIfNeeded.int.test.js +289 -126
  209. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/integration/createSwap.int.test.js +320 -225
  210. package/src/swaps-lib/test/external-apis/goexmeSwapProvider/integration/getSwapInfo.int.test.js +138 -127
  211. package/src/ui-kit/components/atoms/QrCode/QrCode.jsx +2 -8
  212. package/src/ui-kit/components/atoms/QrCode/qr-code.module.scss +4 -11
@@ -1,171 +1,334 @@
1
1
  import "dotenv/config";
2
- import { describe, it, beforeEach, afterEach, expect, vi } from "vitest";
2
+ import sinon from "sinon";
3
+ import should from "should";
4
+ import { describe, it, beforeEach, afterEach } from "vitest";
3
5
  import axios from "axios";
6
+
4
7
  import { Cache } from "../../../../../common-apis/utils/cache.js";
5
8
  import { GoexmeSwapProvider } from "../../../../external-apis/goexmeSwapProvider.js";
9
+ import { FALLBACK_ASSET_ICON_URL } from "../../../../../common-apis/globalConstants.jsx";
6
10
 
7
11
  const GOEXME_API_KEY = process.env.GOEXME_API_KEY?.trim?.() || "";
8
12
  const maybeDescribe = GOEXME_API_KEY ? describe : describe.skip;
9
13
 
10
- maybeDescribe("GoexmeSwapProvider – live integration tests", () => {
11
- let provider;
12
- const axiosOriginalGet = axios.get;
14
+ maybeDescribe("external-apis/goexmeSwapProvider integration", function () {
15
+ describe("_fetchSupportedCurrenciesIfNeeded", function () {
16
+ let provider;
17
+ let axiosGetOriginal;
13
18
 
14
- beforeEach(() => {
15
- provider = new GoexmeSwapProvider("/", new Cache(), () => null, false, GOEXME_API_KEY);
16
- });
19
+ beforeEach(() => {
20
+ provider = new GoexmeSwapProvider("/", new Cache(), () => null, false, GOEXME_API_KEY);
21
+ axiosGetOriginal = axios.get;
22
+ });
17
23
 
18
- afterEach(() => {
19
- axios.get = axiosOriginalGet;
20
- });
24
+ afterEach(() => {
25
+ if (axios.get.restore) {
26
+ axios.get.restore();
27
+ } else {
28
+ axios.get = axiosGetOriginal;
29
+ }
30
+ });
31
+
32
+ const fetchRawCurrencies = async () => {
33
+ const { data } = await axiosGetOriginal(`${provider._URL}/currencies`, {
34
+ params: { key: GOEXME_API_KEY },
35
+ });
36
+ return data;
37
+ };
21
38
 
22
- const fetchRawCurrencies = async () => {
23
- const { data } = await axiosOriginalGet(`${provider._URL}/currencies`, {
24
- params: { key: GOEXME_API_KEY },
39
+ it("Should filter out unavailable coins", async () => {
40
+ const raw = await fetchRawCurrencies();
41
+ await provider._fetchSupportedCurrenciesIfNeeded();
42
+
43
+ const providerCodes = new Set(provider._supportedCoins.map(c => c.code));
44
+ const unavailableCodes = Object.entries(raw)
45
+ .filter(([, meta]) => meta?.available === false)
46
+ .map(([code]) => code.toUpperCase());
47
+
48
+ unavailableCodes.forEach(code => providerCodes.has(code).should.be.false());
49
+ providerCodes.size.should.be.above(0);
25
50
  });
26
- return data;
27
- };
28
51
 
29
- it("filters out unavailable coins", async () => {
30
- const raw = await fetchRawCurrencies();
31
- await provider._fetchSupportedCurrenciesIfNeeded();
52
+ it("Should set hasExtraId and extraIdName correctly", async () => {
53
+ const raw = await fetchRawCurrencies();
54
+ await provider._fetchSupportedCurrenciesIfNeeded();
32
55
 
33
- const providerCodes = new Set(provider._supportedCoins.map(c => c.code));
34
- const unavailableCodes = Object.entries(raw)
35
- .filter(([, meta]) => meta?.available === false)
36
- .map(([code]) => code.toUpperCase());
56
+ const infoWithTag = provider._supportedCoins.find(i => i.hasExtraId);
57
+ should.exist(infoWithTag);
37
58
 
38
- unavailableCodes.forEach(code => expect(providerCodes.has(code)).toBe(false));
39
- expect(providerCodes.size).toBeGreaterThan(0);
40
- });
59
+ const meta =
60
+ raw[infoWithTag.code] ??
61
+ Object.values(raw).find(m => (m.code ?? m.ticker ?? "").toUpperCase() === infoWithTag.code);
62
+ should.exist(meta);
63
+ (meta.tagname ?? "").trim().should.not.be.empty();
41
64
 
42
- it("sets hasExtraId and extraIdName correctly", async () => {
43
- const raw = await fetchRawCurrencies();
44
- await provider._fetchSupportedCurrenciesIfNeeded();
65
+ infoWithTag.extraIdName.should.equal(meta.tagname);
66
+ });
45
67
 
46
- const infoWithTag = provider._supportedCoins.find(i => i.hasExtraId);
47
- expect(infoWithTag).toBeDefined();
68
+ it("Should handle duplicate tickers across networks", async () => {
69
+ await provider._fetchSupportedCurrenciesIfNeeded();
48
70
 
49
- const meta =
50
- raw[infoWithTag.code] ??
51
- Object.values(raw).find(m => (m.code ?? m.ticker ?? "").toUpperCase() === infoWithTag.code);
52
- expect(meta).toBeDefined();
53
- expect((meta.tagname ?? "").trim()).not.toBe("");
71
+ const suffixRx = /(ERC20|TRC20|BEP20|BSC|AVALANCHEC|OPTIMISM|SOLANA|ARBITRUM)$/i;
72
+ const grouped = {};
54
73
 
55
- expect(infoWithTag.extraIdName).toBe(meta.tagname);
56
- });
74
+ provider._supportedCoins.forEach(i => {
75
+ const base = i.code.toUpperCase().replace(suffixRx, "");
76
+ grouped[base] = grouped[base] || [];
77
+ grouped[base].push(i);
78
+ });
57
79
 
58
- it("handles duplicate tickers across networks", async () => {
59
- await provider._fetchSupportedCurrenciesIfNeeded();
80
+ const entry = Object.entries(grouped).find(([, arr]) => arr.length >= 2);
81
+ if (!entry) return;
60
82
 
61
- const suffixRx = /(ERC20|TRC20|BEP20|BSC|AVALANCHEC|OPTIMISM|SOLANA|ARBITRUM)$/i;
62
- const grouped = {};
83
+ const [, infos] = entry;
84
+ infos.length.should.be.aboveOrEqual(2);
63
85
 
64
- provider._supportedCoins.forEach(i => {
65
- const base = i.code.toUpperCase().replace(suffixRx, "");
66
- grouped[base] = grouped[base] || [];
67
- grouped[base].push(i);
86
+ infos.forEach(info => {
87
+ provider._findInfoByTicker(info.coin.ticker).should.equal(info);
88
+ });
68
89
  });
69
90
 
70
- const entry = Object.entries(grouped).find(([, arr]) => arr.length >= 2);
71
- if (!entry) {
72
- console.warn("No duplicate tickers among allowed coins – skipping duplicate assertion");
73
- return;
74
- }
91
+ it("Should skip HTTP call when cached list is fresh", async () => {
92
+ provider._supportedCoins = [{ dummy: true }];
93
+ provider._supportedCoinsLastUpdateTimestamp = Date.now();
75
94
 
76
- const [, infos] = entry;
77
- expect(infos.length).toBeGreaterThanOrEqual(2);
95
+ let calls = 0;
96
+ sinon.stub(axios, "get").callsFake((url, opts) => {
97
+ if (url.includes("/currencies")) calls += 1;
98
+ return axiosGetOriginal(url, opts);
99
+ });
78
100
 
79
- infos.forEach(info => {
80
- expect(provider._findInfoByTicker(info.coin.ticker)).toBe(info);
101
+ await provider._fetchSupportedCurrenciesIfNeeded();
102
+ calls.should.equal(0);
81
103
  });
82
- });
83
104
 
84
- it("uses currencies cache within TTL", async () => {
85
- let calls = 0;
86
- axios.get = async (...args) => {
87
- if (args[0].includes("/currencies")) calls += 1;
88
- return axiosOriginalGet(...args);
89
- };
105
+ it("Should make one HTTP call when cache empty, then reuse cache within TTL", async () => {
106
+ let calls = 0;
107
+ sinon.stub(axios, "get").callsFake((url, opts) => {
108
+ if (url.includes("/currencies")) calls += 1;
109
+ return axiosGetOriginal(url, opts);
110
+ });
90
111
 
91
- await provider._fetchSupportedCurrenciesIfNeeded();
92
- provider._supportedCoinsLastUpdateTimestamp -= 4 * 60 * 1000;
93
- await provider._fetchSupportedCurrenciesIfNeeded();
112
+ await provider._fetchSupportedCurrenciesIfNeeded();
113
+ provider._supportedCoinsLastUpdateTimestamp -= 4 * 60 * 1000;
114
+ await provider._fetchSupportedCurrenciesIfNeeded();
94
115
 
95
- expect(calls).toBe(1);
96
- });
116
+ calls.should.equal(1);
117
+ });
97
118
 
98
- it("reloads currencies cache after TTL expiry", async () => {
99
- let calls = 0;
100
- axios.get = async (...args) => {
101
- if (args[0].includes("/currencies")) calls += 1;
102
- return axiosOriginalGet(...args);
103
- };
119
+ it("Should refresh list after TTL expiry", async () => {
120
+ let calls = 0;
121
+ sinon.stub(axios, "get").callsFake((url, opts) => {
122
+ if (url.includes("/currencies")) calls += 1;
123
+ return axiosGetOriginal(url, opts);
124
+ });
104
125
 
105
- await provider._fetchSupportedCurrenciesIfNeeded();
106
- provider._supportedCoinsLastUpdateTimestamp -= 10 * 60 * 1000;
107
- await provider._fetchSupportedCurrenciesIfNeeded();
126
+ await provider._fetchSupportedCurrenciesIfNeeded();
127
+ provider._supportedCoinsLastUpdateTimestamp -= 10 * 60 * 1000;
128
+ await provider._fetchSupportedCurrenciesIfNeeded();
108
129
 
109
- expect(calls).toBe(2);
110
- });
130
+ calls.should.equal(2);
131
+ });
111
132
 
112
- it("uses pairs cache within TTL", async () => {
113
- let calls = 0;
114
- axios.get = async (...args) => {
115
- if (args[0].includes("/pairs")) calls += 1;
116
- return axiosOriginalGet(...args);
117
- };
133
+ it("Should return empty list for status 200 with empty object", async () => {
134
+ sinon.stub(axios, "get").callsFake((url, opts = {}) => {
135
+ if (url.endsWith("/currencies")) {
136
+ return Promise.resolve({ status: 200, data: {} });
137
+ }
138
+ return axiosGetOriginal(url, opts);
139
+ });
118
140
 
119
- await provider._ensurePairsLoaded();
120
- provider._pairsCacheTimestamp -= 4 * 60 * 1000;
121
- await provider._ensurePairsLoaded();
141
+ await provider._fetchSupportedCurrenciesIfNeeded();
122
142
 
123
- expect(calls).toBe(1);
124
- });
143
+ Array.isArray(provider._supportedCoins).should.be.true();
144
+ provider._supportedCoins.length.should.equal(0);
145
+ });
125
146
 
126
- it("reloads pairs cache after TTL expiry", async () => {
127
- let calls = 0;
128
- axios.get = async (...args) => {
129
- if (args[0].includes("/pairs")) calls += 1;
130
- return axiosOriginalGet(...args);
131
- };
147
+ it("Should throw when status 200 with null data", async () => {
148
+ sinon.stub(axios, "get").callsFake((url, opts = {}) => {
149
+ if (url.endsWith("/currencies")) {
150
+ return Promise.resolve({ status: 200, data: null });
151
+ }
152
+ return axiosGetOriginal(url, opts);
153
+ });
132
154
 
133
- await provider._ensurePairsLoaded();
134
- provider._pairsCacheTimestamp -= 10 * 60 * 1000;
135
- await provider._ensurePairsLoaded();
155
+ await provider._fetchSupportedCurrenciesIfNeeded().should.be.rejected();
156
+ });
136
157
 
137
- expect(calls).toBe(2);
138
- });
158
+ it("Should return empty list for status 200 with data array", async () => {
159
+ sinon.stub(axios, "get").callsFake((url, opts = {}) => {
160
+ if (url.endsWith("/currencies")) {
161
+ return Promise.resolve({ status: 200, data: [] });
162
+ }
163
+ return axiosGetOriginal(url, opts);
164
+ });
139
165
 
140
- it("throws on non-200 response", async () => {
141
- axios.get = vi.fn((url, opts = {}) =>
142
- url.endsWith("/currencies") ? Promise.resolve({ status: 500, data: {} }) : axiosOriginalGet(url, opts)
143
- );
144
- await expect(provider._fetchSupportedCurrenciesIfNeeded()).rejects.toThrow();
145
- });
166
+ await provider._fetchSupportedCurrenciesIfNeeded();
167
+
168
+ Array.isArray(provider._supportedCoins).should.be.true();
169
+ provider._supportedCoins.length.should.equal(0);
170
+ });
146
171
 
147
- it("keeps cache consistent under concurrent calls", async () => {
148
- await Promise.all([
149
- provider._fetchSupportedCurrenciesIfNeeded(),
150
- provider._fetchSupportedCurrenciesIfNeeded(),
151
- provider._fetchSupportedCurrenciesIfNeeded(),
152
- ]);
172
+ it("Should throw when /currencies responds with non-200 status", async () => {
173
+ sinon.stub(axios, "get").callsFake((url, opts = {}) => {
174
+ if (url.endsWith("/currencies")) {
175
+ return Promise.resolve({ status: 400, data: {} });
176
+ }
177
+ return axiosGetOriginal(url, opts);
178
+ });
153
179
 
154
- expect(provider._supportedCoins.length).toBeGreaterThan(0);
155
- expect(provider._supportedCoinsLastUpdateTimestamp).toBeGreaterThan(0);
156
- });
180
+ await provider._fetchSupportedCurrenciesIfNeeded().should.be.rejected();
181
+ });
182
+
183
+ it("Should ensure every coin has a non-empty icon URL", async () => {
184
+ await provider._fetchSupportedCurrenciesIfNeeded();
185
+ provider._supportedCoins.length.should.be.above(0);
186
+ provider._supportedCoins.every(i => typeof i.iconURL === "string" && i.iconURL.length > 0).should.be.true();
187
+ });
188
+
189
+ it("Should persist raw meta fields exactly", async () => {
190
+ const raw = await fetchRawCurrencies();
191
+ const entry = Object.entries(raw).find(([code, meta]) => provider._convertCurrencyMeta(code, meta));
192
+ should.exist(entry);
193
+ const [code, meta] = entry;
194
+ await provider._fetchSupportedCurrenciesIfNeeded();
195
+
196
+ const info = provider._supportedCoins.find(i => i.code === code.toUpperCase());
197
+ should.exist(info);
198
+ info.code.should.equal(code.toUpperCase());
199
+
200
+ const net = (meta.network || "").toUpperCase() || null;
201
+ (info.network ?? null).should.equal(net ?? null);
202
+
203
+ const tag = (meta.tagname ?? "").trim();
204
+ if (tag) {
205
+ info.hasExtraId.should.be.true();
206
+ info.extraIdName.should.equal(tag);
207
+ } else {
208
+ info.hasExtraId.should.be.false();
209
+ }
210
+ });
211
+
212
+ it("Should mark isPopular and use fallback icon when icon is missing", async () => {
213
+ sinon.stub(axios, "get").callsFake((url, opts = {}) => {
214
+ if (url.endsWith("/currencies")) {
215
+ return Promise.resolve({
216
+ status: 200,
217
+ data: {
218
+ BTC: { coinName: "Bitcoin", available: true },
219
+ DOGE: { coinName: "Dogecoin", available: true },
220
+ },
221
+ });
222
+ }
223
+ return axiosGetOriginal(url, opts);
224
+ });
225
+
226
+ await provider._fetchSupportedCurrenciesIfNeeded();
227
+ const btc = provider._supportedCoins.find(i => i.code === "BTC");
228
+ const doge = provider._supportedCoins.find(i => i.code === "DOGE");
229
+
230
+ btc.iconURL.should.equal(FALLBACK_ASSET_ICON_URL);
231
+ should.exist(btc.isPopular);
232
+ should.exist(doge.isPopular);
233
+ });
234
+
235
+ it("Should sort _supportedCoins: popular first, then alphabetically by ticker", async () => {
236
+ await provider._fetchSupportedCurrenciesIfNeeded();
237
+ const popular = [
238
+ "HMSTRTON",
239
+ "BTC",
240
+ "ETH",
241
+ "USDTERC20",
242
+ "USDTTRC20",
243
+ "USDCERC20",
244
+ "XRP",
245
+ "TON",
246
+ "XMR",
247
+ "TRX",
248
+ "DAIERC20",
249
+ "DOGE",
250
+ "BNB",
251
+ "PEPEERC20",
252
+ "NOTTON",
253
+ "SOL",
254
+ "DOT",
255
+ "LTC",
256
+ "SHIBERC20",
257
+ "AVAX",
258
+ "UNIERC20",
259
+ "LINKERC20",
260
+ "MATIC",
261
+ "BUSDBEP20",
262
+ "AAVEERC20",
263
+ "ATOM",
264
+ "RUNE",
265
+ "ADA",
266
+ ];
267
+ const list = provider._supportedCoins;
268
+
269
+ let reachedNonPopular = false;
270
+ for (const info of list) {
271
+ const isPop = popular.includes(info.coin.ticker);
272
+ if (!reachedNonPopular && !isPop) reachedNonPopular = true;
273
+ if (reachedNonPopular) isPop.should.be.false();
274
+ }
275
+
276
+ const nonPopularTickers = list.filter(i => !popular.includes(i.coin.ticker)).map(i => i.coin.ticker);
277
+ const sorted = [...nonPopularTickers].sort((a, b) => a.localeCompare(b));
278
+ nonPopularTickers.should.eql(sorted);
279
+ });
157
280
 
158
- it("_mapGoexmeStatus maps every value", () => {
159
- const m = provider._mapGoexmeStatus.bind(provider);
160
- expect(m("new")).toBe(provider.constructor.SWAP_STATUSES.WAITING_FOR_PAYMENT);
161
- expect(m("waiting_deposit")).toBe(provider.constructor.SWAP_STATUSES.CONFIRMING);
162
- expect(m("deposit_received")).toBe(provider.constructor.SWAP_STATUSES.PAYMENT_RECEIVED);
163
- expect(m("exchanging")).toBe(provider.constructor.SWAP_STATUSES.EXCHANGING);
164
- expect(m("sending")).toBe(provider.constructor.SWAP_STATUSES.EXCHANGING);
165
- expect(m("success")).toBe(provider.constructor.SWAP_STATUSES.COMPLETED);
166
- expect(m("time_expired")).toBe(provider.constructor.SWAP_STATUSES.EXPIRED);
167
- expect(m("failed")).toBe(provider.constructor.SWAP_STATUSES.FAILED);
168
- expect(m("sending_failed")).toBe(provider.constructor.SWAP_STATUSES.FAILED);
169
- expect(m("reverted")).toBe(provider.constructor.SWAP_STATUSES.REFUNDED);
281
+ it("Should use pairs cache within TTL", async () => {
282
+ let calls = 0;
283
+ sinon.stub(axios, "get").callsFake((url, opts) => {
284
+ if (url.includes("/pairs")) calls += 1;
285
+ return axiosGetOriginal(url, opts);
286
+ });
287
+
288
+ await provider._ensurePairsLoaded();
289
+ provider._pairsCacheTimestamp -= 4 * 60 * 1000;
290
+ await provider._ensurePairsLoaded();
291
+
292
+ calls.should.equal(1);
293
+ });
294
+
295
+ it("Should reload pairs cache after TTL expiry", async () => {
296
+ let calls = 0;
297
+ sinon.stub(axios, "get").callsFake((url, opts) => {
298
+ if (url.includes("/pairs")) calls += 1;
299
+ return axiosGetOriginal(url, opts);
300
+ });
301
+
302
+ await provider._ensurePairsLoaded();
303
+ provider._pairsCacheTimestamp -= 10 * 60 * 1000;
304
+ await provider._ensurePairsLoaded();
305
+
306
+ calls.should.equal(2);
307
+ });
308
+
309
+ it("Should keep cache consistent under concurrent calls", async () => {
310
+ await Promise.all([
311
+ provider._fetchSupportedCurrenciesIfNeeded(),
312
+ provider._fetchSupportedCurrenciesIfNeeded(),
313
+ provider._fetchSupportedCurrenciesIfNeeded(),
314
+ ]);
315
+
316
+ provider._supportedCoins.length.should.be.above(0);
317
+ provider._supportedCoinsLastUpdateTimestamp.should.be.above(0);
318
+ });
319
+
320
+ it("Should map all known provider statuses via _mapGoexmeStatus", () => {
321
+ const mapGoexmeStatus = provider._mapGoexmeStatus.bind(provider);
322
+ mapGoexmeStatus("new").should.equal(provider.constructor.SWAP_STATUSES.WAITING_FOR_PAYMENT);
323
+ mapGoexmeStatus("waiting_deposit").should.equal(provider.constructor.SWAP_STATUSES.CONFIRMING);
324
+ mapGoexmeStatus("deposit_received").should.equal(provider.constructor.SWAP_STATUSES.PAYMENT_RECEIVED);
325
+ mapGoexmeStatus("exchanging").should.equal(provider.constructor.SWAP_STATUSES.EXCHANGING);
326
+ mapGoexmeStatus("sending").should.equal(provider.constructor.SWAP_STATUSES.EXCHANGING);
327
+ mapGoexmeStatus("success").should.equal(provider.constructor.SWAP_STATUSES.COMPLETED);
328
+ mapGoexmeStatus("time_expired").should.equal(provider.constructor.SWAP_STATUSES.EXPIRED);
329
+ mapGoexmeStatus("failed").should.equal(provider.constructor.SWAP_STATUSES.FAILED);
330
+ mapGoexmeStatus("sending_failed").should.equal(provider.constructor.SWAP_STATUSES.FAILED);
331
+ mapGoexmeStatus("reverted").should.equal(provider.constructor.SWAP_STATUSES.REFUNDED);
332
+ });
170
333
  });
171
334
  });