@rabbitio/ui-kit 1.0.0-beta.10 → 1.0.0-beta.100

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 (457) hide show
  1. package/.gitlab-ci.yml +29 -0
  2. package/.husky/commit-msg +19 -0
  3. package/.husky/pre-push +1 -0
  4. package/CHANGELOG.md +0 -0
  5. package/README.md +27 -18
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +21036 -0
  9. package/coverage/coverage-final.json +185 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +1271 -0
  12. package/coverage/prettify.css +1 -0
  13. package/coverage/prettify.js +2 -0
  14. package/coverage/sort-arrow-sprite.png +0 -0
  15. package/coverage/sorter.js +196 -0
  16. package/coverage/ui-kit/index.html +116 -0
  17. package/coverage/ui-kit/index.js.html +88 -0
  18. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/googleAnalyticsAdapter.js.html +151 -0
  19. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/index.html +146 -0
  20. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/metrikaAdapter.js.html +172 -0
  21. package/coverage/ui-kit/src/common-apis/adapters/analyticsAdapters/mixpanelAdapter.js.html +199 -0
  22. package/coverage/ui-kit/src/common-apis/adapters/axiosAdapter.js.html +190 -0
  23. package/coverage/ui-kit/src/common-apis/adapters/index.html +131 -0
  24. package/coverage/ui-kit/src/common-apis/adapters/qrUtils.js.html +139 -0
  25. package/coverage/ui-kit/src/common-apis/external-apis/apiGroups.js.html +250 -0
  26. package/coverage/ui-kit/src/common-apis/external-apis/emailAPI.js.html +133 -0
  27. package/coverage/ui-kit/src/common-apis/external-apis/index.html +146 -0
  28. package/coverage/ui-kit/src/common-apis/external-apis/ipAddressProviders.js.html +352 -0
  29. package/coverage/ui-kit/src/common-apis/globalConstants.jsx.html +94 -0
  30. package/coverage/ui-kit/src/common-apis/index.html +116 -0
  31. package/coverage/ui-kit/src/common-apis/models/blockchain.js.html +115 -0
  32. package/coverage/ui-kit/src/common-apis/models/coin.js.html +829 -0
  33. package/coverage/ui-kit/src/common-apis/models/index.html +146 -0
  34. package/coverage/ui-kit/src/common-apis/models/protocol.js.html +100 -0
  35. package/coverage/ui-kit/src/common-apis/services/fiatCurrenciesService.js.html +544 -0
  36. package/coverage/ui-kit/src/common-apis/services/index.html +116 -0
  37. package/coverage/ui-kit/src/common-apis/utils/amountUtils.js.html +1234 -0
  38. package/coverage/ui-kit/src/common-apis/utils/cache.js.html +811 -0
  39. package/coverage/ui-kit/src/common-apis/utils/errorUtils.js.html +211 -0
  40. package/coverage/ui-kit/src/common-apis/utils/index.html +191 -0
  41. package/coverage/ui-kit/src/common-apis/utils/logging/index.html +131 -0
  42. package/coverage/ui-kit/src/common-apis/utils/logging/logger.js.html +208 -0
  43. package/coverage/ui-kit/src/common-apis/utils/logging/logsStorage.js.html +268 -0
  44. package/coverage/ui-kit/src/common-apis/utils/postponeExecution.js.html +118 -0
  45. package/coverage/ui-kit/src/common-apis/utils/rabbitTicker.js.html +157 -0
  46. package/coverage/ui-kit/src/common-apis/utils/safeStringify.js.html +235 -0
  47. package/coverage/ui-kit/src/index.html +116 -0
  48. package/coverage/ui-kit/src/index.js.html +376 -0
  49. package/coverage/ui-kit/src/robust-api-caller/cacheAndConcurrentRequestsResolver.js.html +1570 -0
  50. package/coverage/ui-kit/src/robust-api-caller/cachedRobustExternalApiCallerService.js.html +526 -0
  51. package/coverage/ui-kit/src/robust-api-caller/cancelProcessing.js.html +172 -0
  52. package/coverage/ui-kit/src/robust-api-caller/concurrentCalculationsMetadataHolder.js.html +310 -0
  53. package/coverage/ui-kit/src/robust-api-caller/externalApiProvider.js.html +553 -0
  54. package/coverage/ui-kit/src/robust-api-caller/externalServicesStatsCollector.js.html +319 -0
  55. package/coverage/ui-kit/src/robust-api-caller/index.html +206 -0
  56. package/coverage/ui-kit/src/robust-api-caller/robustExternalAPICallerService.js.html +997 -0
  57. package/coverage/ui-kit/src/swaps-lib/external-apis/exolixSwapProvider.js.html +1849 -0
  58. package/coverage/ui-kit/src/swaps-lib/external-apis/index.html +176 -0
  59. package/coverage/ui-kit/src/swaps-lib/external-apis/letsExchangeSwapProvider.js.html +1633 -0
  60. package/coverage/ui-kit/src/swaps-lib/external-apis/swapProvider.js.html +1825 -0
  61. package/coverage/ui-kit/src/swaps-lib/external-apis/swapspaceSwapProvider.js.html +1900 -0
  62. package/coverage/ui-kit/src/swaps-lib/external-apis/utils.js.html +130 -0
  63. package/coverage/ui-kit/src/swaps-lib/models/baseSwapCreationInfo.js.html +319 -0
  64. package/coverage/ui-kit/src/swaps-lib/models/existingSwap.js.html +514 -0
  65. package/coverage/ui-kit/src/swaps-lib/models/existingSwapWithFiatData.js.html +529 -0
  66. package/coverage/ui-kit/src/swaps-lib/models/index.html +176 -0
  67. package/coverage/ui-kit/src/swaps-lib/models/partner.js.html +166 -0
  68. package/coverage/ui-kit/src/swaps-lib/models/swapProviderCoinInfo.js.html +331 -0
  69. package/coverage/ui-kit/src/swaps-lib/services/index.html +116 -0
  70. package/coverage/ui-kit/src/swaps-lib/services/publicSwapService.js.html +1570 -0
  71. package/coverage/ui-kit/src/swaps-lib/utils/index.html +116 -0
  72. package/coverage/ui-kit/src/swaps-lib/utils/swapUtils.js.html +670 -0
  73. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/arrowIcon.jsx.html +124 -0
  74. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/arrowTosca.jsx.html +127 -0
  75. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/arrowWhite.jsx.html +127 -0
  76. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/darkRectangle.jsx.html +106 -0
  77. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/determinedError.jsx.html +439 -0
  78. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/failedValidationIcon.jsx.html +202 -0
  79. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/index.html +281 -0
  80. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/infoIcon.jsx.html +133 -0
  81. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/messageIcon.jsx.html +346 -0
  82. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/noticeQuestionIcon.jsx.html +247 -0
  83. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/successfulValidationIcon.jsx.html +163 -0
  84. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/supportDialogImage.jsx.html +268 -0
  85. package/coverage/ui-kit/src/ui-kit/assets/wrappedImages/walletIcon.jsx.html +151 -0
  86. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetIcon/AssetIcon.jsx.html +256 -0
  87. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetIcon/index.html +116 -0
  88. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetSelection/AssetSelection.jsx.html +289 -0
  89. package/coverage/ui-kit/src/ui-kit/components/atoms/AssetSelection/index.html +116 -0
  90. package/coverage/ui-kit/src/ui-kit/components/atoms/BackgroundTitle/BackgroundTitle.jsx.html +187 -0
  91. package/coverage/ui-kit/src/ui-kit/components/atoms/BackgroundTitle/index.html +116 -0
  92. package/coverage/ui-kit/src/ui-kit/components/atoms/InformationMessage/InformationMessage.jsx.html +238 -0
  93. package/coverage/ui-kit/src/ui-kit/components/atoms/InformationMessage/index.html +116 -0
  94. package/coverage/ui-kit/src/ui-kit/components/atoms/Input/Input.jsx.html +634 -0
  95. package/coverage/ui-kit/src/ui-kit/components/atoms/Input/index.html +116 -0
  96. package/coverage/ui-kit/src/ui-kit/components/atoms/LoadingDots/LoadingDots.jsx.html +196 -0
  97. package/coverage/ui-kit/src/ui-kit/components/atoms/LoadingDots/index.html +116 -0
  98. package/coverage/ui-kit/src/ui-kit/components/atoms/NoticeIcon/NoticeIcon.jsx.html +277 -0
  99. package/coverage/ui-kit/src/ui-kit/components/atoms/NoticeIcon/index.html +116 -0
  100. package/coverage/ui-kit/src/ui-kit/components/atoms/QrCode/QrCode.jsx.html +217 -0
  101. package/coverage/ui-kit/src/ui-kit/components/atoms/QrCode/index.html +116 -0
  102. package/coverage/ui-kit/src/ui-kit/components/atoms/RateSelector/RateSelector.jsx.html +175 -0
  103. package/coverage/ui-kit/src/ui-kit/components/atoms/RateSelector/index.html +116 -0
  104. package/coverage/ui-kit/src/ui-kit/components/atoms/SupportChat/SupportChat.jsx.html +217 -0
  105. package/coverage/ui-kit/src/ui-kit/components/atoms/SupportChat/index.html +116 -0
  106. package/coverage/ui-kit/src/ui-kit/components/atoms/Textarea/Textarea.jsx.html +529 -0
  107. package/coverage/ui-kit/src/ui-kit/components/atoms/Textarea/index.html +116 -0
  108. package/coverage/ui-kit/src/ui-kit/components/atoms/TitleBox/TitleBox.jsx.html +508 -0
  109. package/coverage/ui-kit/src/ui-kit/components/atoms/TitleBox/index.html +116 -0
  110. package/coverage/ui-kit/src/ui-kit/components/atoms/Tooltip/Tooltip.jsx.html +316 -0
  111. package/coverage/ui-kit/src/ui-kit/components/atoms/Tooltip/index.html +116 -0
  112. package/coverage/ui-kit/src/ui-kit/components/atoms/TwoLinesOfText/LinesOfText.jsx.html +313 -0
  113. package/coverage/ui-kit/src/ui-kit/components/atoms/TwoLinesOfText/index.html +116 -0
  114. package/coverage/ui-kit/src/ui-kit/components/atoms/Validation/Validation.jsx.html +202 -0
  115. package/coverage/ui-kit/src/ui-kit/components/atoms/Validation/index.html +116 -0
  116. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Button/Button.jsx.html +733 -0
  117. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Button/index.html +116 -0
  118. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Close/Close.jsx.html +259 -0
  119. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/Close/index.html +116 -0
  120. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/LinkButton/LinkButton.jsx.html +433 -0
  121. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/LinkButton/index.html +116 -0
  122. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/RadioButtonWithText/RadioButtonWithText.jsx.html +415 -0
  123. package/coverage/ui-kit/src/ui-kit/components/atoms/buttons/RadioButtonWithText/index.html +116 -0
  124. package/coverage/ui-kit/src/ui-kit/components/molecules/AmountInput/AmountInput.jsx.html +1429 -0
  125. package/coverage/ui-kit/src/ui-kit/components/molecules/AmountInput/index.html +116 -0
  126. package/coverage/ui-kit/src/ui-kit/components/molecules/CoinPicker/CoinPicker.jsx.html +1474 -0
  127. package/coverage/ui-kit/src/ui-kit/components/molecules/CoinPicker/index.html +116 -0
  128. package/coverage/ui-kit/src/ui-kit/components/molecules/ColoredNotice/ColoredNotice.jsx.html +241 -0
  129. package/coverage/ui-kit/src/ui-kit/components/molecules/ColoredNotice/index.html +116 -0
  130. package/coverage/ui-kit/src/ui-kit/components/molecules/LineWithIconLink/LineWithIconLink.jsx.html +190 -0
  131. package/coverage/ui-kit/src/ui-kit/components/molecules/LineWithIconLink/index.html +116 -0
  132. package/coverage/ui-kit/src/ui-kit/components/molecules/LogoCarousel/LogoCarousel.jsx.html +307 -0
  133. package/coverage/ui-kit/src/ui-kit/components/molecules/LogoCarousel/index.html +116 -0
  134. package/coverage/ui-kit/src/ui-kit/components/molecules/SearchableCoinsList/SearchableCoinsList.jsx.html +496 -0
  135. package/coverage/ui-kit/src/ui-kit/components/molecules/SearchableCoinsList/index.html +116 -0
  136. package/coverage/ui-kit/src/ui-kit/components/molecules/TitledLineWithIconLink/TitledLineWithIconLink.jsx.html +181 -0
  137. package/coverage/ui-kit/src/ui-kit/components/molecules/TitledLineWithIconLink/index.html +116 -0
  138. package/coverage/ui-kit/src/ui-kit/components/organisms/CoinPickerDialogStep/CoinPickerDialogStep.jsx.html +283 -0
  139. package/coverage/ui-kit/src/ui-kit/components/organisms/CoinPickerDialogStep/index.html +116 -0
  140. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/Dialog.jsx.html +1567 -0
  141. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogButtons/DialogButtons.jsx.html +481 -0
  142. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogButtons/index.html +116 -0
  143. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogStep/DialogStep.jsx.html +1747 -0
  144. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/DialogStep/index.html +116 -0
  145. package/coverage/ui-kit/src/ui-kit/components/organisms/Dialog/index.html +116 -0
  146. package/coverage/ui-kit/src/ui-kit/components/organisms/SwapForm/SwapForm.jsx.html +4228 -0
  147. package/coverage/ui-kit/src/ui-kit/components/organisms/SwapForm/index.html +116 -0
  148. package/coverage/ui-kit/src/ui-kit/components/organisms/WaitlistSubscription/WaitlistSubscription.jsx.html +559 -0
  149. package/coverage/ui-kit/src/ui-kit/components/organisms/WaitlistSubscription/index.html +116 -0
  150. package/coverage/ui-kit/src/ui-kit/components/templates/DeterminedErrorDialogStep/DeterminedErrorDialogStep.jsx.html +316 -0
  151. package/coverage/ui-kit/src/ui-kit/components/templates/DeterminedErrorDialogStep/index.html +116 -0
  152. package/coverage/ui-kit/src/ui-kit/hooks/index.html +146 -0
  153. package/coverage/ui-kit/src/ui-kit/hooks/useCallHandlingErrors.js.html +166 -0
  154. package/coverage/ui-kit/src/ui-kit/hooks/useIsHydrated.js.html +121 -0
  155. package/coverage/ui-kit/src/ui-kit/hooks/useReferredState.js.html +157 -0
  156. package/coverage/ui-kit/src/ui-kit/utils/index.html +161 -0
  157. package/coverage/ui-kit/src/ui-kit/utils/inputValueProviders.js.html +235 -0
  158. package/coverage/ui-kit/src/ui-kit/utils/textUtils.js.html +139 -0
  159. package/coverage/ui-kit/src/ui-kit/utils/uiUtils.js.html +121 -0
  160. package/coverage/ui-kit/src/ui-kit/utils/urlQueryUtils.js.html +271 -0
  161. package/coverage/ui-kit/stories/atoms/BackgroundTitle.stories.jsx.html +202 -0
  162. package/coverage/ui-kit/stories/atoms/LinesOfText.stories.jsx.html +283 -0
  163. package/coverage/ui-kit/stories/atoms/LoadingDots.stories.jsx.html +226 -0
  164. package/coverage/ui-kit/stories/atoms/QrCode.stories.jsx.html +175 -0
  165. package/coverage/ui-kit/stories/atoms/RateSelector.stories.jsx.html +136 -0
  166. package/coverage/ui-kit/stories/atoms/Validation.stories.jsx.html +178 -0
  167. package/coverage/ui-kit/stories/atoms/buttons/Button.stories.jsx.html +883 -0
  168. package/coverage/ui-kit/stories/atoms/buttons/Close.stories.jsx.html +211 -0
  169. package/coverage/ui-kit/stories/atoms/buttons/LinkButton.stories.jsx.html +301 -0
  170. package/coverage/ui-kit/stories/atoms/buttons/index.html +146 -0
  171. package/coverage/ui-kit/stories/atoms/index.html +191 -0
  172. package/coverage/ui-kit/stories/molecules/AmountInput.stories.jsx.html +289 -0
  173. package/coverage/ui-kit/stories/molecules/CoinPicker.stories.jsx.html +322 -0
  174. package/coverage/ui-kit/stories/molecules/ColoredNotice.stories.jsx.html +178 -0
  175. package/coverage/ui-kit/stories/molecules/LineWithIconLink.stories.jsx.html +154 -0
  176. package/coverage/ui-kit/stories/molecules/LogoCarousel.stories.jsx.html +235 -0
  177. package/coverage/ui-kit/stories/molecules/TitledLineWithIconLink.stories.jsx.html +160 -0
  178. package/coverage/ui-kit/stories/molecules/index.html +191 -0
  179. package/coverage/ui-kit/stories/organisms/Dialog/Dialog.stories.jsx.html +523 -0
  180. package/coverage/ui-kit/stories/organisms/Dialog/DialogButtons/DialogButtons.stories.jsx.html +328 -0
  181. package/coverage/ui-kit/stories/organisms/Dialog/DialogButtons/index.html +116 -0
  182. package/coverage/ui-kit/stories/organisms/Dialog/DialogStep/DialogStep.stories.jsx.html +337 -0
  183. package/coverage/ui-kit/stories/organisms/Dialog/DialogStep/index.html +116 -0
  184. package/coverage/ui-kit/stories/organisms/Dialog/index.html +116 -0
  185. package/coverage/ui-kit/stories/organisms/WaitlistSubscription.stories.jsx.html +151 -0
  186. package/coverage/ui-kit/stories/organisms/index.html +116 -0
  187. package/coverage/ui-kit/stories/stubs/coins.jsx.html +6880 -0
  188. package/coverage/ui-kit/stories/stubs/exampleContent.jsx.html +145 -0
  189. package/coverage/ui-kit/stories/stubs/index.html +131 -0
  190. package/coverage/ui-kit/stories/templates/DeterminedErrorDialogStep.stories.jsx.html +190 -0
  191. package/coverage/ui-kit/stories/templates/index.html +116 -0
  192. package/coverage/ui-kit/storybook-static/230.7eace282.iframe.bundle.js.html +85 -0
  193. package/coverage/ui-kit/storybook-static/242.dda46cfa.iframe.bundle.js.html +85 -0
  194. package/coverage/ui-kit/storybook-static/312.6f62bbd9.iframe.bundle.js.html +85 -0
  195. package/coverage/ui-kit/storybook-static/341.57a15f57.iframe.bundle.js.html +85 -0
  196. package/coverage/ui-kit/storybook-static/374.99dab897.iframe.bundle.js.html +85 -0
  197. package/coverage/ui-kit/storybook-static/43.c12e28b8.iframe.bundle.js.html +85 -0
  198. package/coverage/ui-kit/storybook-static/450.d467c07c.iframe.bundle.js.html +85 -0
  199. package/coverage/ui-kit/storybook-static/506.07d46882.iframe.bundle.js.html +85 -0
  200. package/coverage/ui-kit/storybook-static/547.cc28f1fd.iframe.bundle.js.html +85 -0
  201. package/coverage/ui-kit/storybook-static/586.e7130528.iframe.bundle.js.html +85 -0
  202. package/coverage/ui-kit/storybook-static/595.2e40d981.iframe.bundle.js.html +85 -0
  203. package/coverage/ui-kit/storybook-static/607.3ea32459.iframe.bundle.js.html +85 -0
  204. package/coverage/ui-kit/storybook-static/609.097df435.iframe.bundle.js.html +85 -0
  205. package/coverage/ui-kit/storybook-static/797.c87cdf19.iframe.bundle.js.html +85 -0
  206. package/coverage/ui-kit/storybook-static/889.4a86fe2b.iframe.bundle.js.html +85 -0
  207. package/coverage/ui-kit/storybook-static/976.b5f1a5d4.iframe.bundle.js.html +85 -0
  208. package/coverage/ui-kit/storybook-static/996.07a638d5.iframe.bundle.js.html +85 -0
  209. package/coverage/ui-kit/storybook-static/AmountUtils-stories.e2f66b30.iframe.bundle.js.html +85 -0
  210. package/coverage/ui-kit/storybook-static/atoms-BackgroundTitle-stories.1a5386a1.iframe.bundle.js.html +85 -0
  211. package/coverage/ui-kit/storybook-static/atoms-LinesOfText-stories.b7c8f08a.iframe.bundle.js.html +85 -0
  212. package/coverage/ui-kit/storybook-static/atoms-LoadingDots-stories.5180c2f1.iframe.bundle.js.html +85 -0
  213. package/coverage/ui-kit/storybook-static/atoms-QrCode-stories.1581ad1e.iframe.bundle.js.html +85 -0
  214. package/coverage/ui-kit/storybook-static/atoms-RateSelector-stories.19c65c98.iframe.bundle.js.html +85 -0
  215. package/coverage/ui-kit/storybook-static/atoms-Validation-stories.d561b311.iframe.bundle.js.html +85 -0
  216. package/coverage/ui-kit/storybook-static/atoms-buttons-Button-stories.e8e6b930.iframe.bundle.js.html +85 -0
  217. package/coverage/ui-kit/storybook-static/atoms-buttons-Close-stories.0a902a7c.iframe.bundle.js.html +85 -0
  218. package/coverage/ui-kit/storybook-static/atoms-buttons-LinkButton-stories.10813be5.iframe.bundle.js.html +85 -0
  219. package/coverage/ui-kit/storybook-static/index.html +686 -0
  220. package/coverage/ui-kit/storybook-static/main.da938fde.iframe.bundle.js.html +85 -0
  221. package/coverage/ui-kit/storybook-static/molecules-AmountInput-stories.a703ba8d.iframe.bundle.js.html +85 -0
  222. package/coverage/ui-kit/storybook-static/molecules-ColoredNotice-stories.7a5d624e.iframe.bundle.js.html +85 -0
  223. package/coverage/ui-kit/storybook-static/molecules-LineWithIconLink-stories.b7f70ee2.iframe.bundle.js.html +85 -0
  224. package/coverage/ui-kit/storybook-static/molecules-LogoCarousel-stories.2ce1402f.iframe.bundle.js.html +85 -0
  225. package/coverage/ui-kit/storybook-static/molecules-TitledLineWithIconLink-stories.1383fe3f.iframe.bundle.js.html +85 -0
  226. package/coverage/ui-kit/storybook-static/organisms-Dialog-Dialog-stories.4e6da717.iframe.bundle.js.html +85 -0
  227. package/coverage/ui-kit/storybook-static/organisms-Dialog-DialogButtons-DialogButtons-stories.1d1f9803.iframe.bundle.js.html +85 -0
  228. package/coverage/ui-kit/storybook-static/organisms-Dialog-DialogStep-DialogStep-stories.74896048.iframe.bundle.js.html +85 -0
  229. package/coverage/ui-kit/storybook-static/organisms-WaitlistSubscription-stories.a7c49a29.iframe.bundle.js.html +85 -0
  230. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/dist/global.css.html +118 -0
  231. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/dist/index.html +116 -0
  232. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/@storybook/addon-backgrounds/dist/index.html +116 -0
  233. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/@storybook/addon-backgrounds/dist/preview.js.html +118 -0
  234. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/@storybook/components/dist/formatter-SWP5E3XI.mjs.html +118 -0
  235. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/@storybook/components/dist/index.html +116 -0
  236. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/buffer/index.html +116 -0
  237. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/buffer/index.js.html +118 -0
  238. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/markdown-to-jsx/dist/index.html +116 -0
  239. package/coverage/ui-kit/storybook-static/rabbitio/ui-kit/node_modules/markdown-to-jsx/dist/index.modern.js.html +118 -0
  240. package/coverage/ui-kit/storybook-static/runtime~main.795022f7.iframe.bundle.js.html +85 -0
  241. package/coverage/ui-kit/storybook-static/sb-addons/actions-9/index.html +116 -0
  242. package/coverage/ui-kit/storybook-static/sb-addons/actions-9/manager-bundle.js.html +94 -0
  243. package/coverage/ui-kit/storybook-static/sb-addons/essentials-backgrounds-2/index.html +116 -0
  244. package/coverage/ui-kit/storybook-static/sb-addons/essentials-backgrounds-2/manager-bundle.js.html +121 -0
  245. package/coverage/ui-kit/storybook-static/sb-addons/essentials-controls-1/index.html +116 -0
  246. package/coverage/ui-kit/storybook-static/sb-addons/essentials-controls-1/manager-bundle.js.html +274 -0
  247. package/coverage/ui-kit/storybook-static/sb-addons/essentials-measure-4/index.html +116 -0
  248. package/coverage/ui-kit/storybook-static/sb-addons/essentials-measure-4/manager-bundle.js.html +94 -0
  249. package/coverage/ui-kit/storybook-static/sb-addons/essentials-outline-5/index.html +116 -0
  250. package/coverage/ui-kit/storybook-static/sb-addons/essentials-outline-5/manager-bundle.js.html +94 -0
  251. package/coverage/ui-kit/storybook-static/sb-addons/essentials-toolbars-3/index.html +116 -0
  252. package/coverage/ui-kit/storybook-static/sb-addons/essentials-toolbars-3/manager-bundle.js.html +94 -0
  253. package/coverage/ui-kit/storybook-static/sb-addons/interactions-7/index.html +116 -0
  254. package/coverage/ui-kit/storybook-static/sb-addons/interactions-7/manager-bundle.js.html +121 -0
  255. package/coverage/ui-kit/storybook-static/sb-addons/links-0/index.html +116 -0
  256. package/coverage/ui-kit/storybook-static/sb-addons/links-0/manager-bundle.js.html +94 -0
  257. package/coverage/ui-kit/storybook-static/sb-addons/onboarding-6/index.html +116 -0
  258. package/coverage/ui-kit/storybook-static/sb-addons/onboarding-6/manager-bundle.js.html +1588 -0
  259. package/coverage/ui-kit/storybook-static/sb-addons/viewport-8/index.html +116 -0
  260. package/coverage/ui-kit/storybook-static/sb-addons/viewport-8/manager-bundle.js.html +94 -0
  261. package/coverage/ui-kit/storybook-static/sb-manager/WithTooltip-V3YHNWJZ-LVYLGZW2.js.html +88 -0
  262. package/coverage/ui-kit/storybook-static/sb-manager/chunk-2IXBUOFS.js.html +106 -0
  263. package/coverage/ui-kit/storybook-static/sb-manager/chunk-INSKDKQB.js.html +1129 -0
  264. package/coverage/ui-kit/storybook-static/sb-manager/chunk-NGTUFCUO.js.html +112 -0
  265. package/coverage/ui-kit/storybook-static/sb-manager/chunk-UUEAOBSN.js.html +1303 -0
  266. package/coverage/ui-kit/storybook-static/sb-manager/chunk-ZEU7PDD3.js.html +88 -0
  267. package/coverage/ui-kit/storybook-static/sb-manager/formatter-SWP5E3XI-7BGIK6BL.js.html +553 -0
  268. package/coverage/ui-kit/storybook-static/sb-manager/globals-module-info.js.html +88 -0
  269. package/coverage/ui-kit/storybook-static/sb-manager/globals.js.html +88 -0
  270. package/coverage/ui-kit/storybook-static/sb-manager/index.html +281 -0
  271. package/coverage/ui-kit/storybook-static/sb-manager/index.js.html +88 -0
  272. package/coverage/ui-kit/storybook-static/sb-manager/runtime.js.html +88 -0
  273. package/coverage/ui-kit/storybook-static/sb-manager/syntaxhighlighter-V7JZZA35-DXZCI2WR.js.html +88 -0
  274. package/coverage/ui-kit/storybook-static/sb-preview/globals.js.html +88 -0
  275. package/coverage/ui-kit/storybook-static/sb-preview/index.html +131 -0
  276. package/coverage/ui-kit/storybook-static/sb-preview/runtime.js.html +421 -0
  277. package/coverage/ui-kit/storybook-static/templates-DeterminedErrorDialogStep-stories.3cc14214.iframe.bundle.js.html +85 -0
  278. package/dist/global.css +197 -0
  279. package/dist/global.css.map +1 -0
  280. package/dist/index.cjs +12420 -333
  281. package/dist/index.cjs.map +1 -1
  282. package/dist/index.css +2357 -8490
  283. package/dist/index.css.map +1 -1
  284. package/dist/index.modern.js +9558 -300
  285. package/dist/index.modern.js.map +1 -1
  286. package/dist/index.module.js +12325 -332
  287. package/dist/index.module.js.map +1 -1
  288. package/dist/index.umd.js +12411 -336
  289. package/dist/index.umd.js.map +1 -1
  290. package/package.json +35 -9
  291. package/raw +1000 -0
  292. package/src/common-apis/adapters/analyticsAdapters/googleAnalyticsAdapter.js +22 -0
  293. package/src/common-apis/adapters/analyticsAdapters/metrikaAdapter.js +29 -0
  294. package/src/common-apis/adapters/analyticsAdapters/mixpanelAdapter.js +38 -0
  295. package/src/common-apis/adapters/axiosAdapter.js +35 -0
  296. package/src/common-apis/adapters/qrUtils.js +18 -0
  297. package/src/common-apis/external-apis/apiGroups.js +55 -0
  298. package/src/common-apis/external-apis/emailAPI.js +16 -0
  299. package/src/common-apis/external-apis/ipAddressProviders.js +89 -0
  300. package/src/common-apis/globalConstants.jsx +3 -0
  301. package/src/common-apis/models/blockchain.js +10 -0
  302. package/src/common-apis/models/coin.js +248 -0
  303. package/src/common-apis/models/protocol.js +5 -0
  304. package/src/{common → common-apis/services}/fiatCurrenciesService.js +4 -12
  305. package/src/common-apis/tests/integration/external-apis/ipAddressProviders/getClientIpAddress.test.js +12 -0
  306. package/src/common-apis/tests/units/utils/amountUtils/composeRateText.test.js +152 -0
  307. package/src/{common → common-apis/utils}/amountUtils.js +100 -140
  308. package/src/common-apis/utils/cache.js +242 -0
  309. package/src/{common → common-apis/utils}/errorUtils.js +15 -0
  310. package/src/common-apis/utils/logging/logger.js +41 -0
  311. package/src/common-apis/utils/logging/logsStorage.js +61 -0
  312. package/src/common-apis/utils/postponeExecution.js +11 -0
  313. package/src/common-apis/utils/rabbitTicker.js +24 -0
  314. package/src/common-apis/utils/safeStringify.js +50 -0
  315. package/src/index.js +96 -9
  316. package/src/robust-api-caller/cacheAndConcurrentRequestsResolver.js +495 -0
  317. package/src/robust-api-caller/cachedRobustExternalApiCallerService.js +147 -0
  318. package/src/robust-api-caller/cancelProcessing.js +29 -0
  319. package/src/robust-api-caller/concurrentCalculationsMetadataHolder.js +75 -0
  320. package/src/robust-api-caller/externalApiProvider.js +156 -0
  321. package/src/robust-api-caller/externalServicesStatsCollector.js +78 -0
  322. package/src/robust-api-caller/robustExternalAPICallerService.js +304 -0
  323. package/src/robust-api-caller/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/_performCallAttempt.test.js +533 -0
  324. package/src/robust-api-caller/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/callExternalAPI.test.js +532 -0
  325. package/src/robust-api-caller/tests/robustExternalAPICallerService/robustExternalAPICallerService/constructor.test.js +19 -0
  326. package/src/swaps-lib/external-apis/exolixSwapProvider.js +588 -0
  327. package/src/swaps-lib/external-apis/letsExchangeSwapProvider.js +516 -0
  328. package/src/swaps-lib/external-apis/swapProvider.js +580 -0
  329. package/src/swaps-lib/external-apis/swapspaceSwapProvider.js +605 -0
  330. package/src/swaps-lib/external-apis/utils.js +15 -0
  331. package/src/swaps-lib/models/baseSwapCreationInfo.js +78 -0
  332. package/src/swaps-lib/models/existingSwap.js +143 -0
  333. package/src/swaps-lib/models/existingSwapWithFiatData.js +148 -0
  334. package/src/swaps-lib/models/partner.js +27 -0
  335. package/src/swaps-lib/models/swapProviderCoinInfo.js +82 -0
  336. package/src/swaps-lib/services/publicSwapService.js +495 -0
  337. package/src/swaps-lib/test/external-apis/exolixSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +34 -0
  338. package/src/swaps-lib/test/external-apis/exolixSwapProvider/createSwap.test.js +1043 -0
  339. package/src/swaps-lib/test/external-apis/exolixSwapProvider/getSwapInfo.test.js +611 -0
  340. package/src/swaps-lib/test/external-apis/swapProvider/getAllSupportedCurrencies.test.js +63 -0
  341. package/src/swaps-lib/test/external-apis/swapProvider/getDepositCurrencies.test.js +73 -0
  342. package/src/swaps-lib/test/external-apis/swapProvider/getWithdrawalCurrencies.test.js +102 -0
  343. package/src/swaps-lib/test/external-apis/swapProvider/removeProtocolNameFromCoinName.test.js +152 -0
  344. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +536 -0
  345. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/createSwap.test.js +1214 -0
  346. package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getSwapInfo.test.js +1743 -0
  347. package/src/swaps-lib/test/utils/swapUtils/safeHandleRequestsLimitExceeding.test.js +80 -0
  348. package/src/swaps-lib/utils/swapUtils.js +195 -0
  349. package/{styles → src/ui-kit/assets/styles}/_functions.scss +5 -0
  350. package/{styles → src/ui-kit/assets/styles}/_mixins.scss +2 -2
  351. package/{styles → src/ui-kit/assets/styles}/_placeholder.scss +3 -3
  352. package/{styles → src/ui-kit/assets/styles}/_variables.scss +17 -15
  353. package/src/ui-kit/assets/styles/fonts/NunitoSans-Bold.ttf +0 -0
  354. package/src/ui-kit/assets/styles/fonts/NunitoSans-ExtraBold.ttf +0 -0
  355. package/src/ui-kit/assets/styles/fonts/NunitoSans-Light.ttf +0 -0
  356. package/src/ui-kit/assets/styles/fonts/NunitoSans-Regular.ttf +0 -0
  357. package/src/ui-kit/assets/styles/fonts/NunitoSans-SemiBold.ttf +0 -0
  358. package/src/ui-kit/assets/styles/global.scss +171 -0
  359. package/src/ui-kit/assets/styles/index.scss +10 -0
  360. package/src/ui-kit/assets/wrappedImages/arrowIcon.jsx +13 -0
  361. package/src/ui-kit/assets/wrappedImages/arrowTosca.jsx +14 -0
  362. package/src/ui-kit/assets/wrappedImages/arrowWhite.jsx +14 -0
  363. package/src/ui-kit/assets/wrappedImages/darkRectangle.jsx +7 -0
  364. package/src/ui-kit/assets/wrappedImages/determinedError.jsx +118 -0
  365. package/src/ui-kit/assets/wrappedImages/failedValidationIcon.jsx +39 -0
  366. package/src/ui-kit/assets/wrappedImages/infoIcon.jsx +16 -0
  367. package/src/ui-kit/assets/wrappedImages/messageIcon.jsx +87 -0
  368. package/src/ui-kit/assets/wrappedImages/noticeQuestionIcon.jsx +54 -0
  369. package/src/ui-kit/assets/wrappedImages/successfulValidationIcon.jsx +26 -0
  370. package/src/ui-kit/assets/wrappedImages/supportDialogImage.jsx +61 -0
  371. package/src/ui-kit/assets/wrappedImages/walletIcon.jsx +22 -0
  372. package/src/ui-kit/components/atoms/AssetIcon/AssetIcon.jsx +57 -0
  373. package/src/{components → ui-kit/components}/atoms/AssetIcon/asset-icon.module.scss +1 -1
  374. package/src/ui-kit/components/atoms/AssetSelection/AssetSelection.jsx +68 -0
  375. package/src/ui-kit/components/atoms/AssetSelection/asset-selection.module.scss +56 -0
  376. package/src/ui-kit/components/atoms/BackgroundTitle/BackgroundTitle.jsx +34 -0
  377. package/src/ui-kit/components/atoms/BackgroundTitle/background-title.module.scss +52 -0
  378. package/src/ui-kit/components/atoms/InformationMessage/InformationMessage.jsx +51 -0
  379. package/src/ui-kit/components/atoms/InformationMessage/information-message.module.scss +38 -0
  380. package/src/ui-kit/components/atoms/Input/Input.jsx +183 -0
  381. package/src/ui-kit/components/atoms/Input/input.module.scss +107 -0
  382. package/src/{components → ui-kit/components}/atoms/LoadingDots/LoadingDots.jsx +8 -28
  383. package/src/{components → ui-kit/components}/atoms/LoadingDots/LoadingDots.module.scss +3 -2
  384. package/src/ui-kit/components/atoms/NoticeIcon/NoticeIcon.jsx +64 -0
  385. package/src/ui-kit/components/atoms/NoticeIcon/notice-icon.module.scss +14 -0
  386. package/src/ui-kit/components/atoms/QrCode/QrCode.jsx +44 -0
  387. package/src/ui-kit/components/atoms/QrCode/qr-code.module.scss +15 -0
  388. package/src/ui-kit/components/atoms/RateSelector/RateSelector.jsx +30 -0
  389. package/src/ui-kit/components/atoms/RateSelector/rate-selector.module.scss +47 -0
  390. package/src/{components → ui-kit/components}/atoms/SupportChat/SupportChat.jsx +5 -1
  391. package/src/ui-kit/components/atoms/Textarea/Textarea.jsx +148 -0
  392. package/src/ui-kit/components/atoms/Textarea/textarea.module.scss +71 -0
  393. package/src/ui-kit/components/atoms/TitleBox/TitleBox.jsx +141 -0
  394. package/src/ui-kit/components/atoms/TitleBox/title-box.module.scss +32 -0
  395. package/src/ui-kit/components/atoms/Tooltip/Tooltip.jsx +77 -0
  396. package/src/ui-kit/components/atoms/Tooltip/tooltip.module.scss +237 -0
  397. package/src/ui-kit/components/atoms/TwoLinesOfText/LinesOfText.jsx +76 -0
  398. package/src/ui-kit/components/atoms/TwoLinesOfText/lines-of-text.module.scss +65 -0
  399. package/src/ui-kit/components/atoms/Validation/Validation.jsx +39 -0
  400. package/src/ui-kit/components/atoms/Validation/validation.module.scss +19 -0
  401. package/src/{components → ui-kit/components}/atoms/buttons/Button/Button.jsx +26 -45
  402. package/src/{components → ui-kit/components}/atoms/buttons/Button/Button.module.scss +1 -1
  403. package/src/ui-kit/components/atoms/buttons/Close/Close.jsx +58 -0
  404. package/src/ui-kit/components/atoms/buttons/Close/close.module.scss +75 -0
  405. package/src/ui-kit/components/atoms/buttons/LinkButton/LinkButton.jsx +116 -0
  406. package/src/ui-kit/components/atoms/buttons/LinkButton/link-button.module.scss +53 -0
  407. package/src/ui-kit/components/atoms/buttons/RadioButtonWithText/RadioButtonWithText.jsx +110 -0
  408. package/src/ui-kit/components/atoms/buttons/RadioButtonWithText/radio-button-with-text.module.scss +86 -0
  409. package/src/ui-kit/components/molecules/AmountInput/AmountInput.jsx +448 -0
  410. package/src/ui-kit/components/molecules/AmountInput/amount-input.module.scss +233 -0
  411. package/src/ui-kit/components/molecules/CoinPicker/CoinPicker.jsx +463 -0
  412. package/src/ui-kit/components/molecules/CoinPicker/coin-picker.module.scss +207 -0
  413. package/src/ui-kit/components/molecules/ColoredNotice/ColoredNotice.jsx +52 -0
  414. package/src/ui-kit/components/molecules/ColoredNotice/colored-notice.module.scss +36 -0
  415. package/src/ui-kit/components/molecules/LineWithIconLink/LineWithIconLink.jsx +35 -0
  416. package/src/ui-kit/components/molecules/LineWithIconLink/line-with-icon-link.module.scss +25 -0
  417. package/src/ui-kit/components/molecules/LogoCarousel/LogoCarousel.jsx +74 -0
  418. package/src/ui-kit/components/molecules/LogoCarousel/logo-carousel.module.scss +106 -0
  419. package/src/ui-kit/components/molecules/SearchableCoinsList/SearchableCoinsList.jsx +137 -0
  420. package/src/ui-kit/components/molecules/TitledLineWithIconLink/TitledLineWithIconLink.jsx +32 -0
  421. package/src/ui-kit/components/organisms/CoinPickerDialogStep/CoinPickerDialogStep.jsx +66 -0
  422. package/src/ui-kit/components/organisms/Dialog/Dialog.jsx +494 -0
  423. package/src/ui-kit/components/organisms/Dialog/DialogButtons/DialogButtons.jsx +132 -0
  424. package/src/ui-kit/components/organisms/Dialog/DialogButtons/dialog-buttons.module.scss +25 -0
  425. package/src/ui-kit/components/organisms/Dialog/DialogStep/DialogStep.jsx +554 -0
  426. package/src/ui-kit/components/organisms/Dialog/DialogStep/dialog-step.module.scss +382 -0
  427. package/src/ui-kit/components/organisms/Dialog/dialog.module.scss +226 -0
  428. package/src/ui-kit/components/organisms/SwapForm/SwapForm.jsx +1381 -0
  429. package/src/ui-kit/components/organisms/SwapForm/swap-form.module.scss +134 -0
  430. package/src/ui-kit/components/organisms/WaitlistSubscription/WaitlistSubscription.jsx +158 -0
  431. package/src/ui-kit/components/templates/DeterminedErrorDialogStep/DeterminedErrorDialogStep.jsx +77 -0
  432. package/src/ui-kit/hooks/useCallHandlingErrors.js +27 -0
  433. package/src/ui-kit/hooks/useIsHydrated.js +12 -0
  434. package/src/ui-kit/hooks/useReferredState.js +24 -0
  435. package/src/ui-kit/tests/utils/inputValueProviders/provideFormatOfFloatValueByInputString.test.js +146 -0
  436. package/src/ui-kit/tests/utils/urlQueryUtils/getQueryParameterValues.test.js +65 -0
  437. package/src/ui-kit/tests/utils/urlQueryUtils/saveQueryParameterAndValues.test.js +104 -0
  438. package/src/ui-kit/utils/inputValueProviders.js +50 -0
  439. package/src/ui-kit/utils/textUtils.js +18 -0
  440. package/src/ui-kit/utils/uiUtils.js +12 -0
  441. package/src/ui-kit/utils/urlQueryUtils.js +62 -0
  442. package/stories/font.scss +40 -0
  443. package/stories/stubs/coins.jsx +2266 -0
  444. package/stories/stubs/exampleContent.jsx +20 -0
  445. package/src/components/atoms/AssetIcon/AssetIcon.jsx +0 -55
  446. package/styles/_global-classes.scss +0 -433
  447. package/styles/fonts/NunitoSans-Bold.ttf +0 -0
  448. package/styles/fonts/NunitoSans-ExtraBold.ttf +0 -0
  449. package/styles/fonts/NunitoSans-Light.ttf +0 -0
  450. package/styles/fonts/NunitoSans-Regular.ttf +0 -0
  451. package/styles/fonts/NunitoSans-SemiBold.ttf +0 -0
  452. package/styles/global-styles-index.scss +0 -74
  453. package/styles/index.scss +0 -33
  454. /package/{styles → src/ui-kit/assets/styles}/colors/_light-colors.scss +0 -0
  455. /package/{styles → src/ui-kit/assets/styles}/colors/_solid-colors.scss +0 -0
  456. /package/{styles → src/ui-kit/assets/styles}/size/_margin-size.scss +0 -0
  457. /package/{styles → src/ui-kit/assets/styles}/size/_padding-size.scss +0 -0
