@rabbitio/ui-kit 1.0.0-beta.9 → 1.0.0-beta.91
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.
- package/.gitlab-ci.yml +29 -0
- package/.husky/commit-msg +19 -0
- package/.husky/pre-push +1 -0
- package/CHANGELOG.md +0 -0
- package/README.md +27 -18
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +16765 -0
- package/coverage/coverage-final.json +116 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +1001 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/rabbit-ui-kit/index.html +116 -0
- package/coverage/rabbit-ui-kit/index.js.html +88 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/analyticsAdapters/googleAnalyticsAdapter.js.html +148 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/analyticsAdapters/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/analyticsAdapters/metrikaAdapter.js.html +169 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/analyticsAdapters/mixpanelAdapter.js.html +199 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/axiosAdapter.js.html +190 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/index.html +131 -0
- package/coverage/rabbit-ui-kit/src/common-apis/adapters/qrUtils.js.html +139 -0
- package/coverage/rabbit-ui-kit/src/common-apis/external-apis/apiGroups.js.html +250 -0
- package/coverage/rabbit-ui-kit/src/common-apis/external-apis/emailAPI.js.html +133 -0
- package/coverage/rabbit-ui-kit/src/common-apis/external-apis/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/common-apis/external-apis/ipAddressProviders.js.html +352 -0
- package/coverage/rabbit-ui-kit/src/common-apis/globalConstants.jsx.html +94 -0
- package/coverage/rabbit-ui-kit/src/common-apis/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/common-apis/models/blockchain.js.html +115 -0
- package/coverage/rabbit-ui-kit/src/common-apis/models/coin.js.html +829 -0
- package/coverage/rabbit-ui-kit/src/common-apis/models/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/common-apis/models/protocol.js.html +100 -0
- package/coverage/rabbit-ui-kit/src/common-apis/services/fiatCurrenciesService.js.html +544 -0
- package/coverage/rabbit-ui-kit/src/common-apis/services/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/amountUtils.js.html +1162 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/cache.js.html +811 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/errorUtils.js.html +211 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/index.html +191 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/logging/index.html +131 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/logging/logger.js.html +208 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/logging/logsStorage.js.html +268 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/postponeExecution.js.html +118 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/rabbitTicker.js.html +157 -0
- package/coverage/rabbit-ui-kit/src/common-apis/utils/safeStringify.js.html +235 -0
- package/coverage/rabbit-ui-kit/src/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/index.js.html +376 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/cacheAndConcurrentRequestsResolver.js.html +1570 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/cachedRobustExternalApiCallerService.js.html +526 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/cancelProcessing.js.html +172 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/concurrentCalculationsMetadataHolder.js.html +310 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/externalApiProvider.js.html +553 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/externalServicesStatsCollector.js.html +319 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/index.html +206 -0
- package/coverage/rabbit-ui-kit/src/robust-api-caller/robustExternalAPICallerService.js.html +997 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/exolixSwapProvider.js.html +1825 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/index.html +161 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/letsExchangeSwapProvider.js.html +1618 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/swapProvider.js.html +1819 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/external-apis/swapspaceSwapProvider.js.html +1861 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/baseSwapCreationInfo.js.html +319 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/existingSwap.js.html +514 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/existingSwapWithFiatData.js.html +529 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/index.html +176 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/partner.js.html +166 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/models/swapProviderCoinInfo.js.html +331 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/services/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/services/publicSwapService.js.html +1555 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/utils/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/swaps-lib/utils/swapUtils.js.html +670 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/arrowIcon.jsx.html +124 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/arrowTosca.jsx.html +127 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/arrowWhite.jsx.html +127 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/darkRectangle.jsx.html +106 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/determinedError.jsx.html +439 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/failedValidationIcon.jsx.html +202 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/index.html +281 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/infoIcon.jsx.html +133 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/messageIcon.jsx.html +346 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/noticeQuestionIcon.jsx.html +247 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/successfulValidationIcon.jsx.html +163 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/supportDialogImage.jsx.html +268 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/assets/wrappedImages/walletIcon.jsx.html +151 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/AssetIcon/AssetIcon.jsx.html +256 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/AssetIcon/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/AssetSelection/AssetSelection.jsx.html +289 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/AssetSelection/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/BackgroundTitle/BackgroundTitle.jsx.html +187 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/BackgroundTitle/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/InformationMessage/InformationMessage.jsx.html +238 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/InformationMessage/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Input/Input.jsx.html +634 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Input/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/LoadingDots/LoadingDots.jsx.html +196 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/LoadingDots/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/NoticeIcon/NoticeIcon.jsx.html +277 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/NoticeIcon/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/QrCode/QrCode.jsx.html +217 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/QrCode/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/RateSelector/RateSelector.jsx.html +175 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/RateSelector/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/SupportChat/SupportChat.jsx.html +217 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/SupportChat/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Textarea/Textarea.jsx.html +529 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Textarea/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/TitleBox/TitleBox.jsx.html +508 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/TitleBox/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Tooltip/Tooltip.jsx.html +316 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Tooltip/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/TwoLinesOfText/LinesOfText.jsx.html +313 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/TwoLinesOfText/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Validation/Validation.jsx.html +202 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/Validation/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/Button/Button.jsx.html +712 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/Button/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/Close/Close.jsx.html +259 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/Close/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/LinkButton/LinkButton.jsx.html +421 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/LinkButton/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/RadioButtonWithText/RadioButtonWithText.jsx.html +415 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/atoms/buttons/RadioButtonWithText/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/AmountInput/AmountInput.jsx.html +1429 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/AmountInput/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/CoinPicker/CoinPicker.jsx.html +1474 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/CoinPicker/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/ColoredNotice/ColoredNotice.jsx.html +211 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/ColoredNotice/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/LineWithIconLink/LineWithIconLink.jsx.html +190 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/LineWithIconLink/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/LogoCarousel/LogoCarousel.jsx.html +307 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/LogoCarousel/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/SearchableCoinsList/SearchableCoinsList.jsx.html +496 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/SearchableCoinsList/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/TitledLineWithIconLink/TitledLineWithIconLink.jsx.html +181 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/molecules/TitledLineWithIconLink/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/CoinPickerDialogStep/CoinPickerDialogStep.jsx.html +283 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/CoinPickerDialogStep/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/Dialog/Dialog.jsx.html +1567 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/Dialog/DialogButtons/DialogButtons.jsx.html +481 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/Dialog/DialogButtons/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/Dialog/DialogStep/DialogStep.jsx.html +1747 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/Dialog/DialogStep/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/Dialog/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/SwapForm/SwapForm.jsx.html +4207 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/SwapForm/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/WaitlistSubscription/WaitlistSubscription.jsx.html +559 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/organisms/WaitlistSubscription/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/templates/DeterminedErrorDialogStep/DeterminedErrorDialogStep.jsx.html +316 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/components/templates/DeterminedErrorDialogStep/index.html +116 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/hooks/index.html +146 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/hooks/useCallHandlingErrors.js.html +151 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/hooks/useIsHydrated.js.html +121 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/hooks/useReferredState.js.html +157 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/utils/index.html +161 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/utils/inputValueProviders.js.html +235 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/utils/textUtils.js.html +139 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/utils/uiUtils.js.html +121 -0
- package/coverage/rabbit-ui-kit/src/ui-kit/utils/urlQueryUtils.js.html +271 -0
- package/coverage/rabbit-ui-kit/stories/atoms/BackgroundTitle.stories.jsx.html +202 -0
- package/coverage/rabbit-ui-kit/stories/atoms/LinesOfText.stories.jsx.html +283 -0
- package/coverage/rabbit-ui-kit/stories/atoms/LoadingDots.stories.jsx.html +226 -0
- package/coverage/rabbit-ui-kit/stories/atoms/QrCode.stories.jsx.html +175 -0
- package/coverage/rabbit-ui-kit/stories/atoms/RateSelector.stories.jsx.html +136 -0
- package/coverage/rabbit-ui-kit/stories/atoms/Validation.stories.jsx.html +178 -0
- package/coverage/rabbit-ui-kit/stories/atoms/buttons/Button.stories.jsx.html +883 -0
- package/coverage/rabbit-ui-kit/stories/atoms/buttons/Close.stories.jsx.html +211 -0
- package/coverage/rabbit-ui-kit/stories/atoms/buttons/LinkButton.stories.jsx.html +301 -0
- package/coverage/rabbit-ui-kit/stories/atoms/buttons/index.html +146 -0
- package/coverage/rabbit-ui-kit/stories/atoms/index.html +191 -0
- package/coverage/rabbit-ui-kit/stories/molecules/AmountInput.stories.jsx.html +289 -0
- package/coverage/rabbit-ui-kit/stories/molecules/CoinPicker.stories.jsx.html +322 -0
- package/coverage/rabbit-ui-kit/stories/molecules/ColoredNotice.stories.jsx.html +178 -0
- package/coverage/rabbit-ui-kit/stories/molecules/LineWithIconLink.stories.jsx.html +154 -0
- package/coverage/rabbit-ui-kit/stories/molecules/LogoCarousel.stories.jsx.html +235 -0
- package/coverage/rabbit-ui-kit/stories/molecules/TitledLineWithIconLink.stories.jsx.html +160 -0
- package/coverage/rabbit-ui-kit/stories/molecules/index.html +191 -0
- package/coverage/rabbit-ui-kit/stories/organisms/Dialog/Dialog.stories.jsx.html +523 -0
- package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogButtons/DialogButtons.stories.jsx.html +328 -0
- package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogButtons/index.html +116 -0
- package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogStep/DialogStep.stories.jsx.html +337 -0
- package/coverage/rabbit-ui-kit/stories/organisms/Dialog/DialogStep/index.html +116 -0
- package/coverage/rabbit-ui-kit/stories/organisms/Dialog/index.html +116 -0
- package/coverage/rabbit-ui-kit/stories/organisms/WaitlistSubscription.stories.jsx.html +151 -0
- package/coverage/rabbit-ui-kit/stories/organisms/index.html +116 -0
- package/coverage/rabbit-ui-kit/stories/stubs/coins.jsx.html +6880 -0
- package/coverage/rabbit-ui-kit/stories/stubs/exampleContent.jsx.html +145 -0
- package/coverage/rabbit-ui-kit/stories/stubs/index.html +131 -0
- package/coverage/rabbit-ui-kit/stories/templates/DeterminedErrorDialogStep.stories.jsx.html +190 -0
- package/coverage/rabbit-ui-kit/stories/templates/index.html +116 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/dist/global.css +197 -0
- package/dist/global.css.map +1 -0
- package/dist/index.cjs +12451 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +2339 -8491
- package/dist/index.css.map +1 -1
- package/dist/index.modern.js +9597 -26
- package/dist/index.modern.js.map +1 -1
- package/dist/index.module.js +12357 -27
- package/dist/index.module.js.map +1 -1
- package/dist/index.umd.js +12442 -29
- package/dist/index.umd.js.map +1 -1
- package/package.json +35 -9
- package/raw +1000 -0
- package/src/common-apis/adapters/analyticsAdapters/googleAnalyticsAdapter.js +21 -0
- package/src/common-apis/adapters/analyticsAdapters/metrikaAdapter.js +28 -0
- package/src/common-apis/adapters/analyticsAdapters/mixpanelAdapter.js +38 -0
- package/src/common-apis/adapters/axiosAdapter.js +35 -0
- package/src/common-apis/adapters/qrUtils.js +18 -0
- package/src/common-apis/external-apis/apiGroups.js +55 -0
- package/src/common-apis/external-apis/emailAPI.js +16 -0
- package/src/common-apis/external-apis/ipAddressProviders.js +89 -0
- package/src/common-apis/globalConstants.jsx +3 -0
- package/src/common-apis/models/blockchain.js +10 -0
- package/src/common-apis/models/coin.js +248 -0
- package/src/common-apis/models/protocol.js +5 -0
- package/src/{common → common-apis/services}/fiatCurrenciesService.js +4 -12
- package/src/common-apis/tests/integration/external-apis/ipAddressProviders/getClientIpAddress.test.js +12 -0
- package/src/common-apis/tests/units/utils/amountUtils/composeRateText.test.js +152 -0
- package/src/{common → common-apis/utils}/amountUtils.js +72 -136
- package/src/common-apis/utils/cache.js +242 -0
- package/src/{common → common-apis/utils}/errorUtils.js +15 -0
- package/src/common-apis/utils/logging/logger.js +41 -0
- package/src/common-apis/utils/logging/logsStorage.js +61 -0
- package/src/common-apis/utils/postponeExecution.js +11 -0
- package/src/common-apis/utils/rabbitTicker.js +24 -0
- package/src/common-apis/utils/safeStringify.js +50 -0
- package/src/index.js +96 -9
- package/src/robust-api-caller/cacheAndConcurrentRequestsResolver.js +495 -0
- package/src/robust-api-caller/cachedRobustExternalApiCallerService.js +147 -0
- package/src/robust-api-caller/cancelProcessing.js +29 -0
- package/src/robust-api-caller/concurrentCalculationsMetadataHolder.js +75 -0
- package/src/robust-api-caller/externalApiProvider.js +156 -0
- package/src/robust-api-caller/externalServicesStatsCollector.js +78 -0
- package/src/robust-api-caller/robustExternalAPICallerService.js +304 -0
- package/src/robust-api-caller/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/_performCallAttempt.test.js +533 -0
- package/src/robust-api-caller/tests/robustExternalAPICallerService/robustExternalAPICallerService/callExternalAPI/callExternalAPI.test.js +532 -0
- package/src/robust-api-caller/tests/robustExternalAPICallerService/robustExternalAPICallerService/constructor.test.js +19 -0
- package/src/swaps-lib/external-apis/exolixSwapProvider.js +580 -0
- package/src/swaps-lib/external-apis/letsExchangeSwapProvider.js +511 -0
- package/src/swaps-lib/external-apis/swapProvider.js +578 -0
- package/src/swaps-lib/external-apis/swapspaceSwapProvider.js +592 -0
- package/src/swaps-lib/models/baseSwapCreationInfo.js +78 -0
- package/src/swaps-lib/models/existingSwap.js +143 -0
- package/src/swaps-lib/models/existingSwapWithFiatData.js +148 -0
- package/src/swaps-lib/models/partner.js +27 -0
- package/src/swaps-lib/models/swapProviderCoinInfo.js +82 -0
- package/src/swaps-lib/services/publicSwapService.js +490 -0
- package/src/swaps-lib/test/external-apis/exolixSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +34 -0
- package/src/swaps-lib/test/external-apis/exolixSwapProvider/createSwap.test.js +1043 -0
- package/src/swaps-lib/test/external-apis/exolixSwapProvider/getSwapInfo.test.js +611 -0
- package/src/swaps-lib/test/external-apis/swapProvider/getAllSupportedCurrencies.test.js +63 -0
- package/src/swaps-lib/test/external-apis/swapProvider/getDepositCurrencies.test.js +73 -0
- package/src/swaps-lib/test/external-apis/swapProvider/getWithdrawalCurrencies.test.js +102 -0
- package/src/swaps-lib/test/external-apis/swapProvider/removeProtocolNameFromCoinName.test.js +152 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/_fetchSupportedCurrenciesIfNeeded.test.js +536 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/createSwap.test.js +1214 -0
- package/src/swaps-lib/test/external-apis/swapspaceSwapProvider/getSwapInfo.test.js +1707 -0
- package/src/swaps-lib/test/utils/swapUtils/safeHandleRequestsLimitExceeding.test.js +80 -0
- package/src/swaps-lib/utils/swapUtils.js +195 -0
- package/{styles → src/ui-kit/assets/styles}/_functions.scss +5 -0
- package/{styles → src/ui-kit/assets/styles}/_mixins.scss +2 -2
- package/{styles → src/ui-kit/assets/styles}/_placeholder.scss +3 -3
- package/{styles → src/ui-kit/assets/styles}/_variables.scss +17 -15
- package/src/ui-kit/assets/styles/fonts/NunitoSans-Bold.ttf +0 -0
- package/src/ui-kit/assets/styles/fonts/NunitoSans-ExtraBold.ttf +0 -0
- package/src/ui-kit/assets/styles/fonts/NunitoSans-Light.ttf +0 -0
- package/src/ui-kit/assets/styles/fonts/NunitoSans-Regular.ttf +0 -0
- package/src/ui-kit/assets/styles/fonts/NunitoSans-SemiBold.ttf +0 -0
- package/src/ui-kit/assets/styles/global.scss +171 -0
- package/src/ui-kit/assets/styles/index.scss +10 -0
- package/src/ui-kit/assets/wrappedImages/arrowIcon.jsx +13 -0
- package/src/ui-kit/assets/wrappedImages/arrowTosca.jsx +14 -0
- package/src/ui-kit/assets/wrappedImages/arrowWhite.jsx +14 -0
- package/src/ui-kit/assets/wrappedImages/darkRectangle.jsx +7 -0
- package/src/ui-kit/assets/wrappedImages/determinedError.jsx +118 -0
- package/src/ui-kit/assets/wrappedImages/failedValidationIcon.jsx +39 -0
- package/src/ui-kit/assets/wrappedImages/infoIcon.jsx +16 -0
- package/src/ui-kit/assets/wrappedImages/messageIcon.jsx +87 -0
- package/src/ui-kit/assets/wrappedImages/noticeQuestionIcon.jsx +54 -0
- package/src/ui-kit/assets/wrappedImages/successfulValidationIcon.jsx +26 -0
- package/src/ui-kit/assets/wrappedImages/supportDialogImage.jsx +61 -0
- package/src/ui-kit/assets/wrappedImages/walletIcon.jsx +22 -0
- package/src/ui-kit/components/atoms/AssetIcon/AssetIcon.jsx +57 -0
- package/src/{components → ui-kit/components}/atoms/AssetIcon/asset-icon.module.scss +1 -1
- package/src/ui-kit/components/atoms/AssetSelection/AssetSelection.jsx +68 -0
- package/src/ui-kit/components/atoms/AssetSelection/asset-selection.module.scss +56 -0
- package/src/ui-kit/components/atoms/BackgroundTitle/BackgroundTitle.jsx +34 -0
- package/src/ui-kit/components/atoms/BackgroundTitle/background-title.module.scss +52 -0
- package/src/ui-kit/components/atoms/InformationMessage/InformationMessage.jsx +51 -0
- package/src/ui-kit/components/atoms/InformationMessage/information-message.module.scss +38 -0
- package/src/ui-kit/components/atoms/Input/Input.jsx +183 -0
- package/src/ui-kit/components/atoms/Input/input.module.scss +107 -0
- package/src/{components → ui-kit/components}/atoms/LoadingDots/LoadingDots.jsx +8 -28
- package/src/{components → ui-kit/components}/atoms/LoadingDots/LoadingDots.module.scss +3 -2
- package/src/ui-kit/components/atoms/NoticeIcon/NoticeIcon.jsx +64 -0
- package/src/ui-kit/components/atoms/NoticeIcon/notice-icon.module.scss +14 -0
- package/src/ui-kit/components/atoms/QrCode/QrCode.jsx +44 -0
- package/src/ui-kit/components/atoms/QrCode/qr-code.module.scss +15 -0
- package/src/ui-kit/components/atoms/RateSelector/RateSelector.jsx +30 -0
- package/src/ui-kit/components/atoms/RateSelector/rate-selector.module.scss +47 -0
- package/src/{components → ui-kit/components}/atoms/SupportChat/SupportChat.jsx +5 -1
- package/src/ui-kit/components/atoms/Textarea/Textarea.jsx +148 -0
- package/src/ui-kit/components/atoms/Textarea/textarea.module.scss +71 -0
- package/src/ui-kit/components/atoms/TitleBox/TitleBox.jsx +141 -0
- package/src/ui-kit/components/atoms/TitleBox/title-box.module.scss +32 -0
- package/src/ui-kit/components/atoms/Tooltip/Tooltip.jsx +77 -0
- package/src/ui-kit/components/atoms/Tooltip/tooltip.module.scss +237 -0
- package/src/ui-kit/components/atoms/TwoLinesOfText/LinesOfText.jsx +76 -0
- package/src/ui-kit/components/atoms/TwoLinesOfText/lines-of-text.module.scss +65 -0
- package/src/ui-kit/components/atoms/Validation/Validation.jsx +39 -0
- package/src/ui-kit/components/atoms/Validation/validation.module.scss +19 -0
- package/src/{components → ui-kit/components}/atoms/buttons/Button/Button.jsx +24 -50
- package/src/{components → ui-kit/components}/atoms/buttons/Button/Button.module.scss +1 -1
- package/src/ui-kit/components/atoms/buttons/Close/Close.jsx +58 -0
- package/src/ui-kit/components/atoms/buttons/Close/close.module.scss +75 -0
- package/src/ui-kit/components/atoms/buttons/LinkButton/LinkButton.jsx +112 -0
- package/src/ui-kit/components/atoms/buttons/LinkButton/link-button.module.scss +49 -0
- package/src/ui-kit/components/atoms/buttons/RadioButtonWithText/RadioButtonWithText.jsx +110 -0
- package/src/ui-kit/components/atoms/buttons/RadioButtonWithText/radio-button-with-text.module.scss +86 -0
- package/src/ui-kit/components/molecules/AmountInput/AmountInput.jsx +448 -0
- package/src/ui-kit/components/molecules/AmountInput/amount-input.module.scss +233 -0
- package/src/ui-kit/components/molecules/CoinPicker/CoinPicker.jsx +463 -0
- package/src/ui-kit/components/molecules/CoinPicker/coin-picker.module.scss +207 -0
- package/src/ui-kit/components/molecules/ColoredNotice/ColoredNotice.jsx +42 -0
- package/src/ui-kit/components/molecules/ColoredNotice/colored-notice.module.scss +20 -0
- package/src/ui-kit/components/molecules/LineWithIconLink/LineWithIconLink.jsx +35 -0
- package/src/ui-kit/components/molecules/LineWithIconLink/line-with-icon-link.module.scss +25 -0
- package/src/ui-kit/components/molecules/LogoCarousel/LogoCarousel.jsx +74 -0
- package/src/ui-kit/components/molecules/LogoCarousel/logo-carousel.module.scss +106 -0
- package/src/ui-kit/components/molecules/SearchableCoinsList/SearchableCoinsList.jsx +137 -0
- package/src/ui-kit/components/molecules/TitledLineWithIconLink/TitledLineWithIconLink.jsx +32 -0
- package/src/ui-kit/components/organisms/CoinPickerDialogStep/CoinPickerDialogStep.jsx +66 -0
- package/src/ui-kit/components/organisms/Dialog/Dialog.jsx +494 -0
- package/src/ui-kit/components/organisms/Dialog/DialogButtons/DialogButtons.jsx +132 -0
- package/src/ui-kit/components/organisms/Dialog/DialogButtons/dialog-buttons.module.scss +25 -0
- package/src/ui-kit/components/organisms/Dialog/DialogStep/DialogStep.jsx +554 -0
- package/src/ui-kit/components/organisms/Dialog/DialogStep/dialog-step.module.scss +381 -0
- package/src/ui-kit/components/organisms/Dialog/dialog.module.scss +226 -0
- package/src/ui-kit/components/organisms/SwapForm/SwapForm.jsx +1374 -0
- package/src/ui-kit/components/organisms/SwapForm/swap-form.module.scss +134 -0
- package/src/ui-kit/components/organisms/WaitlistSubscription/WaitlistSubscription.jsx +158 -0
- package/src/ui-kit/components/templates/DeterminedErrorDialogStep/DeterminedErrorDialogStep.jsx +77 -0
- package/src/ui-kit/hooks/useCallHandlingErrors.js +22 -0
- package/src/ui-kit/hooks/useIsHydrated.js +12 -0
- package/src/ui-kit/hooks/useReferredState.js +24 -0
- package/src/ui-kit/tests/utils/inputValueProviders/provideFormatOfFloatValueByInputString.test.js +146 -0
- package/src/ui-kit/tests/utils/urlQueryUtils/getQueryParameterValues.test.js +65 -0
- package/src/ui-kit/tests/utils/urlQueryUtils/saveQueryParameterAndValues.test.js +104 -0
- package/src/ui-kit/utils/inputValueProviders.js +50 -0
- package/src/ui-kit/utils/textUtils.js +18 -0
- package/src/ui-kit/utils/uiUtils.js +12 -0
- package/src/ui-kit/utils/urlQueryUtils.js +62 -0
- package/stories/font.scss +40 -0
- package/stories/stubs/coins.jsx +2266 -0
- package/stories/stubs/exampleContent.jsx +20 -0
- package/src/components/atoms/AssetIcon/AssetIcon.jsx +0 -55
- package/styles/_global-classes.scss +0 -433
- package/styles/fonts/NunitoSans-Bold.ttf +0 -0
- package/styles/fonts/NunitoSans-ExtraBold.ttf +0 -0
- package/styles/fonts/NunitoSans-Light.ttf +0 -0
- package/styles/fonts/NunitoSans-Regular.ttf +0 -0
- package/styles/fonts/NunitoSans-SemiBold.ttf +0 -0
- package/styles/global-styles-index.scss +0 -74
- package/styles/index.scss +0 -33
- /package/{styles → src/ui-kit/assets/styles}/colors/_light-colors.scss +0 -0
- /package/{styles → src/ui-kit/assets/styles}/colors/_solid-colors.scss +0 -0
- /package/{styles → src/ui-kit/assets/styles}/size/_margin-size.scss +0 -0
- /package/{styles → src/ui-kit/assets/styles}/size/_padding-size.scss +0 -0
|
@@ -0,0 +1,1374 @@
|
|
|
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
|
+
|
|
385
|
+
const [confirmButtonTo, setConfirmButtonTo] = useState(
|
|
386
|
+
composeConfirmButtonTo(sendingAssetTicker, receivingAssetTicker, preservedAmount)
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
const [transactionFee, setTransactionFee] = useState();
|
|
390
|
+
const [balanceValid, setBalanceValid] = useState(true); // Whether the amount is less than total balance
|
|
391
|
+
const [isSwapAll, setIsSwapAll] = useReferredState(null);
|
|
392
|
+
const [swapAllButtonLoaderReSetter, setSwapAllButtonLoaderReSetter] = useState([]);
|
|
393
|
+
|
|
394
|
+
const [dataUpdateTimeoutId, setDataUpdateTimeoutId] = useReferredState(null);
|
|
395
|
+
const [idleDataUpdateTimeoutId, setIdleDataUpdateTimeoutId] = useReferredState(null);
|
|
396
|
+
|
|
397
|
+
const [recipientAddress, setRecipientAddress] = useReferredState("");
|
|
398
|
+
const [recipientAddressExtraId, setRecipientAddressExtraId] = useReferredState("");
|
|
399
|
+
const [isRecipientAddressValid, setIsRecipientAddressValid] = useReferredState(false);
|
|
400
|
+
const [isRefundAddressRequired, setIsRefundAddressRequired] = useState(false);
|
|
401
|
+
const [refundAddress, setRefundAddress] = useReferredState("");
|
|
402
|
+
const [refundAddressExtraId, setRefundAddressExtraId] = useReferredState("");
|
|
403
|
+
const [isRefundAddressValid, setIsRefundAddressValid] = useReferredState(false);
|
|
404
|
+
|
|
405
|
+
const callHandlingErrors = useCallHandlingErrors();
|
|
406
|
+
const isHydrated = useIsHydrated();
|
|
407
|
+
|
|
408
|
+
const recalculationDelayOnTyping = 1000;
|
|
409
|
+
|
|
410
|
+
const isAddressFieldEnabled = !formHasBalance;
|
|
411
|
+
const displayRateSelector = !formHasBalance;
|
|
412
|
+
|
|
413
|
+
const handleSendAssetAmountChange = amount => {
|
|
414
|
+
setIsLastEditedReceiving(false);
|
|
415
|
+
let receiveAmount = "";
|
|
416
|
+
if (amount != null && amount !== "" && swapRate != null) {
|
|
417
|
+
receiveAmount = AmountUtils.trim(BigNumber(amount).times(swapRate), receivingAssetDecimalCount);
|
|
418
|
+
}
|
|
419
|
+
setReceiveAssetAmount(receiveAmount);
|
|
420
|
+
setUpdateReceiveInputTo(receiveAmount);
|
|
421
|
+
setSendAssetAmount(amount);
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
const handleReceiveAssetAmountChange = amount => {
|
|
425
|
+
setReceiveAssetAmount(amount);
|
|
426
|
+
if (isFixedRate.current) setIsLastEditedReceiving(true);
|
|
427
|
+
let sendAssetAmount = "";
|
|
428
|
+
if (amount != null && amount !== "" && swapRate != null) {
|
|
429
|
+
sendAssetAmount = AmountUtils.trim(BigNumber(amount).div(swapRate), sendingAssetDecimalCount);
|
|
430
|
+
}
|
|
431
|
+
setUpdateSendInputTo(sendAssetAmount);
|
|
432
|
+
setSendAssetAmount(sendAssetAmount);
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const handleMinimalAmountClick = () => {
|
|
436
|
+
if (!minimalAmount.current) return;
|
|
437
|
+
|
|
438
|
+
if (isLastEditedReceiving.current) {
|
|
439
|
+
setUpdateReceiveInputTo(minimalAmount.current?.crypto);
|
|
440
|
+
handleReceiveAssetAmountChange(minimalAmount.current?.crypto);
|
|
441
|
+
} else {
|
|
442
|
+
setUpdateSendInputTo(minimalAmount.current?.crypto);
|
|
443
|
+
handleSendAssetAmountChange(minimalAmount.current?.crypto);
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
const handleMaximumAmountClick = () => {
|
|
448
|
+
if (!maximumAmount.current) return;
|
|
449
|
+
|
|
450
|
+
if (isLastEditedReceiving.current) {
|
|
451
|
+
setUpdateReceiveInputTo(maximumAmount.current?.crypto);
|
|
452
|
+
handleReceiveAssetAmountChange(maximumAmount.current?.crypto);
|
|
453
|
+
} else {
|
|
454
|
+
setUpdateSendInputTo(maximumAmount.current?.crypto);
|
|
455
|
+
handleSendAssetAmountChange(maximumAmount.current?.crypto);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
const handleSwapAllClick = resetButtonLoader => {
|
|
460
|
+
setIsSwapAll(prev => {
|
|
461
|
+
if (prev) {
|
|
462
|
+
// Setting amount inputs to empty string if we are handling the disabling of previously enabled swap all
|
|
463
|
+
setUpdateSendInputTo("");
|
|
464
|
+
setUpdateReceiveInputTo("");
|
|
465
|
+
setSendAssetAmount(null);
|
|
466
|
+
setReceiveAssetAmount(null);
|
|
467
|
+
}
|
|
468
|
+
return !prev;
|
|
469
|
+
});
|
|
470
|
+
setSwapAllButtonLoaderReSetter([resetButtonLoader]);
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const processMinMaxAmounts = amount => {
|
|
474
|
+
if (amount === null) return;
|
|
475
|
+
|
|
476
|
+
setMaximumAmountValid(
|
|
477
|
+
!maximumAmount.current || BigNumber(amount).eq("0") || BigNumber(amount).lte(maximumAmount.current.crypto)
|
|
478
|
+
);
|
|
479
|
+
setMinimalAmountValid(
|
|
480
|
+
!minimalAmount.current || BigNumber(amount).eq("0") || BigNumber(amount).gte(minimalAmount.current?.crypto)
|
|
481
|
+
);
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
const requestDataRefresh = (amount, immediately = false, isSwapAll = false, ignoreEmptyAmount = false) => {
|
|
485
|
+
try {
|
|
486
|
+
clearTimeout(dataUpdateTimeoutId.current);
|
|
487
|
+
|
|
488
|
+
if (isSwapAll) {
|
|
489
|
+
loadFullEstimation(null);
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (!amount && !ignoreEmptyAmount) {
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
if (BigNumber(amount).eq("0") || amount == null || amount === "") {
|
|
498
|
+
if (immediately) {
|
|
499
|
+
loadMinimalAmountAndSwapRate(true);
|
|
500
|
+
} else {
|
|
501
|
+
setDataUpdateTimeoutId(
|
|
502
|
+
setTimeout(() => loadMinimalAmountAndSwapRate(true), recalculationDelayOnTyping)
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
} else {
|
|
506
|
+
if (immediately) {
|
|
507
|
+
loadFullEstimation(amount, preservedAmount && String(preservedAmount) !== "0" ? true : undefined);
|
|
508
|
+
} else {
|
|
509
|
+
setDataUpdateTimeoutId(setTimeout(() => loadFullEstimation(amount), recalculationDelayOnTyping));
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
} catch (e) {
|
|
513
|
+
handleUnexpectedError(e);
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
const setAmountLimitsAndRate = details => {
|
|
518
|
+
setSwapRate(details?.rate ?? null);
|
|
519
|
+
if (!details?.rate) {
|
|
520
|
+
if (isLastEditedReceiving.current) {
|
|
521
|
+
setUpdateSendInputTo("");
|
|
522
|
+
setSendAssetAmount("");
|
|
523
|
+
} else {
|
|
524
|
+
setUpdateReceiveInputTo("");
|
|
525
|
+
setReceiveAssetAmount("");
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
setMinimalAmount(details.min == null ? null : { crypto: details.min, fiat: details.fiatMin });
|
|
529
|
+
setMaximumAmount(details.max == null ? null : { crypto: details.max, fiat: details.fiatMax });
|
|
530
|
+
if (details.feeCoins != null) {
|
|
531
|
+
setTransactionFee({
|
|
532
|
+
crypto: details.feeCoins,
|
|
533
|
+
fiat: details.feeFiat,
|
|
534
|
+
});
|
|
535
|
+
} else {
|
|
536
|
+
setTransactionFee(null);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
const loadFullEstimation = (amount, isForPreserved = false) => {
|
|
541
|
+
(async () => {
|
|
542
|
+
try {
|
|
543
|
+
const dataMemento = {
|
|
544
|
+
rate: swapRate,
|
|
545
|
+
min: minimalAmount.current?.crypto,
|
|
546
|
+
max: maximumAmount.current?.crypto,
|
|
547
|
+
feeCoins: transactionFee?.crypto,
|
|
548
|
+
feeFiat: transactionFee?.fiat,
|
|
549
|
+
};
|
|
550
|
+
setIsLoading(true);
|
|
551
|
+
setMinimalAmount(null);
|
|
552
|
+
setMaximumAmount(null);
|
|
553
|
+
setTransactionFee(null);
|
|
554
|
+
setValidationContent(null);
|
|
555
|
+
setSwapCreationEstimation(null);
|
|
556
|
+
setIsSameCoins(false);
|
|
557
|
+
setIsPairSupported(true);
|
|
558
|
+
setIsSwapCalculated(false);
|
|
559
|
+
|
|
560
|
+
// Saving the selected coins at the moment, so we can cancel
|
|
561
|
+
// the processing if they get changed during the loading.
|
|
562
|
+
const currentSendingAssetTicker = sendingAssetTicker;
|
|
563
|
+
const currentReceivingAssetTicker = receivingAssetTicker;
|
|
564
|
+
|
|
565
|
+
const response = await retrieveSwapDetails(
|
|
566
|
+
currentSendingAssetTicker,
|
|
567
|
+
currentReceivingAssetTicker,
|
|
568
|
+
amount,
|
|
569
|
+
isSwapAll.current,
|
|
570
|
+
isFixedRate.current ?? IS_FIXED_BY_DEFAULT,
|
|
571
|
+
isFixedRate.current ? isLastEditedReceiving.current : false
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
if (
|
|
575
|
+
currentSendingAssetTicker !== sendingAssetTickerReferred.current ||
|
|
576
|
+
currentReceivingAssetTicker !== receivingAssetTickerReferred.current
|
|
577
|
+
) {
|
|
578
|
+
// Cancelling the further processing in case the
|
|
579
|
+
// selected coins were changed during the loading.
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (
|
|
584
|
+
!isSwapAll.current &&
|
|
585
|
+
String(amount) !==
|
|
586
|
+
String(
|
|
587
|
+
isForPreserved && sendAssetAmount.current == null && receiveAssetAmount.current == null
|
|
588
|
+
? preservedAmount
|
|
589
|
+
: isFixedRate.current && isLastEditedReceiving.current
|
|
590
|
+
? receiveAssetAmount.current
|
|
591
|
+
: sendAssetAmount.current
|
|
592
|
+
)
|
|
593
|
+
) {
|
|
594
|
+
// Means amount changed and we no more need to do this exact calculation
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (response.result) {
|
|
599
|
+
const swapCreationInfo = response?.swapCreationInfo;
|
|
600
|
+
|
|
601
|
+
if (isSwapAll.current) {
|
|
602
|
+
setIsAmountZero(BigNumber("0").eq(swapCreationInfo.fromAmountCoins));
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
setUpdateSendInputTo(swapCreationInfo.fromAmountCoins);
|
|
606
|
+
setUpdateReceiveInputTo(swapCreationInfo.toAmountCoins);
|
|
607
|
+
|
|
608
|
+
if (isLastEditedReceiving.current) {
|
|
609
|
+
setSendAssetAmount(swapCreationInfo.fromAmountCoins);
|
|
610
|
+
} else {
|
|
611
|
+
setReceiveAssetAmount(swapCreationInfo.toAmountCoins);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
setAmountLimitsAndRate(swapCreationInfo);
|
|
615
|
+
setSwapCreationEstimation(swapCreationInfo);
|
|
616
|
+
setIsRefundAddressRequired(swapCreationInfo?.isRefundAddressRequired);
|
|
617
|
+
processMinMaxAmounts(isSwapAll.current ? swapCreationInfo.fromAmountCoins : amount);
|
|
618
|
+
setIsSwapCalculated(true);
|
|
619
|
+
} else {
|
|
620
|
+
handleSwapServiceError(
|
|
621
|
+
response.reason,
|
|
622
|
+
setValidationContent,
|
|
623
|
+
setBalanceValid,
|
|
624
|
+
setMinimalAmountValid,
|
|
625
|
+
setMaximumAmountValid,
|
|
626
|
+
setIsPairSupported,
|
|
627
|
+
setIsSameCoins
|
|
628
|
+
);
|
|
629
|
+
if (isSwapAll.current) {
|
|
630
|
+
/* We disable swap all if swap all details retrieval fails and set
|
|
631
|
+
* previous limits and rate. We set null to avoid triggering reloading of initial data.
|
|
632
|
+
*/
|
|
633
|
+
setIsSwapAll(null);
|
|
634
|
+
setAmountLimitsAndRate(dataMemento);
|
|
635
|
+
} else {
|
|
636
|
+
/* We set returned amount limits and rate only if the failed details retrieval is not
|
|
637
|
+
* for the swap All case.
|
|
638
|
+
*/
|
|
639
|
+
setAmountLimitsAndRate(response);
|
|
640
|
+
if (isLastEditedReceiving.current) {
|
|
641
|
+
setSendAssetAmount("");
|
|
642
|
+
} else {
|
|
643
|
+
setReceiveAssetAmount("");
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
setIsLoading(false);
|
|
648
|
+
} catch (e) {
|
|
649
|
+
handleUnexpectedError(e);
|
|
650
|
+
}
|
|
651
|
+
})();
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
const loadMinimalAmountAndSwapRate = (isCalledForClearedInput = false) => {
|
|
655
|
+
(async () => {
|
|
656
|
+
try {
|
|
657
|
+
setIsLoading(true);
|
|
658
|
+
setMinimalAmount(null);
|
|
659
|
+
setMaximumAmount(null);
|
|
660
|
+
setSwapRate(null);
|
|
661
|
+
setValidationContent(null);
|
|
662
|
+
setIsPairSupported(true);
|
|
663
|
+
setIsSwapCalculated(false);
|
|
664
|
+
|
|
665
|
+
const swapData = await retrieveInitialSwapData(sendingAssetTicker, receivingAssetTicker);
|
|
666
|
+
|
|
667
|
+
if (
|
|
668
|
+
(isFixedRate.current && isLastEditedReceiving.current
|
|
669
|
+
? receiveAssetAmount.current != null
|
|
670
|
+
: sendAssetAmount.current != null) &&
|
|
671
|
+
!isCalledForClearedInput
|
|
672
|
+
) {
|
|
673
|
+
// Means user already entered amount after starting the form initialization
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (swapData.result === true) {
|
|
678
|
+
setAmountLimitsAndRate(swapData);
|
|
679
|
+
} else {
|
|
680
|
+
handleSwapServiceError(
|
|
681
|
+
swapData.reason,
|
|
682
|
+
setValidationContent,
|
|
683
|
+
setBalanceValid,
|
|
684
|
+
setMinimalAmountValid,
|
|
685
|
+
setMaximumAmountValid,
|
|
686
|
+
setIsPairSupported,
|
|
687
|
+
setIsSameCoins
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
setIsLoading(false);
|
|
692
|
+
} catch (e) {
|
|
693
|
+
handleUnexpectedError(e);
|
|
694
|
+
}
|
|
695
|
+
})();
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
const handleChangeAssetsIconClick = e => {
|
|
699
|
+
callHandlingErrors(() => {
|
|
700
|
+
if (!isLoading.current) {
|
|
701
|
+
setIsSwapAll(null);
|
|
702
|
+
setMaximumAmountValid(true);
|
|
703
|
+
setMinimalAmountValid(true);
|
|
704
|
+
|
|
705
|
+
const sendAssetAmountMemento = sendAssetAmount.current;
|
|
706
|
+
const receiveAssetAmountMemento = receiveAssetAmount.current;
|
|
707
|
+
|
|
708
|
+
if (isLastEditedReceiving.current) {
|
|
709
|
+
setSendAssetAmount("");
|
|
710
|
+
setUpdateSendInputTo("");
|
|
711
|
+
|
|
712
|
+
setReceiveAssetAmount(sendAssetAmountMemento);
|
|
713
|
+
setUpdateReceiveInputTo(sendAssetAmountMemento);
|
|
714
|
+
} else {
|
|
715
|
+
setSendAssetAmount(receiveAssetAmountMemento);
|
|
716
|
+
setUpdateSendInputTo(receiveAssetAmountMemento);
|
|
717
|
+
|
|
718
|
+
setReceiveAssetAmount("");
|
|
719
|
+
setUpdateReceiveInputTo("");
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
rotateAssets(sendingAssetTicker, receivingAssetTicker);
|
|
723
|
+
}
|
|
724
|
+
}, e);
|
|
725
|
+
};
|
|
726
|
+
|
|
727
|
+
const handleRateModeChanged = isFixed => {
|
|
728
|
+
setIsFixedRate(isFixed);
|
|
729
|
+
requestDataRefresh(
|
|
730
|
+
isLastEditedReceiving.current ? receiveAssetAmount.current : sendAssetAmount.current,
|
|
731
|
+
true,
|
|
732
|
+
null,
|
|
733
|
+
true
|
|
734
|
+
);
|
|
735
|
+
};
|
|
736
|
+
|
|
737
|
+
useEffect(() => {
|
|
738
|
+
if (isSwapAll.current === true) {
|
|
739
|
+
requestDataRefresh(undefined, true, true);
|
|
740
|
+
} else if (isSwapAll.current === false) {
|
|
741
|
+
loadMinimalAmountAndSwapRate();
|
|
742
|
+
}
|
|
743
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
744
|
+
}, [isSwapAll.current]);
|
|
745
|
+
|
|
746
|
+
useEffect(() => {
|
|
747
|
+
onIsFixedChange(isFixedRate.current);
|
|
748
|
+
if (!isFixedRate.current) setIsLastEditedReceiving(false);
|
|
749
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
750
|
+
}, [isFixedRate.current]);
|
|
751
|
+
|
|
752
|
+
useEffect(() => {
|
|
753
|
+
if (!sendingAssetTicker || !receivingAssetTicker) return;
|
|
754
|
+
|
|
755
|
+
const currentAmount = isLastEditedReceiving.current ? receiveAssetAmount.current : sendAssetAmount.current;
|
|
756
|
+
|
|
757
|
+
const isCurrentAmountNotZero = currentAmount && !BigNumber("0").eq(currentAmount);
|
|
758
|
+
if (isCurrentAmountNotZero) {
|
|
759
|
+
loadFullEstimation(currentAmount);
|
|
760
|
+
} else {
|
|
761
|
+
loadMinimalAmountAndSwapRate(true);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
765
|
+
}, [sendingAssetTicker, receivingAssetTicker]);
|
|
766
|
+
|
|
767
|
+
useEffect(() => {
|
|
768
|
+
if (!minimalAmountValid || isAmountZero) {
|
|
769
|
+
setTransactionFee(null);
|
|
770
|
+
}
|
|
771
|
+
if (isAmountZero) {
|
|
772
|
+
clearTimeout(dataUpdateTimeoutId.current);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
setReadyToSwap(
|
|
776
|
+
swapButtonAlwaysActive ||
|
|
777
|
+
((balanceValid || !formHasBalance) &&
|
|
778
|
+
minimalAmountValid &&
|
|
779
|
+
!isAmountZero &&
|
|
780
|
+
isSwapCalculated &&
|
|
781
|
+
(!isSameCoins || !formHasBalance) &&
|
|
782
|
+
isPairSupported &&
|
|
783
|
+
(!isAddressFieldEnabled || isRecipientAddressValid.current) &&
|
|
784
|
+
(!isRefundAddressRequired || isRefundAddressValid.current))
|
|
785
|
+
);
|
|
786
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
787
|
+
}, [
|
|
788
|
+
balanceValid,
|
|
789
|
+
formHasBalance,
|
|
790
|
+
minimalAmountValid,
|
|
791
|
+
isAmountZero,
|
|
792
|
+
isSwapCalculated,
|
|
793
|
+
isSameCoins,
|
|
794
|
+
isPairSupported,
|
|
795
|
+
isAddressFieldEnabled,
|
|
796
|
+
isRecipientAddressValid.current,
|
|
797
|
+
isRefundAddressRequired,
|
|
798
|
+
isRefundAddressValid.current,
|
|
799
|
+
]);
|
|
800
|
+
|
|
801
|
+
useEffect(() => {
|
|
802
|
+
setIsRecipientAddressValid(false);
|
|
803
|
+
setRecipientAddress("");
|
|
804
|
+
setRecipientAddressExtraId("");
|
|
805
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
806
|
+
}, [receivingAssetTicker]);
|
|
807
|
+
|
|
808
|
+
useEffect(() => {
|
|
809
|
+
setIsRefundAddressValid(false);
|
|
810
|
+
setRefundAddress("");
|
|
811
|
+
setRefundAddressExtraId("");
|
|
812
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
813
|
+
}, [sendingAssetTicker]);
|
|
814
|
+
|
|
815
|
+
useEffect(() => {
|
|
816
|
+
(async () => {
|
|
817
|
+
if (!receivingAssetTicker) return;
|
|
818
|
+
setValidationContent("");
|
|
819
|
+
setIsRecipientAddressValid(
|
|
820
|
+
recipientAddress.current === ""
|
|
821
|
+
? false
|
|
822
|
+
: await validateAddressByTicker(
|
|
823
|
+
receivingAssetTicker,
|
|
824
|
+
recipientAddress.current,
|
|
825
|
+
isFixedRate.current,
|
|
826
|
+
setValidationContent
|
|
827
|
+
)
|
|
828
|
+
);
|
|
829
|
+
})();
|
|
830
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
831
|
+
}, [recipientAddress.current, recipientAddressExtraId.current, receivingAssetTicker]);
|
|
832
|
+
|
|
833
|
+
useEffect(() => {
|
|
834
|
+
(async () => {
|
|
835
|
+
if (!sendingAssetTicker || !isRefundAddressRequired) return;
|
|
836
|
+
setValidationContent("");
|
|
837
|
+
setIsRefundAddressValid(
|
|
838
|
+
refundAddress.current === ""
|
|
839
|
+
? false
|
|
840
|
+
: await validateAddressByTicker(
|
|
841
|
+
sendingAssetTicker,
|
|
842
|
+
refundAddress.current,
|
|
843
|
+
isFixedRate.current,
|
|
844
|
+
setValidationContent
|
|
845
|
+
)
|
|
846
|
+
);
|
|
847
|
+
})();
|
|
848
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
849
|
+
}, [refundAddress.current, refundAddressExtraId.current, sendingAssetTicker, isRefundAddressRequired]);
|
|
850
|
+
|
|
851
|
+
useEffect(() => {
|
|
852
|
+
// Here we set up auto recalculations for the swap details if the form is ready to swap but is idle for some time
|
|
853
|
+
let timeoutId = null;
|
|
854
|
+
if (readyToSwap) {
|
|
855
|
+
timeoutId = setTimeout(
|
|
856
|
+
() =>
|
|
857
|
+
requestDataRefresh(
|
|
858
|
+
isLastEditedReceiving.current
|
|
859
|
+
? receiveAssetAmount.current
|
|
860
|
+
: sendAssetAmount.current ?? preservedAmount,
|
|
861
|
+
true
|
|
862
|
+
),
|
|
863
|
+
DETAIL_REFRESH_INTERVAL_MS
|
|
864
|
+
);
|
|
865
|
+
setIdleDataUpdateTimeoutId(timeoutId);
|
|
866
|
+
} else {
|
|
867
|
+
clearTimeout(idleDataUpdateTimeoutId.current);
|
|
868
|
+
setIdleDataUpdateTimeoutId(null);
|
|
869
|
+
}
|
|
870
|
+
return () => {
|
|
871
|
+
timeoutId != null && clearTimeout(timeoutId);
|
|
872
|
+
};
|
|
873
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
874
|
+
}, [readyToSwap]);
|
|
875
|
+
|
|
876
|
+
// TODO: [refactoring, critical] this code looks like a hack related to task_id=6e328d39063142b7b9fa01d497e616da
|
|
877
|
+
useEffect(() => {
|
|
878
|
+
if (triggerDataUpdateResetting) {
|
|
879
|
+
clearTimeout(dataUpdateTimeoutId.current);
|
|
880
|
+
setDataUpdateTimeoutId(null);
|
|
881
|
+
|
|
882
|
+
clearTimeout(idleDataUpdateTimeoutId.current);
|
|
883
|
+
setIdleDataUpdateTimeoutId(null);
|
|
884
|
+
}
|
|
885
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
886
|
+
}, [triggerDataUpdateResetting]);
|
|
887
|
+
|
|
888
|
+
// Resets the passed "set value to" param to null, so it can be used multiple times with any value
|
|
889
|
+
useEffect(() => {
|
|
890
|
+
if (!!updateSendInputTo) setUpdateSendInputTo(null);
|
|
891
|
+
if (!!updateReceiveInputTo) setUpdateReceiveInputTo(null);
|
|
892
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
893
|
+
}, [updateSendInputTo, updateReceiveInputTo]);
|
|
894
|
+
|
|
895
|
+
useEffect(() => {
|
|
896
|
+
if (
|
|
897
|
+
swapRate != null &&
|
|
898
|
+
(isLastEditedReceiving.current ? receiveAssetAmount.current : sendAssetAmount.current) != null
|
|
899
|
+
) {
|
|
900
|
+
if (isLastEditedReceiving.current) {
|
|
901
|
+
setUpdateSendInputTo(
|
|
902
|
+
AmountUtils.trim(BigNumber(receiveAssetAmount.current).div(swapRate), sendingAssetDecimalCount)
|
|
903
|
+
);
|
|
904
|
+
} else {
|
|
905
|
+
setUpdateReceiveInputTo(
|
|
906
|
+
AmountUtils.trim(BigNumber(sendAssetAmount.current).times(swapRate), receivingAssetDecimalCount)
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
911
|
+
}, [swapRate]);
|
|
912
|
+
|
|
913
|
+
useEffect(() => {
|
|
914
|
+
if (isLoading.current === false && swapAllButtonLoaderReSetter?.length) {
|
|
915
|
+
swapAllButtonLoaderReSetter[0]();
|
|
916
|
+
setSwapAllButtonLoaderReSetter([]);
|
|
917
|
+
}
|
|
918
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
919
|
+
}, [isLoading.current, swapAllButtonLoaderReSetter]);
|
|
920
|
+
|
|
921
|
+
const handleAmountChange = amount => {
|
|
922
|
+
requestDataRefresh(amount);
|
|
923
|
+
processMinMaxAmounts(amount);
|
|
924
|
+
setIsAmountZero(BigNumber("0").eq(amount));
|
|
925
|
+
setIsSwapCalculated(false);
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
useEffect(() => {
|
|
929
|
+
if (isLastEditedReceiving.current)
|
|
930
|
+
handleAmountChange(receiveAssetAmount.current === "" ? "0" : receiveAssetAmount.current);
|
|
931
|
+
}, [receiveAssetAmount.current]);
|
|
932
|
+
|
|
933
|
+
useEffect(() => {
|
|
934
|
+
if (!isLastEditedReceiving.current)
|
|
935
|
+
handleAmountChange(sendAssetAmount.current === "" ? "0" : sendAssetAmount.current);
|
|
936
|
+
}, [sendAssetAmount.current]);
|
|
937
|
+
|
|
938
|
+
const recipientAddressExtraIdName = getExtraIdNameByTicker(receivingAssetTicker);
|
|
939
|
+
const refundAddressExtraIdName = getExtraIdNameByTicker(sendingAssetTicker);
|
|
940
|
+
|
|
941
|
+
return (
|
|
942
|
+
<div className={s["swap-form"]}>
|
|
943
|
+
<TitleBox
|
|
944
|
+
linkButtonClick={
|
|
945
|
+
BigNumber(sendingAssetBalance?.assetAmount).eq(0)
|
|
946
|
+
? null
|
|
947
|
+
: resetButtonLoader => handleSwapAllClick(resetButtonLoader)
|
|
948
|
+
}
|
|
949
|
+
linkText={
|
|
950
|
+
!formHasBalance
|
|
951
|
+
? ""
|
|
952
|
+
: isSwapAll.current
|
|
953
|
+
? translations.swapAllButtonTitles.cancel
|
|
954
|
+
: translations.swapAllButtonTitles.enable
|
|
955
|
+
}
|
|
956
|
+
linkButtonLoader={true}
|
|
957
|
+
isLinkButtonDisabled={
|
|
958
|
+
isLoading.current ||
|
|
959
|
+
sendingAssetTicker === receivingAssetTicker ||
|
|
960
|
+
BigNumber(sendingAssetBalance?.assetAmount).eq(0)
|
|
961
|
+
}
|
|
962
|
+
>
|
|
963
|
+
{displayRateSelector ? (
|
|
964
|
+
<div className={s["swap-form-rate-selector"]}>
|
|
965
|
+
<RateSelector
|
|
966
|
+
isFixed={isFixedRate.current ?? IS_FIXED_BY_DEFAULT}
|
|
967
|
+
setIsFixed={handleRateModeChanged}
|
|
968
|
+
translations={translations.rateSelector}
|
|
969
|
+
/>
|
|
970
|
+
</div>
|
|
971
|
+
) : (
|
|
972
|
+
""
|
|
973
|
+
)}
|
|
974
|
+
|
|
975
|
+
<div className={s["swap-form-inputs"]}>
|
|
976
|
+
<AmountInput
|
|
977
|
+
ticker={sendingAssetTicker}
|
|
978
|
+
tickerPrintable={sendingAssetTickerPrintable}
|
|
979
|
+
assetDecimalPlaces={sendingAssetDecimalCount}
|
|
980
|
+
assetBalance={sendingAssetBalance}
|
|
981
|
+
assetIconSrc={sendingAssetIconSrc}
|
|
982
|
+
assetIconProtocolSrc={sendingAssetProtocolIconSrc}
|
|
983
|
+
fallbackAssetIconSrc={fallBackAssetIconSrc}
|
|
984
|
+
disabled={isSwapAll.current || sendingAssetTicker === null || receivingAssetTicker === null}
|
|
985
|
+
handleCoinAmountChange={handleSendAssetAmountChange}
|
|
986
|
+
handleChangeAssetClick={handleChangeSendingAssetClick}
|
|
987
|
+
handleBalanceValidationChange={isValid => setBalanceValid(!isValid)}
|
|
988
|
+
updateAssetInputTo={updateSendInputTo}
|
|
989
|
+
showBalance={formHasBalance}
|
|
990
|
+
showBalanceValidation={formHasBalance}
|
|
991
|
+
showChangeAssetButton
|
|
992
|
+
changeAssetButtonProtocol={sendingAssetProtocol}
|
|
993
|
+
upperFormPosition
|
|
994
|
+
errorEncountered={
|
|
995
|
+
!isLastEditedReceiving.current && (!minimalAmountValid || !maximumAmountValid)
|
|
996
|
+
}
|
|
997
|
+
ref={fromAssetSelectionButtonRef}
|
|
998
|
+
isLoading={isLastEditedReceiving.current ? isLoading.current : false}
|
|
999
|
+
cryptoAssetToFiatRate={sendingAssetToFiatRate}
|
|
1000
|
+
fiatCurrencyCode={
|
|
1001
|
+
formHasFiat && (isLoading.current || sendingAssetToFiatRate != null)
|
|
1002
|
+
? fiatCurrencyCode
|
|
1003
|
+
: null
|
|
1004
|
+
}
|
|
1005
|
+
fiatCurrencyDecimals={fiatCurrencyDecimals}
|
|
1006
|
+
balanceLoaderText={translations.input.balanceLoaderText}
|
|
1007
|
+
fiatInputPlaceholderText={translations.input.fiatPlaceholder}
|
|
1008
|
+
/>
|
|
1009
|
+
<div
|
|
1010
|
+
className={
|
|
1011
|
+
s["swap-form-inputs-separator"] +
|
|
1012
|
+
" " +
|
|
1013
|
+
(isLoading.current || sendingAssetTicker === null || receivingAssetTicker === null
|
|
1014
|
+
? s["disabled"]
|
|
1015
|
+
: "")
|
|
1016
|
+
}
|
|
1017
|
+
>
|
|
1018
|
+
<img
|
|
1019
|
+
src={swapSeparatorIconSrc}
|
|
1020
|
+
alt="swap icon"
|
|
1021
|
+
draggable={false}
|
|
1022
|
+
onClick={e => callHandlingErrors(handleChangeAssetsIconClick, e)}
|
|
1023
|
+
loading="lazy"
|
|
1024
|
+
/>
|
|
1025
|
+
</div>
|
|
1026
|
+
<AmountInput
|
|
1027
|
+
ticker={receivingAssetTicker}
|
|
1028
|
+
tickerPrintable={receivingAssetTickerPrintable}
|
|
1029
|
+
assetDecimalPlaces={receivingAssetDecimalCount}
|
|
1030
|
+
assetBalance={receivingAssetBalance}
|
|
1031
|
+
assetIconSrc={receivingAssetIconSrc}
|
|
1032
|
+
assetIconProtocolSrc={receivingAssetProtocolIconSrc}
|
|
1033
|
+
fallbackAssetIconSrc={fallBackAssetIconSrc}
|
|
1034
|
+
disabled={isSwapAll.current || sendingAssetTicker === null || receivingAssetTicker === null}
|
|
1035
|
+
locked
|
|
1036
|
+
handleCoinAmountChange={handleReceiveAssetAmountChange}
|
|
1037
|
+
handleChangeAssetClick={handleChangeReceivingAssetClick}
|
|
1038
|
+
updateAssetInputTo={updateReceiveInputTo}
|
|
1039
|
+
showChangeAssetButton
|
|
1040
|
+
changeAssetButtonProtocol={receivingAssetProtocol}
|
|
1041
|
+
showBalance={formHasBalance}
|
|
1042
|
+
lowerFormPosition
|
|
1043
|
+
errorEncountered={isLastEditedReceiving.current && (!minimalAmountValid || !maximumAmountValid)}
|
|
1044
|
+
estimateAmount={!isFixedRate.current}
|
|
1045
|
+
ref={toAssetSelectionButtonRef}
|
|
1046
|
+
isLoading={isLastEditedReceiving.current ? false : isLoading.current}
|
|
1047
|
+
cryptoAssetToFiatRate={receivingAssetToFiatRate}
|
|
1048
|
+
fiatCurrencyCode={
|
|
1049
|
+
formHasFiat && (isLoading.current || receivingAssetToFiatRate != null)
|
|
1050
|
+
? fiatCurrencyCode
|
|
1051
|
+
: null
|
|
1052
|
+
}
|
|
1053
|
+
fiatCurrencyDecimals={fiatCurrencyDecimals}
|
|
1054
|
+
balanceLoaderText={translations.input.balanceLoaderText}
|
|
1055
|
+
fiatInputPlaceholderText={translations.input.fiatPlaceholder}
|
|
1056
|
+
/>
|
|
1057
|
+
</div>
|
|
1058
|
+
<div className={s["swap-form-information-field"]}>
|
|
1059
|
+
{/* TODO: [refactoring, moderate] Add flags calculation for each message to avoid this ugly cumbersome implicit unclear logic of message displaying. task_id=8bc31dbcd94d46a598346e8bfb505971 */}
|
|
1060
|
+
<p>
|
|
1061
|
+
{!isPairSupported ? (
|
|
1062
|
+
translations.informationBlock.pairNotAvailable
|
|
1063
|
+
) : transactionFee && minimalAmountValid ? (
|
|
1064
|
+
<>
|
|
1065
|
+
{translations.informationBlock.transactionFee}
|
|
1066
|
+
<span>
|
|
1067
|
+
{AmountUtils.crypto(transactionFee?.crypto, sendingAssetFeeCoinTickerPrintable)}
|
|
1068
|
+
</span>
|
|
1069
|
+
{transactionFee?.fiat != null && transactionFee?.fiat !== "" ? (
|
|
1070
|
+
<span className={"semi-transparent"}>
|
|
1071
|
+
{" ~ " + AmountUtils.fiat(transactionFee?.fiat, fiatCurrencyCode)}
|
|
1072
|
+
</span>
|
|
1073
|
+
) : (
|
|
1074
|
+
""
|
|
1075
|
+
)}
|
|
1076
|
+
</>
|
|
1077
|
+
) : !isLoading.current && (isSwapCalculated || (!minimalAmount.current && swapRate)) ? (
|
|
1078
|
+
<>
|
|
1079
|
+
{translations.informationBlock.swapRate}
|
|
1080
|
+
<span>
|
|
1081
|
+
{AmountUtils.composeRateText(
|
|
1082
|
+
sendingAssetTickerPrintable,
|
|
1083
|
+
receivingAssetTickerPrintable,
|
|
1084
|
+
swapRate,
|
|
1085
|
+
receivingAssetDecimalCount,
|
|
1086
|
+
isFixedRate.current ?? IS_FIXED_BY_DEFAULT
|
|
1087
|
+
)}
|
|
1088
|
+
</span>
|
|
1089
|
+
</>
|
|
1090
|
+
) : minimalAmount.current || maximumAmount.current ? (
|
|
1091
|
+
!maximumAmountValid && maximumAmount.current != null ? (
|
|
1092
|
+
<>
|
|
1093
|
+
{translations.informationBlock.maximumAmount}
|
|
1094
|
+
<span
|
|
1095
|
+
className={s["interactable"] + " " + s["red"]}
|
|
1096
|
+
onClick={
|
|
1097
|
+
isLoading.current
|
|
1098
|
+
? () => {}
|
|
1099
|
+
: e => callHandlingErrors(handleMaximumAmountClick, e)
|
|
1100
|
+
}
|
|
1101
|
+
>
|
|
1102
|
+
{AmountUtils.crypto(
|
|
1103
|
+
maximumAmount.current?.crypto,
|
|
1104
|
+
isLastEditedReceiving.current
|
|
1105
|
+
? receivingAssetTickerPrintable
|
|
1106
|
+
: sendingAssetTickerPrintable
|
|
1107
|
+
)}
|
|
1108
|
+
</span>
|
|
1109
|
+
{maximumAmount.current?.fiat != null && maximumAmount.current?.fiat !== "" ? (
|
|
1110
|
+
<span className={"semi-transparent"}>
|
|
1111
|
+
{" ~ " + AmountUtils.fiat(maximumAmount.current.fiat, fiatCurrencyCode)}
|
|
1112
|
+
</span>
|
|
1113
|
+
) : (
|
|
1114
|
+
""
|
|
1115
|
+
)}
|
|
1116
|
+
</>
|
|
1117
|
+
) : !minimalAmount.current ? (
|
|
1118
|
+
""
|
|
1119
|
+
) : (
|
|
1120
|
+
<>
|
|
1121
|
+
{translations.informationBlock.minimumAmount}
|
|
1122
|
+
<span
|
|
1123
|
+
className={s["interactable"] + " " + (!minimalAmountValid ? s["red"] : "")}
|
|
1124
|
+
onClick={
|
|
1125
|
+
isLoading.current
|
|
1126
|
+
? () => {}
|
|
1127
|
+
: e => callHandlingErrors(handleMinimalAmountClick, e)
|
|
1128
|
+
}
|
|
1129
|
+
>
|
|
1130
|
+
{AmountUtils.crypto(
|
|
1131
|
+
minimalAmount.current.crypto,
|
|
1132
|
+
isLastEditedReceiving.current
|
|
1133
|
+
? receivingAssetTickerPrintable
|
|
1134
|
+
: sendingAssetTickerPrintable
|
|
1135
|
+
)}
|
|
1136
|
+
</span>
|
|
1137
|
+
{minimalAmount.current?.fiat != null && minimalAmount.current.fiat !== "" ? (
|
|
1138
|
+
<span className={"semi-transparent"}>
|
|
1139
|
+
{" ~ " + AmountUtils.fiat(minimalAmount.current.fiat, fiatCurrencyCode)}
|
|
1140
|
+
</span>
|
|
1141
|
+
) : (
|
|
1142
|
+
""
|
|
1143
|
+
)}
|
|
1144
|
+
</>
|
|
1145
|
+
)
|
|
1146
|
+
) : isLoading.current ? (
|
|
1147
|
+
sendAssetAmount.current || receiveAssetAmount.current || isSwapAll.current ? (
|
|
1148
|
+
translations.informationBlock[
|
|
1149
|
+
formHasBalance ? "calculatingNetworkFee" : "calculatingSwapRates"
|
|
1150
|
+
]
|
|
1151
|
+
) : (
|
|
1152
|
+
translations.informationBlock.loadingMinimalAmount
|
|
1153
|
+
)
|
|
1154
|
+
) : (
|
|
1155
|
+
""
|
|
1156
|
+
)}
|
|
1157
|
+
</p>
|
|
1158
|
+
</div>
|
|
1159
|
+
|
|
1160
|
+
{isAddressFieldEnabled ? (
|
|
1161
|
+
<div className={s["swap-form-address-field"]}>
|
|
1162
|
+
<TitleBox title={translations.addressFields.addressTitle}>
|
|
1163
|
+
<Textarea
|
|
1164
|
+
type={"text"}
|
|
1165
|
+
onChange={e => setRecipientAddress(e.target.value)}
|
|
1166
|
+
value={recipientAddress.current}
|
|
1167
|
+
adaptiveHeight={true}
|
|
1168
|
+
errorEncountered={recipientAddress.current !== "" && !isRecipientAddressValid.current}
|
|
1169
|
+
/>
|
|
1170
|
+
</TitleBox>
|
|
1171
|
+
{isHydrated && recipientAddressExtraIdName ? (
|
|
1172
|
+
<TitleBox
|
|
1173
|
+
title={translations.addressFields.receivingAddressExtraIdTitle}
|
|
1174
|
+
titleNoticeText={translations.addressFields.receivingAddressExtraIdNotice}
|
|
1175
|
+
titleNoticePosition={TOOLTIP_POSITIONS.TOP_LEFT}
|
|
1176
|
+
>
|
|
1177
|
+
<Textarea
|
|
1178
|
+
type={"text"}
|
|
1179
|
+
onChange={e => setRecipientAddressExtraId(e.target.value)}
|
|
1180
|
+
value={recipientAddressExtraId.current}
|
|
1181
|
+
adaptiveHeight={true}
|
|
1182
|
+
placeholder={translations.addressFields.extraIdPlaceholder}
|
|
1183
|
+
/>
|
|
1184
|
+
</TitleBox>
|
|
1185
|
+
) : null}
|
|
1186
|
+
{isHydrated && isRefundAddressRequired ? (
|
|
1187
|
+
<>
|
|
1188
|
+
<TitleBox title={translations.addressFields.refundAddressTitle}>
|
|
1189
|
+
<Textarea
|
|
1190
|
+
type={"text"}
|
|
1191
|
+
onChange={e => setRefundAddress(e.target.value)}
|
|
1192
|
+
value={refundAddress.current}
|
|
1193
|
+
adaptiveHeight={true}
|
|
1194
|
+
errorEncountered={refundAddress.current !== "" && !isRefundAddressValid.current}
|
|
1195
|
+
/>
|
|
1196
|
+
</TitleBox>
|
|
1197
|
+
{refundAddressExtraIdName ? (
|
|
1198
|
+
<TitleBox
|
|
1199
|
+
title={translations.addressFields.refundAddressExtraIdTitle}
|
|
1200
|
+
titleNoticeText={translations.addressFields.refundAddressExtraIdNotice}
|
|
1201
|
+
titleNoticePosition={TOOLTIP_POSITIONS.TOP_LEFT}
|
|
1202
|
+
>
|
|
1203
|
+
<Textarea
|
|
1204
|
+
type={"text"}
|
|
1205
|
+
onChange={e => setRefundAddressExtraId(e.target.value)}
|
|
1206
|
+
value={refundAddressExtraId.current}
|
|
1207
|
+
adaptiveHeight={true}
|
|
1208
|
+
placeholder={translations.addressFields.extraIdPlaceholder}
|
|
1209
|
+
/>
|
|
1210
|
+
</TitleBox>
|
|
1211
|
+
) : null}
|
|
1212
|
+
</>
|
|
1213
|
+
) : null}
|
|
1214
|
+
</div>
|
|
1215
|
+
) : null}
|
|
1216
|
+
|
|
1217
|
+
{validationContent ? (
|
|
1218
|
+
<div className={s["swap-form-validation-text"]}>
|
|
1219
|
+
<Validation text={validationContent} />
|
|
1220
|
+
</div>
|
|
1221
|
+
) : (
|
|
1222
|
+
""
|
|
1223
|
+
)}
|
|
1224
|
+
<div className={s["swap-form-button-container"]}>
|
|
1225
|
+
{!termsOfUseUrl || !privacyPolicyUrl ? null : (
|
|
1226
|
+
<p className={s["swap-form-button-container-consent-text"]}>
|
|
1227
|
+
{translations.consents.consentText + " "}
|
|
1228
|
+
<a
|
|
1229
|
+
href={termsOfUseUrl}
|
|
1230
|
+
className={s["swap-form-button-container-consent-text-link"]}
|
|
1231
|
+
target="_blank"
|
|
1232
|
+
>
|
|
1233
|
+
{translations.consents.termsOfUse}
|
|
1234
|
+
</a>
|
|
1235
|
+
{" " + translations.consents.and + " "}
|
|
1236
|
+
<a
|
|
1237
|
+
href={privacyPolicyUrl}
|
|
1238
|
+
className={s["swap-form-button-container-consent-text-link"]}
|
|
1239
|
+
target="_blank"
|
|
1240
|
+
>
|
|
1241
|
+
{translations.consents.privacyPolicy}
|
|
1242
|
+
</a>
|
|
1243
|
+
.
|
|
1244
|
+
</p>
|
|
1245
|
+
)}
|
|
1246
|
+
<Button
|
|
1247
|
+
size="lg"
|
|
1248
|
+
mode="primary"
|
|
1249
|
+
content={translations.confirmButtonText}
|
|
1250
|
+
onClick={resetButtonLoader =>
|
|
1251
|
+
handleConfirmButtonClick(
|
|
1252
|
+
resetButtonLoader,
|
|
1253
|
+
setValidationContent,
|
|
1254
|
+
setBalanceValid,
|
|
1255
|
+
setMinimalAmountValid,
|
|
1256
|
+
setMaximumAmountValid,
|
|
1257
|
+
setIsPairSupported,
|
|
1258
|
+
setIsSameCoins,
|
|
1259
|
+
recipientAddress.current,
|
|
1260
|
+
recipientAddressExtraId.current,
|
|
1261
|
+
refundAddress.current,
|
|
1262
|
+
refundAddressExtraId.current,
|
|
1263
|
+
isLastEditedReceiving.current
|
|
1264
|
+
)
|
|
1265
|
+
}
|
|
1266
|
+
fullWidthOnMobiles
|
|
1267
|
+
isDisabled={!readyToSwap}
|
|
1268
|
+
to={formHasBalance ? "" : confirmButtonTo}
|
|
1269
|
+
loader
|
|
1270
|
+
handleError={callHandlingErrors}
|
|
1271
|
+
/>
|
|
1272
|
+
</div>
|
|
1273
|
+
</TitleBox>
|
|
1274
|
+
</div>
|
|
1275
|
+
);
|
|
1276
|
+
};
|
|
1277
|
+
|
|
1278
|
+
SwapForm.propTypes = {
|
|
1279
|
+
sendingAssetTicker: PropTypes.string.isRequired,
|
|
1280
|
+
receivingAssetTicker: PropTypes.string.isRequired,
|
|
1281
|
+
sendingAssetDecimalCount: PropTypes.number,
|
|
1282
|
+
receivingAssetDecimalCount: PropTypes.number,
|
|
1283
|
+
sendingAssetTickerPrintable: PropTypes.string.isRequired,
|
|
1284
|
+
receivingAssetTickerPrintable: PropTypes.string.isRequired,
|
|
1285
|
+
sendingAssetProtocol: PropTypes.string,
|
|
1286
|
+
receivingAssetProtocol: PropTypes.string,
|
|
1287
|
+
sendingAssetIconSrc: PropTypes.string.isRequired,
|
|
1288
|
+
sendingAssetProtocolIconSrc: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1289
|
+
receivingAssetIconSrc: PropTypes.string.isRequired,
|
|
1290
|
+
receivingAssetProtocolIconSrc: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1291
|
+
fallBackAssetIconSrc: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1292
|
+
sendingAssetFeeCoinTickerPrintable: PropTypes.string,
|
|
1293
|
+
sendingAssetBalance: PropTypes.string,
|
|
1294
|
+
receivingAssetBalance: PropTypes.string,
|
|
1295
|
+
handleChangeSendingAssetClick: PropTypes.func.isRequired,
|
|
1296
|
+
handleChangeReceivingAssetClick: PropTypes.func.isRequired,
|
|
1297
|
+
handleConfirmButtonClick: PropTypes.func,
|
|
1298
|
+
composeConfirmButtonTo: PropTypes.func,
|
|
1299
|
+
setSwapCreationEstimation: PropTypes.func,
|
|
1300
|
+
handleUnexpectedError: PropTypes.func,
|
|
1301
|
+
rotateAssets: PropTypes.func,
|
|
1302
|
+
preservedAmount: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1303
|
+
handleSwapServiceError: PropTypes.func.isRequired,
|
|
1304
|
+
formHasBalance: PropTypes.bool,
|
|
1305
|
+
retrieveSwapDetails: PropTypes.func.isRequired,
|
|
1306
|
+
retrieveInitialSwapData: PropTypes.func.isRequired,
|
|
1307
|
+
triggerDataUpdateResetting: PropTypes.number,
|
|
1308
|
+
fromAssetSelectionButtonRef: PropTypes.any,
|
|
1309
|
+
toAssetSelectionButtonRef: PropTypes.any,
|
|
1310
|
+
sendingAssetToFiatRate: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]),
|
|
1311
|
+
receivingAssetToFiatRate: PropTypes.oneOfType([PropTypes.number, PropTypes.string, null]),
|
|
1312
|
+
fiatCurrencyCode: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1313
|
+
fiatCurrencyDecimals: PropTypes.oneOfType([PropTypes.number, null]),
|
|
1314
|
+
formHasFiat: PropTypes.bool,
|
|
1315
|
+
termsOfUseUrl: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1316
|
+
privacyPolicyUrl: PropTypes.oneOfType([PropTypes.string, null]),
|
|
1317
|
+
getExtraIdNameByTicker: PropTypes.func,
|
|
1318
|
+
translations: PropTypes.object,
|
|
1319
|
+
validateAddressByTicker: PropTypes.func,
|
|
1320
|
+
swapSeparatorIconSrc: PropTypes.string.isRequired,
|
|
1321
|
+
swapButtonAlwaysActive: PropTypes.bool,
|
|
1322
|
+
onIsFixedChange: PropTypes.func,
|
|
1323
|
+
};
|
|
1324
|
+
|
|
1325
|
+
SwapForm.defaultProps = {
|
|
1326
|
+
sendingAssetDecimalCount: AmountUtils.significantDecimalCount,
|
|
1327
|
+
receivingAssetDecimalCount: AmountUtils.significantDecimalCount,
|
|
1328
|
+
sendingAssetProtocolIconSrc: null,
|
|
1329
|
+
receivingAssetProtocolIconSrc: null,
|
|
1330
|
+
fallBackAssetIconSrc: null,
|
|
1331
|
+
handleConfirmButtonClick: (
|
|
1332
|
+
resetButtonLoader,
|
|
1333
|
+
setValidationContent,
|
|
1334
|
+
setBalanceValid,
|
|
1335
|
+
setMinimalAmountValid,
|
|
1336
|
+
setMaximumAmountValid,
|
|
1337
|
+
setIsPairSupported,
|
|
1338
|
+
setIsSameCoins,
|
|
1339
|
+
recipientAddress,
|
|
1340
|
+
recipientAddressExtraId,
|
|
1341
|
+
refundAddress,
|
|
1342
|
+
refundAddressExtraId
|
|
1343
|
+
) => {},
|
|
1344
|
+
composeConfirmButtonTo: (fromTicker, toTicker, fromAmount) => "",
|
|
1345
|
+
setSwapCreationEstimation: details => {},
|
|
1346
|
+
handleUnexpectedError: error => {},
|
|
1347
|
+
rotateAssets: (fromTicker, toTicker) => {},
|
|
1348
|
+
preservedAmount: null,
|
|
1349
|
+
handleSwapServiceError: (
|
|
1350
|
+
errorCode,
|
|
1351
|
+
setValidationContent,
|
|
1352
|
+
setBalanceValid,
|
|
1353
|
+
setMinimalAmountValid,
|
|
1354
|
+
setMaximumAmountValid,
|
|
1355
|
+
setIsPairSupported,
|
|
1356
|
+
setIsSameCoins
|
|
1357
|
+
) => {},
|
|
1358
|
+
retrieveSwapDetails: async (sendingAssetTicker, receivingAssetTicker, amount, isSwapAll = false) => {},
|
|
1359
|
+
retrieveInitialSwapData: async (sendingAssetTicker, receivingAssetTicker) => {},
|
|
1360
|
+
triggerDataUpdateResetting: 0,
|
|
1361
|
+
fromAssetSelectionButtonRef: null,
|
|
1362
|
+
toAssetSelectionButtonRef: null,
|
|
1363
|
+
sendingAssetToFiatRate: null,
|
|
1364
|
+
receivingAssetToFiatRate: null,
|
|
1365
|
+
fiatCurrencyCode: null,
|
|
1366
|
+
fiatCurrencyDecimals: null,
|
|
1367
|
+
formHasFiat: true,
|
|
1368
|
+
termsOfUseUrl: null,
|
|
1369
|
+
privacyPolicyUrl: null,
|
|
1370
|
+
getExtraIdNameByTicker: ticker => null,
|
|
1371
|
+
validateAddressByTicker: ticker => false,
|
|
1372
|
+
swapButtonAlwaysActive: false,
|
|
1373
|
+
onIsFixedChange: () => {},
|
|
1374
|
+
};
|