@@ -0,0 +1,1381 @@
1
+ import { BigNumber } from "bignumber.js";
2
+ import React, { useEffect, useState } from "react";
3
+ import PropTypes from "prop-types";
4
+
5
+ import s from "./swap-form.module.scss";
6
+
7
+ import { useReferredState } from "../../../hooks/useReferredState.js";
8
+ import { useCallHandlingErrors } from "../../../hooks/useCallHandlingErrors.js";
9
+
10
+ import { AmountUtils } from "../../../../common-apis/utils/amountUtils.js";
11
+ import { TitleBox } from "../../atoms/TitleBox/TitleBox.jsx";
12
+ import { AmountInput } from "../../molecules/AmountInput/AmountInput.jsx";
13
+ import { Validation } from "../../atoms/Validation/Validation.jsx";
14
+ import { Button } from "../../atoms/buttons/Button/Button.jsx";
15
+ import { Textarea } from "../../atoms/Textarea/Textarea.jsx";
16
+ import { RateSelector } from "../../atoms/RateSelector/RateSelector.jsx";
17
+ import { TOOLTIP_POSITIONS } from "../../atoms/Tooltip/Tooltip.jsx";
18
+ import { useIsHydrated } from "../../../hooks/useIsHydrated.js";
19
+
20
+ /**
21
+ * This is the type definition of a function used inside SwapForm to compose the URL for the hero button.
22
+ *
23
+ * @function
24
+ * @name composeConfirmButtonTo
25
+ * @param {string} [fromTicker] - Ticker symbol of the asset being sent.
26
+ * @param {string} [toTicker] - Ticker symbol of the asset being received.
27
+ * @param {string} [fromAmount] - Amount of the asset being sent.
28
+ * @return {string} Full URL or relative URL that can be used for <a href="..." />.
29
+ */
30
+
31
+ /**
32
+ * Common click handler without parameters and return value, just your logic execution.
33
+ *
34
+ * @function
35
+ * @name handleClick
36
+ * @return {void}
37
+ */
38
+
39
+ /**
40
+ * Form executes this function when swap creation info retrieval is finished successfully.
41
+ *
42
+ * @function
43
+ * @name setSwapCreationEstimation
44
+ * @param {BaseSwapCreationInfo} details - Details of the swap creation estimation.
45
+ * @return {void}
46
+ */
47
+
48
+ /**
49
+ * Error handler for unexpected errors.
50
+ *
51
+ * @function
52
+ * @name handleUnexpectedError
53
+ * @param {Error} error - The unexpected error encountered.
54
+ * @return {void}
55
+ */
56
+
57
+ /**
58
+ * Should implement the logic with rotating assets (if you want "to" to become "from" and "from" to become "to").
59
+ *
60
+ * @function
61
+ * @name rotateAssets
62
+ * @param {string} sendingAssetTicker - Ticker symbol of the asset being sent.
63
+ * @param {string} receivingAssetTicker - Ticker symbol of the asset being received.
64
+ * @return {void}
65
+ */
66
+
67
+ /**
68
+ * Error handler for standard errors that we can recognize.
69
+ *
70
+ * @function
71
+ * @name handleSwapServiceError
72
+ * @param {string} errorCode - Error code returned as "reason" from your handlers.
73
+ * @param {function} setValidationContent - Function to set the validation error message on the form.
74
+ * @param {function} setBalanceValid - Function to set the balance validity, accepts a boolean.
75
+ * @param {function} setMinimalAmountValid - Function to set the minimal amount validity, accepts a boolean.
76
+ * @param {function} setMaximumAmountValid - Function to set the maximum amount validity, accepts a boolean.
77
+ * @param {function} setIsPairSupported - Function to set the pair support status, accepts a boolean.
78
+ * @param {function} setIsSameCoins - Function to set the status if the same coins are used, accepts a boolean.
79
+ * @return {void}
80
+ */
81
+
82
+ /**
83
+ * Handler for the confirm button click. You should implement error handling inside it.
84
+ *
85
+ * @function
86
+ * @name handleConfirmButtonClick
87
+ * @param {function} resetButtonLoader - Callback for resetting the confirm button loader.
88
+ * @param {function} setValidationContent - Function to set the validation error message on the form.
89
+ * @param {function} setBalanceValid - Function to set the balance validity, accepts a boolean.
90
+ * @param {function} setMinimalAmountValid - Function to set the minimal amount validity, accepts a boolean.
91
+ * @param {function} setMaximumAmountValid - Function to set the maximum amount validity, accepts a boolean.
92
+ * @param {function} setIsPairSupported - Function to set the pair support status, accepts a boolean.
93
+ * @param {function} setIsSameCoins - Function to set the status if the same coins are used, accepts a boolean.
94
+ * @param {string} recipientAddress - The address of the recipient.
95
+ * @param {string} recipientAddressExtraId - Additional identifier for the recipient address.
96
+ * @param {string} refundAddress - The address for refund.
97
+ * @param {string} refundAddressExtraId - Additional identifier for the refund address.
98
+ * @return {void}
99
+ */
100
+
101
+ /**
102
+ * Async function that retrieves swap creation info by given params.
103
+ *
104
+ * @function
105
+ * @name retrieveSwapDetails
106
+ * @param {string} sendingAssetTicker - Ticker symbol of the asset being sent.
107
+ * @param {string} receivingAssetTicker - Ticker symbol of the asset being received.
108
+ * @param {string} amount - Amount of the asset to be swapped.
109
+ * @param {boolean} [isSwapAll=false] - Indicates if the swap should use all available balance.
110
+ * @return {Promise<{
111
+ * result: false,
112
+ * reason: string,
113
+ * min: (string|null),
114
+ * max: (string|null),
115
+ * rate: (string|undefined),
116
+ * fiatMin: (number|null),
117
+ * fiatMax: (number|null)
118
+ * }|{
119
+ * result: true,
120
+ * swapCreationInfo: BaseSwapCreationInfo
121
+ * }>}
122
+ */
123
+
124
+ /**
125
+ * Async function that retrieves initial swap details for a pair like whether the pair is available, min/max swappable amounts, etc.
126
+ *
127
+ * @function
128
+ * @name retrieveInitialSwapData
129
+ * @param {string} sendingAssetTicker - Ticker symbol of the asset being sent.
130
+ * @param {string} receivingAssetTicker - Ticker symbol of the asset being received.
131
+ * @return {Promise<{
132
+ * result: true,
133
+ * min: string,
134
+ * fiatMin: (number|null),
135
+ * max: string,
136
+ * fiatMax: (number|null),
137
+ * rate: (string|null)
138
+ * }|{
139
+ * result: false,
140
+ * reason: string
141
+ * }>}
142
+ */
143
+
144
+ /**
145
+ * Function returning extraId name for asset if present.
146
+ * You must pass it if you use the form with addresses inputs.
147
+ *
148
+ * @function
149
+ * @name getExtraIdNameByTicker
150
+ * @param {string} ticker - Ticker symbol of the asset.
151
+ * @return {string|null}
152
+ */
153
+
154
+ /**
155
+ * Callback to handle isFixed flag change.
156
+ *
157
+ * @function
158
+ * @name onIsFixedChange
159
+ * @param {boolean} isFixedNewValue - new value
160
+ * @return {void}
161
+ */
162
+
163
+ /**
164
+ * Function validating addresses.
165
+ * By default, will treat any addresses as valid.
166
+ * You must pass it if you use the form with addresses inputs and want to validate addresses.
167
+ *
168
+ * @function
169
+ * @name validateAddressByTicker
170
+ * @param {string} ticker - Ticker symbol of the asset.
171
+ * @param {string} address - Address to be validated
172
+ * @param {boolean} isFixed - Is swap rate mode = fixed
173
+ * @param {function} setValidationContent - Function setting validation message text
174
+ * @return {Promise<boolean>}
175
+ */
176
+
177
+ /**
178
+ * Swap form provides basic functionality for entering to/from amounts both in crypto and fiat, switching assets,
179
+ * selecting assets, showing balance for assets. It gracefully handles unavailable fiat rates and can work
180
+ * both with and without a wallet environment (without balances).
181
+ *
182
+ * @param {object} props - Props object for SwapForm component.
183
+ * @param {string} props.sendingAssetTicker - Rabbit format of the ticker symbol for the asset being sent.
184
+ * @param {string} props.receivingAssetTicker - Rabbit format of the ticker symbol for the asset being received.
185
+ * @param {number} [props.sendingAssetDecimalCount=AmountUtils.significantDecimalCount] - Decimal count for the sending asset.
186
+ * @param {number} [props.receivingAssetDecimalCount=AmountUtils.significantDecimalCount] - Decimal count for the receiving asset.
187
+ * @param {string} props.sendingAssetTickerPrintable - Standard ticker symbol for the sending asset.
188
+ * @param {string} props.receivingAssetTickerPrintable - Standard ticker symbol for the receiving asset.
189
+ * @param {string} [props.sendingAssetProtocol] - Protocol name to be displayed in text on the change asset button.
190
+ * @param {string} [props.receivingAssetProtocol] - Protocol name to be displayed in text on the change asset button.
191
+ * @param {string} props.sendingAssetIconSrc - Source URL for the sending asset icon.
192
+ * @param {string} [props.sendingAssetProtocolIconSrc=null] - Optional source URL for the sending asset protocol icon.
193
+ * @param {string} props.receivingAssetIconSrc - Source URL for the receiving asset icon.
194
+ * @param {string} [props.receivingAssetProtocolIconSrc=null] - Optional source URL for the receiving asset protocol icon.
195
+ * @param {string} [props.fallBackAssetIconSrc=null] - Optional source URL for a fallback icon used when an icon fails to load.
196
+ * @param {string} [props.sendingAssetFeeCoinTickerPrintable] - Optional standard ticker symbol for the fee coin of the sending asset.
197
+ * @param {string} [props.sendingAssetBalance] - Balance of the sending asset.
198
+ * @param {string} [props.receivingAssetBalance] - Balance of the receiving asset.
199
+ * @param {handleClick} props.handleChangeSendingAssetClick - Function to handle clicking on the change sending asset button.
200
+ * @param {handleClick} props.handleChangeReceivingAssetClick - Function to handle clicking on the change receiving asset button.
201
+ * @param {handleConfirmButtonClick} props.handleConfirmButtonClick - Function to handle clicking on the confirm button.
202
+ * @param {composeConfirmButtonTo} props.composeConfirmButtonTo - Function to compose the URL for the confirm button.
203
+ * @param {setSwapCreationEstimation} props.setSwapCreationEstimation - Function to set the swap creation estimation.
204
+ * @param {handleUnexpectedError} props.handleUnexpectedError - Function to handle unexpected errors.
205
+ * @param {rotateAssets} props.rotateAssets - Function to rotate the assets (swap sending and receiving assets).
206
+ * @param {string} [props.preservedAmount=null] - Amount to be preserved.
207
+ * @param {handleSwapServiceError} props.handleSwapServiceError - Function to handle standard errors that we can recognize.
208
+ * @param {boolean} [props.formHasBalance] - Indicates if the form has balance information.
209
+ * @param {retrieveSwapDetails} props.retrieveSwapDetails - Function to retrieve swap details based on the given parameters.
210
+ * @param {retrieveInitialSwapData} props.retrieveInitialSwapData - Function to retrieve initial swap data for a given pair of assets.
211
+ * @param {number} props.triggerDataUpdateResetting - Number to reset interval updating the data periodically.
212
+ * @param {React.Ref} props.fromAssetSelectionButtonRef - Reference to the from asset selection button.
213
+ * @param {React.Ref} props.toAssetSelectionButtonRef - Reference to the to asset selection button.
214
+ * @param {number|string} [props.sendingAssetToFiatRate] - Rate for converting the sending asset to fiat.
215
+ * @param {number|string} [props.receivingAssetToFiatRate] - Rate for converting the receiving asset to fiat.
216
+ * @param {string} [props.fiatCurrencyCode] - Code for the fiat currency.
217
+ * @param {number} [props.fiatCurrencyDecimals] - Decimal places for the fiat currency.
218
+ * @param {boolean} [props.formHasFiat] - Indicates if the form supports fiat currency.
219
+ * @param {string|null} [props.termsOfUseUrl] - Terms of use URL, shown only if both terms & privacy policy passed.
220
+ * @param {string|null} [props.privacyPolicyUrl] - Privacy policy of use URL, shown only if both terms & privacy policy passed.
221
+ * @param {object} [props.translations] - Object containing translations, default English texts will be used if omitted.
222
+ * @param {string} props.swapSeparatorIconSrc - Source URL for the swap separator icon.
223
+ * @param {boolean} props.swapButtonAlwaysActive - Setting that allows the form state to proceed to the next step regardless of validity.
224
+ * @param {getExtraIdNameByTicker} props.getExtraIdNameByTicker - Function returning extraId name for asset
225
+ * @param {validateAddressByTicker} [props.validateAddressByTicker] - Function validating address
226
+ * @param {onIsFixedChange} [props.onIsFixedChange] - callback for changed isFixed
227
+ * @return {JSX.Element} Rendered SwapForm component.
228
+ * @constructor
229
+ */
230
+ export const SwapForm = ({
231
+ sendingAssetTicker,
232
+ receivingAssetTicker,
233
+ sendingAssetDecimalCount = AmountUtils.significantDecimalCount,
234
+ receivingAssetDecimalCount = AmountUtils.significantDecimalCount,
235
+ sendingAssetTickerPrintable,
236
+ receivingAssetTickerPrintable,
237
+ sendingAssetProtocol,
238
+ receivingAssetProtocol,
239
+ sendingAssetIconSrc,
240
+ sendingAssetProtocolIconSrc = null,
241
+ receivingAssetIconSrc,
242
+ receivingAssetProtocolIconSrc = null,
243
+ fallBackAssetIconSrc = null,
244
+ sendingAssetFeeCoinTickerPrintable,
245
+ sendingAssetBalance,
246
+ receivingAssetBalance,
247
+ handleChangeSendingAssetClick,
248
+ handleChangeReceivingAssetClick,
249
+ handleConfirmButtonClick = (
250
+ resetButtonLoader,
251
+ setValidationContent,
252
+ setBalanceValid,
253
+ setMinimalAmountValid,
254
+ setMaximumAmountValid,
255
+ setIsPairSupported,
256
+ setIsSameCoins,
257
+ recipientAddress,
258
+ recipientAddressExtraId,
259
+ refundAddress,
260
+ refundAddressExtraId
261
+ ) => {},
262
+ composeConfirmButtonTo = (fromTicker, toTicker, fromAmount) => "",
263
+ setSwapCreationEstimation = details => {},
264
+ handleUnexpectedError = error => {},
265
+ rotateAssets = (fromTicker, toTicker) => {},
266
+ preservedAmount = null,
267
+ handleSwapServiceError = (
268
+ errorCode,
269
+ setValidationContent,
270
+ setBalanceValid,
271
+ setMinimalAmountValid,
272
+ setMaximumAmountValid,
273
+ setIsPairSupported,
274
+ setIsSameCoins
275
+ ) => {},
276
+ formHasBalance = false,
277
+ retrieveSwapDetails = async (
278
+ sendingAssetTicker,
279
+ receivingAssetTicker,
280
+ amount,
281
+ isSwapAll = false,
282
+ isFixed = false,
283
+ amountIsToReceive = false
284
+ ) => {},
285
+ retrieveInitialSwapData = async (sendingAssetTicker, receivingAssetTicker) => {},
286
+ triggerDataUpdateResetting = 0,
287
+ fromAssetSelectionButtonRef = null,
288
+ toAssetSelectionButtonRef = null,
289
+ sendingAssetToFiatRate = null,
290
+ receivingAssetToFiatRate = null,
291
+ fiatCurrencyCode = null,
292
+ fiatCurrencyDecimals = null,
293
+ formHasFiat = true,
294
+ termsOfUseUrl = null,
295
+ privacyPolicyUrl = null,
296
+ getExtraIdNameByTicker = ticker => null,
297
+ validateAddressByTicker = () => false,
298
+ swapSeparatorIconSrc,
299
+ swapButtonAlwaysActive = false,
300
+ onIsFixedChange = () => {},
301
+ translations = {
302
+ swapAllButtonTitles: {
303
+ enable: "Swap all",
304
+ cancel: "Cancel",
305
+ },
306
+ input: {
307
+ fiatPlaceholder: "Enter fiat amount",
308
+ balanceLoaderText: "Loading balance...",
309
+ },
310
+ consents: {
311
+ consentText: 'By clicking "Swap" you agree with Rabbit Swap\'s',
312
+ termsOfUse: "Terms of Use",
313
+ and: "and",
314
+ privacyPolicy: "Privacy Policy",
315
+ },
316
+ informationBlock: {
317
+ minimumAmount: "Minimal amount: ",
318
+ maximumAmount: "Maximum amount: ",
319
+ transactionFee: "Network fee: ",
320
+ calculatingNetworkFee: "Calculating network fee..",
321
+ loadingMinimalAmount: "Loading minimal amount..",
322
+ swapRate: "Rate: ",
323
+ calculatingSwapRates: "Calculating swap rates..",
324
+ pairNotAvailable: "Pair is not available now. Please, try again later or choose another pair.",
325
+ },
326
+ addressFields: {
327
+ addressTitle: "Recepient address",
328
+ refundAddressTitle: "Refund address",
329
+ extraIdPlaceholder: "(optional)",
330
+ refundAddressExtraIdTitle: "Refund extra ID (MEMO):",
331
+ refundAddressExtraIdNotice:
332
+ "Please check if your address requires additional identifier (sometimes called a Memo, Destination Tag, Tag, ID, Label or Note). Including this identifier is crucial when required, as omitting or misentering it can result in lost assets.",
333
+ receivingAddressExtraIdTitle: "Destination extra ID (MEMO):",
334
+ receivingAddressExtraIdNotice:
335
+ "Please check if your address requires additional identifier (sometimes called a Memo, Destination Tag, Tag, ID, Label or Note). Including this identifier is crucial when required, as omitting or misentering it can result in lost assets.",
336
+ },
337
+ rateSelector: {
338
+ floatingRate: "Floating rate",
339
+ fixedRate: "Fixed rate",
340
+ },
341
+ confirmButtonText: "Swap",
342
+ },
343
+ }) => {
344
+ const DETAIL_REFRESH_INTERVAL_MS = 1.5 * 60000;
345
+ const IS_FIXED_BY_DEFAULT = false;
346
+
347
+ // Setting up an asyncronyous states, which can change during the function execution.
348
+ // This is done so that we can cancel the calculation update in case the selected asset changes.
349
+ const [sendingAssetTickerReferred, setSendingAssetTickerReferred] = useReferredState(null);
350
+ const [receivingAssetTickerReferred, setReceivingAssetTickerReferred] = useReferredState(null);
351
+
352
+ // eslint-disable-next-line react-hooks/exhaustive-deps
353
+ useEffect(() => setSendingAssetTickerReferred(sendingAssetTicker), [sendingAssetTicker]);
354
+
355
+ // eslint-disable-next-line react-hooks/exhaustive-deps
356
+ useEffect(() => setReceivingAssetTickerReferred(receivingAssetTicker), [receivingAssetTicker]);
357
+
358
+ // Updating the states below will insert the new value into the send or receive input field
359
+ const [updateSendInputTo, setUpdateSendInputTo] = useState(preservedAmount ?? null);
360
+ const [updateReceiveInputTo, setUpdateReceiveInputTo] = useState(null);
361
+
362
+ const [sendAssetAmount, setSendAssetAmount] = useReferredState(
363
+ preservedAmount == null || preservedAmount === "" ? null : preservedAmount
364
+ );
365
+ const [receiveAssetAmount, setReceiveAssetAmount] = useReferredState(null);
366
+
367
+ const [swapRate, setSwapRate] = useState();
368
+ const [minimalAmount, setMinimalAmount] = useReferredState(null);
369
+ const [maximumAmount, setMaximumAmount] = useReferredState(null);
370
+ const [validationContent, setValidationContent] = useState();
371
+
372
+ const [minimalAmountValid, setMinimalAmountValid] = useState(true); // Whether the amount is above the minimal amount
373
+ const [maximumAmountValid, setMaximumAmountValid] = useState(true);
374
+ const [isPairSupported, setIsPairSupported] = useState(true);
375
+ const [isSameCoins, setIsSameCoins] = useState(false);
376
+ const [isSwapCalculated, setIsSwapCalculated] = useState(false);
377
+ const [readyToSwap, setReadyToSwap] = useState(false); // Basically a param that enables/disables the "Next" button
378
+ // TODO: [refactoring, moderate] instead of handling preservedAmount at a lot of cases below, just
379
+ // write single useEffect setting sendAssetAmount to the=is passed value and simplify the logic below. task_id=6453251e49b04c5e88a3cc771479ffb5
380
+ const [isAmountZero, setIsAmountZero] = useState(preservedAmount == null || String(preservedAmount) === "0");
381
+ const [isLoading, setIsLoading] = useReferredState(false); // Whether the form is in the progress of loading some data (new rates, for example)
382
+ const [isFixedRate, setIsFixedRate] = useReferredState(null);
383
+ const [isLastEditedReceiving, setIsLastEditedReceiving] = useReferredState(false);
384
+ const [isInitialLoading, setIsInitialLoading] = useState(true);
385
+
386
+ const [confirmButtonTo, setConfirmButtonTo] = useState(
387
+ composeConfirmButtonTo(sendingAssetTicker, receivingAssetTicker, preservedAmount)
388
+ );
389
+
390
+ const [transactionFee, setTransactionFee] = useState();
391
+ const [balanceValid, setBalanceValid] = useState(true); // Whether the amount is less than total balance
392
+ const [isSwapAll, setIsSwapAll] = useReferredState(null);
393
+ const [swapAllButtonLoaderReSetter, setSwapAllButtonLoaderReSetter] = useState([]);
394
+
395
+ const [dataUpdateTimeoutId, setDataUpdateTimeoutId] = useReferredState(null);
396
+ const [idleDataUpdateTimeoutId, setIdleDataUpdateTimeoutId] = useReferredState(null);
397
+
398
+ const [recipientAddress, setRecipientAddress] = useReferredState("");
399
+ const [recipientAddressExtraId, setRecipientAddressExtraId] = useReferredState("");
400
+ const [isRecipientAddressValid, setIsRecipientAddressValid] = useReferredState(false);
401
+ const [isRefundAddressRequired, setIsRefundAddressRequired] = useState(false);
402
+ const [refundAddress, setRefundAddress] = useReferredState("");
403
+ const [refundAddressExtraId, setRefundAddressExtraId] = useReferredState("");
404
+ const [isRefundAddressValid, setIsRefundAddressValid] = useReferredState(false);
405
+
406
+ const callHandlingErrors = useCallHandlingErrors();
407
+ const isHydrated = useIsHydrated();
408
+
409
+ const recalculationDelayOnTyping = 1000;
410
+
411
+ const isAddressFieldEnabled = !formHasBalance;
412
+ const displayRateSelector = !formHasBalance;
413
+
414
+ const handleSendAssetAmountChange = amount => {
415
+ setIsLastEditedReceiving(false);
416
+ let receiveAmount = "";
417
+ if (amount != null && amount !== "" && swapRate != null) {
418
+ receiveAmount = AmountUtils.trim(BigNumber(amount).times(swapRate), receivingAssetDecimalCount);
419
+ }
420
+ setReceiveAssetAmount(receiveAmount);
421
+ setUpdateReceiveInputTo(receiveAmount);
422
+ setSendAssetAmount(amount);
423
+ };
424
+
425
+ const handleReceiveAssetAmountChange = amount => {
426
+ setReceiveAssetAmount(amount);
427
+ if (isFixedRate.current) setIsLastEditedReceiving(true);
428
+ let sendAssetAmount = "";
429
+ if (amount != null && amount !== "" && swapRate != null) {
430
+ sendAssetAmount = AmountUtils.trim(BigNumber(amount).div(swapRate), sendingAssetDecimalCount);
431
+ }
432
+ setUpdateSendInputTo(sendAssetAmount);
433
+ setSendAssetAmount(sendAssetAmount);
434
+ };
435
+
436
+ const handleMinimalAmountClick = () => {
437
+ if (!minimalAmount.current) return;
438
+
439
+ if (isLastEditedReceiving.current) {
440
+ setUpdateReceiveInputTo(minimalAmount.current?.crypto);
441
+ handleReceiveAssetAmountChange(minimalAmount.current?.crypto);
442
+ } else {
443
+ setUpdateSendInputTo(minimalAmount.current?.crypto);
444
+ handleSendAssetAmountChange(minimalAmount.current?.crypto);
445
+ }
446
+ };
447
+
448
+ const handleMaximumAmountClick = () => {
449
+ if (!maximumAmount.current) return;
450
+
451
+ if (isLastEditedReceiving.current) {
452
+ setUpdateReceiveInputTo(maximumAmount.current?.crypto);
453
+ handleReceiveAssetAmountChange(maximumAmount.current?.crypto);
454
+ } else {
455
+ setUpdateSendInputTo(maximumAmount.current?.crypto);
456
+ handleSendAssetAmountChange(maximumAmount.current?.crypto);
457
+ }
458
+ };
459
+
460
+ const handleSwapAllClick = resetButtonLoader => {
461
+ setIsSwapAll(prev => {
462
+ if (prev) {
463
+ // Setting amount inputs to empty string if we are handling the disabling of previously enabled swap all
464
+ setUpdateSendInputTo("");
465
+ setUpdateReceiveInputTo("");
466
+ setSendAssetAmount(null);
467
+ setReceiveAssetAmount(null);
468
+ }
469
+ return !prev;
470
+ });
471
+ setSwapAllButtonLoaderReSetter([resetButtonLoader]);
472
+ };
473
+
474
+ const processMinMaxAmounts = amount => {
475
+ if (amount === null) return;
476
+
477
+ setMaximumAmountValid(
478
+ !maximumAmount.current || BigNumber(amount).eq("0") || BigNumber(amount).lte(maximumAmount.current.crypto)
479
+ );
480
+ setMinimalAmountValid(
481
+ !minimalAmount.current || BigNumber(amount).eq("0") || BigNumber(amount).gte(minimalAmount.current?.crypto)
482
+ );
483
+ };
484
+
485
+ const requestDataRefresh = (amount, immediately = false, isSwapAll = false, ignoreEmptyAmount = false) => {
486
+ try {
487
+ clearTimeout(dataUpdateTimeoutId.current);
488
+
489
+ if (isSwapAll) {
490
+ loadFullEstimation(null);
491
+ return;
492
+ }
493
+
494
+ if (!amount && !ignoreEmptyAmount) {
495
+ return;
496
+ }
497
+
498
+ if (BigNumber(amount).eq("0") || amount == null || amount === "") {
499
+ if (immediately) {
500
+ loadMinimalAmountAndSwapRate(true);
501
+ } else {
502
+ setDataUpdateTimeoutId(
503
+ setTimeout(() => loadMinimalAmountAndSwapRate(true), recalculationDelayOnTyping)
504
+ );
505
+ }
506
+ } else {
507
+ if (immediately) {
508
+ loadFullEstimation(amount, preservedAmount && String(preservedAmount) !== "0" ? true : undefined);
509
+ } else {
510
+ setDataUpdateTimeoutId(setTimeout(() => loadFullEstimation(amount), recalculationDelayOnTyping));
511
+ }
512
+ }
513
+ } catch (e) {
514
+ handleUnexpectedError(e);
515
+ }
516
+ };
517
+
518
+ const setAmountLimitsAndRate = details => {
519
+ setSwapRate(details?.rate ?? null);
520
+ if (!details?.rate) {
521
+ if (isLastEditedReceiving.current) {
522
+ setUpdateSendInputTo("");
523
+ setSendAssetAmount("");
524
+ } else {
525
+ setUpdateReceiveInputTo("");
526
+ setReceiveAssetAmount("");
527
+ }
528
+ }
529
+ setMinimalAmount(details.min == null ? null : { crypto: details.min, fiat: details.fiatMin });
530
+ setMaximumAmount(details.max == null ? null : { crypto: details.max, fiat: details.fiatMax });
531
+ if (details.feeCoins != null) {
532
+ setTransactionFee({
533
+ crypto: details.feeCoins,
534
+ fiat: details.feeFiat,
535
+ });
536
+ } else {
537
+ setTransactionFee(null);
538
+ }
539
+ };
540
+
541
+ const loadFullEstimation = (amount, isForPreserved = false) => {
542
+ (async () => {
543
+ try {
544
+ const dataMemento = {
545
+ rate: swapRate,
546
+ min: minimalAmount.current?.crypto,
547
+ max: maximumAmount.current?.crypto,
548
+ feeCoins: transactionFee?.crypto,
549
+ feeFiat: transactionFee?.fiat,
550
+ };
551
+ setIsLoading(true);
552
+ setMinimalAmount(null);
553
+ setMaximumAmount(null);
554
+ setTransactionFee(null);
555
+ setValidationContent(null);
556
+ setSwapCreationEstimation(null);
557
+ setIsSameCoins(false);
558
+ setIsPairSupported(true);
559
+ setIsSwapCalculated(false);
560
+
561
+ // Saving the selected coins at the moment, so we can cancel
562
+ // the processing if they get changed during the loading.
563
+ const currentSendingAssetTicker = sendingAssetTicker;
564
+ const currentReceivingAssetTicker = receivingAssetTicker;
565
+
566
+ const response = await retrieveSwapDetails(
567
+ currentSendingAssetTicker,
568
+ currentReceivingAssetTicker,
569
+ amount,
570
+ isSwapAll.current,
571
+ isFixedRate.current ?? IS_FIXED_BY_DEFAULT,
572
+ isFixedRate.current ? isLastEditedReceiving.current : false
573
+ );
574
+
575
+ if (
576
+ currentSendingAssetTicker !== sendingAssetTickerReferred.current ||
577
+ currentReceivingAssetTicker !== receivingAssetTickerReferred.current
578
+ ) {
579
+ // Cancelling the further processing in case the
580
+ // selected coins were changed during the loading.
581
+ return;
582
+ }
583
+
584
+ if (
585
+ !isSwapAll.current &&
586
+ String(amount) !==
587
+ String(
588
+ isForPreserved && sendAssetAmount.current == null && receiveAssetAmount.current == null
589
+ ? preservedAmount
590
+ : isFixedRate.current && isLastEditedReceiving.current
591
+ ? receiveAssetAmount.current
592
+ : sendAssetAmount.current
593
+ )
594
+ ) {
595
+ // Means amount changed and we no more need to do this exact calculation
596
+ return;
597
+ }
598
+
599
+ if (response.result) {
600
+ const swapCreationInfo = response?.swapCreationInfo;
601
+
602
+ if (isSwapAll.current) {
603
+ setIsAmountZero(BigNumber("0").eq(swapCreationInfo.fromAmountCoins));
604
+ }
605
+
606
+ setUpdateSendInputTo(swapCreationInfo.fromAmountCoins);
607
+ setUpdateReceiveInputTo(swapCreationInfo.toAmountCoins);
608
+
609
+ if (isLastEditedReceiving.current) {
610
+ setSendAssetAmount(swapCreationInfo.fromAmountCoins);
611
+ } else {
612
+ setReceiveAssetAmount(swapCreationInfo.toAmountCoins);
613
+ }
614
+
615
+ setAmountLimitsAndRate(swapCreationInfo);
616
+ setSwapCreationEstimation(swapCreationInfo);
617
+ setIsRefundAddressRequired(swapCreationInfo?.isRefundAddressRequired);
618
+ processMinMaxAmounts(isSwapAll.current ? swapCreationInfo.fromAmountCoins : amount);
619
+ setIsSwapCalculated(true);
620
+ } else {
621
+ handleSwapServiceError(
622
+ response.reason,
623
+ setValidationContent,
624
+ setBalanceValid,
625
+ setMinimalAmountValid,
626
+ setMaximumAmountValid,
627
+ setIsPairSupported,
628
+ setIsSameCoins
629
+ );
630
+ if (isSwapAll.current) {
631
+ /* We disable swap all if swap all details retrieval fails and set
632
+ * previous limits and rate. We set null to avoid triggering reloading of initial data.
633
+ */
634
+ setIsSwapAll(null);
635
+ setAmountLimitsAndRate(dataMemento);
636
+ } else {
637
+ /* We set returned amount limits and rate only if the failed details retrieval is not
638
+ * for the swap All case.
639
+ */
640
+ setAmountLimitsAndRate(response);
641
+ if (isLastEditedReceiving.current) {
642
+ setSendAssetAmount("");
643
+ } else {
644
+ setReceiveAssetAmount("");
645
+ }
646
+ }
647
+ }
648
+ setIsLoading(false);
649
+ } catch (e) {
650
+ handleUnexpectedError(e);
651
+ }
652
+ })();
653
+ };
654
+
655
+ const loadMinimalAmountAndSwapRate = (isCalledForClearedInput = false) => {
656
+ (async () => {
657
+ try {
658
+ setIsLoading(true);
659
+ setMinimalAmount(null);
660
+ setMaximumAmount(null);
661
+ setSwapRate(null);
662
+ setValidationContent(null);
663
+ setIsPairSupported(true);
664
+ setIsSwapCalculated(false);
665
+
666
+ const swapData = await retrieveInitialSwapData(sendingAssetTicker, receivingAssetTicker);
667
+
668
+ if (
669
+ (isFixedRate.current && isLastEditedReceiving.current
670
+ ? receiveAssetAmount.current != null
671
+ : sendAssetAmount.current != null) &&
672
+ !isCalledForClearedInput
673
+ ) {
674
+ // Means user already entered amount after starting the form initialization
675
+ return;
676
+ }
677
+
678
+ if (swapData.result === true) {
679
+ setAmountLimitsAndRate(swapData);
680
+ } else {
681
+ handleSwapServiceError(
682
+ swapData.reason,
683
+ setValidationContent,
684
+ setBalanceValid,
685
+ setMinimalAmountValid,
686
+ setMaximumAmountValid,
687
+ setIsPairSupported,
688
+ setIsSameCoins
689
+ );
690
+ }
691
+
692
+ setIsLoading(false);
693
+ } catch (e) {
694
+ handleUnexpectedError(e);
695
+ }
696
+ })();
697
+ };
698
+
699
+ const handleChangeAssetsIconClick = e => {
700
+ callHandlingErrors(() => {
701
+ if (!isLoading.current) {
702
+ setIsSwapAll(null);
703
+ setMaximumAmountValid(true);
704
+ setMinimalAmountValid(true);
705
+
706
+ const sendAssetAmountMemento = sendAssetAmount.current;
707
+ const receiveAssetAmountMemento = receiveAssetAmount.current;
708
+
709
+ if (isLastEditedReceiving.current) {
710
+ setSendAssetAmount("");
711
+ setUpdateSendInputTo("");
712
+
713
+ setReceiveAssetAmount(sendAssetAmountMemento);
714
+ setUpdateReceiveInputTo(sendAssetAmountMemento);
715
+ } else {
716
+ setSendAssetAmount(receiveAssetAmountMemento);
717
+ setUpdateSendInputTo(receiveAssetAmountMemento);
718
+
719
+ setReceiveAssetAmount("");
720
+ setUpdateReceiveInputTo("");
721
+ }
722
+
723
+ rotateAssets(sendingAssetTicker, receivingAssetTicker);
724
+ }
725
+ }, e);
726
+ };
727
+
728
+ const handleRateModeChanged = isFixed => {
729
+ setIsFixedRate(isFixed);
730
+ requestDataRefresh(
731
+ isLastEditedReceiving.current ? receiveAssetAmount.current : sendAssetAmount.current,
732
+ true,
733
+ null,
734
+ true
735
+ );
736
+ };
737
+
738
+ useEffect(() => {
739
+ if (isSwapAll.current === true) {
740
+ requestDataRefresh(undefined, true, true);
741
+ } else if (isSwapAll.current === false) {
742
+ loadMinimalAmountAndSwapRate();
743
+ }
744
+ // eslint-disable-next-line react-hooks/exhaustive-deps
745
+ }, [isSwapAll.current]);
746
+
747
+ useEffect(() => {
748
+ onIsFixedChange(isFixedRate.current);
749
+ if (!isFixedRate.current) setIsLastEditedReceiving(false);
750
+ // eslint-disable-next-line react-hooks/exhaustive-deps
751
+ }, [isFixedRate.current]);
752
+
753
+ useEffect(() => {
754
+ if (!sendingAssetTicker || !receivingAssetTicker) return;
755
+
756
+ if (isInitialLoading) {
757
+ setIsInitialLoading(false);
758
+ return;
759
+ }
760
+
761
+ const currentAmount = isLastEditedReceiving.current ? receiveAssetAmount.current : sendAssetAmount.current;
762
+
763
+ const isCurrentAmountNotZero = currentAmount && !BigNumber("0").eq(currentAmount);
764
+
765
+ if (isCurrentAmountNotZero) {
766
+ loadFullEstimation(currentAmount);
767
+ } else {
768
+ loadMinimalAmountAndSwapRate(true);
769
+ }
770
+
771
+ // eslint-disable-next-line react-hooks/exhaustive-deps
772
+ }, [sendingAssetTicker, receivingAssetTicker]);
773
+
774
+ useEffect(() => {
775
+ if (!minimalAmountValid || isAmountZero) {
776
+ setTransactionFee(null);
777
+ }
778
+ if (isAmountZero) {
779
+ clearTimeout(dataUpdateTimeoutId.current);
780
+ }
781
+
782
+ setReadyToSwap(
783
+ swapButtonAlwaysActive ||
784
+ ((balanceValid || !formHasBalance) &&
785
+ minimalAmountValid &&
786
+ !isAmountZero &&
787
+ isSwapCalculated &&
788
+ (!isSameCoins || !formHasBalance) &&
789
+ isPairSupported &&
790
+ (!isAddressFieldEnabled || isRecipientAddressValid.current) &&
791
+ (!isRefundAddressRequired || isRefundAddressValid.current))
792
+ );
793
+ // eslint-disable-next-line react-hooks/exhaustive-deps
794
+ }, [
795
+ balanceValid,
796
+ formHasBalance,
797
+ minimalAmountValid,
798
+ isAmountZero,
799
+ isSwapCalculated,
800
+ isSameCoins,
801
+ isPairSupported,
802
+ isAddressFieldEnabled,
803
+ isRecipientAddressValid.current,
804
+ isRefundAddressRequired,
805
+ isRefundAddressValid.current,
806
+ ]);
807
+
808
+ useEffect(() => {
809
+ setIsRecipientAddressValid(false);
810
+ setRecipientAddress("");
811
+ setRecipientAddressExtraId("");
812
+ // eslint-disable-next-line react-hooks/exhaustive-deps
813
+ }, [receivingAssetTicker]);
814
+
815
+ useEffect(() => {
816
+ setIsRefundAddressValid(false);
817
+ setRefundAddress("");
818
+ setRefundAddressExtraId("");
819
+ // eslint-disable-next-line react-hooks/exhaustive-deps
820
+ }, [sendingAssetTicker]);
821
+
822
+ useEffect(() => {
823
+ (async () => {
824
+ if (!receivingAssetTicker) return;
825
+ setValidationContent("");
826
+ setIsRecipientAddressValid(
827
+ recipientAddress.current === ""
828
+ ? false
829
+ : await validateAddressByTicker(
830
+ receivingAssetTicker,
831
+ recipientAddress.current,
832
+ isFixedRate.current,
833
+ setValidationContent
834
+ )
835
+ );
836
+ })();
837
+ // eslint-disable-next-line react-hooks/exhaustive-deps
838
+ }, [recipientAddress.current, recipientAddressExtraId.current, receivingAssetTicker]);
839
+
840
+ useEffect(() => {
841
+ (async () => {
842
+ if (!sendingAssetTicker || !isRefundAddressRequired) return;
843
+ setValidationContent("");
844
+ setIsRefundAddressValid(
845
+ refundAddress.current === ""
846
+ ? false
847
+ : await validateAddressByTicker(
848
+ sendingAssetTicker,
849
+ refundAddress.current,
850
+ isFixedRate.current,
851
+ setValidationContent
852
+ )
853
+ );
854
+ })();
855
+ // eslint-disable-next-line react-hooks/exhaustive-deps
856
+ }, [refundAddress.current, refundAddressExtraId.current, sendingAssetTicker, isRefundAddressRequired]);
857
+
858
+ useEffect(() => {
859
+ // Here we set up auto recalculations for the swap details if the form is ready to swap but is idle for some time
860
+ let timeoutId = null;
861
+ if (readyToSwap) {
862
+ timeoutId = setTimeout(
863
+ () =>
864
+ requestDataRefresh(
865
+ isLastEditedReceiving.current
866
+ ? receiveAssetAmount.current
867
+ : sendAssetAmount.current ?? preservedAmount,
868
+ true
869
+ ),
870
+ DETAIL_REFRESH_INTERVAL_MS
871
+ );
872
+ setIdleDataUpdateTimeoutId(timeoutId);
873
+ } else {
874
+ clearTimeout(idleDataUpdateTimeoutId.current);
875
+ setIdleDataUpdateTimeoutId(null);
876
+ }
877
+ return () => {
878
+ timeoutId != null && clearTimeout(timeoutId);
879
+ };
880
+ // eslint-disable-next-line react-hooks/exhaustive-deps
881
+ }, [readyToSwap]);
882
+
883
+ // TODO: [refactoring, critical] this code looks like a hack related to task_id=6e328d39063142b7b9fa01d497e616da
884
+ useEffect(() => {
885
+ if (triggerDataUpdateResetting) {
886
+ clearTimeout(dataUpdateTimeoutId.current);
887
+ setDataUpdateTimeoutId(null);
888
+
889
+ clearTimeout(idleDataUpdateTimeoutId.current);
890
+ setIdleDataUpdateTimeoutId(null);
891
+ }
892
+ // eslint-disable-next-line react-hooks/exhaustive-deps
893
+ }, [triggerDataUpdateResetting]);
894
+
895
+ // Resets the passed "set value to" param to null, so it can be used multiple times with any value
896
+ useEffect(() => {
897
+ if (!!updateSendInputTo) setUpdateSendInputTo(null);
898
+ if (!!updateReceiveInputTo) setUpdateReceiveInputTo(null);
899
+ // eslint-disable-next-line react-hooks/exhaustive-deps
900
+ }, [updateSendInputTo, updateReceiveInputTo]);
901
+
902
+ useEffect(() => {
903
+ if (
904
+ swapRate != null &&
905
+ (isLastEditedReceiving.current ? receiveAssetAmount.current : sendAssetAmount.current) != null
906
+ ) {
907
+ if (isLastEditedReceiving.current) {
908
+ setUpdateSendInputTo(
909
+ AmountUtils.trim(BigNumber(receiveAssetAmount.current).div(swapRate), sendingAssetDecimalCount)
910
+ );
911
+ } else {
912
+ setUpdateReceiveInputTo(
913
+ AmountUtils.trim(BigNumber(sendAssetAmount.current).times(swapRate), receivingAssetDecimalCount)
914
+ );
915
+ }
916
+ }
917
+ // eslint-disable-next-line react-hooks/exhaustive-deps
918
+ }, [swapRate]);
919
+
920
+ useEffect(() => {
921
+ if (isLoading.current === false && swapAllButtonLoaderReSetter?.length) {
922
+ swapAllButtonLoaderReSetter[0]();
923
+ setSwapAllButtonLoaderReSetter([]);
924
+ }
925
+ // eslint-disable-next-line react-hooks/exhaustive-deps
926
+ }, [isLoading.current, swapAllButtonLoaderReSetter]);
927
+
928
+ const handleAmountChange = amount => {
929
+ requestDataRefresh(amount);
930
+ processMinMaxAmounts(amount);
931
+ setIsAmountZero(BigNumber("0").eq(amount));
932
+ setIsSwapCalculated(false);
933
+ };
934
+
935
+ useEffect(() => {
936
+ if (isLastEditedReceiving.current)
937
+ handleAmountChange(receiveAssetAmount.current === "" ? "0" : receiveAssetAmount.current);
938
+ }, [receiveAssetAmount.current]);
939
+
940
+ useEffect(() => {
941
+ if (!isLastEditedReceiving.current)
942
+ handleAmountChange(sendAssetAmount.current === "" ? "0" : sendAssetAmount.current);
943
+ }, [sendAssetAmount.current]);
944
+
945
+ const recipientAddressExtraIdName = getExtraIdNameByTicker(receivingAssetTicker);
946
+ const refundAddressExtraIdName = getExtraIdNameByTicker(sendingAssetTicker);
947
+
948
+ return (
949
+ <div className={s["swap-form"]}>
950
+ <TitleBox
951
+ linkButtonClick={
952
+ BigNumber(sendingAssetBalance?.assetAmount).eq(0)
953
+ ? null
954
+ : resetButtonLoader => handleSwapAllClick(resetButtonLoader)
955
+ }
956
+ linkText={
957
+ !formHasBalance
958
+ ? ""
959
+ : isSwapAll.current
960
+ ? translations.swapAllButtonTitles.cancel
961
+ : translations.swapAllButtonTitles.enable
962
+ }
963
+ linkButtonLoader={true}
964
+ isLinkButtonDisabled={
965
+ isLoading.current ||
966
+ sendingAssetTicker === receivingAssetTicker ||
967
+ BigNumber(sendingAssetBalance?.assetAmount).eq(0)
968
+ }
969
+ >
970
+ {displayRateSelector ? (
971
+ <div className={s["swap-form-rate-selector"]}>
972
+ <RateSelector
973
+ isFixed={isFixedRate.current ?? IS_FIXED_BY_DEFAULT}
974
+ setIsFixed={handleRateModeChanged}
975
+ translations={translations.rateSelector}
976
+ />
977
+ </div>
978
+ ) : (
979
+ ""
980
+ )}
981
+
982
+ <div className={s["swap-form-inputs"]}>
983
+ <AmountInput
984
+ ticker={sendingAssetTicker}
985
+ tickerPrintable={sendingAssetTickerPrintable}
986
+ assetDecimalPlaces={sendingAssetDecimalCount}
987
+ assetBalance={sendingAssetBalance}
988
+ assetIconSrc={sendingAssetIconSrc}
989
+ assetIconProtocolSrc={sendingAssetProtocolIconSrc}
990
+ fallbackAssetIconSrc={fallBackAssetIconSrc}
991
+ disabled={isSwapAll.current || sendingAssetTicker === null || receivingAssetTicker === null}
992
+ handleCoinAmountChange={handleSendAssetAmountChange}
993
+ handleChangeAssetClick={handleChangeSendingAssetClick}
994
+ handleBalanceValidationChange={isValid => setBalanceValid(!isValid)}
995
+ updateAssetInputTo={updateSendInputTo}
996
+ showBalance={formHasBalance}
997
+ showBalanceValidation={formHasBalance}
998
+ showChangeAssetButton
999
+ changeAssetButtonProtocol={sendingAssetProtocol}
1000
+ upperFormPosition
1001
+ errorEncountered={
1002
+ !isLastEditedReceiving.current && (!minimalAmountValid || !maximumAmountValid)
1003
+ }
1004
+ ref={fromAssetSelectionButtonRef}
1005
+ isLoading={isLastEditedReceiving.current ? isLoading.current : false}
1006
+ cryptoAssetToFiatRate={sendingAssetToFiatRate}
1007
+ fiatCurrencyCode={
1008
+ formHasFiat && (isLoading.current || sendingAssetToFiatRate != null)
1009
+ ? fiatCurrencyCode
1010
+ : null
1011
+ }
1012
+ fiatCurrencyDecimals={fiatCurrencyDecimals}
1013
+ balanceLoaderText={translations.input.balanceLoaderText}
1014
+ fiatInputPlaceholderText={translations.input.fiatPlaceholder}
1015
+ />
1016
+ <div
1017
+ className={
1018
+ s["swap-form-inputs-separator"] +
1019
+ " " +
1020
+ (isLoading.current || sendingAssetTicker === null || receivingAssetTicker === null
1021
+ ? s["disabled"]
1022
+ : "")
1023
+ }
1024
+ >
1025
+ <img
1026
+ src={swapSeparatorIconSrc}
1027
+ alt="swap icon"
1028
+ draggable={false}
1029
+ onClick={e => callHandlingErrors(handleChangeAssetsIconClick, e)}
1030
+ loading="lazy"
1031
+ />
1032
+ </div>
1033
+ <AmountInput
1034
+ ticker={receivingAssetTicker}
1035
+ tickerPrintable={receivingAssetTickerPrintable}
1036
+ assetDecimalPlaces={receivingAssetDecimalCount}
1037
+ assetBalance={receivingAssetBalance}
1038
+ assetIconSrc={receivingAssetIconSrc}
1039
+ assetIconProtocolSrc={receivingAssetProtocolIconSrc}
1040
+ fallbackAssetIconSrc={fallBackAssetIconSrc}
1041
+ disabled={isSwapAll.current || sendingAssetTicker === null || receivingAssetTicker === null}
1042
+ locked
1043
+ handleCoinAmountChange={handleReceiveAssetAmountChange}
1044
+ handleChangeAssetClick={handleChangeReceivingAssetClick}
1045
+ updateAssetInputTo={updateReceiveInputTo}
1046
+ showChangeAssetButton
1047
+ changeAssetButtonProtocol={receivingAssetProtocol}
1048
+ showBalance={formHasBalance}
1049
+ lowerFormPosition
1050
+ errorEncountered={isLastEditedReceiving.current && (!minimalAmountValid || !maximumAmountValid)}
1051
+ estimateAmount={!isFixedRate.current}
1052
+ ref={toAssetSelectionButtonRef}
1053
+ isLoading={isLastEditedReceiving.current ? false : isLoading.current}
1054
+ cryptoAssetToFiatRate={receivingAssetToFiatRate}
1055
+ fiatCurrencyCode={
1056
+ formHasFiat && (isLoading.current || receivingAssetToFiatRate != null)
1057
+ ? fiatCurrencyCode
1058
+ : null
1059
+ }
1060
+ fiatCurrencyDecimals={fiatCurrencyDecimals}
1061
+ balanceLoaderText={translations.input.balanceLoaderText}
1062
+ fiatInputPlaceholderText={translations.input.fiatPlaceholder}
1063
+ />
1064
+ </div>
1065
+ <div className={s["swap-form-information-field"]}>
1066
+ {/* TODO: [refactoring, moderate] Add flags calculation for each message to avoid this ugly cumbersome implicit unclear logic of message displaying. task_id=8bc31dbcd94d46a598346e8bfb505971 */}
1067
+ <p>
1068
+ {!isPairSupported ? (
1069
+ translations.informationBlock.pairNotAvailable
1070
+ ) : transactionFee && minimalAmountValid ? (
1071
+ <>
1072
+ {translations.informationBlock.transactionFee}
1073
+ <span>
1074
+ {AmountUtils.crypto(transactionFee?.crypto, sendingAssetFeeCoinTickerPrintable)}
1075
+ </span>
1076
+ {transactionFee?.fiat != null && transactionFee?.fiat !== "" ? (
1077
+ <span className={"semi-transparent"}>
1078
+ {" ~ " + AmountUtils.fiat(transactionFee?.fiat, fiatCurrencyCode)}
1079
+ </span>
1080
+ ) : (
1081
+ ""
1082
+ )}
1083
+ </>
1084
+ ) : !isLoading.current && (isSwapCalculated || (!minimalAmount.current && swapRate)) ? (
1085
+ <>
1086
+ {translations.informationBlock.swapRate}
1087
+ <span>
1088
+ {AmountUtils.composeRateText(
1089
+ sendingAssetTickerPrintable,
1090
+ receivingAssetTickerPrintable,
1091
+ swapRate,
1092
+ receivingAssetDecimalCount,
1093
+ isFixedRate.current ?? IS_FIXED_BY_DEFAULT
1094
+ )}
1095
+ </span>
1096
+ </>
1097
+ ) : minimalAmount.current || maximumAmount.current ? (
1098
+ !maximumAmountValid && maximumAmount.current != null ? (
1099
+ <>
1100
+ {translations.informationBlock.maximumAmount}
1101
+ <span
1102
+ className={s["interactable"] + " " + s["red"]}
1103
+ onClick={
1104
+ isLoading.current
1105
+ ? () => {}
1106
+ : e => callHandlingErrors(handleMaximumAmountClick, e)
1107
+ }
1108
+ >
1109
+ {AmountUtils.crypto(
1110
+ maximumAmount.current?.crypto,
1111
+ isLastEditedReceiving.current
1112
+ ? receivingAssetTickerPrintable
1113
+ : sendingAssetTickerPrintable
1114
+ )}
1115
+ </span>
1116
+ {maximumAmount.current?.fiat != null && maximumAmount.current?.fiat !== "" ? (
1117
+ <span className={"semi-transparent"}>
1118
+ {" ~ " + AmountUtils.fiat(maximumAmount.current.fiat, fiatCurrencyCode)}
1119
+ </span>
1120
+ ) : (
1121
+ ""
1122
+ )}
1123
+ </>
1124
+ ) : !minimalAmount.current ? (
1125
+ ""
1126
+ ) : (
1127
+ <>
1128
+ {translations.informationBlock.minimumAmount}
1129
+ <span
1130
+ className={s["interactable"] + " " + (!minimalAmountValid ? s["red"] : "")}
1131
+ onClick={
1132
+ isLoading.current
1133
+ ? () => {}
1134
+ : e => callHandlingErrors(handleMinimalAmountClick, e)
1135
+ }
1136
+ >
1137
+ {AmountUtils.crypto(
1138
+ minimalAmount.current.crypto,
1139
+ isLastEditedReceiving.current
1140
+ ? receivingAssetTickerPrintable
1141
+ : sendingAssetTickerPrintable
1142
+ )}
1143
+ </span>
1144
+ {minimalAmount.current?.fiat != null && minimalAmount.current.fiat !== "" ? (
1145
+ <span className={"semi-transparent"}>
1146
+ {" ~ " + AmountUtils.fiat(minimalAmount.current.fiat, fiatCurrencyCode)}
1147
+ </span>
1148
+ ) : (
1149
+ ""
1150
+ )}
1151
+ </>
1152
+ )
1153
+ ) : isLoading.current ? (
1154
+ sendAssetAmount.current || receiveAssetAmount.current || isSwapAll.current ? (
1155
+ translations.informationBlock[
1156
+ formHasBalance ? "calculatingNetworkFee" : "calculatingSwapRates"
1157
+ ]
1158
+ ) : (
1159
+ translations.informationBlock.loadingMinimalAmount
1160
+ )
1161
+ ) : (
1162
+ translations?.informationBlock?.enterAmount
1163
+ )}
1164
+ </p>
1165
+ </div>
1166
+
1167
+ {isAddressFieldEnabled ? (
1168
+ <div className={s["swap-form-address-field"]}>
1169
+ <TitleBox title={translations.addressFields.addressTitle}>
1170
+ <Textarea
1171
+ type={"text"}
1172
+ onChange={e => setRecipientAddress(e.target.value)}
1173
+ value={recipientAddress.current}
1174
+ adaptiveHeight={true}
1175
+ errorEncountered={recipientAddress.current !== "" && !isRecipientAddressValid.current}
1176
+ />
1177
+ </TitleBox>
1178
+ {isHydrated && recipientAddressExtraIdName ? (
1179
+ <TitleBox
1180
+ title={translations.addressFields.receivingAddressExtraIdTitle}
1181
+ titleNoticeText={translations.addressFields.receivingAddressExtraIdNotice}
1182
+ titleNoticePosition={TOOLTIP_POSITIONS.TOP_LEFT}
1183
+ >
1184
+ <Textarea
1185
+ type={"text"}
1186
+ onChange={e => setRecipientAddressExtraId(e.target.value)}
1187
+ value={recipientAddressExtraId.current}
1188
+ adaptiveHeight={true}
1189
+ placeholder={translations.addressFields.extraIdPlaceholder}
1190
+ />
1191
+ </TitleBox>
1192
+ ) : null}
1193
+ {isHydrated && isRefundAddressRequired ? (
1194
+ <>
1195
+ <TitleBox title={translations.addressFields.refundAddressTitle}>
1196
+ <Textarea
1197
+ type={"text"}
1198
+ onChange={e => setRefundAddress(e.target.value)}
1199
+ value={refundAddress.current}
1200
+ adaptiveHeight={true}
1201
+ errorEncountered={refundAddress.current !== "" && !isRefundAddressValid.current}
1202
+ />
1203
+ </TitleBox>
1204
+ {refundAddressExtraIdName ? (
1205
+ <TitleBox
1206
+ title={translations.addressFields.refundAddressExtraIdTitle}
1207
+ titleNoticeText={translations.addressFields.refundAddressExtraIdNotice}
1208
+ titleNoticePosition={TOOLTIP_POSITIONS.TOP_LEFT}
1209
+ >
1210
+ <Textarea
1211
+ type={"text"}
1212
+ onChange={e => setRefundAddressExtraId(e.target.value)}
1213
+ value={refundAddressExtraId.current}
1214
+ adaptiveHeight={true}
1215
+ placeholder={translations.addressFields.extraIdPlaceholder}
1216
+ />
1217
+ </TitleBox>
1218
+ ) : null}
1219
+ </>
1220
+ ) : null}
1221
+ </div>
1222
+ ) : null}
1223
+
1224
+ {validationContent ? (
1225
+ <div className={s["swap-form-validation-text"]}>
1226
+ <Validation text={validationContent} />
1227
+ </div>
1228
+ ) : (
1229
+ ""
1230
+ )}
1231
+ <div className={s["swap-form-button-container"]}>
1232
+ {!termsOfUseUrl || !privacyPolicyUrl ? null : (
1233
+ <p className={s["swap-form-button-container-consent-text"]}>
1234
+ {translations.consents.consentText + " "}
1235
+ <a
1236
+ href={termsOfUseUrl}
1237
+ className={s["swap-form-button-container-consent-text-link"]}
1238
+ target="_blank"
1239
+ >
1240
+ {translations.consents.termsOfUse}
1241
+ </a>
1242
+ {" " + translations.consents.and + " "}
1243
+ <a
1244
+ href={privacyPolicyUrl}
1245
+ className={s["swap-form-button-container-consent-text-link"]}
1246
+ target="_blank"
1247
+ >
1248
+ {translations.consents.privacyPolicy}
1249
+ </a>
1250
+ .
1251
+ </p>
1252
+ )}
1253
+ <Button
1254
+ size="lg"
1255
+ mode="primary"
1256
+ content={translations.confirmButtonText}
1257
+ onClick={resetButtonLoader =>
1258
+ handleConfirmButtonClick(
1259
+ resetButtonLoader,
1260
+ setValidationContent,
1261
+ setBalanceValid,
1262
+ setMinimalAmountValid,
1263
+ setMaximumAmountValid,
1264
+ setIsPairSupported,
1265
+ setIsSameCoins,
1266
+ recipientAddress.current,
1267
+ recipientAddressExtraId.current,
1268
+ refundAddress.current,
1269
+ refundAddressExtraId.current,
1270
+ isLastEditedReceiving.current
1271
+ )
1272
+ }
1273
+ fullWidthOnMobiles
1274
+ isDisabled={!readyToSwap}
1275
+ to={formHasBalance ? "" : confirmButtonTo}
1276
+ loader
1277
+ handleError={callHandlingErrors}
1278
+ />
1279
+ </div>
1280
+ </TitleBox>
1281
+ </div>
1282
+ );
1283
+ };
1284
+
1285
+ SwapForm.propTypes = {
1286
+ sendingAssetTicker: PropTypes.string.isRequired,
1287
+ receivingAssetTicker: PropTypes.string.isRequired,
1288
+ sendingAssetDecimalCount: PropTypes.number,
1289
+ receivingAssetDecimalCount: PropTypes.number,
1290
+ sendingAssetTickerPrintable: PropTypes.string.isRequired,
1291
+ receivingAssetTickerPrintable: PropTypes.string.isRequired,
1292
+ sendingAssetProtocol: PropTypes.string,
1293
+ receivingAssetProtocol: PropTypes.string,
1294
+ sendingAssetIconSrc: PropTypes.string.isRequired,
1295
+ sendingAssetProtocolIconSrc: PropTypes.oneOfType([PropTypes.string, null]),
1296
+ receivingAssetIconSrc: PropTypes.string.isRequired,
1297
+ receivingAssetProtocolIconSrc: PropTypes.oneOfType([PropTypes.string, null]),
1298
+ fallBackAssetIconSrc: PropTypes.oneOfType([PropTypes.string, null]),
1299
+ sendingAssetFeeCoinTickerPrintable: PropTypes.string,
1300
+ sendingAssetBalance: PropTypes.string,
1301
+ receivingAssetBalance: PropTypes.string,
1302
+ handleChangeSendingAssetClick: PropTypes.func.isRequired,
1303
+ handleChangeReceivingAssetClick: PropTypes.func.isRequired,
1304
+ handleConfirmButtonClick: PropTypes.func,
1305
+ composeConfirmButtonTo: PropTypes.func,
1306
+ setSwapCreationEstimation: PropTypes.func,
1307
+ handleUnexpectedError: PropTypes.func,
1308
+ rotateAssets: PropTypes.func,
1309
+ preservedAmount: PropTypes.oneOfType([PropTypes.string, null]),
1310
+ handleSwapServiceError: PropTypes.func.isRequired,
1311
+ formHasBalance: PropTypes.bool,
1312
+ retrieveSwapDetails: PropTypes.func.isRequired,
1313
+ retrieveInitialSwapData: PropTypes.func.isRequired,
1314
+ triggerDataUpdateResetting: PropTypes.number,
1315
+ fromAssetSelectionButtonRef: PropTypes.any,
1316
+ toAssetSelectionButtonRef: PropTypes.any,
1317
+ sendingAssetToFiatRate: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]),
1318
+ receivingAssetToFiatRate: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]),
1319
+ fiatCurrencyCode: PropTypes.oneOfType([PropTypes.string, null]),
1320
+ fiatCurrencyDecimals: PropTypes.oneOfType([PropTypes.number, null]),
1321
+ formHasFiat: PropTypes.bool,
1322
+ termsOfUseUrl: PropTypes.oneOfType([PropTypes.string, null]),
1323
+ privacyPolicyUrl: PropTypes.oneOfType([PropTypes.string, null]),
1324
+ getExtraIdNameByTicker: PropTypes.func,
1325
+ translations: PropTypes.object,
1326
+ validateAddressByTicker: PropTypes.func,
1327
+ swapSeparatorIconSrc: PropTypes.string.isRequired,
1328
+ swapButtonAlwaysActive: PropTypes.bool,
1329
+ onIsFixedChange: PropTypes.func,
1330
+ };
1331
+
1332
+ SwapForm.defaultProps = {
1333
+ sendingAssetDecimalCount: AmountUtils.significantDecimalCount,
1334
+ receivingAssetDecimalCount: AmountUtils.significantDecimalCount,
1335
+ sendingAssetProtocolIconSrc: null,
1336
+ receivingAssetProtocolIconSrc: null,
1337
+ fallBackAssetIconSrc: null,
1338
+ handleConfirmButtonClick: (
1339
+ resetButtonLoader,
1340
+ setValidationContent,
1341
+ setBalanceValid,
1342
+ setMinimalAmountValid,
1343
+ setMaximumAmountValid,
1344
+ setIsPairSupported,
1345
+ setIsSameCoins,
1346
+ recipientAddress,
1347
+ recipientAddressExtraId,
1348
+ refundAddress,
1349
+ refundAddressExtraId
1350
+ ) => {},
1351
+ composeConfirmButtonTo: (fromTicker, toTicker, fromAmount) => "",
1352
+ setSwapCreationEstimation: details => {},
1353
+ handleUnexpectedError: error => {},
1354
+ rotateAssets: (fromTicker, toTicker) => {},
1355
+ preservedAmount: null,
1356
+ handleSwapServiceError: (
1357
+ errorCode,
1358
+ setValidationContent,
1359
+ setBalanceValid,
1360
+ setMinimalAmountValid,
1361
+ setMaximumAmountValid,
1362
+ setIsPairSupported,
1363
+ setIsSameCoins
1364
+ ) => {},
1365
+ retrieveSwapDetails: async (sendingAssetTicker, receivingAssetTicker, amount, isSwapAll = false) => {},
1366
+ retrieveInitialSwapData: async (sendingAssetTicker, receivingAssetTicker) => {},
1367
+ triggerDataUpdateResetting: 0,
1368
+ fromAssetSelectionButtonRef: null,
1369
+ toAssetSelectionButtonRef: null,
1370
+ sendingAssetToFiatRate: null,
1371
+ receivingAssetToFiatRate: null,
1372
+ fiatCurrencyCode: null,
1373
+ fiatCurrencyDecimals: null,
1374
+ formHasFiat: true,
1375
+ termsOfUseUrl: null,
1376
+ privacyPolicyUrl: null,
1377
+ getExtraIdNameByTicker: ticker => null,
1378
+ validateAddressByTicker: ticker => false,
1379
+ swapButtonAlwaysActive: false,
1380
+ onIsFixedChange: () => {},
1381
+ };