├── .editorconfig ├── .env ├── .eslintrc.json ├── .gitattributes ├── .github └── workflows │ ├── crowdin.yml │ ├── dev.yml │ ├── push.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .nvmrc ├── .prettierignore ├── .prettierrc.json ├── .stylelintrc.json ├── LICENSE ├── README.md ├── crowdin.yml ├── index.html ├── lingui.config.ts ├── package.json ├── public ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── favicon.svg ├── manifest.json ├── og-image.png ├── robots.txt ├── spectrum-finance-token-logo.svg └── token-ada.svg ├── src ├── @types │ ├── dapp-cardano-wallet-web-bridge.d.ts │ ├── dapp-wallet-web-bridge.d.ts │ ├── price.d.ts │ ├── window.d.ts │ └── worker.d.ts ├── App.tsx ├── ApplicationRoutes.tsx ├── api │ └── convertToConvenientNetworkAsset.ts ├── applicationConfig.ts ├── assets │ ├── icons │ │ ├── block-icon.svg │ │ ├── checked-icon.svg │ │ ├── darkmode.svg │ │ ├── empty.svg │ │ ├── ergo-logo-icon.svg │ │ ├── flint-logo-icon.svg │ │ ├── icon-copy.svg │ │ ├── icon-dots-vertical.svg │ │ ├── icon-dots.svg │ │ ├── icon-explore.svg │ │ ├── icon-logout.svg │ │ ├── nautilus-logo-icon.svg │ │ ├── relock-icon.svg │ │ ├── social │ │ │ ├── Discord.svg │ │ │ ├── Medium.svg │ │ │ ├── Reddit.svg │ │ │ ├── Telegram.svg │ │ │ └── Twitter.svg │ │ ├── sprite │ │ │ └── sprite.svg │ │ ├── tokens │ │ │ ├── token-ada-disabled.svg │ │ │ ├── token-ada.svg │ │ │ ├── token-empty.svg │ │ │ ├── token-erdoge.svg │ │ │ ├── token-erg.svg │ │ │ ├── token-kushti.svg │ │ │ ├── token-lunadog.svg │ │ │ ├── token-sigrsv.svg │ │ │ └── token-sigusd.svg │ │ ├── verification-icon.svg │ │ ├── wallet-icon.svg │ │ ├── withdrawal-icon.svg │ │ └── yoroi-logo-icon.svg │ ├── images │ │ ├── glow-v2.png │ │ ├── smartphone.svg │ │ └── snek-glow.png │ └── styles │ │ ├── sizes.less │ │ ├── styles.less │ │ ├── themes │ │ ├── dark.less │ │ ├── hosky.less │ │ ├── light.less │ │ ├── snek-dark.less │ │ ├── snek.less │ │ └── system.less │ │ └── variables │ │ └── gradients.less ├── common │ ├── constants │ │ ├── erg.ts │ │ ├── ispo.ts │ │ ├── locales.ts │ │ ├── settings.ts │ │ ├── size.ts │ │ ├── spf.ts │ │ ├── url.ts │ │ └── usdAsset.ts │ ├── hooks │ │ ├── useObservable.ts │ │ ├── useParamsStrict.ts │ │ └── useSearchParams.ts │ ├── initializers │ │ ├── analyticsInitializer.ts │ │ ├── core.ts │ │ ├── gaInitializer.ts │ │ ├── networkDomInitializer.ts │ │ ├── sentryInitializer.ts │ │ └── walletConnectInitializer.ts │ ├── models │ │ ├── Address.ts │ │ ├── AmmPool.ts │ │ ├── AssetInfo.ts │ │ ├── AssetLock.ts │ │ ├── Balance.ts │ │ ├── Currency.ts │ │ ├── Farm.ts │ │ ├── Operation.ts │ │ ├── OperationV2.ts │ │ ├── PoolChartData.ts │ │ ├── Position.ts │ │ └── Ratio.ts │ ├── services │ │ ├── AssetGraph.ts │ │ ├── CurrencyConverter.ts │ │ ├── DefaultTokenList.ts │ │ ├── ErrorLogs.ts │ │ └── NetworkDomManager │ │ │ ├── NetworkDomManager.tsx │ │ │ └── SelectDefaultNetwork │ │ │ ├── SelectDefaultNetwork.tsx │ │ │ └── SelectDefaultNetworkItem │ │ │ ├── SelectDefaultNetworkItem.tsx │ │ │ ├── cardano-bg.png │ │ │ └── ergo-bg.png │ ├── streams │ │ ├── appTick.ts │ │ ├── networkConnection.ts │ │ ├── poolAnalytic.ts │ │ ├── tabClosing.ts │ │ └── verifiedAssets.ts │ ├── types.ts │ └── utils │ │ ├── Dictionary.ts │ │ ├── Searchable.ts │ │ ├── amount.ts │ │ ├── blocks.ts │ │ ├── calculateOutputs.ts │ │ ├── calculateTotalFee.ts │ │ ├── comparePoolByTvl.ts │ │ ├── comparePositionByTvl.ts │ │ ├── createFormatter.ts │ │ ├── env.ts │ │ ├── isCurrenctAddressValid.ts │ │ ├── isDeprecatedPool.ts │ │ ├── localStorageManager.ts │ │ ├── makeId.ts │ │ ├── normalizeAvailableLp.ts │ │ └── unpacked.ts ├── components │ ├── AddLiquidityForm │ │ ├── AddLiquidityForm.tsx │ │ ├── AddLiquidityFormModel.ts │ │ ├── LiquidityPercentInput │ │ │ └── LiquidityPercentInput.tsx │ │ └── LowLiquidityWarning │ │ │ └── LowLiquidityWarning.tsx │ ├── AssetIcon │ │ └── AssetIcon.tsx │ ├── AssetIconPair │ │ └── AssetIconPair.tsx │ ├── AssetLocksTable │ │ ├── AssetLocksTable.tsx │ │ ├── cells │ │ │ ├── PairCell │ │ │ │ └── PairCell.tsx │ │ │ ├── StatusCell │ │ │ │ └── StatusCell.tsx │ │ │ ├── UnlockBlockCell │ │ │ │ └── UnlockBlockCell.tsx │ │ │ └── UnlockDateCell │ │ │ │ └── UnlockDateCell.tsx │ │ └── selectableItemRowRenderer │ │ │ └── selectableItemRowRenderer.tsx │ ├── AssetPairTitle │ │ └── AssetPairTitle.tsx │ ├── AssetTitle │ │ └── AssetTitle.tsx │ ├── BadgeCustom │ │ └── BadgeCustom.tsx │ ├── BaseAddLiquidityConfirmationModal │ │ └── BaseAddLiquidityConfirmationModal.tsx │ ├── BaseCreatePoolConfirmationModal │ │ └── BaseCreatePoolConfirmationModal.tsx │ ├── BaseRedeemConfirmationModal │ │ └── BaseRedeemConfirmationModal.tsx │ ├── BaseSwapCollapse │ │ ├── BaseSwapCollapse.tsx │ │ ├── RatioView │ │ │ └── RatioView.tsx │ │ └── SwapInfoItem │ │ │ └── SwapInfoItem.tsx │ ├── BaseSwapConfirmationModal │ │ └── BaseSwapConfirmationModal.tsx │ ├── BoostedPoolTag │ │ └── BoostedPoolTag.tsx │ ├── BoxInfoItem │ │ └── BoxInfoItem.tsx │ ├── ConfirmationModal │ │ └── ConfirmationModal.tsx │ ├── ConvenientAssetView │ │ └── ConvenientAssetView.tsx │ ├── CurrencyPreview │ │ └── CurrencyPreview.tsx │ ├── DeprecatedPoolTag │ │ └── DeprecatedPoolTag.tsx │ ├── ErrorBoundary │ │ └── ErrorEventProvider.tsx │ ├── FarmsButton │ │ └── FarmsButton.tsx │ ├── FeesView │ │ └── FeesView.tsx │ ├── IOSNotSupportedScreen │ │ └── IOSNotSupportedScreen.tsx │ ├── InfoTooltip │ │ └── InfoTooltip.tsx │ ├── InlineGrid │ │ └── InlineGrid.tsx │ ├── IsCardano │ │ └── IsCardano.tsx │ ├── IsErgo │ │ └── IsErgo.tsx │ ├── LabeledContent │ │ └── LabeledContent.tsx │ ├── LbspBanner │ │ ├── LbspBanner.tsx │ │ ├── LbspTimer │ │ │ └── LbspTimer.tsx │ │ └── tokens-img.png │ ├── LbspCalculatorModal │ │ ├── DurationSlider │ │ │ └── DurationSlider.tsx │ │ ├── LbspCalculatorModal.tsx │ │ └── RewardsBox │ │ │ └── RewardsBox.tsx │ ├── LbspFaqModal │ │ └── LbspFaqModal.tsx │ ├── LbspPoolTag │ │ └── LbspPoolTag.tsx │ ├── List │ │ ├── List.tsx │ │ ├── ListContext │ │ │ └── ListContext.ts │ │ ├── ListStateView │ │ │ └── ListStateView.tsx │ │ ├── Overlay │ │ │ └── Overlay.tsx │ │ ├── common │ │ │ ├── Expand.ts │ │ │ ├── ListItem.ts │ │ │ └── ListState.ts │ │ └── utils │ │ │ ├── constants.ts │ │ │ ├── getHeight.ts │ │ │ ├── getRowHeight.ts │ │ │ └── normalizeMeasure.ts │ ├── NetworkHeight │ │ ├── NetworkHeight.less │ │ └── NetworkHeight.tsx │ ├── NewFeatureTag │ │ └── NewFeatureTag.tsx │ ├── OperationForm │ │ ├── OperationForm.less │ │ └── OperationForm.tsx │ ├── OperationHistoryModal │ │ ├── OperationHistory │ │ │ ├── OperationHistoryV2.tsx │ │ │ ├── OperationPagination │ │ │ │ └── OperationPagination.tsx │ │ │ ├── cells │ │ │ │ ├── AssetsCell │ │ │ │ │ ├── AddLiquidityAssetsCell │ │ │ │ │ │ └── AddLiquidityAssetsCell.tsx │ │ │ │ │ ├── AssetsCell.tsx │ │ │ │ │ ├── LmDepositAssetsCell │ │ │ │ │ │ └── LmDepositAssetsCell.tsx │ │ │ │ │ ├── LmRedeemAssetsCell │ │ │ │ │ │ └── LmRedeemAssetsCell.tsx │ │ │ │ │ ├── LockAssetsCell │ │ │ │ │ │ └── LockAssetsCell.tsx │ │ │ │ │ ├── RemoveLiquidityAssetsCell │ │ │ │ │ │ └── RemoveLiquidityAssetsCell.tsx │ │ │ │ │ └── SwapAssetsCell │ │ │ │ │ │ ├── ArrowIcon │ │ │ │ │ │ └── ArrowIcon.tsx │ │ │ │ │ │ └── SwapAssetsCell.tsx │ │ │ │ ├── CancelOrderCell │ │ │ │ │ └── CancelOrderCell.tsx │ │ │ │ ├── DateTimeCell │ │ │ │ │ └── DateTimeCell.tsx │ │ │ │ ├── FeeCell │ │ │ │ │ └── FeeCell.tsx │ │ │ │ ├── StatusCell │ │ │ │ │ └── StatusCell.tsx │ │ │ │ └── TypeCell │ │ │ │ │ └── TypeCell.tsx │ │ │ ├── common │ │ │ │ ├── AssetBox │ │ │ │ │ └── AssetBox.tsx │ │ │ │ ├── LpAssetBox │ │ │ │ │ └── LpAssetBox.tsx │ │ │ │ ├── PairAssetBox │ │ │ │ │ └── PairAssetBox.tsx │ │ │ │ └── SingleAssetBox │ │ │ │ │ └── SingleAssetBox.tsx │ │ │ ├── filters │ │ │ │ └── statusFilter.tsx │ │ │ └── states │ │ │ │ ├── ErrorState │ │ │ │ └── ErrorState.tsx │ │ │ │ ├── OperationSearchEmptyState │ │ │ │ └── OperationSearchEmptyState.tsx │ │ │ │ └── OperationsEmptyState │ │ │ │ └── OperationsEmptyState.tsx │ │ └── OperationHistoryModal.tsx │ ├── OperationSettings │ │ ├── FeeCurrencySelector │ │ │ ├── FeeCurrencySelector.tsx │ │ │ └── OperationSettingsButton │ │ │ │ └── OperationSettingsButton.tsx │ │ ├── NitroInput │ │ │ └── NitroInput.tsx │ │ ├── OperationSettings.tsx │ │ └── SlippageInput │ │ │ └── SlippageInput.tsx │ ├── OverlayBox │ │ └── OverlayBox.tsx │ ├── Page │ │ ├── Page.less │ │ ├── Page.tsx │ │ ├── PageHeader │ │ │ └── PageHeader.tsx │ │ ├── PageSection │ │ │ └── PageSection.tsx │ │ ├── Tongue │ │ │ ├── Tongue.tsx │ │ │ └── TongueArrowButton │ │ │ │ └── TongueArrowButton.tsx │ │ └── useResize.ts │ ├── PoolSelector │ │ ├── PoolSelector.tsx │ │ ├── PoolSelectorOverlay │ │ │ ├── PoolSelectorOverlay.tsx │ │ │ └── PoolSelectorOverlayItemView │ │ │ │ └── PoolSelectorOverlayItemView.tsx │ │ └── PoolView │ │ │ └── PoolView.tsx │ ├── PriceImpact │ │ └── PriceImpact.tsx │ ├── RatioBox │ │ └── RatioBox.tsx │ ├── RouterTitle │ │ ├── RouteConfigExtended.ts │ │ ├── RouteMatchExtended.ts │ │ └── RouterTitle.tsx │ ├── SearchInput │ │ └── SearchInput.tsx │ ├── Section │ │ └── Section.tsx │ ├── SensitiveContent │ │ └── SensitiveContent.tsx │ ├── SensitiveContentToggle │ │ └── SensitiveContentToggle.tsx │ ├── ShareXButton │ │ ├── ShareXButton.tsx │ │ └── X.svg │ ├── SimpeCollapse │ │ └── SimpeCollapse.tsx │ ├── SkeletonLoader │ │ ├── ListSkeletonLoadingState.tsx │ │ ├── SkeletonLoader.tsx │ │ └── makeSkeletonLoader.tsx │ ├── SocialLinks │ │ ├── SocialLinks.less │ │ └── SocialLinks.tsx │ ├── SpfLogo │ │ └── SpfLogo.tsx │ ├── SplashModal │ │ └── SplashModal.tsx │ ├── SubmitButton │ │ ├── SubmitButton.less │ │ └── SubmitButton.tsx │ ├── TableView │ │ ├── FilterButton │ │ │ └── FilterButton.tsx │ │ ├── SortButton │ │ │ └── SortButton.tsx │ │ ├── TableView.tsx │ │ ├── TableViewAction │ │ │ └── TableViewAction.tsx │ │ ├── TableViewColumn │ │ │ └── TableViewColumn.tsx │ │ ├── TableViewContent │ │ │ └── TableViewContent.tsx │ │ ├── TableViewContext │ │ │ └── TableViewContext.ts │ │ ├── TableViewDetails.tsx │ │ ├── TableViewHeader │ │ │ └── TableViewHeader.tsx │ │ ├── TableViewRow │ │ │ └── TableViewRow.tsx │ │ ├── TableViewRowRenderer │ │ │ └── TableViewRowRenderer.tsx │ │ ├── TableViewState │ │ │ └── TableViewState.tsx │ │ ├── common │ │ │ ├── Action.ts │ │ │ ├── Column.ts │ │ │ ├── Expand.ts │ │ │ ├── FilterDescription.ts │ │ │ ├── RowRenderer.ts │ │ │ ├── Sort.ts │ │ │ ├── State.ts │ │ │ ├── constants.ts │ │ │ ├── filterItem.ts │ │ │ └── sortItems.ts │ │ └── filters │ │ │ └── MultiselectFilter │ │ │ └── MultiselectFilter.tsx │ ├── ThemeSwitch │ │ ├── ThemeSwitch.tsx │ │ ├── hoski-logo.jpeg │ │ └── snek-logo.jpeg │ ├── TitledBox │ │ └── TitledBox.tsx │ ├── Truncate │ │ └── Truncate.tsx │ ├── UnknownTokenIcon │ │ ├── UnknownTokenIcon.tsx │ │ └── colorTable.ts │ ├── VerificationMark │ │ └── VerificationMark.tsx │ ├── WalletModal │ │ ├── AddressesTab │ │ │ └── AddressesTab.tsx │ │ ├── LowBalanceWarning │ │ │ └── LowBalanceWarning.tsx │ │ ├── WalletActiveAddress │ │ │ └── WalletActiveAddress.tsx │ │ ├── WalletModal.tsx │ │ ├── WalletModalSkeletonLoader │ │ │ └── WalletModalSkeletonLoader.tsx │ │ ├── WalletTokens │ │ │ ├── TokenListItem │ │ │ │ └── TokenListItem.tsx │ │ │ └── WalletTokens.tsx │ │ └── WalletTotalBalance │ │ │ └── WalletTotalBalance.tsx │ └── common │ │ ├── AppLogo │ │ ├── AppLogo.tsx │ │ └── splash-logo.svg │ │ ├── ConnectWalletButton │ │ ├── ChooseWalletModal │ │ │ ├── ChooseWalletModal.tsx │ │ │ └── ProtocolDisclaimerAlert │ │ │ │ └── ProtocolDisclaimerAlert.tsx │ │ ├── ConnectWalletButton.tsx │ │ └── VesprConnectButton │ │ │ ├── VesprConnectButton.tsx │ │ │ └── vespr-icon.svg │ │ ├── CopyButton │ │ └── CopyButton.tsx │ │ ├── DataTag │ │ └── DataTag.tsx │ │ ├── DateTimeView │ │ └── DateTimeView.tsx │ │ ├── ExploreButton │ │ └── ExploreButton.tsx │ │ ├── FeeTag │ │ └── FeeTag.tsx │ │ ├── FormView │ │ ├── FormFeesSection │ │ │ └── FormFeesSection.tsx │ │ ├── FormPairSection │ │ │ └── FormPairSection.tsx │ │ ├── FormSlider │ │ │ └── FormSlider.tsx │ │ └── FormSpace │ │ │ └── FormSpace.tsx │ │ ├── Icons │ │ └── DotsIcon.tsx │ │ ├── Layout │ │ ├── CardanoUpdate │ │ │ └── CardanoUpdate.tsx │ │ ├── DeprecatedPositions │ │ │ └── DeprecatedPosition.tsx │ │ ├── FooterNavigation │ │ │ └── FooterNavigation.tsx │ │ ├── Glow │ │ │ ├── Glow.tsx │ │ │ ├── snek-img-1.png │ │ │ └── snek-img-2.png │ │ ├── Header │ │ │ ├── Analytics │ │ │ │ ├── AnalyticTag │ │ │ │ │ └── AnalyticTag.tsx │ │ │ │ ├── Analytics.tsx │ │ │ │ └── AnalyticsSkeletonLoader │ │ │ │ │ └── AnalyticsSkeletonLoader.tsx │ │ │ ├── BurgerMenu │ │ │ │ ├── BurgerMenu.tsx │ │ │ │ ├── ManualRefundModal │ │ │ │ │ ├── ManualRefundModal.tsx │ │ │ │ │ ├── ManualRefundModalV2 │ │ │ │ │ │ └── ManualRefundModalV2.tsx │ │ │ │ │ └── common │ │ │ │ │ │ └── TransactionFindForm │ │ │ │ │ │ └── TransactionFindForm.tsx │ │ │ │ └── ergopay-icon.svg │ │ │ ├── ClaimSpfButton │ │ │ │ ├── ClaimSpfButton.tsx │ │ │ │ ├── ClaimSpfModal │ │ │ │ │ ├── AlreadyRewardState │ │ │ │ │ │ └── AlreadyRewardState.tsx │ │ │ │ │ ├── ClaimSpfModal.tsx │ │ │ │ │ ├── ClainRewardState │ │ │ │ │ │ └── ClaimRewardState.tsx │ │ │ │ │ ├── GotRewardState │ │ │ │ │ │ └── GotRewardState.tsx │ │ │ │ │ ├── NothingToClaimState │ │ │ │ │ │ └── NothingToClaimState.tsx │ │ │ │ │ ├── PendingState │ │ │ │ │ │ └── PendingState.tsx │ │ │ │ │ ├── RewardInfo │ │ │ │ │ │ ├── RewardDetails │ │ │ │ │ │ │ └── RewardDetails.tsx │ │ │ │ │ │ ├── RewardInfo.tsx │ │ │ │ │ │ └── RewardStatistic │ │ │ │ │ │ │ └── RewardStatistic.tsx │ │ │ │ │ ├── bottom-backgroud.svg │ │ │ │ │ └── top-background.svg │ │ │ │ ├── ClaimSpfNotification │ │ │ │ │ ├── ClaimSpfNotification.less │ │ │ │ │ ├── ClaimSpfNotification.tsx │ │ │ │ │ └── bottom-background.svg │ │ │ │ ├── bottom-background.svg │ │ │ │ ├── spf-token.svg │ │ │ │ └── top-background.svg │ │ │ ├── ConnectWallet │ │ │ │ ├── ConnectWallet.tsx │ │ │ │ ├── HeaderConnectWalletButton │ │ │ │ │ └── HeaderConnectWalletButton.tsx │ │ │ │ └── WalletInfoButton │ │ │ │ │ ├── AddressTag │ │ │ │ │ ├── AddressContent │ │ │ │ │ │ └── AddressContent.tsx │ │ │ │ │ ├── AddressTag.tsx │ │ │ │ │ ├── LoadingContent │ │ │ │ │ │ └── LoadingContent.tsx │ │ │ │ │ └── TagTypography │ │ │ │ │ │ └── TagTypography.tsx │ │ │ │ │ ├── BalanceView │ │ │ │ │ └── BalanceView.tsx │ │ │ │ │ └── WalletInfoButton.tsx │ │ │ ├── Header.tsx │ │ │ ├── Navigation │ │ │ │ └── Navigation.tsx │ │ │ └── NetworkDropdown │ │ │ │ ├── NetworkDropdown.less │ │ │ │ └── NetworkDropdown.tsx │ │ ├── Layout.tsx │ │ ├── NeedUpdateModal │ │ │ └── NeedUpdateModal.tsx │ │ └── OperationsHistory │ │ │ └── OperationsHistory.tsx │ │ ├── OptionsButton │ │ └── OptionsButton.tsx │ │ └── TokenControl │ │ ├── AssetAmountInput │ │ ├── AssetAmountInput.tsx │ │ └── format.ts │ │ ├── AssetBalance │ │ └── AssetBalance.tsx │ │ ├── AssetControl.tsx │ │ └── AssetSelect │ │ ├── AssetListModal │ │ ├── AssetListImportConfirmationTokenState │ │ │ ├── AssetListImportConfirmationTokenState.tsx │ │ │ ├── ImportTokenInfo │ │ │ │ └── ImportTokenInfo.tsx │ │ │ ├── ImportTokenPairSelectControl │ │ │ │ └── ImportTokenPairSelectControl.tsx │ │ │ └── ImportTokenWarning │ │ │ │ └── ImportTokenWarning.tsx │ │ ├── AssetListModal.tsx │ │ └── AssetListSelectTokenState │ │ │ ├── AssetListExtendedSearchItem │ │ │ └── AssetListExtendedSearchItem.tsx │ │ │ ├── AssetListGroupTitle │ │ │ └── AssetListGroupTitle.tsx │ │ │ ├── AssetListItem │ │ │ └── AssetListItem.tsx │ │ │ └── AssetListSelectTokenState.tsx │ │ └── AssetSelect.tsx ├── context │ ├── AppLoadingContext.tsx │ ├── AppicationSettingsContext.tsx │ └── index.ts ├── gateway │ ├── analytics │ │ └── fireOperationAnalyticsEvent.ts │ ├── api │ │ ├── addresses.ts │ │ ├── ammPools.ts │ │ ├── assetBalance.ts │ │ ├── assets.ts │ │ ├── createPool.ts │ │ ├── explorer.ts │ │ ├── getPoolChartData.ts │ │ ├── hasNeedRefundOperations.ts │ │ ├── locks.ts │ │ ├── networkAsset.ts │ │ ├── networkAssetBalance.ts │ │ ├── networkContext.ts │ │ ├── operations │ │ │ ├── createPool.ts │ │ │ ├── deposit.ts │ │ │ ├── lmDeposit.ts │ │ │ ├── lmRedeem.ts │ │ │ ├── redeem.ts │ │ │ ├── refund.ts │ │ │ └── swap.ts │ │ ├── pendingOperations.ts │ │ ├── platformStats.ts │ │ ├── positions.ts │ │ ├── queuedOperation.ts │ │ ├── supportedFeatures.ts │ │ ├── transactionsHistory.ts │ │ ├── useHandleCreatePoolMaxButtonClick.ts │ │ ├── useHandleDepositMaxButtonClick.ts │ │ ├── useHandleSwapMaxButtonClick.ts │ │ ├── validationFees.ts │ │ └── wallets.ts │ ├── common │ │ └── network.ts │ ├── settings │ │ └── settings.ts │ ├── utils │ │ └── exploreAddress.ts │ └── widgets │ │ ├── operationsSettings.ts │ │ ├── refundConfirmationInfo.ts │ │ └── swapCallapse.ts ├── hooks │ ├── useBodyClass.ts │ ├── useGuard.ts │ ├── useInterval.ts │ ├── useLocale.ts │ ├── useMetaThemeColor.ts │ └── useQuery.ts ├── i18n │ ├── README.MD │ ├── i18n.tsx │ └── locales │ │ ├── ar-SA.po │ │ ├── cs-CZ.po │ │ ├── de-DE.po │ │ ├── en-US.po │ │ ├── es-ES.po │ │ ├── fr-FR.po │ │ ├── he-IL.po │ │ ├── id-ID.po │ │ ├── it-IT.po │ │ ├── ja-JP.po │ │ ├── pt-BR.po │ │ ├── pt-PT.po │ │ ├── ro-RO.po │ │ ├── sk-SK.po │ │ ├── tr-TR.po │ │ ├── zh-CN.po │ │ └── zh-TW.po ├── index.tsx ├── mappers │ ├── tokenMapper.ts │ ├── varifiedTokensMapper.ts │ └── verifiedPoolsMapper.ts ├── mocks │ ├── asset.ts │ └── pool.ts ├── network │ ├── cardano │ │ ├── api │ │ │ ├── adaHandle │ │ │ │ └── index.ts │ │ │ ├── adaRatio │ │ │ │ └── adaRatio.ts │ │ │ ├── addresses │ │ │ │ └── addresses.ts │ │ │ ├── ammPools │ │ │ │ ├── CardanoAmmPool.ts │ │ │ │ ├── ammPools.ts │ │ │ │ ├── analyticPoolNetwork.ts │ │ │ │ └── utils.ts │ │ │ ├── balance │ │ │ │ ├── assetBalance.ts │ │ │ │ ├── balance.ts │ │ │ │ ├── lpBalance.ts │ │ │ │ └── networkAssetBalance.ts │ │ │ ├── common │ │ │ │ ├── cardanoAssetInfo │ │ │ │ │ ├── getCardanoAssetInfo.ts │ │ │ │ │ └── mocks.ts │ │ │ │ ├── cardanoNetwork.ts │ │ │ │ ├── cardanoWasm.ts │ │ │ │ ├── defaultTokenList.ts │ │ │ │ └── tokenLocks.ts │ │ │ ├── const.ts │ │ │ ├── lbspWhitelist │ │ │ │ └── lbspWhitelist.ts │ │ │ ├── networkAsset │ │ │ │ └── networkAsset.ts │ │ │ ├── networkContext │ │ │ │ └── networkContext.ts │ │ │ ├── operations │ │ │ │ ├── common │ │ │ │ │ ├── ammTxFeeMapping.ts │ │ │ │ │ ├── inputSelector.ts │ │ │ │ │ ├── minExecutorReward.ts │ │ │ │ │ ├── submitTxCandidate.ts │ │ │ │ │ └── transactionBuilder.ts │ │ │ │ ├── createPool.tsx │ │ │ │ ├── deposit.tsx │ │ │ │ ├── redeem.tsx │ │ │ │ ├── refund.ts │ │ │ │ └── swap.tsx │ │ │ ├── platformStats │ │ │ │ └── platformStats.ts │ │ │ ├── poolChart │ │ │ │ └── poolChart.ts │ │ │ ├── positions │ │ │ │ └── positions.ts │ │ │ ├── rewards │ │ │ │ ├── claimRewards.ts │ │ │ │ ├── rewards.ts │ │ │ │ └── utils.ts │ │ │ ├── tokens │ │ │ │ └── tokens.ts │ │ │ ├── transactionHistory │ │ │ │ ├── operationsHistory.ts │ │ │ │ └── types │ │ │ │ │ ├── AddLiquidityOperation.ts │ │ │ │ │ ├── BaseOperation.ts │ │ │ │ │ ├── OperationItem.ts │ │ │ │ │ ├── RemoveLiquidityOperation.ts │ │ │ │ │ └── SwapOperation.ts │ │ │ ├── utxos │ │ │ │ └── utxos.ts │ │ │ └── wallet │ │ │ │ ├── common │ │ │ │ ├── AdditionalData.ts │ │ │ │ ├── BoxSelector.ts │ │ │ │ ├── Wallet.ts │ │ │ │ ├── WalletManager.tsx │ │ │ │ └── old │ │ │ │ │ ├── CardanoWalletContract.ts │ │ │ │ │ └── makeCardanoWallet.tsx │ │ │ │ ├── connectedWalletChange.ts │ │ │ │ ├── consts.ts │ │ │ │ ├── eternl │ │ │ │ ├── eternl-icon.svg │ │ │ │ └── eternl.tsx │ │ │ │ ├── exodus │ │ │ │ ├── exodus-icon.svg │ │ │ │ └── exodus.tsx │ │ │ │ ├── flint │ │ │ │ ├── flint-icon.svg │ │ │ │ └── flint.tsx │ │ │ │ ├── gero │ │ │ │ ├── gero.tsx │ │ │ │ └── gerowallet-icon.svg │ │ │ │ ├── lace │ │ │ │ ├── lace-icon.svg │ │ │ │ └── lace.tsx │ │ │ │ ├── nami │ │ │ │ ├── nami-icon.svg │ │ │ │ └── nami.tsx │ │ │ │ ├── nufi │ │ │ │ ├── nufi-icon.svg │ │ │ │ └── nufi.tsx │ │ │ │ ├── typhon │ │ │ │ ├── typhon-icon.svg │ │ │ │ └── typhon.tsx │ │ │ │ ├── vespr │ │ │ │ ├── vespr-icon.svg │ │ │ │ └── vespr.tsx │ │ │ │ ├── wallet.ts │ │ │ │ ├── walletConnect │ │ │ │ ├── walletConnect.tsx │ │ │ │ └── wc-logo.png │ │ │ │ └── yoroi │ │ │ │ ├── yoroi-icon.svg │ │ │ │ └── yoroi.tsx │ │ ├── cardano.ts │ │ ├── components │ │ │ ├── FeesSkeletonLoading │ │ │ │ └── FeesSkeletonLoading.tsx │ │ │ └── RefundableDepositTooltipContent │ │ │ │ └── RefundableDepositTooltipContent.tsx │ │ ├── initialized.ts │ │ ├── settings │ │ │ └── settings.ts │ │ ├── utils │ │ │ ├── cardanoNetworkData.ts │ │ │ └── utils.ts │ │ └── widgets │ │ │ ├── AdaHandle │ │ │ ├── ActiveAdaHandle │ │ │ │ └── ActiveAdaHandle.tsx │ │ │ ├── AdaHandleChangeButton │ │ │ │ └── AdaHandleChangeButton.tsx │ │ │ ├── AdaHandleModal │ │ │ │ └── AdaHandleModal.tsx │ │ │ └── ada-handle-icon.svg │ │ │ ├── CreatePoolConfirmationInfo │ │ │ └── CreatePoolConfirmationInfo.tsx │ │ │ ├── DepositConfirmationModal │ │ │ ├── DepositConfirmationInfo │ │ │ │ └── DepositConfirmationInfo.tsx │ │ │ └── DepositConfirmationModal.tsx │ │ │ ├── OperationSettings │ │ │ └── OperationsSettings.tsx │ │ │ ├── RedeemConfirmationModal │ │ │ ├── RedeemConfirmationInfo │ │ │ │ └── RedeemConfirmationInfo.tsx │ │ │ └── RedeemConfirmationModal.tsx │ │ │ ├── SwapCollapse │ │ │ └── SwapCollapse.tsx │ │ │ ├── SwapConfirmationModal │ │ │ ├── SwapConfirmationInfo │ │ │ │ └── SwapConfirmationInfo.tsx │ │ │ └── SwapConfirmationModal.tsx │ │ │ └── common │ │ │ ├── useDepositTxInfo.ts │ │ │ ├── useRedeemTxInfo.ts │ │ │ └── useSwapTxInfo.ts │ ├── common │ │ ├── Network.ts │ │ ├── NetworkContext.ts │ │ ├── NetworkData.ts │ │ ├── NetworkOperations.ts │ │ ├── NetworkSettings.ts │ │ ├── NetworkUtils.ts │ │ ├── NetworkWidgets.ts │ │ ├── PlatformStats.ts │ │ ├── PoolChartDataParams.ts │ │ ├── SupportedFeatures.ts │ │ ├── Wallet.ts │ │ ├── WalletManager.ts │ │ └── depositMaxButtonClickForNative.ts │ └── ergo │ │ ├── analytics │ │ └── ergopay.ts │ │ ├── api │ │ ├── addresses │ │ │ └── addresses.ts │ │ ├── ammPools │ │ │ ├── ErgoAmmPool.ts │ │ │ ├── ammPools.ts │ │ │ └── utils.ts │ │ ├── ammPoolsStats │ │ │ └── ammPoolsStats.ts │ │ ├── assets │ │ │ └── assets.ts │ │ ├── balance │ │ │ ├── assetBalance.ts │ │ │ ├── assetInfoManager.ts │ │ │ ├── common.ts │ │ │ ├── lpBalance.ts │ │ │ └── networkAssetBalance.ts │ │ ├── common │ │ │ ├── AnalyticsData.ts │ │ │ ├── assetInfoManager.ts │ │ │ ├── availablePoolsOrTokens.ts │ │ │ ├── defaultTokenList.ts │ │ │ ├── rawAmmPools.ts │ │ │ ├── rawLmPools.ts │ │ │ └── tokenLocks.ts │ │ ├── ergoUsdRatio │ │ │ └── ergoUsdRatio.ts │ │ ├── ergopay │ │ │ ├── getErgopayAddresses.ts │ │ │ └── getErgopayRequestId.ts │ │ ├── locks │ │ │ └── locks.ts │ │ ├── networkAsset │ │ │ └── networkAsset.ts │ │ ├── networkContext │ │ │ └── networkContext.ts │ │ ├── operations │ │ │ ├── common │ │ │ │ ├── mapToOperationOrEmpty.ts │ │ │ │ └── toDexOperation.ts │ │ │ ├── history │ │ │ │ ├── tabManager.ts │ │ │ │ ├── transactionHistory.ts │ │ │ │ ├── transactionHistory.worker.ts │ │ │ │ ├── v2 │ │ │ │ │ ├── operationsHistory.ts │ │ │ │ │ └── types │ │ │ │ │ │ ├── AddLiquidityOperation.ts │ │ │ │ │ │ ├── BaseOperation.ts │ │ │ │ │ │ ├── LmDepositOperation.ts │ │ │ │ │ │ ├── LmRedeemOperation.ts │ │ │ │ │ │ ├── LockOperation.ts │ │ │ │ │ │ ├── OperationItem.ts │ │ │ │ │ │ ├── RemoveLiquidityOperation.ts │ │ │ │ │ │ └── SwapOperation.ts │ │ │ │ └── workerMessages │ │ │ │ │ ├── workerBatchMessage.ts │ │ │ │ │ ├── workerStartMessage.ts │ │ │ │ │ └── workerSyncEndMessage.ts │ │ │ ├── operations.ts │ │ │ └── pending │ │ │ │ ├── inProgressOperations.ts │ │ │ │ ├── pendingOperations.ts │ │ │ │ └── queuedOperation.ts │ │ ├── platformStats │ │ │ └── platformStats.ts │ │ ├── poolChart │ │ │ └── poolChart.ts │ │ ├── positions │ │ │ └── positions.ts │ │ ├── spfFaucet │ │ │ ├── claimSpf.ts │ │ │ ├── common.ts │ │ │ ├── spfReward.ts │ │ │ └── spfStatus.ts │ │ ├── uiFee │ │ │ └── uiFee.ts │ │ ├── utxos │ │ │ └── utxos.ts │ │ └── wallet │ │ │ ├── common │ │ │ └── ErgoWalletContract.ts │ │ │ ├── connectedWalletChange.ts │ │ │ ├── ergopay │ │ │ └── ergopay.tsx │ │ │ ├── nautilus │ │ │ ├── connectWallet.tsx │ │ │ ├── getAddresses.ts │ │ │ ├── getUtxos.ts │ │ │ ├── nautilus.tsx │ │ │ ├── sign.ts │ │ │ ├── signInput.ts │ │ │ ├── submitTx.ts │ │ │ └── walletSupportedFeatures.ts │ │ │ └── wallet.ts │ │ ├── ergo.ts │ │ ├── initialized.ts │ │ ├── lm │ │ ├── api │ │ │ ├── farms │ │ │ │ ├── analytics.ts │ │ │ │ ├── farms.ts │ │ │ │ └── utils.ts │ │ │ └── stakes │ │ │ │ └── stakes.ts │ │ ├── models │ │ │ ├── ErgoFarm.ts │ │ │ └── Stake.ts │ │ └── operations │ │ │ ├── common │ │ │ ├── inputSelector.ts │ │ │ └── lmPoolActions.ts │ │ │ ├── lmDeposit │ │ │ ├── LmDepositModalContent │ │ │ │ └── LmDepositModalContent.tsx │ │ │ ├── createLmDepositData.ts │ │ │ ├── ergopayLmDeposit.ts │ │ │ ├── lmDeposit.tsx │ │ │ └── walletLmDeposit.ts │ │ │ └── lmRedeem │ │ │ ├── LmRedeemModalContent │ │ │ └── LmRedeemModalContent.tsx │ │ │ ├── createLmRedeemData.ts │ │ │ ├── egopayLmRedeem.ts │ │ │ ├── lmRedeem.tsx │ │ │ └── walletLmRedeem.ts │ │ ├── operations │ │ ├── common │ │ │ ├── ergopayMessageManager.ts │ │ │ ├── getInputs.ts │ │ │ ├── getTxContext.ts │ │ │ ├── makeTarget.ts │ │ │ ├── nativeFeePoolActions.ts │ │ │ ├── proverMediator.ts │ │ │ ├── submitErgopayTx.ts │ │ │ └── submitTx.ts │ │ ├── createPool │ │ │ ├── createCreatePoolTxData.ts │ │ │ ├── createPool.tsx │ │ │ ├── useCreatePoolValidators.ts │ │ │ └── walletCreatePool.ts │ │ ├── deposit │ │ │ ├── deposit.tsx │ │ │ ├── ergopayDeposit.ts │ │ │ ├── nativeFee │ │ │ │ ├── createDepositTxData.ts │ │ │ │ ├── ergopayDeposit.ts │ │ │ │ └── walletDeposit.ts │ │ │ ├── spfFee │ │ │ │ ├── createDepositTxData.ts │ │ │ │ ├── ergopayDeposit.ts │ │ │ │ └── walletDeposit.ts │ │ │ ├── useDepositValidators.ts │ │ │ ├── useHandleCreatePoolMaxButtonClick.ts │ │ │ ├── useHandleDepositMaxButtonClick.ts │ │ │ └── walletDeposit.ts │ │ ├── redeem │ │ │ ├── ergopayRedeem.ts │ │ │ ├── nativeFee │ │ │ │ ├── createRedeemTxData.ts │ │ │ │ ├── ergopayRedeem.ts │ │ │ │ └── walletRedeem.ts │ │ │ ├── redeem.tsx │ │ │ ├── spfFee │ │ │ │ ├── createRedeemTxData.ts │ │ │ │ ├── ergopayRedeem.ts │ │ │ │ └── walletRedeem.ts │ │ │ └── walletRedeem.ts │ │ ├── refund │ │ │ ├── createRefundTxData.ts │ │ │ ├── ergopayRefund.ts │ │ │ ├── refund.tsx │ │ │ └── walletRefund.ts │ │ └── swap │ │ │ ├── ergopaySwap.ts │ │ │ ├── nativeFee │ │ │ ├── createSwapTxData.ts │ │ │ ├── ergopaySwap.ts │ │ │ └── walletSwap.ts │ │ │ ├── spfFee │ │ │ ├── createSwapTxData.ts │ │ │ ├── ergopaySwap.ts │ │ │ └── walletSwap.ts │ │ │ ├── swap.tsx │ │ │ ├── useHandleSwapMaxButtonClick.ts │ │ │ ├── useSwapValidators.ts │ │ │ └── walletSwap.ts │ │ ├── settings │ │ ├── executionFee.ts │ │ ├── executionFee │ │ │ ├── executionFee.ts │ │ │ ├── nativeExecutionFee.ts │ │ │ └── spfExecutionFee.ts │ │ ├── minerFee.ts │ │ ├── nitro.ts │ │ ├── settings.ts │ │ ├── slippage.ts │ │ └── totalFees.ts │ │ ├── utils │ │ └── utils.ts │ │ └── widgets │ │ ├── CreatePoolConfirmationInfo │ │ └── CreatePoolConfirmationInfo.tsx │ │ ├── DepositConfirmationModal │ │ ├── DepositConfirmationInfo │ │ │ └── DepositConfirmationInfo.tsx │ │ └── DepositConfirmationModal.tsx │ │ ├── DepositOpenWallet │ │ └── DepositOpenWallet.tsx │ │ ├── ErgoPayModal │ │ ├── ErgoPayCompatibleWalletLink │ │ │ └── ErgoPayCompatibleWalletLink.tsx │ │ ├── ErgoPayModal.tsx │ │ ├── ErgoPayRequestLoadingContent │ │ │ └── ErgoPayRequestLoadingContent.tsx │ │ ├── ErgoPayTabPaneContent │ │ │ ├── ErgoPayTabPaneContent.tsx │ │ │ ├── ErgoPayTabPaneContentDesktop.tsx │ │ │ └── ErgoPayTabPaneContentMobile.tsx │ │ ├── ErgoPayTxInfoContent │ │ │ └── ErgoPayTxInfoContent.tsx │ │ └── common │ │ │ └── ergopayLinks.ts │ │ ├── LmDepositOpenWallet │ │ └── LmDepositOpenWallet.tsx │ │ ├── LmRedeemOpenWallet │ │ └── LmRedeemOpenWallet.tsx │ │ ├── OperationSettings │ │ └── OperationsSettings.tsx │ │ ├── RedeemConfirmationModal │ │ ├── RedeemConfirmationInfo │ │ │ └── RedeemConfirmationInfo.tsx │ │ └── RedeemConfirmationModal.tsx │ │ ├── RedeemOpenWallet │ │ └── RedeemOpenWallet.tsx │ │ ├── RefundConfirmationModal │ │ ├── RefundConfirmationInfo │ │ │ └── RefundConfirmationInfo.tsx │ │ └── RefundConfirmationModal.tsx │ │ ├── RefundOpenWallet │ │ └── RefundOpenWallet.tsx │ │ ├── SwapCollapse │ │ └── SwapCollapse.tsx │ │ ├── SwapConfirmationModal │ │ ├── SwapConfirmationInfo │ │ │ └── SwapConfirmationInfo.tsx │ │ └── SwapConfirmationModal.tsx │ │ └── SwapOpenWallet │ │ └── SwapOpenWallet.tsx ├── nodespecific.ts ├── pages │ ├── AddLiquidity │ │ └── AddLiquidity.tsx │ ├── AddLiquidityOrCreatePool │ │ └── common │ │ │ └── utils.ts │ ├── CreatePool │ │ ├── CreatePool.tsx │ │ ├── CreatePoolConfirmationModal │ │ │ └── CreatePoolConfirmationModal.tsx │ │ ├── CreatePoolFormModel.ts │ │ ├── FeeSelector │ │ │ ├── FeeBox │ │ │ │ └── FeeBox.tsx │ │ │ └── FeeSelector.tsx │ │ ├── InitialPrice │ │ │ └── InitialPriceInput.tsx │ │ └── Overlay │ │ │ └── Overlay.tsx │ ├── Farms │ │ ├── FarmActionModals │ │ │ └── FarmWithdrawalModal │ │ │ │ └── StakeItem │ │ │ │ └── FarmWithdrawalStakeItem.tsx │ │ ├── FarmGridView │ │ │ ├── FarmCardView │ │ │ │ └── FarmCardView.tsx │ │ │ └── FarmGridView.tsx │ │ ├── FarmGuides │ │ │ └── FarmGuides.tsx │ │ ├── FarmOperationModal │ │ │ ├── FarmOperationModal.tsx │ │ │ └── FarmOperationModalHeader │ │ │ │ └── FarmOperationModalHeader.tsx │ │ ├── FarmTableView │ │ │ ├── FarmTableExpandComponent │ │ │ │ ├── ClaimedRewardsCell │ │ │ │ │ └── ClaimedRewardsCell.tsx │ │ │ │ ├── DistributionCell │ │ │ │ │ └── DistributionCell.tsx │ │ │ │ ├── DistributionFrequencyCell │ │ │ │ │ └── DistributionFrequencyCell.tsx │ │ │ │ ├── FarmActionCell │ │ │ │ │ └── FarmActionCell.tsx │ │ │ │ ├── FarmTableExpandComponent.tsx │ │ │ │ ├── LivePeriodCell │ │ │ │ │ └── LivePeriodCell.tsx │ │ │ │ ├── NextRewardCell │ │ │ │ │ └── NextRewardCell.tsx │ │ │ │ ├── TotalStakedCell │ │ │ │ │ └── TotalStakedCell.tsx │ │ │ │ ├── YourStakeCell │ │ │ │ │ └── YourStakeCell.tsx │ │ │ │ └── common │ │ │ │ │ ├── RewardCell │ │ │ │ │ └── RewardCell.tsx │ │ │ │ │ └── UsdCell │ │ │ │ │ └── UsdCell.tsx │ │ │ ├── FarmTableView.tsx │ │ │ ├── columns │ │ │ │ ├── FarmActionColumn │ │ │ │ │ └── FarmActionColumn.tsx │ │ │ │ ├── FarmAprColumn │ │ │ │ │ └── FarmAprColumn.tsx │ │ │ │ ├── FarmDistributedColumn │ │ │ │ │ └── FarmDistributedColumn.tsx │ │ │ │ ├── FarmPairColumn │ │ │ │ │ └── FarmPairColumn.tsx │ │ │ │ ├── FarmTotalStakedColumn │ │ │ │ │ └── FarmTotalStakedColumn.tsx │ │ │ │ ├── FarmYourStakeColumn │ │ │ │ │ └── FarmYourStakeColumn.tsx │ │ │ │ └── common │ │ │ │ │ └── FarmTagColumn │ │ │ │ │ └── FarmTagColumn.tsx │ │ │ └── common │ │ │ │ └── FarmAction │ │ │ │ └── FarmAction.tsx │ │ ├── FarmTopPanel │ │ │ ├── CreateFarmModal │ │ │ │ ├── ConfirmFarmCreateModal.tsx │ │ │ │ ├── CreateFarmFormModel.ts │ │ │ │ ├── FarmDistributionIntervalInput │ │ │ │ │ └── FarmDistributionIntervalInput.tsx │ │ │ │ ├── FarmPeriodSelector │ │ │ │ │ ├── FarmPeriodSelector.tsx │ │ │ │ │ └── PeriodType.ts │ │ │ │ ├── FarmPoolSelector │ │ │ │ │ └── FarmPoolSelector.tsx │ │ │ │ └── validators │ │ │ │ │ └── validators.ts │ │ │ ├── FarmStateFilter │ │ │ │ └── FarmStateFilter.tsx │ │ │ ├── FarmTopPanel.tsx │ │ │ ├── FarmViewModeSwitch │ │ │ │ ├── FarmViewMode.ts │ │ │ │ └── FarmViewModeSwitch.tsx │ │ │ └── MyFarmsFilter │ │ │ │ └── MyFarmsFilter.tsx │ │ ├── Farms.tsx │ │ └── types │ │ │ ├── FarmTabs.ts │ │ │ └── FarmViewMode.ts │ ├── IspoRewards │ │ └── IspoRewards.tsx │ ├── Liquidity │ │ ├── Liquidity.tsx │ │ ├── common │ │ │ ├── columns │ │ │ │ ├── LockedPositionsColumns │ │ │ │ │ ├── PairColumn │ │ │ │ │ │ └── PairColumn.tsx │ │ │ │ │ ├── ShareColumn │ │ │ │ │ │ └── ShareColumn.tsx │ │ │ │ │ ├── TotalLockedColumn │ │ │ │ │ │ └── TotalLockedColumn.tsx │ │ │ │ │ └── WithdrawableLockedColumn │ │ │ │ │ │ └── WithdrawableLockedColumn.tsx │ │ │ │ └── PoolsOrPositionsColumns │ │ │ │ │ └── columns │ │ │ │ │ ├── ActionsColumn.tsx │ │ │ │ │ ├── AprColumn │ │ │ │ │ ├── AprColumn.tsx │ │ │ │ │ ├── CardanoAprColumnContent │ │ │ │ │ │ ├── CardanoAprColumnContent.tsx │ │ │ │ │ │ └── calculateLbspApr.ts │ │ │ │ │ └── ErgoAprColumnContent │ │ │ │ │ │ └── ErgoAprColumnContent.tsx │ │ │ │ │ ├── PairColumn │ │ │ │ │ └── PairColumn.tsx │ │ │ │ │ └── TvlOrVolume24Column │ │ │ │ │ └── TvlOrVolume24Column.tsx │ │ │ ├── components │ │ │ │ ├── Apr24InfoTooltip │ │ │ │ │ └── Apr24InfoTooltip.tsx │ │ │ │ ├── LiquidityFilter │ │ │ │ │ └── LiquidityFilter.tsx │ │ │ │ └── LockLiquidityDatePicker │ │ │ │ │ ├── LiquidityDatePicker.less │ │ │ │ │ └── LiquidityDatePicker.tsx │ │ │ ├── tableViewStates │ │ │ │ ├── LiquiditySearchState │ │ │ │ │ └── LiquiditySearchState.tsx │ │ │ │ └── PositionEmptyState │ │ │ │ │ └── PositionEmptyState.tsx │ │ │ └── types │ │ │ │ ├── LiquidityActiveStateProps.ts │ │ │ │ ├── LiquidityFilterProps.ts │ │ │ │ ├── LiquidityLayoutProps.ts │ │ │ │ ├── LiquidityLockedPositionsProps.ts │ │ │ │ ├── LiquidityPoolOrPositionDetailsProps.ts │ │ │ │ ├── LiquidityPoolsOverviewProps.ts │ │ │ │ ├── LiquiditySearchProps.ts │ │ │ │ ├── LiquidityState.ts │ │ │ │ ├── LiquidityYourPositionsProps.ts │ │ │ │ └── PoolsOrPositionsTableViewProps.ts │ │ ├── default │ │ │ ├── LiquidityDefaultLayout.tsx │ │ │ ├── common │ │ │ │ ├── PoolOrPositionDetails │ │ │ │ │ └── PoolOrPositionDetails.tsx │ │ │ │ └── PoolsOrPositionsTableView │ │ │ │ │ └── PoolsOrPositionsTableView.tsx │ │ │ └── components │ │ │ │ ├── LockedPositions │ │ │ │ └── LockedPositions.tsx │ │ │ │ ├── PoolsOverview │ │ │ │ ├── PoolDetails │ │ │ │ │ └── PoolDetails.tsx │ │ │ │ └── PoolsOverview.tsx │ │ │ │ └── YourPositions │ │ │ │ ├── PositionDetails │ │ │ │ └── PositionDetails.tsx │ │ │ │ └── YourPositions.tsx │ │ ├── mobile │ │ │ ├── LiquidityMobileLayout.tsx │ │ │ ├── common │ │ │ │ ├── DetailsBox │ │ │ │ │ └── DetailsBox.tsx │ │ │ │ ├── LockedPositions │ │ │ │ │ ├── LockedPositionDetails │ │ │ │ │ │ └── LockedPositionDetails.tsx │ │ │ │ │ └── LockedPositions.tsx │ │ │ │ ├── PoolOrPositionDetails │ │ │ │ │ └── PoolOrPositionDetails.tsx │ │ │ │ └── PoolsOrPositionsTableView │ │ │ │ │ └── PoolsOrPositionsTableView.tsx │ │ │ └── components │ │ │ │ ├── LiquidityStateSelect │ │ │ │ └── LiquidityStateSelect.tsx │ │ │ │ ├── PoolsOverview │ │ │ │ ├── PoolDetails │ │ │ │ │ └── PoolDetails.tsx │ │ │ │ └── PoolsOverview.tsx │ │ │ │ └── YourPositions │ │ │ │ ├── PositionDetails │ │ │ │ └── PositionDetails.tsx │ │ │ │ └── YourPositions.tsx │ │ └── utils.ts │ ├── LockLiquidity │ │ ├── LockLiquidity.tsx │ │ ├── LockLiquidityModel.ts │ │ ├── cardano │ │ │ ├── CardanoLockLiquidity.tsx │ │ │ └── LockLiquidityConfirmationModal │ │ │ │ └── LockLiquidityConfirmationModal.tsx │ │ └── ergo │ │ │ ├── ErgoLockLiquidity.tsx │ │ │ └── LockLiquidityConfirmationModal │ │ │ └── LockLiquidityConfirmationModal.tsx │ ├── PoolOverview │ │ ├── AmmPoolConfidenceAnalytic.ts │ │ ├── LockLiquidity │ │ │ ├── AnalyticOverview │ │ │ │ └── AnalyticOverview.tsx │ │ │ ├── LockLiquidity.less │ │ │ └── LockLiquidity.tsx │ │ ├── PoolInfoView │ │ │ ├── MyLiquidity │ │ │ │ └── MyLiquidity.tsx │ │ │ ├── PoolFeeTag │ │ │ │ └── PoolFeeTag.tsx │ │ │ ├── PoolInfoView.tsx │ │ │ └── TotalLiquidity │ │ │ │ └── TotalLiquidity.tsx │ │ ├── PoolOverview.tsx │ │ ├── PoolRatio │ │ │ └── PoolRatio.tsx │ │ └── PriceHistory │ │ │ ├── Difference │ │ │ └── Difference.tsx │ │ │ ├── PriceHistory.less │ │ │ └── PriceHistory.tsx │ ├── RelockLiquidity │ │ ├── RelockLiquidity.tsx │ │ └── RelockLiquidityConfirmationModal │ │ │ └── RelockLiquidityConfirmationModal.tsx │ ├── RemoveLiquidity │ │ ├── RemoveLiquidity.tsx │ │ └── RemoveLiquidityFormModel.ts │ ├── Rewards │ │ ├── Rewards.tsx │ │ ├── RewardsBugFixing │ │ │ └── RewardsBugFixing.tsx │ │ ├── RewardsDashboard │ │ │ ├── ClaimRewardsButton │ │ │ │ └── ClaimRewardsButton.tsx │ │ │ ├── RewardsDashboard.tsx │ │ │ ├── RewardsDashboardSection │ │ │ │ └── RewardsDashboardSection.tsx │ │ │ └── TotalRewardsSection │ │ │ │ └── TotalRewardsSection.tsx │ │ ├── RewardsError │ │ │ └── RewardsError.tsx │ │ └── Tags │ │ │ ├── RewardInfoTag │ │ │ └── RewardInfoTag.tsx │ │ │ └── RewardStatusTag │ │ │ └── RewardStatusTag.tsx │ ├── Swap │ │ ├── PoolSelector │ │ │ ├── PoolSelector.tsx │ │ │ └── PoolSelectorModal │ │ │ │ ├── PoolItemView │ │ │ │ └── PoolItemView.tsx │ │ │ │ └── PoolSelectorModal.tsx │ │ ├── PriceImpactWarning │ │ │ └── PriceImpactWarning.tsx │ │ ├── Swap.tsx │ │ ├── SwapFormModel.ts │ │ ├── SwapGraph │ │ │ ├── Difference │ │ │ │ └── Difference.tsx │ │ │ ├── SwapGraph.tsx │ │ │ ├── useAggregatedByDateData.ts │ │ │ ├── usePeriodSettings.ts │ │ │ └── useTicks.ts │ │ ├── SwitchButton │ │ │ └── SwitchButton.tsx │ │ └── YieldFarmingBadge │ │ │ ├── YieldFarmingBadge.tsx │ │ │ ├── banner-bg-left.png │ │ │ ├── banner-bg-right.png │ │ │ └── link.svg │ └── WithdrawalLiquidity │ │ ├── WithdrawalLiquidity.tsx │ │ ├── cardano │ │ ├── CardanoWithdrawalLiquidity.tsx │ │ └── WithdrawalLiquidityConfirmationModal │ │ │ └── WithdrawalLiquidityConfirmationModal.tsx │ │ └── ergo │ │ ├── ErgoWithdrawalLiquidity.tsx │ │ └── WithdrawalLiquidityConfirmationModal │ │ └── WithdrawalLiquidityConfirmationModal.tsx ├── services │ ├── amm.ts │ ├── defaultTxAssembler.ts │ ├── explorer.ts │ ├── locker │ │ └── parser.ts │ ├── networkHistory.ts │ ├── new │ │ └── analytics.ts │ ├── notifications │ │ ├── CollateralGuideNotification │ │ │ └── CollateralGuideNotification.tsx │ │ ├── CookiePolicy │ │ │ ├── CookiePolicy.less │ │ │ └── CookiePolicy.tsx │ │ ├── RefundOperation │ │ │ └── RefundOperation.tsx │ │ └── notificationKeys.ts │ ├── number.ts │ ├── poolActions.ts │ └── yoroi │ │ ├── index.ts │ │ └── prover.ts ├── utils │ ├── adaHandle.ts │ ├── ammMath.ts │ ├── ammOperations.ts │ ├── analytics │ │ └── mapper.ts │ ├── checkPool.ts │ ├── cookies.ts │ ├── getListAvailableTokens.ts │ ├── lbsp.ts │ ├── map.ts │ ├── math.ts │ ├── network.ts │ ├── numbers.ts │ ├── osTheme.ts │ ├── pool │ │ └── index.ts │ ├── price.ts │ ├── specialPools.ts │ ├── string │ │ ├── addres.ts │ │ ├── splitStr.ts │ │ ├── string.ts │ │ └── txId.ts │ ├── subjectToId.ts │ ├── transactions.ts │ ├── userAgent.ts │ ├── verification.ts │ └── walletMath.ts ├── vite-env-override.d.ts └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.{md, markdown, eex}] 12 | trim_trailing_whitespace = false 13 | 14 | [Makefile] 15 | indent_style = tab 16 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | VITE_AMPLITUDE_PROXY_URL="https://amplitude-proxy.spectrum.fi" 2 | VITE_SENTRY_DSN="https://9096bad706c5ecc72e40a700eaed59be@o1083190.ingest.sentry.io/4505758197612544" 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | 2 | # generated by `typings-for-css-modules-loader` webpack plugin 3 | *.module.scss.d.ts linguist-generated=true 4 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release app 2 | on: 3 | push: 4 | tags: 5 | - '[0-9]+.[0-9]+.[0-9]+' 6 | jobs: 7 | deploy: 8 | name: Release 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Release 12 | uses: appleboy/ssh-action@master 13 | with: 14 | host: ${{secrets.HOST}} 15 | username: ${{secrets.USERNAME}} 16 | key: ${{secrets.KEY}} 17 | script: cp -r /var/www/test/. /var/www/app 18 | 19 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # locales 15 | /src/i18n/locales 16 | 17 | # misc 18 | .DS_Store 19 | .env.local 20 | .env.development.local 21 | .env.test.local 22 | .env.production.local 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | .idea 29 | .tool-versions 30 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v16 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | /build 2 | /node_modules 3 | 4 | yarn.lock 5 | 6 | # ignore types generated by css-modules-typescript-loader 7 | *.module.scss.d.ts -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": true, 4 | "trailingComma": "all", 5 | "arrowParens": "always", 6 | "endOfLine":"auto" 7 | } 8 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "stylelint-less" 4 | ], 5 | "rules": { 6 | "length-zero-no-unit": true, 7 | "max-nesting-depth": 8, 8 | "selector-class-pattern": ".[a-z][a-zA-Z0-9]+$", 9 | "selector-max-compound-selectors": 8 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /src/i18n/locales/en-US.po 3 | translation: /src/i18n/locales/%locale%.po 4 | -------------------------------------------------------------------------------- /lingui.config.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | catalogs: [ 3 | { 4 | path: '/src/i18n/locales/{locale}', 5 | include: ['/src'], 6 | exclude: ['**/*.d.ts'], 7 | }, 8 | ], 9 | compileNamespace: 'es', 10 | fallbackLocales: { 11 | default: 'en-US', 12 | }, 13 | format: 'po', 14 | formatOptions: { 15 | lineNumbers: false, 16 | }, 17 | locales: [ 18 | 'en-US', 19 | 'fr-FR', 20 | 'de-DE', 21 | 'cs-CZ', 22 | 'ro-RO', 23 | 'it-IT', 24 | 'he-IL', 25 | 'sk-SK', 26 | 'tr-TR', 27 | 'id-ID', 28 | 'es-ES', 29 | 'pt-PT', 30 | 'pt-BR', 31 | 'ar-SA', 32 | 'ja-JP', 33 | 'zh-CN', 34 | 'zh-TW', 35 | 'pseudo', 36 | ], 37 | orderBy: 'messageId', 38 | rootDir: '.', 39 | runtimeConfigModule: ['@lingui/core', 'i18n'], 40 | sourceLocale: 'en-US', 41 | pseudoLocale: 'pseudo', 42 | }; 43 | -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Spectrum Finance", 3 | "name": "Spectrum Finance is an open source cross-chain DEX", 4 | "icons": [ 5 | { 6 | "src": "favicon.svg", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "apple-touch-icon.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "android-chrome-512x512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/og-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/public/og-image.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/spectrum-finance-token-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/@types/price.d.ts: -------------------------------------------------------------------------------- 1 | type Ratio = { 2 | xPerY: number; 3 | yPerX: number; 4 | }; 5 | -------------------------------------------------------------------------------- /src/@types/window.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | ergo_request_read_access: () => Promise; 3 | ergo_check_read_access: () => Promise; 4 | needUpdate: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /src/@types/worker.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'worker-loader!*' { 2 | class WebpackWorker extends Worker { 3 | constructor(); 4 | } 5 | 6 | export default WebpackWorker; 7 | } 8 | -------------------------------------------------------------------------------- /src/api/convertToConvenientNetworkAsset.ts: -------------------------------------------------------------------------------- 1 | import { Observable, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { Currency } from '../common/models/Currency'; 4 | import { selectedNetwork$ } from '../gateway/common/network'; 5 | 6 | export const convertToConvenientNetworkAsset = ( 7 | from: Currency | Currency[], 8 | ): Observable => 9 | selectedNetwork$.pipe( 10 | switchMap((n) => n.convertToConvenientNetworkAsset(from)), 11 | publishReplay(1), 12 | refCount(), 13 | ); 14 | -------------------------------------------------------------------------------- /src/assets/icons/block-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/checked-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/darkmode.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/ergo-logo-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/icon-copy.svg: -------------------------------------------------------------------------------- 1 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/icons/icon-explore.svg: -------------------------------------------------------------------------------- 1 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /src/assets/icons/social/Medium.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/assets/icons/tokens/token-empty.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/tokens/token-erg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/icons/wallet-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/images/glow-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/assets/images/glow-v2.png -------------------------------------------------------------------------------- /src/assets/images/snek-glow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/assets/images/snek-glow.png -------------------------------------------------------------------------------- /src/assets/styles/sizes.less: -------------------------------------------------------------------------------- 1 | @s: 320px; 2 | @m: 768px; 3 | @l: 960px; 4 | @xl: 1280px; 5 | @xxl: 1920px; 6 | 7 | .s(@rules) { @media (min-width: @s) { @rules(); }} 8 | .m(@rules) { @media (min-width: @m) { @rules(); }} 9 | .l(@rules) { @media (min-width: @l) { @rules(); }} 10 | .xl(@rules) { @media (min-width: @xl) { @rules(); }} 11 | .xxl(@rules) { @media (min-width: @xxl) { @rules(); }} 12 | 13 | -------------------------------------------------------------------------------- /src/assets/styles/variables/gradients.less: -------------------------------------------------------------------------------- 1 | @gradient-ergo-dropdown: linear-gradient(264.34deg, #ff5135 2.83%, #FF8C00 98.67%); 2 | @gradient-cardano-dropdown: linear-gradient(264.34deg, #4467BF 2.83%, #244BB0 98.67%); 3 | -------------------------------------------------------------------------------- /src/common/constants/erg.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_MINER_FEE = BigInt(2_000_000); 2 | export const ERG_DECIMALS = 9; 3 | 4 | export const MIN_EX_FEE = BigInt(7_000_000); 5 | export const MIN_NITRO = 1.2; 6 | 7 | export const UI_FEE = 0; 8 | export const UI_FEE_BIGINT = 0n; 9 | 10 | export const NEW_MIN_BOX_VALUE = 400000n; 11 | -------------------------------------------------------------------------------- /src/common/constants/ispo.ts: -------------------------------------------------------------------------------- 1 | export const SPF0_URL = 2 | 'https://cardanoscan.io/pool/27eba5dbeb2b52f5613aa452cf54cab7f9894538d6efb7d271ccc36f'; 3 | export const SPF1_URL = 4 | 'https://cardanoscan.io/pool/1392b9f04cf0d7083651b4e922ed5dfd171d5e593061e84c5cf244c1'; 5 | -------------------------------------------------------------------------------- /src/common/constants/settings.ts: -------------------------------------------------------------------------------- 1 | import { fractionsToNum } from '../../utils/math'; 2 | import { makeId } from '../utils/makeId.ts'; 3 | import { DEFAULT_MINER_FEE, ERG_DECIMALS, MIN_EX_FEE } from './erg'; 4 | 5 | export const defaultMinerFee = fractionsToNum(DEFAULT_MINER_FEE, ERG_DECIMALS); 6 | export const defaultExFee = fractionsToNum(MIN_EX_FEE, ERG_DECIMALS); 7 | export const MinerFeeMax = 5; 8 | export const MinerFeeDecimals = 2; 9 | 10 | export const defaultSlippage = 3; 11 | export const MIN_SLIPPAGE = 0.01; 12 | 13 | export const MAX_SLIPPAGE = 50; 14 | 15 | export const INFINITY_SLIPPAGE = 50; 16 | export const SlippageDecimals = 2; 17 | 18 | export const PoolFeeMax = 0.25; 19 | 20 | export const UI_REWARD_ADDRESS = ''; 21 | 22 | export const appId = makeId(10); 23 | -------------------------------------------------------------------------------- /src/common/constants/size.ts: -------------------------------------------------------------------------------- 1 | export const size = { 2 | s: 320, 3 | m: 768, 4 | l: 960, 5 | xl: 1280, 6 | xxl: 1920, 7 | }; 8 | 9 | export type Sizes = keyof typeof size; 10 | 11 | export const device: Record = { 12 | s: `@media (min-width: ${size.s}px)`, 13 | m: `@media (min-width: ${size.m}px)`, 14 | l: `@media (min-width: ${size.l}px)`, 15 | xl: `@media (min-width: ${size.xl}px)`, 16 | xxl: `@media (min-width: ${size.xxl}px)`, 17 | }; 18 | -------------------------------------------------------------------------------- /src/common/constants/spf.ts: -------------------------------------------------------------------------------- 1 | export const SPF_TOKEN_ERGO_ID = 2 | '9a06d9e545a41fd51eeffc5e20d818073bf820c635e2a9d922269913e0de369d'; 3 | -------------------------------------------------------------------------------- /src/common/constants/url.ts: -------------------------------------------------------------------------------- 1 | export const SPECTRUM_DISCORD_LINK = 'https://discord.com/invite/zY2gmTYQVD'; 2 | 3 | export const SPECTRUM_TELEGRAM_LINK = ''; 4 | export const SPECTRUM_TELEGRAM_COMMUNITY_LINK = 5 | 'https://t.me/spectrum_labs_community'; 6 | 7 | export const SPECTRUM_PRIVACY_POLICY_LINK = 'https://spectrum.fi/privacy'; 8 | 9 | export const SPECTRUM_TERMS_OF_SERVICE_LINK = 'https://spectrum.fi/terms'; 10 | -------------------------------------------------------------------------------- /src/common/constants/usdAsset.ts: -------------------------------------------------------------------------------- 1 | import { AssetInfo } from '../models/AssetInfo'; 2 | import { Currency } from '../models/Currency'; 3 | 4 | export const usdAsset: AssetInfo = { 5 | id: 'USD', 6 | name: 'USD', 7 | prefix: '$', 8 | decimals: 2, 9 | }; 10 | 11 | export const emptyUsdCurrency = new Currency(0n, usdAsset); 12 | -------------------------------------------------------------------------------- /src/common/hooks/useParamsStrict.ts: -------------------------------------------------------------------------------- 1 | import { useParams } from 'react-router-dom'; 2 | 3 | export const useParamsStrict = < 4 | P extends Record | string = string, 5 | >(): P => useParams() as P; 6 | -------------------------------------------------------------------------------- /src/common/initializers/analyticsInitializer.ts: -------------------------------------------------------------------------------- 1 | import { AppName, initAnalytics } from '@spectrumlabs/analytics'; 2 | import { of } from 'rxjs'; 3 | 4 | import { version } from '../../../package.json'; 5 | import { isProductionEnv } from '../utils/env'; 6 | import { Initializer } from './core'; 7 | 8 | const ANALYTICS_DUMMY_KEY = '00000000000000000000000000000000'; 9 | const ANALYTICS_PROXY_URL = import.meta.env.VITE_AMPLITUDE_PROXY_URL; 10 | 11 | export const analyticsInitializer: Initializer = () => { 12 | initAnalytics(ANALYTICS_DUMMY_KEY, AppName.WEB_APP, { 13 | proxyUrl: ANALYTICS_PROXY_URL, 14 | version: version, 15 | isProdEnv: isProductionEnv(), 16 | isDebug: !isProductionEnv(), 17 | }); 18 | 19 | return of(true); 20 | }; 21 | -------------------------------------------------------------------------------- /src/common/initializers/core.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | export type Initializer = (...args: any[]) => Observable; 4 | -------------------------------------------------------------------------------- /src/common/initializers/gaInitializer.ts: -------------------------------------------------------------------------------- 1 | import ReactGA from 'react-ga'; 2 | import { of } from 'rxjs'; 3 | 4 | import { Initializer } from './core'; 5 | 6 | export const gaInitializer: Initializer = () => { 7 | ReactGA.initialize('G-JNZLSMXX77'); 8 | ReactGA.pageview(window.location.pathname + window.location.search); 9 | return of(true); 10 | }; 11 | -------------------------------------------------------------------------------- /src/common/initializers/networkDomInitializer.ts: -------------------------------------------------------------------------------- 1 | import { filter, first } from 'rxjs'; 2 | 3 | import { RouteConfigExtended } from '../../components/RouterTitle/RouteConfigExtended'; 4 | import { NetworkDomManager } from '../services/NetworkDomManager/NetworkDomManager'; 5 | import { Initializer } from './core'; 6 | 7 | export const networkDomInitializer: Initializer = ( 8 | routesConfig: RouteConfigExtended[], 9 | ) => { 10 | NetworkDomManager.init(routesConfig); 11 | return NetworkDomManager.initialized$.pipe(filter(Boolean), first()); 12 | }; 13 | -------------------------------------------------------------------------------- /src/common/models/Address.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from './Currency'; 2 | 3 | export interface Address { 4 | readonly addr: string; 5 | readonly networkAssetBalance: Currency; 6 | } 7 | -------------------------------------------------------------------------------- /src/common/models/AssetInfo.ts: -------------------------------------------------------------------------------- 1 | export interface AssetInfo { 2 | readonly id: string; 3 | readonly name?: string; 4 | readonly ticker?: string; 5 | readonly description?: string; 6 | readonly icon?: string; 7 | readonly url?: string; 8 | readonly iconFallback?: string; 9 | readonly prefix?: string; 10 | readonly decimals?: number; 11 | readonly emissionAmount?: bigint; 12 | readonly data?: T; 13 | } 14 | -------------------------------------------------------------------------------- /src/common/models/Balance.ts: -------------------------------------------------------------------------------- 1 | import { AssetInfo } from './AssetInfo'; 2 | import { Currency } from './Currency'; 3 | 4 | export class Balance { 5 | private mapAssetIdToBalance = new Map(); 6 | 7 | constructor(assetAmount: [bigint, AssetInfo][]) { 8 | this.mapAssetIdToBalance = new Map( 9 | assetAmount.map(([amount, info]) => [ 10 | info.id, 11 | new Currency(amount, info), 12 | ]), 13 | ); 14 | } 15 | 16 | get(asset: AssetInfo): Currency { 17 | return this.mapAssetIdToBalance.get(asset.id) || new Currency(0n, asset); 18 | } 19 | 20 | entries(): [string, Currency][] { 21 | return Array.from(this.mapAssetIdToBalance.entries()); 22 | } 23 | 24 | values(): Currency[] { 25 | return Array.from(this.mapAssetIdToBalance.values()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/common/services/NetworkDomManager/SelectDefaultNetwork/SelectDefaultNetworkItem/cardano-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/common/services/NetworkDomManager/SelectDefaultNetwork/SelectDefaultNetworkItem/cardano-bg.png -------------------------------------------------------------------------------- /src/common/services/NetworkDomManager/SelectDefaultNetwork/SelectDefaultNetworkItem/ergo-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/common/services/NetworkDomManager/SelectDefaultNetwork/SelectDefaultNetworkItem/ergo-bg.png -------------------------------------------------------------------------------- /src/common/streams/appTick.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BehaviorSubject, 3 | filter, 4 | interval, 5 | publishReplay, 6 | refCount, 7 | startWith, 8 | switchMap, 9 | } from 'rxjs'; 10 | 11 | import { applicationConfig } from '../../applicationConfig'; 12 | 13 | export const startAppTicks = (): void => appTicksStarted$.next(true); 14 | 15 | const appTicksStarted$ = new BehaviorSubject(false); 16 | 17 | export const appTick$ = appTicksStarted$.pipe( 18 | filter(Boolean), 19 | switchMap(() => 20 | interval(applicationConfig.applicationTick).pipe(startWith(0)), 21 | ), 22 | publishReplay(1), 23 | refCount(), 24 | ); 25 | -------------------------------------------------------------------------------- /src/common/streams/networkConnection.ts: -------------------------------------------------------------------------------- 1 | import { 2 | fromEvent, 3 | mapTo, 4 | merge, 5 | publishReplay, 6 | refCount, 7 | startWith, 8 | } from 'rxjs'; 9 | 10 | export const isOnline$ = merge( 11 | fromEvent(window, 'online').pipe(mapTo(true)), 12 | fromEvent(window, 'offline').pipe(mapTo(false)), 13 | ).pipe(startWith(window.navigator.onLine), publishReplay(1), refCount()); 14 | isOnline$.subscribe(); 15 | -------------------------------------------------------------------------------- /src/common/streams/tabClosing.ts: -------------------------------------------------------------------------------- 1 | import { fromEvent } from 'rxjs'; 2 | 3 | export const tabClosing$ = fromEvent(window, 'beforeunload'); 4 | -------------------------------------------------------------------------------- /src/common/streams/verifiedAssets.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { from, map } from 'rxjs'; 3 | 4 | import { applicationConfig } from '../../applicationConfig'; 5 | 6 | export const verifiedAssets$ = from( 7 | axios.get( 8 | `${applicationConfig.networksSettings.ergo.metadataUrl}/verifiedAssets.json`, 9 | ), 10 | ).pipe(map((res) => res.data)); 11 | -------------------------------------------------------------------------------- /src/common/types.ts: -------------------------------------------------------------------------------- 1 | export type Address = string; 2 | export type TxId = string; 3 | export type PoolId = string; 4 | export type Percent = number; 5 | export type Nitro = number; 6 | export type uint = number; 7 | -------------------------------------------------------------------------------- /src/common/utils/Dictionary.ts: -------------------------------------------------------------------------------- 1 | export type Dictionary = { [key: string]: T }; 2 | -------------------------------------------------------------------------------- /src/common/utils/Searchable.ts: -------------------------------------------------------------------------------- 1 | export interface Searchable { 2 | match: (term: string) => boolean; 3 | } 4 | -------------------------------------------------------------------------------- /src/common/utils/amount.ts: -------------------------------------------------------------------------------- 1 | import { AssetInfo } from '@ergolabs/ergo-sdk/build/main/entities/assetInfo'; 2 | 3 | export const getDecimalsCount = (amount: string): number => { 4 | const decimals = amount.split('.')[1]; 5 | 6 | if (decimals) { 7 | return decimals.length; 8 | } 9 | return 0; 10 | }; 11 | 12 | export const normalizeAmount = (amount: string, asset: AssetInfo): string => { 13 | const currentDecimalsCount = getDecimalsCount(amount); 14 | 15 | if (currentDecimalsCount <= (asset.decimals || 0)) { 16 | return amount; 17 | } 18 | 19 | return amount.slice( 20 | 0, 21 | amount.length - currentDecimalsCount + (asset.decimals || 0), 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/common/utils/blocks.ts: -------------------------------------------------------------------------------- 1 | import { blocksToTimestamp, timestampToBlocks } from '@ergolabs/ergo-dex-sdk'; 2 | import { DateTime } from 'luxon'; 3 | 4 | export const dateTimeToBlock = ( 5 | currentHeight: number, 6 | dateTime: DateTime, 7 | ): number => timestampToBlocks(currentHeight, dateTime.toMillis()); 8 | 9 | export const blockToDateTime = ( 10 | currentHeight: number, 11 | block: number, 12 | ): DateTime => 13 | DateTime.fromMillis(Number(blocksToTimestamp(currentHeight, block))); 14 | -------------------------------------------------------------------------------- /src/common/utils/calculateTotalFee.ts: -------------------------------------------------------------------------------- 1 | import { parseUserInputToFractions } from '../../utils/math'; 2 | import { AssetInfo } from '../models/AssetInfo'; 3 | import { Currency } from '../models/Currency'; 4 | 5 | type Fee = Currency | string | number | bigint; 6 | 7 | export const calculateTotalFee = ( 8 | fees: Fee[], 9 | assetInfo: AssetInfo, 10 | ): Currency => { 11 | const feeSum = fees.reduce((acc, fee) => { 12 | if (typeof fee === 'string' || typeof fee === 'number') { 13 | return acc + parseUserInputToFractions(fee, assetInfo.decimals); 14 | } 15 | if (typeof fee === 'bigint') { 16 | return acc + fee; 17 | } 18 | 19 | return acc + fee.amount; 20 | }, 0n); 21 | 22 | return new Currency(feeSum, assetInfo); 23 | }; 24 | -------------------------------------------------------------------------------- /src/common/utils/comparePoolByTvl.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../../applicationConfig.ts'; 2 | import { AmmPool } from '../models/AmmPool'; 3 | 4 | export const comparePoolByTvl = (poolA: AmmPool, poolB: AmmPool): number => { 5 | if (poolA.id === applicationConfig.spfPoolId) { 6 | return -1; 7 | } 8 | 9 | if (poolB.id === applicationConfig.spfPoolId) { 10 | return 1; 11 | } 12 | 13 | if (!poolA.tvl && !poolB.tvl) { 14 | return Number( 15 | poolB.x.amount * poolB.y.amount - poolA.x.amount * poolA.y.amount, 16 | ); 17 | } 18 | 19 | if (!poolA.tvl) { 20 | return 1; 21 | } 22 | if (!poolB.tvl) { 23 | return -1; 24 | } 25 | return Number(poolB.tvl.toAmount()) - Number(poolA.tvl.toAmount()); 26 | }; 27 | -------------------------------------------------------------------------------- /src/common/utils/comparePositionByTvl.ts: -------------------------------------------------------------------------------- 1 | import { Position } from '../models/Position'; 2 | 3 | export const comparePositionByTvl = ( 4 | positionA: Position, 5 | positionB: Position, 6 | ): number => { 7 | if (!positionA.pool.tvl) { 8 | return 1; 9 | } 10 | if (!positionB.pool.tvl) { 11 | return -1; 12 | } 13 | return ( 14 | Number(positionB.pool.tvl.toAmount()) - 15 | Number(positionA.pool.tvl.toAmount()) 16 | ); 17 | }; 18 | -------------------------------------------------------------------------------- /src/common/utils/env.ts: -------------------------------------------------------------------------------- 1 | export const isProductionEnv = (): boolean => 2 | import.meta.env.NODE_ENV === 'production'; 3 | 4 | export const getSentryEnv = (): string => { 5 | if (location.host === 'app.spectrum.fi') { 6 | return 'production'; 7 | } 8 | if (location.host === 'test.spectrum.fi') { 9 | return 'test'; 10 | } 11 | if (location.host === 'dev.spectrum.fi') { 12 | return 'dev'; 13 | } 14 | return 'local'; 15 | }; 16 | -------------------------------------------------------------------------------- /src/common/utils/isCurrenctAddressValid.ts: -------------------------------------------------------------------------------- 1 | import { Address } from '@ergolabs/ergo-sdk'; 2 | 3 | export const isCurrentAddressValid = ( 4 | address: Address | undefined, 5 | addresses: Address[], 6 | ): boolean => !!address && addresses.includes(address); 7 | -------------------------------------------------------------------------------- /src/common/utils/isDeprecatedPool.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../../applicationConfig'; 2 | 3 | export const isDeprecatedPool = (poolId: string): boolean => 4 | applicationConfig.deprecatedPools.includes(poolId); 5 | -------------------------------------------------------------------------------- /src/common/utils/makeId.ts: -------------------------------------------------------------------------------- 1 | export function makeId(length: number): string { 2 | let result = ''; 3 | const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 4 | const charactersLength = characters.length; 5 | for (let i = 0; i < length; i++) { 6 | result += characters.charAt(Math.floor(Math.random() * charactersLength)); 7 | } 8 | return result; 9 | } 10 | -------------------------------------------------------------------------------- /src/common/utils/unpacked.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | export type Unpacked = T extends (infer U)[] 4 | ? U 5 | : T extends (...args: any[]) => infer U 6 | ? U 7 | : T extends Promise 8 | ? U 9 | : T extends Observable 10 | ? U 11 | : T; 12 | -------------------------------------------------------------------------------- /src/components/AddLiquidityForm/AddLiquidityFormModel.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool } from '../../common/models/AmmPool'; 2 | import { AssetInfo } from '../../common/models/AssetInfo'; 3 | import { Currency } from '../../common/models/Currency'; 4 | 5 | export interface AddLiquidityFormModel { 6 | readonly x?: Currency; 7 | readonly y?: Currency; 8 | readonly xAsset?: AssetInfo; 9 | readonly yAsset?: AssetInfo; 10 | readonly pool?: AmmPool; 11 | } 12 | -------------------------------------------------------------------------------- /src/components/AssetLocksTable/cells/StatusCell/StatusCell.tsx: -------------------------------------------------------------------------------- 1 | import { Tag } from '@ergolabs/ui-kit'; 2 | import { t } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | import { 6 | AssetLock, 7 | AssetLockStatus, 8 | } from '../../../../common/models/AssetLock'; 9 | 10 | export interface StatusCellProps { 11 | readonly lock: AssetLock; 12 | } 13 | 14 | export const StatusCell: FC = ({ lock }) => ( 15 | 16 | {lock.status === 0 ? t`Locked` : t`Withdrawable`} 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /src/components/AssetLocksTable/cells/UnlockBlockCell/UnlockBlockCell.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { AssetLock } from '../../../../common/models/AssetLock'; 5 | 6 | export interface UnlockBlockCellProps { 7 | readonly lock: AssetLock; 8 | } 9 | 10 | export const UnlockBlockCell: FC = ({ lock }) => ( 11 | {lock.deadline} 12 | ); 13 | -------------------------------------------------------------------------------- /src/components/AssetLocksTable/cells/UnlockDateCell/UnlockDateCell.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@ergolabs/ui-kit'; 2 | import { DateTime } from 'luxon'; 3 | import { FC } from 'react'; 4 | 5 | import { AssetLock } from '../../../../common/models/AssetLock'; 6 | 7 | export interface UnlockDateCellProps { 8 | readonly lock: AssetLock; 9 | } 10 | 11 | export const UnlockDateCell: FC = ({ lock }) => ( 12 | 13 | {lock.unlockDate.toLocaleString(DateTime.DATE_FULL)} 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /src/components/BadgeCustom/BadgeCustom.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | interface BadgeCustomProps { 4 | isShow?: boolean; 5 | isAnimate?: boolean; 6 | } 7 | export const BadgeCustom = styled.div` 8 | position: relative; 9 | &::after { 10 | display: ${(props) => (props.isShow ? 'block' : 'none')}; 11 | content: ''; 12 | position: absolute; 13 | top: -3px; 14 | right: -3px; 15 | 16 | width: 12px; 17 | height: 12px; 18 | border-radius: 100%; 19 | background: var(--spectrum-warning-color); 20 | } 21 | `; 22 | -------------------------------------------------------------------------------- /src/components/BoostedPoolTag/BoostedPoolTag.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Tag } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | import { AssetInfo } from '../../common/models/AssetInfo.ts'; 6 | import { AssetIcon } from '../AssetIcon/AssetIcon.tsx'; 7 | 8 | interface BoostedPoolTagProps { 9 | asset: AssetInfo; 10 | } 11 | 12 | export const BoostedPoolTag: FC = ({ asset }) => { 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | Boosted 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/BoxInfoItem/BoxInfoItem.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC, ReactNode } from 'react'; 3 | 4 | export interface BoxInfoItemProps { 5 | title: ReactNode | ReactNode[] | string; 6 | value: ReactNode | ReactNode[] | string; 7 | } 8 | 9 | export const BoxInfoItem: FC = ({ title, value }) => ( 10 | 11 | {title} 12 | {value} 13 | 14 | ); 15 | -------------------------------------------------------------------------------- /src/components/DeprecatedPoolTag/DeprecatedPoolTag.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Tag, Tooltip } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | export const DeprecatedPoolTag: FC = () => ( 6 | 10 | 11 | 12 | A more secure variant of this pool is available. We advise you to 13 | migrate your liquidity to a new one. 14 | 15 | 16 | 17 | } 18 | > 19 | 20 | Deprecated 21 | 22 | 23 | ); 24 | -------------------------------------------------------------------------------- /src/components/IOSNotSupportedScreen/IOSNotSupportedScreen.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Typography } from '@ergolabs/ui-kit'; 2 | 3 | export const IOSNotSupportedScreen = () => { 4 | return ( 5 | 6 | 7 | Your OS is not supported 8 | 9 | 10 | 11 | Update the operating system and try 12 |
13 | refreshing the page 14 |
15 |
16 |
17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/InlineGrid/InlineGrid.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC, ReactNode } from 'react'; 3 | 4 | export interface InlineGridItemProps { 5 | readonly title: ReactNode | ReactNode[] | string; 6 | readonly value: ReactNode | ReactNode[] | string; 7 | } 8 | 9 | const InlineGridItem: FC = ({ title, value }) => ( 10 | 11 | {title} 12 | {value} 13 | 14 | ); 15 | 16 | export interface InlineGridProps { 17 | readonly gap?: number; 18 | readonly children?: ReactNode | ReactNode[] | string; 19 | } 20 | 21 | export const InlineGrid: FC & { 22 | Item: FC; 23 | } = ({ gap, children }) => { 24 | return ( 25 | 26 | {children} 27 | 28 | ); 29 | }; 30 | 31 | InlineGrid.Item = InlineGridItem; 32 | -------------------------------------------------------------------------------- /src/components/IsCardano/IsCardano.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | import { useSelectedNetwork } from '../../gateway/common/network'; 4 | 5 | export interface IsCardanoProps { 6 | readonly children: ReactNode | ReactNode[] | string; 7 | } 8 | 9 | export const IsCardano: FC = ({ children }) => { 10 | const [selectedNetwork] = useSelectedNetwork(); 11 | 12 | return <>{selectedNetwork.name !== 'ergo' && children}; 13 | }; 14 | -------------------------------------------------------------------------------- /src/components/IsErgo/IsErgo.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | import { useSelectedNetwork } from '../../gateway/common/network'; 4 | 5 | export interface IsErgoProps { 6 | readonly children: ReactNode | ReactNode[] | string; 7 | } 8 | 9 | export const IsErgo: FC = ({ children }) => { 10 | const [selectedNetwork] = useSelectedNetwork(); 11 | 12 | return <>{selectedNetwork.name === 'ergo' && children}; 13 | }; 14 | -------------------------------------------------------------------------------- /src/components/LbspBanner/tokens-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/components/LbspBanner/tokens-img.png -------------------------------------------------------------------------------- /src/components/List/ListContext/ListContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext, useContext } from 'react'; 2 | 3 | import { Dictionary } from '../../../common/utils/Dictionary'; 4 | import { ListState } from '../common/ListState'; 5 | 6 | interface ListContextType { 7 | readonly states: Dictionary; 8 | readonly addState: (s: ListState) => void; 9 | } 10 | 11 | const listContextDefaultValue: ListContextType = { 12 | states: {}, 13 | addState: () => {}, 14 | }; 15 | 16 | export const ListContext = createContext( 17 | listContextDefaultValue, 18 | ); 19 | 20 | export const useListContext = (): ListContextType => useContext(ListContext); 21 | -------------------------------------------------------------------------------- /src/components/List/ListStateView/ListStateView.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useEffect } from 'react'; 2 | 3 | import { ListState } from '../common/ListState'; 4 | import { useListContext } from '../ListContext/ListContext'; 5 | 6 | export const ListStateView: FC = (state) => { 7 | const { addState } = useListContext(); 8 | 9 | useEffect(() => { 10 | addState(state); 11 | }, [state.condition]); 12 | 13 | return null; 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/List/common/Expand.ts: -------------------------------------------------------------------------------- 1 | export interface Expand { 2 | readonly height: number; 3 | readonly accordion?: boolean; 4 | } 5 | -------------------------------------------------------------------------------- /src/components/List/common/ListItem.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { uint } from '../../../common/types'; 4 | 5 | export interface ListItem { 6 | readonly item: T; 7 | readonly index: uint; 8 | readonly height: number; 9 | readonly itemHeight: number; 10 | readonly expandHeight: number; 11 | readonly expanded: boolean; 12 | readonly expand: () => void; 13 | readonly collapse: () => void; 14 | readonly group?: string; 15 | } 16 | 17 | export type ListItemFn = ( 18 | childProps: ListItem, 19 | ) => ReactNode | ReactNode[] | string; 20 | -------------------------------------------------------------------------------- /src/components/List/common/ListState.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | export interface ListState { 4 | readonly name: string; 5 | readonly condition: boolean; 6 | readonly children?: ReactNode | ReactNode[] | string; 7 | } 8 | -------------------------------------------------------------------------------- /src/components/List/utils/constants.ts: -------------------------------------------------------------------------------- 1 | export const BASE_GUTTER = 4; 2 | -------------------------------------------------------------------------------- /src/components/List/utils/getRowHeight.ts: -------------------------------------------------------------------------------- 1 | import { uint } from '../../../common/types'; 2 | import { Dictionary } from '../../../common/utils/Dictionary'; 3 | import { BASE_GUTTER } from './constants'; 4 | 5 | export const getRowHeight = ( 6 | index: number, 7 | itemCount: uint, 8 | selectedItems: uint[], 9 | itemHeight: number, 10 | expandHeight: number, 11 | groups: Dictionary<{ height: number }>, 12 | gap = 0, 13 | ): number => { 14 | if (groups[index]) { 15 | return groups[index].height + gap * BASE_GUTTER; 16 | } 17 | 18 | const isItemSelected = selectedItems.includes(index); 19 | 20 | if (index === itemCount - 1) { 21 | return isItemSelected ? itemHeight + expandHeight : itemHeight; 22 | } 23 | 24 | return ( 25 | (isItemSelected ? itemHeight + expandHeight : itemHeight) + 26 | gap * BASE_GUTTER 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /src/components/List/utils/normalizeMeasure.ts: -------------------------------------------------------------------------------- 1 | export const normalizeMeasure = (value: number | string): string => { 2 | return typeof value === 'number' ? `${value}px` : value; 3 | }; 4 | -------------------------------------------------------------------------------- /src/components/NetworkHeight/NetworkHeight.less: -------------------------------------------------------------------------------- 1 | .network-height { 2 | position: fixed; 3 | right: 1rem; 4 | bottom: 1rem; 5 | 6 | @media (max-width: 720px) { 7 | display: none; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/components/OperationForm/OperationForm.less: -------------------------------------------------------------------------------- 1 | .operation-form-submit-button { 2 | width: 100%; 3 | } 4 | 5 | .connect-wallet-button { 6 | width: 100%; 7 | font-size: 20px; 8 | line-height: 28px; 9 | } 10 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/AddLiquidityAssetsCell/AddLiquidityAssetsCell.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { AddLiquidityItem } from '../../../../../../common/models/OperationV2'; 5 | import { SingleAssetBox } from '../../../common/SingleAssetBox/SingleAssetBox'; 6 | 7 | export interface AddLiquidityAssetsCellProps { 8 | readonly addLiquidityItem: AddLiquidityItem; 9 | } 10 | 11 | export const AddLiquidityAssetsCell: FC = ({ 12 | addLiquidityItem, 13 | }) => ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/LmDepositAssetsCell/LmDepositAssetsCell.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { LmDepositItem } from '../../../../../../common/models/OperationV2'; 5 | import { PairAssetBox } from '../../../common/PairAssetBox/PairAssetBox'; 6 | 7 | export interface LmDepositAssetsCellProps { 8 | readonly lmDepositItem: LmDepositItem; 9 | } 10 | 11 | export const LmDepositAssetsCell: FC = ({ 12 | lmDepositItem, 13 | }) => ( 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/LmRedeemAssetsCell/LmRedeemAssetsCell.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { LmRedeemItem } from '../../../../../../common/models/OperationV2'; 5 | import { PairAssetBox } from '../../../common/PairAssetBox/PairAssetBox'; 6 | 7 | export interface LmDepositAssetsCellProps { 8 | readonly lmRedeemItem: LmRedeemItem; 9 | } 10 | 11 | export const LmRedeemAssetsCell: FC = ({ 12 | lmRedeemItem, 13 | }) => ( 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/LockAssetsCell/LockAssetsCell.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { LockItem } from '../../../../../../common/models/OperationV2'; 5 | import { PairAssetBox } from '../../../common/PairAssetBox/PairAssetBox'; 6 | 7 | export interface LockAssetsCellProps { 8 | readonly lockItem: LockItem; 9 | } 10 | 11 | export const LockAssetsCell: FC = ({ lockItem }) => ( 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/RemoveLiquidityAssetsCell/RemoveLiquidityAssetsCell.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { RemoveLiquidityItem } from '../../../../../../common/models/OperationV2'; 5 | import { LpAssetBox } from '../../../common/LpAssetBox/LpAssetBox'; 6 | 7 | export interface RemoveLiquidityAssetsCellProps { 8 | readonly removeLiquidityItem: RemoveLiquidityItem; 9 | } 10 | 11 | export const RemoveLiquidityAssetsCell: FC = ({ 12 | removeLiquidityItem, 13 | }) => { 14 | return ( 15 | 16 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/SwapAssetsCell/ArrowIcon/ArrowIcon.tsx: -------------------------------------------------------------------------------- 1 | import { ArrowDownOutlined, Box, Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | interface ArrowIcon { 6 | readonly className?: string; 7 | } 8 | 9 | const _ArrowIcon: FC = ({ className }) => ( 10 |
11 | 12 | 13 | 14 | 15 | 16 |
17 | ); 18 | 19 | export const ArrowIcon = styled(_ArrowIcon)` 20 | border-radius: 2px; 21 | color: var(--spectrum-primary-text); 22 | height: 0.75rem; 23 | top: -0.5rem; 24 | left: 50%; 25 | position: absolute; 26 | transform: translateX(-50%); 27 | width: 0.75rem; 28 | z-index: 1; 29 | `; 30 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/AssetsCell/SwapAssetsCell/SwapAssetsCell.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { SwapItem } from '../../../../../../common/models/OperationV2'; 5 | import { SingleAssetBox } from '../../../common/SingleAssetBox/SingleAssetBox'; 6 | import { ArrowIcon } from './ArrowIcon/ArrowIcon'; 7 | 8 | export interface SwapAssetsCellProps { 9 | readonly swapItem: SwapItem; 10 | } 11 | 12 | export const SwapAssetsCell: FC = ({ swapItem }) => ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/cells/DateTimeCell/DateTimeCell.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { OperationItem } from '../../../../../common/models/OperationV2'; 5 | 6 | export interface DateTimeCellProps { 7 | readonly operationItem: OperationItem; 8 | } 9 | 10 | export const DateTimeCell: FC = ({ operationItem }) => ( 11 | 12 | {operationItem.registerTx.dateTime.toFormat('dd MMM, yy')}{' '} 13 | 14 | {operationItem.registerTx.dateTime.toFormat('HH:mm')} 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/common/PairAssetBox/PairAssetBox.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { Currency } from '../../../../../common/models/Currency'; 4 | import { AssetPairTitle } from '../../../../AssetPairTitle/AssetPairTitle'; 5 | import { ConvenientAssetView } from '../../../../ConvenientAssetView/ConvenientAssetView'; 6 | import { AssetBox } from '../AssetBox/AssetBox'; 7 | 8 | export interface SingleAssetBoxProps { 9 | readonly pair: [Currency, Currency]; 10 | } 11 | 12 | export const PairAssetBox: FC = ({ pair }) => ( 13 | 21 | } 22 | value={} 23 | /> 24 | ); 25 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/common/SingleAssetBox/SingleAssetBox.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | import { Currency } from '../../../../../common/models/Currency'; 4 | import { AssetTitle } from '../../../../AssetTitle/AssetTitle'; 5 | import { SensitiveContent } from '../../../../SensitiveContent/SensitiveContent.tsx'; 6 | import { AssetBox } from '../AssetBox/AssetBox'; 7 | 8 | export interface SingleAssetBoxProps { 9 | readonly currency: Currency; 10 | readonly icon?: ReactNode | ReactNode[] | string; 11 | } 12 | 13 | export const SingleAssetBox: FC = ({ currency, icon }) => ( 14 | } 17 | value={ 18 | 19 | {currency.toString(Math.max(currency.asset.decimals || 0, 2), 2)} 20 | 21 | } 22 | /> 23 | ); 24 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/states/OperationSearchEmptyState/OperationSearchEmptyState.tsx: -------------------------------------------------------------------------------- 1 | import { SearchDataState } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | export const OperationSearchEmptyState: FC = () => ( 6 | 7 | {/* eslint-disable-next-line react/no-unescaped-entities */} 8 | We didn't find anything. 9 |
10 | Try something else. 11 |
12 | ); 13 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistory/states/OperationsEmptyState/OperationsEmptyState.tsx: -------------------------------------------------------------------------------- 1 | import { Button, EmptyDataState, Flex } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | export interface OperationsEmptyStateProps { 6 | readonly onSwapNowButtonClick?: () => void; 7 | readonly height?: number; 8 | } 9 | 10 | export const OperationsEmptyState: FC = ({ 11 | onSwapNowButtonClick, 12 | height, 13 | }) => ( 14 | 15 | 16 | 17 | Your transactions will appear here 18 | 19 | 22 | 23 | 24 | ); 25 | -------------------------------------------------------------------------------- /src/components/OperationHistoryModal/OperationHistoryModal.tsx: -------------------------------------------------------------------------------- 1 | import { Modal, ModalRef } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | import { OperationHistoryV2 } from './OperationHistory/OperationHistoryV2'; 6 | 7 | export const OperationHistoryModal: FC = ({ close }) => { 8 | return ( 9 | <> 10 | 11 | Orders 12 | 13 | 14 | {} 15 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/OverlayBox/OverlayBox.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | import styled, { css } from 'styled-components'; 3 | 4 | export interface OverlayBoxProps { 5 | readonly overlayed?: boolean; 6 | readonly children?: ReactNode | ReactNode[] | string; 7 | readonly className?: string; 8 | } 9 | 10 | const Container = styled.div` 11 | position: relative; 12 | `; 13 | 14 | const _OverlayBox: FC = ({ children, className }) => ( 15 | 16 | {children} 17 |
18 | 19 | ); 20 | 21 | export const OverlayBox = styled(_OverlayBox)` 22 | bottom: 0; 23 | display: none; 24 | left: 0; 25 | position: absolute; 26 | right: 0; 27 | top: 0; 28 | 29 | ${(props) => 30 | props.overlayed && 31 | css` 32 | background: var(--spectrum-box-bg); 33 | display: block; 34 | opacity: 0.8; 35 | `} 36 | `; 37 | -------------------------------------------------------------------------------- /src/components/Page/Page.less: -------------------------------------------------------------------------------- 1 | .ergodex-form-page-wrapper { 2 | position: relative; 3 | animation: fadein 400ms; 4 | } 5 | 6 | @keyframes fadein { 7 | from { 8 | opacity: 0; 9 | } 10 | to { 11 | opacity: 1; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/components/RouterTitle/RouteConfigExtended.ts: -------------------------------------------------------------------------------- 1 | import { RouteObject } from 'react-router/lib/router'; 2 | 3 | export interface RouteConfigExtended extends Omit { 4 | title?: string; 5 | children?: RouteConfigExtended[]; 6 | } 7 | -------------------------------------------------------------------------------- /src/components/RouterTitle/RouteMatchExtended.ts: -------------------------------------------------------------------------------- 1 | import { Location } from 'history'; 2 | import { RouteMatch } from 'react-router/lib/router'; 3 | import { matchRoutes as _matchRoutes } from 'react-router-dom'; 4 | 5 | import { RouteConfigExtended } from './RouteConfigExtended'; 6 | 7 | export interface RouteMatchExtended extends Omit { 8 | readonly route: RouteConfigExtended; 9 | } 10 | 11 | export const matchRoutesExtended = ( 12 | routes: RouteConfigExtended[], 13 | locationArg: Partial | string, 14 | basename?: string, 15 | ): RouteMatchExtended[] => _matchRoutes(routes, locationArg, basename) || []; 16 | -------------------------------------------------------------------------------- /src/components/SearchInput/SearchInput.tsx: -------------------------------------------------------------------------------- 1 | import { Input, InputProps, SearchOutlined } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | export type SearchInputProps = Omit; 5 | 6 | export const SearchInput: FC = (props) => ( 7 | } {...props} /> 8 | ); 9 | -------------------------------------------------------------------------------- /src/components/SensitiveContent/SensitiveContent.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | import { useApplicationSettings } from '../../context'; 4 | 5 | interface SensitiveContent { 6 | children: ReactNode | string; 7 | } 8 | export const SensitiveContent: FC = ({ children }) => { 9 | const [{ isSensitiveHidden }] = useApplicationSettings(); 10 | return ( 11 | 21 | {children} 22 | 23 | ); 24 | }; 25 | -------------------------------------------------------------------------------- /src/components/SensitiveContentToggle/SensitiveContentToggle.tsx: -------------------------------------------------------------------------------- 1 | import { Button, EyeInvisibleOutlined, EyeOutlined } from '@ergolabs/ui-kit'; 2 | 3 | import { useApplicationSettings } from '../../context'; 4 | 5 | export const SensitiveContentToggle = () => { 6 | const [settings, setSettings] = useApplicationSettings(); 7 | 8 | const handleSensitiveContentToggle = () => { 9 | setSettings({ 10 | ...settings, 11 | isSensitiveHidden: !settings.isSensitiveHidden, 12 | }); 13 | }; 14 | 15 | return ( 16 | 11 | ); 12 | }; 13 | 14 | export { SubmitButton }; 15 | -------------------------------------------------------------------------------- /src/components/TableView/FilterButton/FilterButton.tsx: -------------------------------------------------------------------------------- 1 | import { FilterFilled } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | export interface FilterIconProps { 6 | readonly className?: string; 7 | readonly active?: boolean; 8 | readonly onClick?: () => void; 9 | } 10 | 11 | const _FilterIcon: FC = ({ className, onClick }) => ( 12 | 15 | ); 16 | 17 | export const FilterButton = styled(_FilterIcon)` 18 | background: transparent; 19 | border: none; 20 | outline: none; 21 | padding: 0; 22 | 23 | .anticon { 24 | cursor: pointer; 25 | color: ${(props) => 26 | props.active 27 | ? 'var(--spectrum-primary-color)' 28 | : 'var(--spectrum-table-view-column-icon)'}; 29 | font-size: 12px; 30 | } 31 | `; 32 | -------------------------------------------------------------------------------- /src/components/TableView/TableViewAction/TableViewAction.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useEffect, useState } from 'react'; 2 | 3 | import { makeId } from '../../../common/utils/makeId'; 4 | import { Action } from '../common/Action'; 5 | import { useTableViewContext } from '../TableViewContext/TableViewContext'; 6 | 7 | export const TableViewAction: FC> = (action) => { 8 | const [id] = useState(makeId(10)); 9 | const { addAction } = useTableViewContext(); 10 | 11 | useEffect(() => { 12 | addAction({ ...action, id }); 13 | }, [action]); 14 | 15 | return null; 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/TableView/TableViewColumn/TableViewColumn.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useEffect, useState } from 'react'; 2 | 3 | import { makeId } from '../../../common/utils/makeId'; 4 | import { Column } from '../common/Column'; 5 | import { useTableViewContext } from '../TableViewContext/TableViewContext'; 6 | 7 | export const TableViewColumn: FC> = (column) => { 8 | const [name] = useState(makeId(10)); 9 | const { addColumn } = useTableViewContext(); 10 | 11 | useEffect(() => { 12 | addColumn({ ...column, name, show: column.show !== false }); 13 | }, [column]); 14 | 15 | return null; 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/TableView/TableViewDetails.tsx: -------------------------------------------------------------------------------- 1 | import { getGutter, Gutter } from '@ergolabs/ui-kit'; 2 | import { FC, PropsWithChildren } from 'react'; 3 | 4 | export interface TableViewDetailsProps { 5 | readonly height: number; 6 | readonly padding?: Gutter; 7 | } 8 | 9 | export const TableViewDetails: FC> = ({ 10 | height, 11 | padding, 12 | children, 13 | }) => ( 14 |
15 | {children} 16 |
17 | ); 18 | -------------------------------------------------------------------------------- /src/components/TableView/TableViewRowRenderer/TableViewRowRenderer.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | import { RowRendererProps } from '../common/RowRenderer'; 6 | 7 | const _TableViewRowRenderer: FC = ({ 8 | children, 9 | padding, 10 | height, 11 | className, 12 | }) => ( 13 | 21 | {children} 22 | 23 | ); 24 | 25 | export const TableViewRowRenderer = styled(_TableViewRowRenderer)` 26 | overflow: hidden; 27 | transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); 28 | width: 100%; 29 | `; 30 | -------------------------------------------------------------------------------- /src/components/TableView/TableViewState/TableViewState.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useEffect } from 'react'; 2 | 3 | import { State } from '../common/State'; 4 | import { useTableViewContext } from '../TableViewContext/TableViewContext'; 5 | 6 | export const TableViewState: FC> = (state) => { 7 | const { addState } = useTableViewContext(); 8 | 9 | useEffect(() => { 10 | addState(state); 11 | }, [state.condition]); 12 | 13 | return null; 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/TableView/common/Action.ts: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | export interface Action { 4 | readonly id?: string; 5 | readonly children?: ReactNode | ReactNode[] | string; 6 | readonly icon?: ReactNode | ReactNode[] | string; 7 | readonly onClick?: (item: T) => void; 8 | readonly decorator?: FC<{ 9 | item: T; 10 | children: ReactNode | ReactNode[] | string; 11 | }>; 12 | } 13 | -------------------------------------------------------------------------------- /src/components/TableView/common/Column.ts: -------------------------------------------------------------------------------- 1 | import { CSSProperties, ReactNode } from 'react'; 2 | 3 | import { Filter } from './FilterDescription'; 4 | import { SortDirection, SortValueSelector } from './Sort'; 5 | 6 | export interface Column { 7 | readonly title?: ReactNode | ReactNode[] | string; 8 | readonly children?: (item: T) => ReactNode | ReactNode[] | string; 9 | readonly flex?: number; 10 | readonly width?: CSSProperties['width']; 11 | readonly maxWidth?: CSSProperties['maxWidth']; 12 | readonly minWidth?: CSSProperties['minWidth']; 13 | readonly filter?: Filter; 14 | readonly sortBy?: SortValueSelector; 15 | readonly defaultDirection?: SortDirection; 16 | readonly headerWidth?: CSSProperties['width']; 17 | readonly headerMaxWidth?: CSSProperties['maxWidth']; 18 | readonly headerMinWidth?: CSSProperties['minWidth']; 19 | readonly show?: boolean; 20 | readonly name?: string; 21 | } 22 | -------------------------------------------------------------------------------- /src/components/TableView/common/Expand.ts: -------------------------------------------------------------------------------- 1 | import { CSSProperties, FC } from 'react'; 2 | 3 | import { uint } from '../../../common/types'; 4 | import { Expand } from '../../List/common/Expand'; 5 | 6 | export interface ExpandComponentProps { 7 | readonly index: uint; 8 | readonly item: T; 9 | readonly collapse: () => void; 10 | readonly expandContentHeight: CSSProperties['height']; 11 | } 12 | 13 | export interface TableExpand extends Expand { 14 | readonly component: FC>; 15 | readonly columnWidth?: CSSProperties['width']; 16 | } 17 | -------------------------------------------------------------------------------- /src/components/TableView/common/FilterDescription.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | export interface FilterDescription { 4 | readonly value?: Set | undefined; 5 | readonly onChange?: (t: Set | undefined) => void; 6 | } 7 | 8 | export interface FilterControlProps extends FilterDescription { 9 | readonly close?: () => void; 10 | } 11 | 12 | export interface FilterState { 13 | readonly opened: boolean; 14 | readonly value: T[keyof T]; 15 | } 16 | 17 | export type FilterRenderer = ( 18 | description: FilterDescription, 19 | ) => ReactNode | ReactNode[] | string; 20 | 21 | export type FilterMatch = (filters: Set, item: T) => boolean; 22 | 23 | export interface Filter { 24 | render: FilterRenderer; 25 | match?: FilterMatch; 26 | onFilterChange?: (filters: Set) => void; 27 | } 28 | -------------------------------------------------------------------------------- /src/components/TableView/common/RowRenderer.ts: -------------------------------------------------------------------------------- 1 | import { Gutter } from '@ergolabs/ui-kit'; 2 | import { FC, PropsWithChildren } from 'react'; 3 | 4 | export type RowRendererProps = PropsWithChildren<{ 5 | padding?: Gutter; 6 | height: number; 7 | hoverable?: boolean; 8 | }>; 9 | 10 | export type RowRenderer = FC; 11 | -------------------------------------------------------------------------------- /src/components/TableView/common/Sort.ts: -------------------------------------------------------------------------------- 1 | import { DateTime } from 'luxon'; 2 | 3 | export enum SortDirection { 4 | ASC = 'ASC', 5 | DESC = 'DESC', 6 | } 7 | 8 | export interface Sort { 9 | direction: SortDirection | undefined; 10 | column: number; 11 | } 12 | 13 | export type SortValueSelector = (item: T) => string | number | DateTime; 14 | -------------------------------------------------------------------------------- /src/components/TableView/common/State.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | export interface State { 4 | readonly name: string; 5 | readonly condition?: boolean; 6 | readonly children?: 7 | | ReactNode 8 | | ReactNode[] 9 | | string 10 | | ((items: T[]) => ReactNode | ReactNode[] | string); 11 | } 12 | -------------------------------------------------------------------------------- /src/components/TableView/common/constants.ts: -------------------------------------------------------------------------------- 1 | export const HEADER_HEIGHT = 40; 2 | // TODO: EXTRACT BORDER_HEIGHT 3 | export const BORDER_HEIGHT = 2; 4 | -------------------------------------------------------------------------------- /src/components/TableView/common/filterItem.ts: -------------------------------------------------------------------------------- 1 | import { Dictionary } from '../../../common/utils/Dictionary'; 2 | import { Column } from './Column'; 3 | import { FilterState } from './FilterDescription'; 4 | 5 | export const filterItem = ( 6 | item: unknown, 7 | column: Column, 8 | columnNum: number, 9 | filtersState: Dictionary>, 10 | ): boolean => { 11 | const filterStateArray = Object.values(filtersState); 12 | 13 | if (!filterStateArray.length || !column.filter?.match) { 14 | return true; 15 | } 16 | 17 | return column.filter.match(filtersState[columnNum]?.value, item); 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/TableView/common/sortItems.ts: -------------------------------------------------------------------------------- 1 | import { Column } from './Column'; 2 | import { Sort, SortDirection } from './Sort'; 3 | 4 | export const sortItems = ( 5 | sort: Sort | undefined, 6 | columns: Column[], 7 | items: any[], 8 | ): any[] => { 9 | if (!sort) { 10 | return items; 11 | } 12 | const sortBy = columns[sort.column].sortBy!; 13 | 14 | return items.slice().sort((itemA: any, itemB: any) => { 15 | const itemAValue = sortBy(itemA); 16 | const itemBValue = sortBy(itemB); 17 | 18 | if (itemAValue > itemBValue) { 19 | return sort.direction === SortDirection.ASC ? 1 : -1; 20 | } 21 | if (itemBValue > itemAValue) { 22 | return sort.direction === SortDirection.ASC ? -1 : 1; 23 | } 24 | return 1; 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /src/components/ThemeSwitch/hoski-logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/components/ThemeSwitch/hoski-logo.jpeg -------------------------------------------------------------------------------- /src/components/ThemeSwitch/snek-logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/components/ThemeSwitch/snek-logo.jpeg -------------------------------------------------------------------------------- /src/components/Truncate/Truncate.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip } from '@ergolabs/ui-kit'; 2 | import * as React from 'react'; 3 | 4 | interface TruncateProps { 5 | children?: string; 6 | limit?: number; 7 | } 8 | 9 | const MAX_SYMBOLS = 7; 10 | 11 | const Truncate: React.FC = ({ children, limit }) => { 12 | if (!children) { 13 | return <>; 14 | } 15 | 16 | const symbols = limit ? limit : MAX_SYMBOLS; 17 | 18 | return ( 19 | <> 20 | {children.length > symbols ? ( 21 | {children.slice(0, symbols) + '...'} 22 | ) : ( 23 | children 24 | )} 25 | 26 | ); 27 | }; 28 | 29 | export { Truncate }; 30 | -------------------------------------------------------------------------------- /src/components/UnknownTokenIcon/colorTable.ts: -------------------------------------------------------------------------------- 1 | export const colorTable: string[] = [ 2 | '#FF5135', 3 | '#AA3E19', 4 | '#A61D24', 5 | '#AA6215', 6 | '#1765AD', 7 | '#AA7714', 8 | '#AA9514', 9 | '#6F9412', 10 | '#3C8618', 11 | '#138585', 12 | '#263EA0', 13 | '#51258F', 14 | '#A02669', 15 | ]; 16 | -------------------------------------------------------------------------------- /src/components/VerificationMark/VerificationMark.tsx: -------------------------------------------------------------------------------- 1 | import { Tooltip } from '@ergolabs/ui-kit'; 2 | import styled from 'styled-components'; 3 | 4 | import { ReactComponent as _VerificationIcon } from '../../assets/icons/verification-icon.svg'; 5 | import { IsErgo } from '../IsErgo/IsErgo'; 6 | 7 | const VerificationIcon = styled(_VerificationIcon)` 8 | cursor: pointer; 9 | color: var(--spectrum-success-color); 10 | transition: 250ms ease; 11 | 12 | &:hover { 13 | color: var(--spectrum-success-color-hover); 14 | } 15 | `; 16 | 17 | const VerificationMark = (): JSX.Element => { 18 | return ( 19 | 20 | 21 | 22 | 23 | 24 | ); 25 | }; 26 | 27 | export { VerificationMark }; 28 | -------------------------------------------------------------------------------- /src/components/WalletModal/WalletModalSkeletonLoader/WalletModalSkeletonLoader.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonLoader } from '../../SkeletonLoader/SkeletonLoader.tsx'; 2 | 3 | export const WalletModalSkeletonLoader = () => ; 4 | -------------------------------------------------------------------------------- /src/components/common/AppLogo/AppLogo.tsx: -------------------------------------------------------------------------------- 1 | import { CSSProperties } from 'react'; 2 | import * as React from 'react'; 3 | import { Link } from 'react-router-dom'; 4 | 5 | import { ReactComponent as SplashLogo } from './splash-logo.svg'; 6 | 7 | interface AppLogoProps { 8 | isNoWording?: boolean; 9 | style?: CSSProperties; 10 | } 11 | 12 | export const AppLogo: React.FC = ({ style }): JSX.Element => { 13 | return ( 14 | 15 | 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/components/common/ConnectWalletButton/VesprConnectButton/vespr-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/components/common/DateTimeView/DateTimeView.tsx: -------------------------------------------------------------------------------- 1 | import { DateTime, Settings } from 'luxon'; 2 | import * as React from 'react'; 3 | 4 | type DateTimeViewType = 'date' | 'time' | 'datetime' | 'datetimeWithWeekday'; 5 | 6 | interface DateTimeViewProps { 7 | type?: DateTimeViewType; 8 | value?: DateTime | null; 9 | } 10 | 11 | const formatMap: Record = { 12 | date: DateTime.DATE_FULL, 13 | time: DateTime.TIME_SIMPLE, 14 | datetime: DateTime.DATETIME_MED, 15 | datetimeWithWeekday: DateTime.DATETIME_MED_WITH_WEEKDAY, 16 | }; 17 | 18 | // TODO: Localize DateTime 19 | 20 | const DateTimeView: React.FC = ({ 21 | type = 'date', 22 | value, 23 | }) => { 24 | const format = formatMap[type] || DateTime.DATE_FULL; 25 | return ( 26 | <>{value?.toLocaleString(format, { locale: Settings.defaultLocale })} 27 | ); 28 | }; 29 | 30 | export { DateTimeView }; 31 | -------------------------------------------------------------------------------- /src/components/common/FeeTag/FeeTag.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { getPoolFee } from '../../../utils/pool'; 4 | import { DataTag } from '../DataTag/DataTag'; 5 | 6 | interface FeeTagProps { 7 | fee: bigint | number; 8 | contrast?: boolean; 9 | size?: 'small' | 'middle' | 'large'; 10 | loading?: boolean; 11 | } 12 | 13 | const FeeTag: React.FC = ({ fee, size, loading }) => { 14 | const _fee = typeof fee === 'number' ? fee : getPoolFee(fee); 15 | return ; 16 | }; 17 | 18 | export { FeeTag }; 19 | -------------------------------------------------------------------------------- /src/components/common/FormView/FormSpace/FormSpace.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from '@ergolabs/ui-kit'; 2 | import * as React from 'react'; 3 | 4 | interface FormSpaceProps { 5 | children: React.ReactChild | React.ReactChild[]; 6 | noPadding?: boolean; 7 | noBorder?: boolean; 8 | glass?: boolean; 9 | height?: number; 10 | } 11 | 12 | const FormSpace: React.FC = ({ 13 | children, 14 | noPadding, 15 | noBorder, 16 | glass, 17 | height, 18 | }): JSX.Element => { 19 | return ( 20 | 28 | {children} 29 | 30 | ); 31 | }; 32 | 33 | export { FormSpace }; 34 | -------------------------------------------------------------------------------- /src/components/common/Icons/DotsIcon.tsx: -------------------------------------------------------------------------------- 1 | import Icon from '@ant-design/icons'; 2 | import { FC } from 'react'; 3 | 4 | import { ReactComponent as Dots } from '../../../assets/icons/icon-dots.svg'; 5 | 6 | const DotsIcon: FC<{ rotate?: boolean }> = ({ rotate }): JSX.Element => ( 7 | 8 | ); 9 | 10 | export { DotsIcon }; 11 | -------------------------------------------------------------------------------- /src/components/common/Layout/Glow/snek-img-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/components/common/Layout/Glow/snek-img-1.png -------------------------------------------------------------------------------- /src/components/common/Layout/Glow/snek-img-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/components/common/Layout/Glow/snek-img-2.png -------------------------------------------------------------------------------- /src/components/common/Layout/Header/Analytics/AnalyticTag/AnalyticTag.tsx: -------------------------------------------------------------------------------- 1 | import { Box } from '@ergolabs/ui-kit'; 2 | import { FC, ReactNode } from 'react'; 3 | 4 | interface AnalyticTag { 5 | className?: string; 6 | children?: ReactNode | ReactNode[] | string; 7 | } 8 | 9 | export const AnalyticTag: FC = ({ className, children }) => ( 10 | 17 | {children} 18 | 19 | ); 20 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/Analytics/AnalyticsSkeletonLoader/AnalyticsSkeletonLoader.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonLoader } from '../../../../../SkeletonLoader/SkeletonLoader.tsx'; 2 | 3 | export const AnalyticsSkeletonLoader = () => { 4 | return ; 5 | }; 6 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/BurgerMenu/ManualRefundModal/ManualRefundModal.tsx: -------------------------------------------------------------------------------- 1 | import { ModalRef } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { ManualRefundModalV2 } from './ManualRefundModalV2/ManualRefundModalV2'; 5 | 6 | export const ManualRefundModal: FC = ({ close }) => { 7 | return ; 8 | }; 9 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/ClaimSpfButton/ClaimSpfNotification/ClaimSpfNotification.less: -------------------------------------------------------------------------------- 1 | .ant-notification-topRightBackward { 2 | z-index: 10; 3 | top: 64px !important; 4 | margin-right: 16px; 5 | } 6 | 7 | .ant-notification-notice.claim-spf { 8 | width: 280px; 9 | height: 300px; 10 | padding: 0; 11 | border-radius: 16px; 12 | 13 | .ant-notification-notice-message { 14 | padding-right: 0; 15 | margin: 0; 16 | } 17 | 18 | .ant-notification-notice-btn { 19 | display: none; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/ConnectWallet/ConnectWallet.tsx: -------------------------------------------------------------------------------- 1 | import { ElementLocation, ElementName } from '@spectrumlabs/analytics'; 2 | import { FC } from 'react'; 3 | 4 | import { HeaderConnectWalletButton } from './HeaderConnectWalletButton/HeaderConnectWalletButton'; 5 | import { WalletInfoButton } from './WalletInfoButton/WalletInfoButton'; 6 | 7 | export const ConnectWallet: FC = () => { 8 | return ( 9 | 16 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/ConnectWallet/HeaderConnectWalletButton/HeaderConnectWalletButton.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | import { ConnectWalletButton } from '../../../../ConnectWalletButton/ConnectWalletButton'; 4 | 5 | export const HeaderConnectWalletButton = styled(ConnectWalletButton)` 6 | width: 175px; 7 | `; 8 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/ConnectWallet/WalletInfoButton/AddressTag/LoadingContent/LoadingContent.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, Spin } from '@ergolabs/ui-kit'; 2 | import { t } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | import { TagTypography } from '../TagTypography/TagTypography'; 6 | 7 | export const LoadingContent: FC = () => ( 8 | 9 | 10 | 14 | 15 | {t`Loading`} 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/ConnectWallet/WalletInfoButton/AddressTag/TagTypography/TagTypography.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@ergolabs/ui-kit'; 2 | import styled from 'styled-components'; 3 | 4 | export const TagTypography = styled(Typography.Body)` 5 | color: var(--spectrum-connect-wallet-address-tag-color) !important; 6 | font-size: 1rem !important; 7 | white-space: nowrap !important; 8 | `; 9 | -------------------------------------------------------------------------------- /src/components/common/Layout/Header/ConnectWallet/WalletInfoButton/BalanceView/BalanceView.tsx: -------------------------------------------------------------------------------- 1 | import { Typography } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | import styled from 'styled-components'; 4 | 5 | import { Currency } from '../../../../../../../common/models/Currency'; 6 | import { SensitiveContent } from '../../../../../../SensitiveContent/SensitiveContent.tsx'; 7 | 8 | export interface BalanceViewProps { 9 | readonly balance: Currency; 10 | readonly className?: string; 11 | } 12 | 13 | const _BalanceView: FC = ({ className, balance }) => ( 14 | 15 | 16 | {balance.toCurrencyString()} 17 | 18 | 19 | ); 20 | 21 | export const BalanceView = styled(_BalanceView)` 22 | font-size: 1rem !important; 23 | white-space: nowrap !important; 24 | `; 25 | -------------------------------------------------------------------------------- /src/components/common/TokenControl/AssetAmountInput/format.ts: -------------------------------------------------------------------------------- 1 | export function escapeRegExp(string: string): string { 2 | return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string 3 | } 4 | -------------------------------------------------------------------------------- /src/components/common/TokenControl/AssetSelect/AssetListModal/AssetListImportConfirmationTokenState/ImportTokenWarning/ImportTokenWarning.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, InfoCircleFilled } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | import styled from 'styled-components'; 5 | 6 | const StyledInfoCircleFilled = styled(InfoCircleFilled)` 7 | color: var(--spectrum-warning-color); 8 | font-size: 0.825rem; 9 | `; 10 | 11 | export const ImportTokenWarning: FC = () => ( 12 | 13 | 14 | 15 | 16 | 17 | {/* eslint-disable-next-line react/no-unescaped-entities */} 18 | This token doesn't appear on the active token list(s). Make sure this is 19 | the token that you want to trade. 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /src/components/common/TokenControl/AssetSelect/AssetListModal/AssetListSelectTokenState/AssetListGroupTitle/AssetListGroupTitle.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Typography } from '@ergolabs/ui-kit'; 2 | import { FC, PropsWithChildren } from 'react'; 3 | 4 | export const AssetListGroupTitle: FC< 5 | PropsWithChildren> 6 | > = ({ children }) => ( 7 | 8 | 9 | {children} 10 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /src/context/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AppicationSettingsContext'; 2 | export * from './AppLoadingContext'; 3 | -------------------------------------------------------------------------------- /src/gateway/api/assetBalance.ts: -------------------------------------------------------------------------------- 1 | import { publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { useObservable } from '../../common/hooks/useObservable'; 4 | import { Balance } from '../../common/models/Balance'; 5 | import { selectedNetwork$ } from '../common/network'; 6 | 7 | export const assetBalance$ = selectedNetwork$.pipe( 8 | switchMap((n) => n.assetBalance$), 9 | publishReplay(1), 10 | refCount(), 11 | ); 12 | 13 | export const useAssetsBalance = (): [Balance, boolean, Error] => 14 | useObservable(assetBalance$, [], new Balance([])); 15 | -------------------------------------------------------------------------------- /src/gateway/api/createPool.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../../applicationConfig'; 2 | import { useSelectedNetwork } from '../common/network'; 3 | 4 | export const useCreatePoolAvailable = (): boolean => { 5 | const [selectedNetwork] = useSelectedNetwork(); 6 | 7 | return applicationConfig.networksSettings[selectedNetwork.name] 8 | .isCreatePoolAvailable; 9 | }; 10 | -------------------------------------------------------------------------------- /src/gateway/api/explorer.ts: -------------------------------------------------------------------------------- 1 | import { 2 | from, 3 | interval, 4 | map, 5 | Observable, 6 | publishReplay, 7 | refCount, 8 | startWith, 9 | switchMap, 10 | } from 'rxjs'; 11 | 12 | import { explorer } from '../../services/explorer'; 13 | 14 | const UPDATE_TIME = 1000 * 10; 15 | 16 | // @ts-ignore 17 | export const ergoExplorerContext$: Observable<{ 18 | height: number; 19 | lastBlockId: string; 20 | }> = interval(UPDATE_TIME).pipe( 21 | startWith(undefined), 22 | switchMap(() => from(explorer.getNetworkContext())), 23 | map((ctx) => ctx), 24 | publishReplay(1), 25 | refCount(), 26 | ); 27 | -------------------------------------------------------------------------------- /src/gateway/api/getPoolChartData.ts: -------------------------------------------------------------------------------- 1 | import { Observable, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { AmmPool } from '../../common/models/AmmPool'; 4 | import { PoolChartData } from '../../common/models/PoolChartData'; 5 | import { PoolChartDataParams } from '../../network/common/PoolChartDataParams'; 6 | import { selectedNetwork$ } from '../common/network'; 7 | 8 | export const getPoolChartData = ( 9 | pool?: AmmPool, 10 | params?: PoolChartDataParams, 11 | ): Observable => 12 | selectedNetwork$.pipe( 13 | switchMap((n) => n.getPoolChartData(pool, params)), 14 | publishReplay(1), 15 | refCount(), 16 | ); 17 | -------------------------------------------------------------------------------- /src/gateway/api/hasNeedRefundOperations.ts: -------------------------------------------------------------------------------- 1 | import { Observable, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const hasNeedRefundOperations$: Observable = 6 | selectedNetwork$.pipe( 7 | switchMap((n) => n.hasNeedRefundOperations$), 8 | publishReplay(1), 9 | refCount(), 10 | ); 11 | -------------------------------------------------------------------------------- /src/gateway/api/locks.ts: -------------------------------------------------------------------------------- 1 | import { map, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const locks$ = selectedNetwork$.pipe( 6 | switchMap((network) => network.locks$), 7 | map((locks) => locks.filter((l) => l.active)), 8 | publishReplay(1), 9 | refCount(), 10 | ); 11 | -------------------------------------------------------------------------------- /src/gateway/api/networkAsset.ts: -------------------------------------------------------------------------------- 1 | import { map, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { useObservable } from '../../common/hooks/useObservable'; 4 | import { AssetInfo } from '../../common/models/AssetInfo'; 5 | import { selectedNetwork, selectedNetwork$ } from '../common/network'; 6 | 7 | export const networkAsset$ = selectedNetwork$.pipe( 8 | map((n) => n.networkAsset), 9 | publishReplay(1), 10 | refCount(), 11 | ); 12 | 13 | export const useNetworkAsset = (): [AssetInfo, boolean, Error] => 14 | useObservable(networkAsset$, [], selectedNetwork.networkAsset); 15 | -------------------------------------------------------------------------------- /src/gateway/api/networkAssetBalance.ts: -------------------------------------------------------------------------------- 1 | import { publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const networkAssetBalance$ = selectedNetwork$.pipe( 6 | switchMap((network) => network.networkAssetBalance$), 7 | publishReplay(1), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/api/networkContext.ts: -------------------------------------------------------------------------------- 1 | import { publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const networkContext$ = selectedNetwork$.pipe( 6 | switchMap((n) => n.networkContext$), 7 | publishReplay(1), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/api/operations/createPool.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, switchMap } from 'rxjs'; 2 | 3 | import { TxId } from '../../../common/types'; 4 | import { CreatePoolFormModel } from '../../../pages/CreatePool/CreatePoolFormModel'; 5 | import { selectedNetwork$ } from '../../common/network'; 6 | 7 | export const createPool = ( 8 | data: Required, 9 | ): Observable => 10 | selectedNetwork$.pipe( 11 | first(), 12 | switchMap((n) => n.createPool(data)), 13 | ); 14 | -------------------------------------------------------------------------------- /src/gateway/api/operations/deposit.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, switchMap } from 'rxjs'; 2 | 3 | import { TxId } from '../../../common/types'; 4 | import { AddLiquidityFormModel } from '../../../components/AddLiquidityForm/AddLiquidityFormModel'; 5 | import { selectedNetwork$ } from '../../common/network'; 6 | 7 | export const deposit = ( 8 | data: Required, 9 | withoutConfirmation?: boolean, 10 | ): Observable => 11 | selectedNetwork$.pipe( 12 | first(), 13 | switchMap((n) => n.deposit(data, withoutConfirmation)), 14 | ); 15 | -------------------------------------------------------------------------------- /src/gateway/api/operations/lmDeposit.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | import { first, Observable, switchMap } from 'rxjs'; 3 | 4 | import { Farm } from '../../../common/models/Farm'; 5 | import { TxId } from '../../../common/types'; 6 | import { selectedNetwork$ } from '../../common/network'; 7 | 8 | export const lmDeposit = ( 9 | farm: Farm, 10 | createFarmModal: ( 11 | children?: ReactNode | ReactNode[] | string, 12 | ) => ReactNode | ReactNode[] | string, 13 | ): Observable => 14 | selectedNetwork$.pipe( 15 | first(), 16 | switchMap((n) => n.lmDeposit(farm, createFarmModal)), 17 | ); 18 | -------------------------------------------------------------------------------- /src/gateway/api/operations/lmRedeem.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | import { first, Observable, switchMap } from 'rxjs'; 3 | 4 | import { Farm } from '../../../common/models/Farm'; 5 | import { TxId } from '../../../common/types'; 6 | import { selectedNetwork$ } from '../../common/network'; 7 | 8 | export const lmRedeem = ( 9 | farm: Farm, 10 | createFarmModal: ( 11 | children?: ReactNode | ReactNode[] | string, 12 | ) => ReactNode | ReactNode[] | string, 13 | ): Observable => 14 | selectedNetwork$.pipe( 15 | first(), 16 | switchMap((n) => n.lmRedeem(farm, createFarmModal)), 17 | ); 18 | -------------------------------------------------------------------------------- /src/gateway/api/operations/redeem.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, switchMap } from 'rxjs'; 2 | 3 | import { AmmPool } from '../../../common/models/AmmPool'; 4 | import { TxId } from '../../../common/types'; 5 | import { RemoveLiquidityFormModel } from '../../../pages/RemoveLiquidity/RemoveLiquidityFormModel'; 6 | import { selectedNetwork$ } from '../../common/network'; 7 | 8 | export const redeem = ( 9 | pool: AmmPool, 10 | data: Required, 11 | withoutConfirmation?: boolean, 12 | ): Observable => 13 | selectedNetwork$.pipe( 14 | first(), 15 | switchMap((n) => n.redeem(pool, data, withoutConfirmation)), 16 | ); 17 | -------------------------------------------------------------------------------- /src/gateway/api/operations/refund.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, switchMap } from 'rxjs'; 2 | 3 | import { Currency } from '../../../common/models/Currency'; 4 | import { TxId } from '../../../common/types'; 5 | import { selectedNetwork$ } from '../../common/network'; 6 | 7 | export const refund = ( 8 | txId: TxId, 9 | xAmount: Currency, 10 | yAmount: Currency, 11 | manual = false, 12 | ): Observable => 13 | selectedNetwork$.pipe( 14 | first(), 15 | switchMap((n) => n.refund(txId, xAmount, yAmount, manual)), 16 | ); 17 | -------------------------------------------------------------------------------- /src/gateway/api/operations/swap.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, switchMap } from 'rxjs'; 2 | 3 | import { TxId } from '../../../common/types'; 4 | import { SwapFormModel } from '../../../pages/Swap/SwapFormModel'; 5 | import { selectedNetwork$ } from '../../common/network'; 6 | 7 | export const swap = (data: Required): Observable => 8 | selectedNetwork$.pipe( 9 | first(), 10 | switchMap((n) => n.swap(data)), 11 | ); 12 | -------------------------------------------------------------------------------- /src/gateway/api/pendingOperations.ts: -------------------------------------------------------------------------------- 1 | import { publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const pendingOperationsCount$ = selectedNetwork$.pipe( 6 | switchMap((n) => n.pendingOperationsCount$), 7 | publishReplay(1), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/api/platformStats.ts: -------------------------------------------------------------------------------- 1 | import { Observable, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { PlatformStats } from '../../network/common/PlatformStats'; 4 | import { selectedNetwork$ } from '../common/network'; 5 | 6 | export const platformStats$: Observable = selectedNetwork$.pipe( 7 | switchMap((n) => n.platformStats$), 8 | publishReplay(1), 9 | refCount(), 10 | ); 11 | -------------------------------------------------------------------------------- /src/gateway/api/queuedOperation.ts: -------------------------------------------------------------------------------- 1 | import { publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const queuedOperation$ = selectedNetwork$.pipe( 6 | switchMap((n) => n.queuedOperation$), 7 | publishReplay(1), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/api/supportedFeatures.ts: -------------------------------------------------------------------------------- 1 | import { publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const supportedFeatures$ = selectedNetwork$.pipe( 6 | switchMap((network) => network.supportedFeatures$), 7 | publishReplay(1), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/api/transactionsHistory.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { OperationItem } from '../../common/models/OperationV2'; 4 | import { selectedNetwork$ } from '../common/network'; 5 | 6 | export const getOperations = ( 7 | limit: number, 8 | offset: number, 9 | ): Observable<[OperationItem[], number]> => 10 | selectedNetwork$.pipe( 11 | first(), 12 | switchMap((n) => n.getOperations(limit, offset)), 13 | publishReplay(), 14 | refCount(), 15 | ); 16 | 17 | export const getOperationByTxId = ( 18 | txId: string, 19 | ): Observable => 20 | selectedNetwork$.pipe( 21 | first(), 22 | switchMap((network) => network.getOperationByTxId(txId)), 23 | ); 24 | -------------------------------------------------------------------------------- /src/gateway/api/useHandleCreatePoolMaxButtonClick.ts: -------------------------------------------------------------------------------- 1 | import { FormGroup } from '@ergolabs/ui-kit'; 2 | 3 | import { Balance } from '../../common/models/Balance'; 4 | import { CreatePoolFormModel } from '../../pages/CreatePool/CreatePoolFormModel'; 5 | import { useSelectedNetwork } from '../common/network'; 6 | 7 | export const useHandleCreatePoolMaxButtonClick = (): (( 8 | pct: number, 9 | form: FormGroup, 10 | balance: Balance, 11 | ) => void) => { 12 | const [selectedNetwork] = useSelectedNetwork(); 13 | 14 | return selectedNetwork.useHandleCreatePoolMaxButtonClick(); 15 | }; 16 | -------------------------------------------------------------------------------- /src/gateway/api/useHandleDepositMaxButtonClick.ts: -------------------------------------------------------------------------------- 1 | import { Balance } from '../../common/models/Balance'; 2 | import { Currency } from '../../common/models/Currency'; 3 | import { AddLiquidityFormModel } from '../../components/AddLiquidityForm/AddLiquidityFormModel'; 4 | import { useSelectedNetwork } from '../common/network'; 5 | 6 | export const useHandleDepositMaxButtonClick = (): (( 7 | pct: number, 8 | value: AddLiquidityFormModel, 9 | balance: Balance, 10 | ) => [Currency, Currency]) => { 11 | const [selectedNetwork] = useSelectedNetwork(); 12 | 13 | return selectedNetwork.useHandleDepositMaxButtonClick(); 14 | }; 15 | -------------------------------------------------------------------------------- /src/gateway/api/useHandleSwapMaxButtonClick.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../../common/models/Currency'; 2 | import { useSelectedNetwork } from '../common/network'; 3 | 4 | export const useHandleSwapMaxButtonClick = (): (( 5 | balance: Currency, 6 | ) => Currency) => { 7 | const [selectedNetwork] = useSelectedNetwork(); 8 | 9 | return selectedNetwork.useHandleSwapMaxButtonClick(); 10 | }; 11 | -------------------------------------------------------------------------------- /src/gateway/settings/settings.ts: -------------------------------------------------------------------------------- 1 | import { first, Observable, publishReplay, refCount, switchMap } from 'rxjs'; 2 | 3 | import { useObservable } from '../../common/hooks/useObservable'; 4 | import { BaseNetworkSettings } from '../../network/common/NetworkSettings'; 5 | import { selectedNetwork, selectedNetwork$ } from '../common/network'; 6 | 7 | export const settings$: Observable = selectedNetwork$.pipe( 8 | switchMap((n) => n.settings$), 9 | publishReplay(), 10 | refCount(), 11 | ); 12 | 13 | export const setSettings = (settings: BaseNetworkSettings): void => { 14 | selectedNetwork$.pipe(first()).subscribe((n) => n.setSettings(settings)); 15 | }; 16 | 17 | export const useSettings = (): BaseNetworkSettings => { 18 | const [settings] = useObservable(settings$, [], selectedNetwork.settings); 19 | 20 | return settings; 21 | }; 22 | -------------------------------------------------------------------------------- /src/gateway/utils/exploreAddress.ts: -------------------------------------------------------------------------------- 1 | import { first } from 'rxjs'; 2 | 3 | import { AssetInfo } from '../../common/models/AssetInfo'; 4 | import { Address, TxId } from '../../common/types'; 5 | import { selectedNetwork$ } from '../common/network'; 6 | 7 | export const exploreAddress = (address: Address): void => { 8 | selectedNetwork$.pipe(first()).subscribe((n) => n.exploreAddress(address)); 9 | }; 10 | 11 | export const exploreTx = (txId: TxId): void => { 12 | selectedNetwork$.pipe(first()).subscribe((n) => n.exploreTx(txId)); 13 | }; 14 | 15 | export const exploreLastBlock = (lastBlockId: number): void => { 16 | selectedNetwork$ 17 | .pipe(first()) 18 | .subscribe((n) => n.exploreLastBlock(lastBlockId)); 19 | }; 20 | 21 | export const exploreToken = (asset: AssetInfo): void => { 22 | selectedNetwork$.pipe(first()).subscribe((n) => n.exploreToken(asset)); 23 | }; 24 | -------------------------------------------------------------------------------- /src/gateway/widgets/operationsSettings.ts: -------------------------------------------------------------------------------- 1 | import { map, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const operationsSettings$ = selectedNetwork$.pipe( 6 | map((n) => n.OperationsSettings), 7 | publishReplay(), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/widgets/refundConfirmationInfo.ts: -------------------------------------------------------------------------------- 1 | import { map, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { selectedNetwork$ } from '../common/network'; 4 | 5 | export const refundConfirmationInfo$ = selectedNetwork$.pipe( 6 | map((n) => n.RefundConfirmationInfo), 7 | publishReplay(), 8 | refCount(), 9 | ); 10 | -------------------------------------------------------------------------------- /src/gateway/widgets/swapCallapse.ts: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | import { map, Observable, publishReplay, refCount } from 'rxjs'; 3 | 4 | import { SwapFormModel } from '../../pages/Swap/SwapFormModel'; 5 | import { selectedNetwork$ } from '../common/network'; 6 | 7 | export const swapCollapse$: Observable> = 8 | selectedNetwork$.pipe( 9 | map((n) => n.SwapCollapse), 10 | publishReplay(), 11 | refCount(), 12 | ); 13 | -------------------------------------------------------------------------------- /src/hooks/useBodyClass.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | const addBodyClass = (className: string) => 4 | document.body.classList.add(className); 5 | const removeBodyClass = (className: string) => 6 | document.body.classList.remove(className); 7 | 8 | export const useBodyClass = (className: string | Array): void => { 9 | useEffect(() => { 10 | className instanceof Array 11 | ? className.map(addBodyClass) 12 | : addBodyClass(className); 13 | 14 | return () => { 15 | className instanceof Array 16 | ? className.map(removeBodyClass) 17 | : removeBodyClass(className); 18 | }; 19 | }, [className]); 20 | }; 21 | -------------------------------------------------------------------------------- /src/hooks/useGuard.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useGuard = ( 4 | item: T, 5 | loading: boolean, 6 | hook: () => void, 7 | ): void => { 8 | useEffect(() => { 9 | if (!item && !loading) { 10 | hook(); 11 | } 12 | }, [item, loading]); 13 | }; 14 | 15 | export const useGuardV2 = (check: () => boolean, hook: () => void): void => { 16 | useEffect(() => { 17 | if (check()) { 18 | hook(); 19 | } 20 | }, [check]); 21 | }; 22 | -------------------------------------------------------------------------------- /src/hooks/useInterval.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from 'react'; 2 | 3 | export const useInterval = (callback: () => void, delay?: number): void => { 4 | const savedCallback = useRef(callback); 5 | 6 | useEffect(() => { 7 | savedCallback.current = callback; 8 | }, [callback]); 9 | 10 | useEffect(() => { 11 | if (delay === undefined) { 12 | return; 13 | } 14 | 15 | const id = setInterval(() => savedCallback.current(), delay); 16 | 17 | return () => clearInterval(id); 18 | }, [delay]); 19 | }; 20 | -------------------------------------------------------------------------------- /src/hooks/useMetaThemeColor.ts: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | export const useMetaThemeColor = ( 4 | config: { [P in K]: string }, 5 | theme: K, 6 | ): void => { 7 | useEffect(() => { 8 | document.documentElement 9 | .querySelector('meta[name="theme-color"]') 10 | ?.setAttribute('content', config[theme]); 11 | }, [theme]); 12 | }; 13 | -------------------------------------------------------------------------------- /src/hooks/useQuery.ts: -------------------------------------------------------------------------------- 1 | import { parse, ParsedQs } from 'qs'; 2 | import { useMemo } from 'react'; 3 | import { useLocation } from 'react-router-dom'; 4 | 5 | export function parsedQueryString(search?: string): ParsedQs { 6 | if (!search) { 7 | // react-router-dom places search string in the hash 8 | const hash = window.location.hash; 9 | search = hash.substr(hash.indexOf('?')); 10 | } 11 | 12 | return search && search.length > 1 13 | ? parse(search, { parseArrays: false, ignoreQueryPrefix: true }) 14 | : {}; 15 | } 16 | 17 | export const useQuery = (): ParsedQs => { 18 | const { search } = useLocation(); 19 | return useMemo(() => parsedQueryString(search), [search]); 20 | }; 21 | -------------------------------------------------------------------------------- /src/i18n/README.MD: -------------------------------------------------------------------------------- 1 | ## How to contribute to translations 2 | 3 | We use [Crowding](https://crowdin.com/project/ergodex-frontend) platform where any user can take a part in interface translation. 4 | Localization bot checks for new translations every hour and update them automatically. 5 | To contribute: 6 | 1. Go to [ErgoDEX Crowding Project](https://crowdin.com/project/ergodex-frontend); 7 | 2. Select a language; 8 | 3. Begin to translate. 9 | -------------------------------------------------------------------------------- /src/mappers/varifiedTokensMapper.ts: -------------------------------------------------------------------------------- 1 | export const VERIFIED_TOKENS = new Map([ 2 | ['0000000000000000000000000000000000000000000000000000000000000000', 'ERG'], 3 | [ 4 | '03faf2cb329f2e90d6d23b58d91bbb6c046aa143261cc21f52fbe2824bfcbf04', 5 | 'SigUSD', 6 | ], 7 | [ 8 | '003bd19d0187117f130b62e1bcab0939929ff5c7709f843c5c4dd158949285d0', 9 | 'SigRSV', 10 | ], 11 | [ 12 | 'fbbaac7337d051c10fc3da0ccb864f4d32d40027551e1c3ea3ce361f39b91e40', 13 | 'kushti', 14 | ], 15 | [ 16 | '36aba4b4a97b65be491cf9f5ca57b5408b0da8d0194f30ec8330d1e8946161c1', 17 | 'Erdoge', 18 | ], 19 | [ 20 | 'd71693c49a84fbbecd4908c94813b46514b18b67a99952dc1e6e4791556de413', 21 | 'ergopad', 22 | ], 23 | [ 24 | '5a34d53ca483924b9a6aa0c771f11888881b516a8d1a9cdc535d063fe26d065e', 25 | 'LunaDog', 26 | ], 27 | ['472c3d4ecaa08fb7392ff041ee2e6af75f4a558810a74b28600549d5392810e8', 'NETA'], 28 | ]); 29 | -------------------------------------------------------------------------------- /src/mocks/asset.ts: -------------------------------------------------------------------------------- 1 | import { AssetAmount, AssetInfo } from '@ergolabs/ergo-sdk'; 2 | 3 | import { Currency } from '../common/models/Currency'; 4 | 5 | const mockAmount = 111n; 6 | 7 | const mockAssetInfo: AssetInfo = { 8 | name: 'ERG', 9 | decimals: 9, 10 | id: '0000000000000000000', 11 | }; 12 | 13 | export const mockAsset = new AssetAmount(mockAssetInfo, mockAmount); 14 | 15 | export const mockCurrency = new Currency(mockAmount, mockAssetInfo); 16 | -------------------------------------------------------------------------------- /src/mocks/pool.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool as BaseAmmPool } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { mockAsset } from './asset'; 4 | 5 | export const basePoolMock = new BaseAmmPool( 6 | '9916d75132593c8b07fe18bd8d583bda1652eed7565cf41a4738ddd90fc992ec', 7 | mockAsset, 8 | mockAsset, 9 | mockAsset, 10 | 995, 11 | ); 12 | -------------------------------------------------------------------------------- /src/network/cardano/api/adaRatio/adaRatio.ts: -------------------------------------------------------------------------------- 1 | import { map, Observable, of, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { Ratio } from '../../../../common/models/Ratio'; 4 | import { AssetGraph } from '../../../../common/services/AssetGraph'; 5 | import { makeCurrencyConverter } from '../../../../common/services/CurrencyConverter'; 6 | import { ammPools$ } from '../ammPools/ammPools'; 7 | import { networkAsset } from '../networkAsset/networkAsset'; 8 | 9 | export interface OracleData { 10 | readonly latest_price: number; 11 | } 12 | 13 | export const adaRatio$: Observable = of( 14 | new Ratio('1', networkAsset, networkAsset), 15 | ); 16 | 17 | const assetGraph$ = ammPools$.pipe( 18 | map(AssetGraph.fromPools), 19 | publishReplay(1), 20 | refCount(), 21 | ); 22 | 23 | export const convertToConvenientNetworkAsset = makeCurrencyConverter( 24 | assetGraph$, 25 | adaRatio$, 26 | networkAsset, 27 | ); 28 | -------------------------------------------------------------------------------- /src/network/cardano/api/ammPools/utils.ts: -------------------------------------------------------------------------------- 1 | export const a = 1; 2 | -------------------------------------------------------------------------------- /src/network/cardano/api/balance/networkAssetBalance.ts: -------------------------------------------------------------------------------- 1 | import { map, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { Currency } from '../../../../common/models/Currency'; 4 | import { networkAsset } from '../networkAsset/networkAsset'; 5 | import { balanceItemsWithUndefined$ } from './balance'; 6 | 7 | export const networkAssetBalance$ = balanceItemsWithUndefined$.pipe( 8 | map((balance) => { 9 | if (!balance) { 10 | return undefined as any; 11 | } 12 | const adaBalanceItem = balance.find(([, info]) => info === networkAsset); 13 | 14 | return new Currency(adaBalanceItem?.[0] || 0n, networkAsset); 15 | }), 16 | publishReplay(1), 17 | refCount(), 18 | ); 19 | -------------------------------------------------------------------------------- /src/network/cardano/api/common/cardanoWasm.ts: -------------------------------------------------------------------------------- 1 | import { 2 | CardanoWasm, 3 | RustModule, 4 | } from '@spectrumlabs/cardano-dex-sdk/build/main/utils/rustLoader'; 5 | import { from, Observable, publishReplay, refCount } from 'rxjs'; 6 | 7 | export const cardanoWasm$: Observable = from( 8 | RustModule.load(), 9 | ).pipe(publishReplay(1), refCount()); 10 | -------------------------------------------------------------------------------- /src/network/cardano/api/common/defaultTokenList.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../../../../applicationConfig'; 2 | import { getDefaultTokenList } from '../../../../common/services/DefaultTokenList'; 3 | import { cardanoNetworkData } from '../../utils/cardanoNetworkData.ts'; 4 | 5 | export interface DefaultTokenListItem { 6 | readonly policyId: string; 7 | readonly subject: string; 8 | readonly description: string; 9 | readonly url: string; 10 | readonly name: string; 11 | readonly ticker: string; 12 | readonly decimals: number; 13 | readonly _logo?: string; 14 | readonly logo?: string; 15 | } 16 | 17 | export const defaultTokenList$ = getDefaultTokenList( 18 | applicationConfig.networksSettings.cardano.defaultTokenListUrl, 19 | (item) => { 20 | return item.subject; 21 | }, 22 | cardanoNetworkData.additionalTokenList, 23 | ); 24 | -------------------------------------------------------------------------------- /src/network/cardano/api/const.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../../../common/models/Currency.ts'; 2 | import { networkAsset } from './networkAsset/networkAsset.ts'; 3 | 4 | export const COLLATERAL_AMOUNT = new Currency('2', networkAsset); 5 | -------------------------------------------------------------------------------- /src/network/cardano/api/lbspWhitelist/lbspWhitelist.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { from, map, Observable, publishReplay, refCount } from 'rxjs'; 3 | 4 | import { applicationConfig } from '../../../../applicationConfig.ts'; 5 | import { PoolId } from '../../../../common/types.ts'; 6 | 7 | export const lbspWhitelist$: Observable = from( 8 | axios.get(applicationConfig.networksSettings.cardano.lbspWhitelistUrl), 9 | ).pipe( 10 | map((res) => res.data.data), 11 | publishReplay(1), 12 | refCount(), 13 | ); 14 | 15 | export const isLbspPool = (poolId: PoolId): Observable => 16 | lbspWhitelist$.pipe( 17 | map((lbspPools) => lbspPools.includes(poolId)), 18 | publishReplay(1), 19 | refCount(), 20 | ); 21 | -------------------------------------------------------------------------------- /src/network/cardano/api/networkAsset/networkAsset.ts: -------------------------------------------------------------------------------- 1 | import { AdaAssetClass } from '@spectrumlabs/cardano-dex-sdk'; 2 | import { Observable, of, publishReplay, refCount } from 'rxjs'; 3 | 4 | import { useObservable } from '../../../../common/hooks/useObservable'; 5 | import { AssetInfo } from '../../../../common/models/AssetInfo'; 6 | 7 | const ADA_ID = 'token-ada'; 8 | const ADA_DECIMALS = 6; 9 | 10 | export const networkAsset = { 11 | name: 'ADA', 12 | ticker: 'ADA', 13 | id: ADA_ID, 14 | decimals: ADA_DECIMALS, 15 | data: AdaAssetClass, 16 | icon: '/token-ada.svg', 17 | }; 18 | 19 | export const networkAsset$: Observable = of(networkAsset).pipe( 20 | publishReplay(1), 21 | refCount(), 22 | ); 23 | 24 | export const useNetworkAsset = (): [AssetInfo, boolean, Error | undefined] => 25 | useObservable(networkAsset$, [], networkAsset); 26 | -------------------------------------------------------------------------------- /src/network/cardano/api/networkContext/networkContext.ts: -------------------------------------------------------------------------------- 1 | import { 2 | from, 3 | map, 4 | Observable, 5 | publishReplay, 6 | refCount, 7 | switchMap, 8 | } from 'rxjs'; 9 | 10 | import { appTick$ } from '../../../../common/streams/appTick'; 11 | import { cardanoNetwork } from '../common/cardanoNetwork'; 12 | 13 | export const networkContext$: Observable<{ 14 | readonly height: number; 15 | readonly lastBlockId: number; 16 | readonly blockHash: string; 17 | readonly slotNo: bigint; 18 | }> = appTick$.pipe( 19 | switchMap(() => from(cardanoNetwork.getNetworkContext())), 20 | map((ctx) => ({ 21 | height: Number(ctx.blockNo), 22 | lastBlockId: Number(ctx.blockNo), 23 | blockHash: (ctx as any).blockHash, 24 | slotNo: BigInt((ctx as any).slotNo), 25 | })), 26 | // distinctUntilKeyChanged('height'), 27 | publishReplay(1), 28 | refCount(), 29 | ); 30 | -------------------------------------------------------------------------------- /src/network/cardano/api/operations/common/ammTxFeeMapping.ts: -------------------------------------------------------------------------------- 1 | import { AmmTxFeeMapping } from '@spectrumlabs/cardano-dex-sdk'; 2 | 3 | export const ammTxFeeMapping: AmmTxFeeMapping = { 4 | swapOrder: 500000n, 5 | depositOrder: 500000n, 6 | redeemOrder: 500000n, 7 | swapExecution: 500000n, 8 | depositExecution: 500000n, 9 | redeemExecution: 500000n, 10 | poolCreation: 2000000n, 11 | lockOrder: 500000n, 12 | }; 13 | -------------------------------------------------------------------------------- /src/network/cardano/api/operations/common/minExecutorReward.ts: -------------------------------------------------------------------------------- 1 | export const minExecutorReward = 1000000n; 2 | -------------------------------------------------------------------------------- /src/network/cardano/api/rewards/utils.ts: -------------------------------------------------------------------------------- 1 | export class ClaimNotAvailableError extends Error {} 2 | -------------------------------------------------------------------------------- /src/network/cardano/api/transactionHistory/types/OperationItem.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AddLiquidityItem, 3 | RemoveLiquidityItem, 4 | SwapItem, 5 | } from '../../../../../common/models/OperationV2'; 6 | import { RawAddLiquidityItem } from './AddLiquidityOperation'; 7 | import { RawRemoveLiquidityItem } from './RemoveLiquidityOperation'; 8 | import { RawSwapItem } from './SwapOperation'; 9 | 10 | export type RawOperationItem = 11 | | RawSwapItem 12 | | RawAddLiquidityItem 13 | | RawRemoveLiquidityItem; 14 | 15 | export type OperationItem = SwapItem | AddLiquidityItem | RemoveLiquidityItem; 16 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/common/AdditionalData.ts: -------------------------------------------------------------------------------- 1 | import { Wallet } from '../../../../common/Wallet'; 2 | 3 | export type AdditionalData = Wallet; 4 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/connectedWalletChange.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | import { AdditionalData } from './common/AdditionalData'; 4 | import { Wallet } from './common/Wallet'; 5 | import { selectedWallet$ } from './wallet'; 6 | 7 | export const connectedWalletChange$: Observable< 8 | Wallet | undefined 9 | > = selectedWallet$; 10 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/consts.ts: -------------------------------------------------------------------------------- 1 | export const CONNECTOR_NAME_WALLET_CONNECT = 'walletconnect'; 2 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/eternl/eternl.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import EternlLogo from './eternl-icon.svg'; 4 | 5 | export const Eternl = createWallet({ 6 | id: 'Eternl', 7 | getConnector: () => cardano.eternl, 8 | name: 'Eternl', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/eternlcc/kmhcihpebfmpgmihbkipmjlmmioameka', 11 | icon: Eternl Logo, 12 | previewIcon: ( 13 | Eternl Logo 14 | ), 15 | walletSupportedFeatures: { createPool: false }, 16 | definition: 'default', 17 | }); 18 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/exodus/exodus.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import ExodusLogo from './exodus-icon.svg'; 4 | 5 | export const Exodus = createWallet({ 6 | id: 'Exodus', 7 | getConnector: () => cardano.exodus, 8 | name: 'Exodus', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/exodus-web3-wallet/aholpfdialjgjfhomihkjbmgjidlcdno', 11 | icon: Exodus Logo, 12 | previewIcon: ( 13 | Exodus Logo 14 | ), 15 | walletSupportedFeatures: { createPool: false }, 16 | definition: 'default', 17 | }); 18 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/flint/flint.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import { ReactComponent as FlintLogo } from './flint-icon.svg'; 4 | 5 | export const Flint = createWallet({ 6 | id: 'Flint', 7 | getConnector: () => cardano.flint, 8 | name: 'Flint', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/flint-wallet/hnhobjmcibchnmglfbldbfabcgaknlkj?hl=en', 11 | walletSupportedFeatures: { createPool: false }, 12 | icon: , 13 | previewIcon: , 14 | definition: 'default', 15 | }); 16 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/gero/gero.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import GeroLogo from './gerowallet-icon.svg'; 4 | 5 | export const Gero = createWallet({ 6 | id: 'Gero', 7 | name: 'Gero', 8 | getConnector: () => cardano.gerowallet, 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/gerowallet/bgpipimickeadkjlklgciifhnalhdjhe/overview', 11 | icon: Gero Logo, 12 | previewIcon: Gero Logo, 13 | walletSupportedFeatures: { createPool: false }, 14 | definition: 'default', 15 | }); 16 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/lace/lace.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import LaceLogo from './lace-icon.svg'; 4 | 5 | export const Lace = createWallet({ 6 | id: 'Lace', 7 | getConnector: () => cardano.lace, 8 | name: 'Lace', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/lace/gafhhkghbfjjkeiendhlofajokpaflmk', 11 | icon: Lace Logo, 12 | previewIcon: Lace Logo, 13 | walletSupportedFeatures: { createPool: false }, 14 | definition: 'default', 15 | }); 16 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/nami/nami.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import NamiLogo from './nami-icon.svg'; 4 | 5 | export const Nami = createWallet({ 6 | id: 'Nami', 7 | getConnector: () => cardano.nami, 8 | name: 'Nami', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/nami/lpfcbjknijpeeillifnkikgncikgfhdo?hl=en', 11 | icon: Nami Logo, 12 | previewIcon: Nami Logo, 13 | walletSupportedFeatures: { createPool: false }, 14 | definition: 'default', 15 | }); 16 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/nufi/nufi.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import NufiLogo from './nufi-icon.svg'; 4 | 5 | export const Nufi = createWallet({ 6 | id: 'Nufi', 7 | getConnector: () => cardano.nufi, 8 | name: 'Nufi', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/nufi/gpnihlnnodeiiaakbikldcihojploeca?hl=en', 11 | icon: Nufi Logo, 12 | previewIcon: Nufi Logo, 13 | walletSupportedFeatures: { createPool: false }, 14 | definition: 'default', 15 | }); 16 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/typhon/typhon.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import TyphonLogo from './typhon-icon.svg'; 4 | 5 | export const Typhon = createWallet({ 6 | id: 'Typhon', 7 | getConnector: () => cardano.typhoncip30, 8 | name: 'Typhon', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/typhon-wallet/kfdniefadaanbjodldohaedphafoffoh', 11 | walletSupportedFeatures: { createPool: false }, 12 | icon: Typhon Logo, 13 | previewIcon: ( 14 | Typhon Logo 15 | ), 16 | definition: 'default', 17 | }); 18 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/vespr/vespr-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/walletConnect/wc-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/network/cardano/api/wallet/walletConnect/wc-logo.png -------------------------------------------------------------------------------- /src/network/cardano/api/wallet/yoroi/yoroi.tsx: -------------------------------------------------------------------------------- 1 | import { AdditionalData } from '../common/AdditionalData'; 2 | import { createWallet } from '../common/Wallet'; 3 | import YoroiLogo from './yoroi-icon.svg'; 4 | 5 | export const Yoroi = createWallet({ 6 | id: 'Yoroi', 7 | getConnector: () => cardano.yoroi, 8 | name: 'Yoroi', 9 | extensionLink: 10 | 'https://chrome.google.com/webstore/detail/yoroi/ffnbelfdoeiohenkjibnmadjiehjhajb', 11 | icon: Yoroi Logo, 12 | previewIcon: Yoroi Logo, 13 | walletSupportedFeatures: { createPool: false }, 14 | definition: 'default', 15 | }); 16 | -------------------------------------------------------------------------------- /src/network/cardano/components/FeesSkeletonLoading/FeesSkeletonLoading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from '@ergolabs/ui-kit'; 2 | 3 | export const FeesSkeletonLoading = () => ( 4 | 5 | ); 6 | -------------------------------------------------------------------------------- /src/network/cardano/components/RefundableDepositTooltipContent/RefundableDepositTooltipContent.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from '@lingui/macro'; 2 | 3 | const RefundableDepositTooltipContent = () => { 4 | return ( 5 | <> 6 | 7 | This amount of ADA will be held to build a transaction and will be 8 | returned when your order is executed or cancelled. 9 | 10 | 11 | ); 12 | }; 13 | 14 | export default RefundableDepositTooltipContent; 15 | -------------------------------------------------------------------------------- /src/network/cardano/initialized.ts: -------------------------------------------------------------------------------- 1 | import { RustModule } from '@spectrumlabs/cardano-dex-sdk/build/main/utils/rustLoader'; 2 | import { BehaviorSubject } from 'rxjs'; 3 | 4 | import { lbspWhitelist$ } from './api/lbspWhitelist/lbspWhitelist.ts'; 5 | import { initializeSettings } from './settings/settings'; 6 | 7 | export const initialized$ = new BehaviorSubject(false); 8 | 9 | export const initialize = (): void => { 10 | RustModule.load().then(() => { 11 | initializeSettings(); 12 | initialized$.next(true); 13 | lbspWhitelist$.subscribe(); 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /src/network/common/NetworkContext.ts: -------------------------------------------------------------------------------- 1 | export interface NetworkContext { 2 | readonly height: number; 3 | readonly lastBlockId: number; 4 | } 5 | -------------------------------------------------------------------------------- /src/network/common/NetworkUtils.ts: -------------------------------------------------------------------------------- 1 | import { AssetInfo } from '../../common/models/AssetInfo'; 2 | import { Address, TxId } from '../../common/types'; 3 | 4 | export interface NetworkUtils { 5 | exploreTx(txId: TxId): unknown; 6 | exploreToken(asset: AssetInfo): unknown; 7 | exploreAddress(address: Address): unknown; 8 | exploreLastBlock(lastBlockId: number): unknown; 9 | } 10 | -------------------------------------------------------------------------------- /src/network/common/NetworkWidgets.ts: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { AmmPool } from '../../common/models/AmmPool'; 4 | import { SwapFormModel } from '../../pages/Swap/SwapFormModel'; 5 | 6 | export interface NetworkWidgets

{ 7 | SwapCollapse: FC<{ value: SwapFormModel

}>; 8 | OperationsSettings: FC<{ hideNitro?: boolean; hideSlippage?: boolean }>; 9 | RefundConfirmationInfo?: FC; 10 | } 11 | -------------------------------------------------------------------------------- /src/network/common/PlatformStats.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../../common/models/Currency'; 2 | 3 | export interface PlatformStats { 4 | readonly tvl: Currency; 5 | readonly volume: Currency; 6 | } 7 | -------------------------------------------------------------------------------- /src/network/common/PoolChartDataParams.ts: -------------------------------------------------------------------------------- 1 | export interface PoolChartDataParams { 2 | from?: number; 3 | to?: number; 4 | resolution?: number; 5 | } 6 | -------------------------------------------------------------------------------- /src/network/common/SupportedFeatures.ts: -------------------------------------------------------------------------------- 1 | import { WalletSupportedFeatures } from './Wallet'; 2 | 3 | export type SupportedFeatures = WalletSupportedFeatures; 4 | -------------------------------------------------------------------------------- /src/network/common/Wallet.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | export interface WalletSupportedFeatures { 4 | createPool: boolean; 5 | } 6 | 7 | export type WalletDefinition = 'experimental' | 'recommended' | 'default'; 8 | 9 | export interface Wallet { 10 | readonly name: string; 11 | readonly icon: ReactNode; 12 | readonly previewIcon: ReactNode; 13 | readonly definition: WalletDefinition; 14 | readonly extensionLink?: string; 15 | readonly onConnect?: () => void; 16 | readonly onDisconnect?: () => void; 17 | readonly hidden?: boolean; 18 | readonly walletSupportedFeatures: WalletSupportedFeatures; 19 | } 20 | 21 | export enum WalletState { 22 | NOT_CONNECTED, 23 | CONNECTING, 24 | CONNECTED, 25 | } 26 | -------------------------------------------------------------------------------- /src/network/ergo/api/ammPools/utils.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AmmPool, 3 | makeNativePools, 4 | makeTokenPools, 5 | Pools, 6 | } from '@ergolabs/ergo-dex-sdk'; 7 | 8 | import { explorer } from '../../../../services/explorer'; 9 | 10 | export const networkPools = (() => { 11 | let networkPools: Pools; 12 | 13 | return (): Pools => { 14 | if (!networkPools) { 15 | networkPools = makeTokenPools(explorer); 16 | } 17 | 18 | return networkPools; 19 | }; 20 | })(); 21 | 22 | export const nativeNetworkPools = (() => { 23 | let networkPools: Pools; 24 | 25 | return (): Pools => { 26 | if (!networkPools) { 27 | networkPools = makeNativePools(explorer); 28 | } 29 | 30 | return networkPools; 31 | }; 32 | })(); 33 | -------------------------------------------------------------------------------- /src/network/ergo/api/balance/assetBalance.ts: -------------------------------------------------------------------------------- 1 | import { 2 | combineLatest, 3 | debounceTime, 4 | map, 5 | publishReplay, 6 | refCount, 7 | } from 'rxjs'; 8 | 9 | import { Balance } from '../../../../common/models/Balance'; 10 | import { ammPools$ } from '../ammPools/ammPools'; 11 | import { availableTokensData$ } from './common'; 12 | import { networkAssetBalance$ } from './networkAssetBalance'; 13 | 14 | export const assetBalance$ = combineLatest([ 15 | networkAssetBalance$, 16 | ammPools$, 17 | availableTokensData$, 18 | ]).pipe( 19 | debounceTime(100), 20 | map(([networkAssetBalance, pools, availableTokensData]) => 21 | availableTokensData 22 | .filter(([, info]) => !pools.some((p) => p.lp.asset.id === info.id)) 23 | .concat([[networkAssetBalance.amount, networkAssetBalance.asset]]), 24 | ), 25 | map((data) => new Balance(data)), 26 | publishReplay(1), 27 | refCount(), 28 | ); 29 | -------------------------------------------------------------------------------- /src/network/ergo/api/balance/assetInfoManager.ts: -------------------------------------------------------------------------------- 1 | import { AugAssetInfo } from '@ergolabs/ergo-sdk/build/main/network/models'; 2 | import { BehaviorSubject, from, Observable, tap } from 'rxjs'; 3 | 4 | import { explorer } from '../../../../services/explorer'; 5 | 6 | const mapIdToBs = new Map>(); 7 | 8 | export const getFullTokenInfo = ( 9 | assetId: string, 10 | ): Observable => { 11 | if (mapIdToBs.has(assetId)) { 12 | return mapIdToBs.get(assetId)!; 13 | } 14 | return from(explorer.getFullTokenInfo(assetId)).pipe( 15 | tap((assetInfo) => { 16 | mapIdToBs.set(assetId, new BehaviorSubject(assetInfo)); 17 | }), 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /src/network/ergo/api/balance/lpBalance.ts: -------------------------------------------------------------------------------- 1 | import { 2 | combineLatest, 3 | debounceTime, 4 | map, 5 | publishReplay, 6 | refCount, 7 | } from 'rxjs'; 8 | 9 | import { Balance } from '../../../../common/models/Balance'; 10 | import { allAmmPools$ } from '../ammPools/ammPools'; 11 | import { availableTokensData$ } from './common'; 12 | 13 | export const lpBalance$ = combineLatest([ 14 | allAmmPools$, 15 | availableTokensData$, 16 | ]).pipe( 17 | debounceTime(100), 18 | map(([pools, availableTokensData]) => 19 | availableTokensData.filter(([, info]) => 20 | pools.some((p) => p.lp.asset.id === info.id), 21 | ), 22 | ), 23 | map((data) => new Balance(data)), 24 | publishReplay(1), 25 | refCount(), 26 | ); 27 | -------------------------------------------------------------------------------- /src/network/ergo/api/common/AnalyticsData.ts: -------------------------------------------------------------------------------- 1 | export interface CurrencyInfo { 2 | id: string; 3 | decimals: number; 4 | } 5 | 6 | export interface Units { 7 | currency: CurrencyInfo; 8 | } 9 | 10 | export interface AnalyticsData { 11 | value: number; 12 | units: Units; 13 | } 14 | -------------------------------------------------------------------------------- /src/network/ergo/api/common/defaultTokenList.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../../../../applicationConfig'; 2 | import { getDefaultTokenList } from '../../../../common/services/DefaultTokenList'; 3 | import { uint } from '../../../../common/types'; 4 | 5 | export interface DefaultTokenListItem { 6 | readonly address: string; 7 | readonly decimals: uint; 8 | readonly name: string; 9 | readonly ticker: string; 10 | readonly logoURI?: string; 11 | } 12 | 13 | export const defaultTokenList$ = getDefaultTokenList( 14 | applicationConfig.networksSettings.ergo.defaultTokenListUrl, 15 | (item) => item.address, 16 | ); 17 | -------------------------------------------------------------------------------- /src/network/ergo/api/ergopay/getErgopayAddresses.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { exhaustMap, filter, first, interval, map, Observable } from 'rxjs'; 3 | 4 | import { applicationConfig } from '../../../../applicationConfig'; 5 | 6 | export const getErgopayAddresses = (requestId: string): Observable => 7 | interval(1000).pipe( 8 | exhaustMap(() => 9 | axios.get<{ addresses: string[]; success: boolean }>( 10 | `${applicationConfig.networksSettings.ergo.ergopayUrl}/addresses/${requestId}`, 11 | ), 12 | ), 13 | map((res) => res.data), 14 | filter((data) => data.success), 15 | first(), 16 | map((data) => data.addresses), 17 | ); 18 | -------------------------------------------------------------------------------- /src/network/ergo/api/ergopay/getErgopayRequestId.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { catchError, from, map, Observable, of } from 'rxjs'; 3 | 4 | import { applicationConfig } from '../../../../applicationConfig'; 5 | 6 | export const getErgopayRequestId = (): Observable => 7 | from( 8 | axios.post<{ requestId: string }>( 9 | `${applicationConfig.networksSettings.ergo.ergopayUrl}/addresses/requestId`, 10 | ), 11 | ).pipe( 12 | map(({ data }) => data.requestId), 13 | catchError(() => of('')), 14 | ); 15 | -------------------------------------------------------------------------------- /src/network/ergo/api/locks/locks.ts: -------------------------------------------------------------------------------- 1 | import { map, Observable, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { AssetLock } from '../../../../common/models/AssetLock'; 4 | import { positions$ } from '../positions/positions'; 5 | 6 | export const locks$: Observable = positions$.pipe( 7 | map((positions) => positions.flatMap((p) => p.locks)), 8 | publishReplay(1), 9 | refCount(), 10 | ); 11 | -------------------------------------------------------------------------------- /src/network/ergo/api/networkContext/networkContext.ts: -------------------------------------------------------------------------------- 1 | import { 2 | distinctUntilKeyChanged, 3 | from, 4 | map, 5 | mapTo, 6 | Observable, 7 | of, 8 | publishReplay, 9 | refCount, 10 | switchMap, 11 | timer, 12 | } from 'rxjs'; 13 | 14 | import { appTick$ } from '../../../../common/streams/appTick'; 15 | import { explorer } from '../../../../services/explorer'; 16 | 17 | //@ts-ignore 18 | export const networkContext$: Observable<{ 19 | readonly height: number; 20 | readonly lastBlockId: number; 21 | }> = appTick$.pipe( 22 | switchMap(() => from(explorer.getNetworkContext())), 23 | map((ctx) => ctx), 24 | distinctUntilKeyChanged('height'), 25 | switchMap((ctx, i) => (i === 0 ? of(ctx) : timer(2000).pipe(mapTo(ctx)))), 26 | publishReplay(1), 27 | refCount(), 28 | ); 29 | -------------------------------------------------------------------------------- /src/network/ergo/api/operations/common/toDexOperation.ts: -------------------------------------------------------------------------------- 1 | import { AmmDexOperation } from '@ergolabs/ergo-dex-sdk'; 2 | import { AugErgoTx } from '@ergolabs/ergo-sdk'; 3 | import { map, Observable, of } from 'rxjs'; 4 | 5 | import networkHistory from '../../../../../services/networkHistory'; 6 | import { getAddresses } from '../../addresses/addresses'; 7 | 8 | export const toDexOperation = ( 9 | tx: AugErgoTx | undefined, 10 | ): Observable => { 11 | if (!tx) { 12 | return of(undefined); 13 | } 14 | 15 | return getAddresses().pipe( 16 | map((addresses) => networkHistory['parseOp'](tx, true, addresses)), 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/network/ergo/api/operations/history/v2/types/OperationItem.ts: -------------------------------------------------------------------------------- 1 | import { RawAddLiquidityItem } from './AddLiquidityOperation'; 2 | import { RawLmDepositItem } from './LmDepositOperation'; 3 | import { RawLmRedeemItem } from './LmRedeemOperation'; 4 | import { RawLockItem } from './LockOperation'; 5 | import { RawRemoveLiquidityItem } from './RemoveLiquidityOperation'; 6 | import { RawSwapItem } from './SwapOperation'; 7 | 8 | export type RawOperationItem = 9 | | RawSwapItem 10 | | RawAddLiquidityItem 11 | | RawRemoveLiquidityItem 12 | | RawLmDepositItem 13 | | RawLmRedeemItem 14 | | RawLockItem; 15 | -------------------------------------------------------------------------------- /src/network/ergo/api/operations/history/workerMessages/workerBatchMessage.ts: -------------------------------------------------------------------------------- 1 | import { AmmDexOperation } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { Dictionary } from '../../../../../../common/utils/Dictionary'; 4 | 5 | export interface WorkerBatchMessageData { 6 | readonly address: string; 7 | readonly handledTxs: Dictionary; 8 | readonly operations: AmmDexOperation[]; 9 | } 10 | 11 | export interface WorkerBatchMessage { 12 | readonly message: 'batch'; 13 | readonly payload: WorkerBatchMessageData; 14 | } 15 | -------------------------------------------------------------------------------- /src/network/ergo/api/operations/history/workerMessages/workerStartMessage.ts: -------------------------------------------------------------------------------- 1 | import { AmmDexOperation } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { Dictionary } from '../../../../../../common/utils/Dictionary'; 4 | 5 | export interface WorkerStartMessageData { 6 | readonly addresses: string[]; 7 | readonly oldHandledTxs: Dictionary>; 8 | readonly oldOperations: Dictionary; 9 | } 10 | 11 | export interface WorkerStartMessage { 12 | readonly message: 'start'; 13 | readonly payload: WorkerStartMessageData; 14 | } 15 | -------------------------------------------------------------------------------- /src/network/ergo/api/operations/history/workerMessages/workerSyncEndMessage.ts: -------------------------------------------------------------------------------- 1 | interface WorkerSyncEndMessageData { 2 | success: boolean; 3 | } 4 | 5 | export interface WorkerSyncEndMessage { 6 | message: 'syncEnd'; 7 | payload: WorkerSyncEndMessageData; 8 | } 9 | -------------------------------------------------------------------------------- /src/network/ergo/api/spfFaucet/claimSpf.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { first, from, Observable, switchMap, tap } from 'rxjs'; 3 | 4 | import { applicationConfig } from '../../../../applicationConfig'; 5 | import { getAddresses } from '../addresses/addresses'; 6 | import { updateReward } from './spfReward'; 7 | import { updateStatus } from './spfStatus'; 8 | 9 | export const claimSpf = (): Observable => 10 | getAddresses().pipe( 11 | first(), 12 | switchMap((addresses) => 13 | from( 14 | axios.post( 15 | `${applicationConfig.networksSettings.ergo.spfFaucet}register`, 16 | { addresses }, 17 | ), 18 | ), 19 | ), 20 | tap(() => { 21 | updateStatus.next(); 22 | updateReward.next(); 23 | }), 24 | ); 25 | -------------------------------------------------------------------------------- /src/network/ergo/api/spfFaucet/common.ts: -------------------------------------------------------------------------------- 1 | import { 2 | interval, 3 | publishReplay, 4 | refCount, 5 | startWith, 6 | Subject, 7 | takeUntil, 8 | } from 'rxjs'; 9 | 10 | const stopPolling$ = new Subject(); 11 | 12 | export const pollingInterval$ = interval(60_000).pipe( 13 | startWith(0), 14 | takeUntil(stopPolling$), 15 | publishReplay(1), 16 | refCount(), 17 | ); 18 | 19 | export const stopPolling = (): void => { 20 | stopPolling$.next(); 21 | }; 22 | -------------------------------------------------------------------------------- /src/network/ergo/api/utxos/utxos.ts: -------------------------------------------------------------------------------- 1 | import { 2 | combineLatest, 3 | debounceTime, 4 | mapTo, 5 | of, 6 | publishReplay, 7 | refCount, 8 | switchMap, 9 | } from 'rxjs'; 10 | 11 | import { networkContext$ } from '../networkContext/networkContext'; 12 | import { mempoolRawOperations$ } from '../operations/history/v2/operationsHistory'; 13 | import { connectedWalletChange$ } from '../wallet/connectedWalletChange'; 14 | 15 | export const utxos$ = connectedWalletChange$.pipe( 16 | switchMap((selectedWallet) => 17 | combineLatest([mempoolRawOperations$, networkContext$]).pipe( 18 | debounceTime(100), 19 | mapTo(selectedWallet), 20 | ), 21 | ), 22 | switchMap((selectedWallet) => 23 | selectedWallet ? selectedWallet.getUtxos() : of([]), 24 | ), 25 | publishReplay(1), 26 | refCount(), 27 | ); 28 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/common/ErgoWalletContract.ts: -------------------------------------------------------------------------------- 1 | import { Address, ErgoBox, ErgoTx, Prover } from '@ergolabs/ergo-sdk'; 2 | import { ReactNode } from 'react'; 3 | import { Observable } from 'rxjs'; 4 | 5 | import { TxId } from '../../../../../common/types'; 6 | import { Wallet } from '../../../../common/Wallet'; 7 | 8 | export interface ErgoWalletContract extends Wallet, Prover { 9 | readonly getUsedAddresses: () => Observable; 10 | readonly getUnusedAddresses: () => Observable; 11 | readonly getChangeAddress: () => Observable

; 12 | readonly getAddresses: () => Observable; 13 | readonly connectWallet: () => Observable; 14 | readonly getUtxos: () => Observable; 15 | readonly submitTx: (tx: ErgoTx) => Observable; 16 | readonly hidden?: boolean; 17 | } 18 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/connectedWalletChange.ts: -------------------------------------------------------------------------------- 1 | import { 2 | filter, 3 | mapTo, 4 | Observable, 5 | of, 6 | publishReplay, 7 | refCount, 8 | switchMap, 9 | } from 'rxjs'; 10 | 11 | import { WalletState } from '../../../common/Wallet'; 12 | import { ErgoWalletContract } from './common/ErgoWalletContract'; 13 | import { selectedWallet$, walletState$ } from './wallet'; 14 | 15 | // TODO: RENAME 16 | export const connectedWalletChange$: Observable< 17 | ErgoWalletContract | undefined 18 | > = selectedWallet$.pipe( 19 | switchMap((selectedWallet) => { 20 | if (!selectedWallet) { 21 | return of(undefined); 22 | } 23 | 24 | return walletState$.pipe( 25 | filter((state) => state === WalletState.CONNECTED), 26 | mapTo(selectedWallet), 27 | ); 28 | }), 29 | publishReplay(1), 30 | refCount(), 31 | ); 32 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/nautilus/connectWallet.tsx: -------------------------------------------------------------------------------- 1 | import { catchError, from, Observable, of, throwError } from 'rxjs'; 2 | 3 | export const connectWallet = (): Observable => { 4 | if (!ergoConnector?.nautilus) { 5 | return throwError(() => new Error('EXTENSION_NOT_FOUND')); 6 | } 7 | 8 | if (!ergoConnector.nautilus?.getContext) { 9 | return of( 10 | <> 11 | Wallet API has changed. Be sure to update your wallet to continue using 12 | it 13 | , 14 | ); 15 | } 16 | return from(ergoConnector.nautilus.connect({ createErgoObject: false })).pipe( 17 | catchError(() => of(false)), 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/nautilus/getUtxos.ts: -------------------------------------------------------------------------------- 1 | import { ErgoBox, ergoBoxFromProxy } from '@ergolabs/ergo-sdk'; 2 | import { from, map, Observable } from 'rxjs'; 3 | 4 | export const getUtxos = (): Observable => 5 | from( 6 | ergoConnector.nautilus.getContext().then((context) => context.get_utxos()), 7 | ).pipe( 8 | map((bs: any) => bs?.map((b: any) => ergoBoxFromProxy(b))), 9 | map((data) => data ?? []), 10 | ); 11 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/nautilus/sign.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ErgoTx, 3 | ergoTxFromProxy, 4 | UnsignedErgoTx, 5 | unsignedErgoTxToProxy, 6 | } from '@ergolabs/ergo-sdk'; 7 | import { CANCEL_REQUEST } from '@ergolabs/ui-kit/dist/components/Modal/presets/Request'; 8 | 9 | export const sign = async (tx: UnsignedErgoTx): Promise => { 10 | const proxy = unsignedErgoTxToProxy(tx); 11 | 12 | const res = await ergoConnector.nautilus 13 | .getContext() 14 | .then((context) => context.sign_tx(proxy)) 15 | .catch((error) => { 16 | if (error.code === 2) { 17 | throw CANCEL_REQUEST; 18 | } 19 | throw error; 20 | }); 21 | return ergoTxFromProxy(res); 22 | }; 23 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/nautilus/signInput.ts: -------------------------------------------------------------------------------- 1 | import { UnsignedErgoTx, unsignedErgoTxToProxy } from '@ergolabs/ergo-sdk'; 2 | import { Input as TxInput } from '@ergolabs/ergo-sdk/build/main/entities/input'; 3 | 4 | export const signInput = async ( 5 | tx: UnsignedErgoTx, 6 | input: number, 7 | ): Promise => { 8 | const proxy = unsignedErgoTxToProxy(tx); 9 | 10 | return ergoConnector.nautilus 11 | .getContext() 12 | .then((context) => context.sign_tx_input(proxy, input)); 13 | }; 14 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/nautilus/submitTx.ts: -------------------------------------------------------------------------------- 1 | import { ErgoTx, ergoTxToProxy } from '@ergolabs/ergo-sdk'; 2 | import { from, Observable } from 'rxjs'; 3 | 4 | import { TxId } from '../../../../../common/types'; 5 | 6 | export const submitTx = (tx: ErgoTx): Observable => 7 | from( 8 | ergoConnector.nautilus 9 | .getContext() 10 | .then((context) => context.submit_tx(ergoTxToProxy(tx))), 11 | ); 12 | -------------------------------------------------------------------------------- /src/network/ergo/api/wallet/nautilus/walletSupportedFeatures.ts: -------------------------------------------------------------------------------- 1 | import { WalletSupportedFeatures } from '../../../../common/Wallet'; 2 | 3 | export const walletSupportedFeatures: WalletSupportedFeatures = { 4 | createPool: true, 5 | }; 6 | -------------------------------------------------------------------------------- /src/network/ergo/initialized.ts: -------------------------------------------------------------------------------- 1 | import { RustModule } from '@ergolabs/ergo-sdk'; 2 | import { BehaviorSubject } from 'rxjs'; 3 | 4 | import { initializeErgoPayAnalytics } from './analytics/ergopay'; 5 | import { initializeSettings } from './settings/settings'; 6 | 7 | export const initialized$ = new BehaviorSubject(false); 8 | 9 | export const initialize = (): void => { 10 | RustModule.load().then(() => { 11 | initializeSettings(); 12 | initializeErgoPayAnalytics(); 13 | initialized$.next(true); 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /src/network/ergo/lm/api/farms/utils.ts: -------------------------------------------------------------------------------- 1 | import { LmPool, makeLmPools, Pools } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { explorer } from '../../../../../services/explorer'; 4 | 5 | export const networkLmPools = (() => { 6 | let networkPools: Pools; 7 | return (): Pools => { 8 | if (!networkPools) { 9 | networkPools = makeLmPools(explorer); 10 | } 11 | 12 | return networkPools; 13 | }; 14 | })(); 15 | -------------------------------------------------------------------------------- /src/network/ergo/lm/models/Stake.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool } from '../../../../common/models/AmmPool'; 2 | import { Currency } from '../../../../common/models/Currency'; 3 | import { RawStakeWithRedeemerKey } from '../api/stakes/stakes'; 4 | import { ErgoFarm } from './ErgoFarm'; 5 | 6 | export class Stake { 7 | get ammPool(): AmmPool { 8 | return this.lmPool.ammPool; 9 | } 10 | 11 | get lq(): Currency { 12 | return new Currency(this.rawStake.lockedLq.amount, this.lmPool.assets.lq); 13 | } 14 | 15 | get shares(): [Currency, Currency] { 16 | return this.ammPool.shares(this.lq); 17 | } 18 | 19 | get x(): Currency { 20 | return this.shares[0]; 21 | } 22 | 23 | get y(): Currency { 24 | return this.shares[1]; 25 | } 26 | 27 | constructor( 28 | public readonly rawStake: RawStakeWithRedeemerKey, 29 | public readonly lmPool: ErgoFarm, 30 | ) {} 31 | } 32 | -------------------------------------------------------------------------------- /src/network/ergo/lm/operations/common/inputSelector.ts: -------------------------------------------------------------------------------- 1 | import { 2 | BoxSelection, 3 | DefaultBoxSelector, 4 | InputSelector, 5 | InsufficientInputs, 6 | OverallAmount, 7 | } from '@ergolabs/ergo-sdk'; 8 | import { first, map } from 'rxjs'; 9 | 10 | import { NEW_MIN_BOX_VALUE } from '../../../../../common/constants/erg'; 11 | import { utxos$ } from '../../../api/utxos/utxos'; 12 | 13 | export class DefaultInputSelector implements InputSelector { 14 | select(target: OverallAmount): Promise { 15 | return utxos$ 16 | .pipe( 17 | first(), 18 | map((utxos) => 19 | DefaultBoxSelector.select(utxos, target, NEW_MIN_BOX_VALUE), 20 | ), 21 | ) 22 | .toPromise() as Promise; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/network/ergo/lm/operations/common/lmPoolActions.ts: -------------------------------------------------------------------------------- 1 | import { mkPoolActions, mkWrappedPoolActions } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { UI_REWARD_ADDRESS } from '../../../../../common/constants/settings'; 4 | import { mainnetTxAssembler } from '../../../../../services/defaultTxAssembler'; 5 | import { proverMediator } from '../../../operations/common/proverMediator'; 6 | import { DefaultInputSelector } from './inputSelector'; 7 | 8 | const defaultInputSelector = new DefaultInputSelector(); 9 | 10 | export const lmPoolErgopayActions = mkPoolActions( 11 | defaultInputSelector, 12 | UI_REWARD_ADDRESS, 13 | ); 14 | 15 | export const lmPoolActions = mkWrappedPoolActions( 16 | defaultInputSelector, 17 | proverMediator, 18 | mainnetTxAssembler, 19 | UI_REWARD_ADDRESS, 20 | ); 21 | -------------------------------------------------------------------------------- /src/network/ergo/operations/common/getTxContext.ts: -------------------------------------------------------------------------------- 1 | import { TransactionContext } from '@ergolabs/ergo-sdk'; 2 | import { Address } from '@ergolabs/ergo-sdk/build/main/entities/address'; 3 | import { NetworkContext } from '@ergolabs/ergo-sdk/build/main/entities/networkContext'; 4 | import { BoxSelection } from '@ergolabs/ergo-sdk/build/main/wallet/entities/boxSelection'; 5 | 6 | export const getTxContext = ( 7 | inputs: BoxSelection, 8 | network: NetworkContext, 9 | address: Address, 10 | minerFee: bigint, 11 | ): TransactionContext => ({ 12 | inputs, 13 | selfAddress: address, 14 | changeAddress: address, 15 | feeNErgs: minerFee, 16 | network, 17 | }); 18 | -------------------------------------------------------------------------------- /src/network/ergo/operations/common/makeTarget.ts: -------------------------------------------------------------------------------- 1 | import { AssetAmount, isNative, OverallAmount } from '@ergolabs/ergo-sdk'; 2 | 3 | export function makeTarget( 4 | assetsIn: AssetAmount[], 5 | minNErgForFee: bigint, 6 | ): OverallAmount { 7 | const nativeAsset = assetsIn.filter((i) => isNative(i.asset))[0]; 8 | const isNativePool = !!nativeAsset; 9 | 10 | const totalNErgs = isNativePool 11 | ? nativeAsset.amount + minNErgForFee 12 | : minNErgForFee; 13 | 14 | const assets = assetsIn 15 | .filter((i) => !isNative(i.asset)) 16 | .map((ai) => ({ 17 | tokenId: ai.asset.id, 18 | amount: ai.amount, 19 | })); 20 | 21 | return { 22 | nErgs: totalNErgs, 23 | assets, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/network/ergo/operations/common/proverMediator.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ErgoTx, 3 | Input as TxInput, 4 | Prover, 5 | UnsignedErgoTx, 6 | } from '@ergolabs/ergo-sdk'; 7 | import { filter, first, switchMap } from 'rxjs'; 8 | 9 | import { selectedWallet$ } from '../../api/wallet/wallet'; 10 | 11 | const sign = (tx: UnsignedErgoTx): Promise => 12 | selectedWallet$ 13 | .pipe( 14 | filter(Boolean), 15 | first(), 16 | switchMap((w) => w.sign(tx)), 17 | ) 18 | .toPromise() as Promise; 19 | 20 | const signInput = (tx: UnsignedErgoTx, input: number): Promise => 21 | selectedWallet$ 22 | .pipe( 23 | filter(Boolean), 24 | first(), 25 | switchMap((w) => w.signInput(tx, input)), 26 | ) 27 | .toPromise() as Promise; 28 | 29 | export const proverMediator: Prover = { 30 | sign, 31 | signInput, 32 | }; 33 | -------------------------------------------------------------------------------- /src/network/ergo/operations/common/submitTx.ts: -------------------------------------------------------------------------------- 1 | import { ErgoTx } from '@ergolabs/ergo-sdk'; 2 | import { filter, first, mapTo, Observable, switchMap } from 'rxjs'; 3 | 4 | import { TxId } from '../../../../common/types'; 5 | import { 6 | addToQueue, 7 | OperationParams, 8 | } from '../../api/operations/pending/queuedOperation'; 9 | import { selectedWallet$ } from '../../api/wallet/wallet'; 10 | 11 | export const submitTx = ( 12 | tx: ErgoTx, 13 | params: OperationParams, 14 | ): Observable => 15 | selectedWallet$.pipe( 16 | filter(Boolean), 17 | first(), 18 | switchMap((w) => w.submitTx(tx)), 19 | switchMap((txId) => addToQueue(tx, params).pipe(mapTo(txId))), 20 | ); 21 | -------------------------------------------------------------------------------- /src/network/ergo/settings/nitro.ts: -------------------------------------------------------------------------------- 1 | import { map, Observable, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { useObservable } from '../../../common/hooks/useObservable'; 4 | import { Percent } from '../../../common/types'; 5 | import { getSettings, settings$ } from './settings'; 6 | 7 | export const nitro$: Observable = settings$.pipe( 8 | map((settings) => settings.nitro), 9 | publishReplay(), 10 | refCount(), 11 | ); 12 | 13 | export const useNitro = (): Percent => { 14 | const [nitro] = useObservable(nitro$, [], getSettings().nitro); 15 | 16 | return nitro; 17 | }; 18 | -------------------------------------------------------------------------------- /src/network/ergo/settings/slippage.ts: -------------------------------------------------------------------------------- 1 | import { map, Observable, publishReplay, refCount } from 'rxjs'; 2 | 3 | import { useObservable } from '../../../common/hooks/useObservable'; 4 | import { Percent } from '../../../common/types'; 5 | import { getSettings, settings$ } from './settings'; 6 | 7 | export const slippage$: Observable = settings$.pipe( 8 | map((settings) => settings.slippage), 9 | publishReplay(), 10 | refCount(), 11 | ); 12 | 13 | export const useSlippage = (): Percent => { 14 | const [slippage] = useObservable(slippage$, [], getSettings().slippage); 15 | 16 | return slippage; 17 | }; 18 | -------------------------------------------------------------------------------- /src/network/ergo/widgets/CreatePoolConfirmationInfo/CreatePoolConfirmationInfo.tsx: -------------------------------------------------------------------------------- 1 | import { t } from '@lingui/macro'; 2 | import { FC } from 'react'; 3 | 4 | import { FeesView } from '../../../../components/FeesView/FeesView'; 5 | import { useMinerFee } from '../../settings/minerFee'; 6 | 7 | export const CreatePoolConfirmationInfo: FC = () => { 8 | const minerFee = useMinerFee(); 9 | return ( 10 | 11 | ); 12 | }; 13 | -------------------------------------------------------------------------------- /src/network/ergo/widgets/DepositConfirmationModal/DepositConfirmationInfo/DepositConfirmationInfo.tsx: -------------------------------------------------------------------------------- 1 | import { t } from '@lingui/macro'; 2 | import { FC } from 'react'; 3 | 4 | import { FeesView } from '../../../../../components/FeesView/FeesView'; 5 | import { useMinExFee } from '../../../settings/executionFee/executionFee'; 6 | import { useMinerFee } from '../../../settings/minerFee'; 7 | 8 | export const DepositConfirmationInfo: FC = () => { 9 | const minExFee = useMinExFee(); 10 | const minerFee = useMinerFee(); 11 | 12 | return ( 13 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/network/ergo/widgets/ErgoPayModal/ErgoPayRequestLoadingContent/ErgoPayRequestLoadingContent.tsx: -------------------------------------------------------------------------------- 1 | import { LoadingDataState, Modal } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | export const ErgoPayRequestLoadingContent: FC = () => ( 6 | <> 7 | ErgoPay request 8 | 9 | 10 | Preparing ergoPay request. 11 |
12 | Please wait. 13 |
14 |
15 | 16 | ); 17 | -------------------------------------------------------------------------------- /src/network/ergo/widgets/ErgoPayModal/common/ergopayLinks.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../../../../../applicationConfig'; 2 | import { TxId } from '../../../../../common/types'; 3 | 4 | export const createUnsignedTxRequestLink = (txId: TxId): string => 5 | `${applicationConfig.networksSettings.ergo.ergopayUrl}/unsignedTx/${txId}`; 6 | 7 | export const createSelectAddressesRequestLink = (requestId: string): string => 8 | `${applicationConfig.networksSettings.ergo.ergopayUrl}/addresses/${requestId}/#P2PK_ADDRESS#`; 9 | 10 | export const createErgoPayDeepLink = (requestLink: string): string => 11 | requestLink.replace('https', 'ergopay'); 12 | -------------------------------------------------------------------------------- /src/network/ergo/widgets/RedeemConfirmationModal/RedeemConfirmationInfo/RedeemConfirmationInfo.tsx: -------------------------------------------------------------------------------- 1 | import { t } from '@lingui/macro'; 2 | import { FC } from 'react'; 3 | 4 | import { FeesView } from '../../../../../components/FeesView/FeesView'; 5 | import { useMinExFee } from '../../../settings/executionFee/executionFee'; 6 | import { useMinerFee } from '../../../settings/minerFee'; 7 | 8 | export const RedeemConfirmationInfo: FC = () => { 9 | const minExFee = useMinExFee(); 10 | const minerFee = useMinerFee(); 11 | 12 | return ( 13 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/network/ergo/widgets/RefundConfirmationModal/RefundConfirmationInfo/RefundConfirmationInfo.tsx: -------------------------------------------------------------------------------- 1 | import { t } from '@lingui/macro'; 2 | import { FC } from 'react'; 3 | 4 | import { FeesView } from '../../../../../components/FeesView/FeesView'; 5 | import { useMinerFee } from '../../../settings/minerFee'; 6 | 7 | export const RefundConfirmationInfo: FC = () => { 8 | const minerFee = useMinerFee(); 9 | 10 | return ; 11 | }; 12 | -------------------------------------------------------------------------------- /src/nodespecific.ts: -------------------------------------------------------------------------------- 1 | import { Buffer } from 'buffer'; 2 | // @ts-ignore 3 | import Process from 'process'; 4 | 5 | // @ts-ignore 6 | globalThis.Buffer = Buffer; 7 | // @ts-ignore 8 | globalThis.process = Process; 9 | -------------------------------------------------------------------------------- /src/pages/AddLiquidityOrCreatePool/common/utils.ts: -------------------------------------------------------------------------------- 1 | import { AssetInfo } from '../../../common/models/AssetInfo'; 2 | import { Currency } from '../../../common/models/Currency'; 3 | 4 | export const normalizeAmountWithFee = ( 5 | amount: Currency, 6 | availableBalance: Currency, 7 | feeAsset: AssetInfo, 8 | fee: Currency, 9 | ): Currency => 10 | amount.asset.id === feeAsset.id && fee.plus(amount).gt(availableBalance) 11 | ? amount.minus(fee) 12 | : amount; 13 | -------------------------------------------------------------------------------- /src/pages/CreatePool/CreatePoolFormModel.ts: -------------------------------------------------------------------------------- 1 | import { AssetInfo } from '../../common/models/AssetInfo'; 2 | import { Currency } from '../../common/models/Currency'; 3 | import { Ratio } from '../../common/models/Ratio'; 4 | 5 | export interface CreatePoolFormModel { 6 | readonly initialPrice?: Ratio; 7 | readonly x?: Currency; 8 | readonly y?: Currency; 9 | readonly xAsset?: AssetInfo; 10 | readonly yAsset?: AssetInfo; 11 | readonly fee?: number; 12 | } 13 | -------------------------------------------------------------------------------- /src/pages/CreatePool/Overlay/Overlay.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | export interface OverlayProps { 4 | readonly enabled?: boolean; 5 | readonly children?: ReactNode | ReactNode[] | string; 6 | } 7 | 8 | export const Overlay: FC = ({ children, enabled }) => ( 9 |
10 | {enabled && ( 11 |
21 | )} 22 |
{children}
23 |
24 | ); 25 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/FarmTableExpandComponent/DistributionCell/DistributionCell.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex, Progress, Typography } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | import { Farm } from '../../../../../common/models/Farm'; 6 | 7 | export interface DistributionCellProps { 8 | readonly farm: Farm; 9 | } 10 | 11 | export const DistributionCell: FC = ({ farm }) => ( 12 | 13 | 14 | 15 | 16 | Distributed 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/FarmTableExpandComponent/FarmActionCell/FarmActionCell.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { Farm } from '../../../../../common/models/Farm'; 5 | import { FarmAction } from '../../common/FarmAction/FarmAction'; 6 | 7 | export interface FarmActionCellProps { 8 | readonly farm: Farm; 9 | } 10 | 11 | export const FarmActionCell: FC = ({ farm }) => ( 12 | 13 | 14 | 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/FarmTableExpandComponent/NextRewardCell/NextRewardCell.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { Farm } from '../../../../../common/models/Farm'; 4 | import { RewardCell } from '../common/RewardCell/RewardCell'; 5 | 6 | export interface NextRewardCellProps { 7 | readonly farm: Farm; 8 | } 9 | 10 | export const NextRewardCell: FC = ({ farm }) => { 11 | return ; 12 | }; 13 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/FarmTableExpandComponent/TotalStakedCell/TotalStakedCell.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from '@lingui/macro'; 2 | import { FC } from 'react'; 3 | 4 | import { Farm } from '../../../../../common/models/Farm'; 5 | import { UsdCell } from '../common/UsdCell/UsdCell'; 6 | 7 | export interface TotalStakedCellProps { 8 | readonly farm: Farm; 9 | } 10 | 11 | export const TotalStakedCell: FC = ({ farm }) => ( 12 | Total staked} 16 | /> 17 | ); 18 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/FarmTableExpandComponent/YourStakeCell/YourStakeCell.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from '@lingui/macro'; 2 | import { FC } from 'react'; 3 | 4 | import { Farm } from '../../../../../common/models/Farm'; 5 | import { UsdCell } from '../common/UsdCell/UsdCell'; 6 | 7 | export interface TotalStakedCellProps { 8 | readonly farm: Farm; 9 | } 10 | 11 | export const YourStakeCell: FC = ({ farm }) => ( 12 | Your stake} 16 | /> 17 | ); 18 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/columns/FarmDistributedColumn/FarmDistributedColumn.tsx: -------------------------------------------------------------------------------- 1 | import { Flex, useDevice } from '@ergolabs/ui-kit'; 2 | import { Progress } from '@ergolabs/ui-kit/dist/components/Progress/Progress'; 3 | import { FC } from 'react'; 4 | 5 | import { Farm } from '../../../../../common/models/Farm'; 6 | 7 | export interface DistributedColumnProps { 8 | readonly farm: Farm; 9 | } 10 | 11 | export const FarmDistributedColumn: FC = ({ farm }) => { 12 | const { valBySize } = useDevice(); 13 | 14 | return ( 15 | 16 | 17 | 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/columns/FarmTotalStakedColumn/FarmTotalStakedColumn.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { Farm } from '../../../../../common/models/Farm'; 4 | import { FarmTagColumn } from '../common/FarmTagColumn/FarmTagColumn'; 5 | 6 | export interface FarmTotalStakedColumnProps { 7 | readonly farm: Farm; 8 | } 9 | 10 | export const FarmTotalStakedColumn: FC = ({ 11 | farm, 12 | }) => ; 13 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTableView/columns/FarmYourStakeColumn/FarmYourStakeColumn.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { Farm } from '../../../../../common/models/Farm'; 4 | import { FarmTagColumn } from '../common/FarmTagColumn/FarmTagColumn'; 5 | 6 | export interface FarmYourStakeColumnPops { 7 | readonly farm: Farm; 8 | readonly sensitive?: boolean; 9 | } 10 | 11 | export const FarmYourStakeColumn: FC = ({ 12 | farm, 13 | sensitive, 14 | }) => ( 15 | 20 | ); 21 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTopPanel/CreateFarmModal/CreateFarmFormModel.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool } from '../../../../common/models/AmmPool'; 2 | import { AssetInfo } from '../../../../common/models/AssetInfo'; 3 | import { IntervalType } from './FarmDistributionIntervalInput/FarmDistributionIntervalInput'; 4 | 5 | export interface CreateFarmFormModel { 6 | pool?: AmmPool; 7 | period?: [number | undefined, number | undefined]; 8 | distributionInterval?: { type: IntervalType; value: number }; 9 | budgetAsset?: AssetInfo; 10 | budgetAmount?: any; 11 | } 12 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTopPanel/CreateFarmModal/FarmPeriodSelector/PeriodType.ts: -------------------------------------------------------------------------------- 1 | export enum PeriodType { 2 | Block = 'block', 3 | Date = 'date', 4 | } 5 | -------------------------------------------------------------------------------- /src/pages/Farms/FarmTopPanel/FarmViewModeSwitch/FarmViewMode.ts: -------------------------------------------------------------------------------- 1 | export enum FarmViewMode { 2 | Grid = 'Grid', 3 | Table = 'Table', 4 | } 5 | -------------------------------------------------------------------------------- /src/pages/Farms/types/FarmTabs.ts: -------------------------------------------------------------------------------- 1 | export enum FarmTabs { 2 | AllFarms = 'AllFarms', 3 | MyFarms = 'MyFarms', 4 | } 5 | -------------------------------------------------------------------------------- /src/pages/Farms/types/FarmViewMode.ts: -------------------------------------------------------------------------------- 1 | export enum FarmViewMode { 2 | Grid = 'Grid', 3 | Table = 'Table', 4 | } 5 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/columns/LockedPositionsColumns/PairColumn/PairColumn.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { Position } from '../../../../../../common/models/Position'; 5 | import { AssetTitle } from '../../../../../../components/AssetTitle/AssetTitle'; 6 | 7 | export interface PairColumnProps { 8 | readonly position: Position; 9 | } 10 | 11 | export const PairColumn: FC = ({ position }) => ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/columns/LockedPositionsColumns/ShareColumn/ShareColumn.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { Position } from '../../../../../../common/models/Position'; 5 | import { DataTag } from '../../../../../../components/common/DataTag/DataTag'; 6 | 7 | export interface ShareColumnProps { 8 | readonly position: Position; 9 | } 10 | 11 | export const ShareColumn: FC = ({ position }) => ( 12 | 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/columns/LockedPositionsColumns/TotalLockedColumn/TotalLockedColumn.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { Position } from '../../../../../../common/models/Position'; 5 | import { DataTag } from '../../../../../../components/common/DataTag/DataTag'; 6 | 7 | export interface TotalLockedColumnProps { 8 | readonly position: Position; 9 | } 10 | 11 | export const TotalLockedColumn: FC = ({ position }) => ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/columns/LockedPositionsColumns/WithdrawableLockedColumn/WithdrawableLockedColumn.tsx: -------------------------------------------------------------------------------- 1 | import { Flex } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { Position } from '../../../../../../common/models/Position'; 5 | import { DataTag } from '../../../../../../components/common/DataTag/DataTag'; 6 | 7 | export interface WithdrawableLockedColumnProps { 8 | readonly position: Position; 9 | } 10 | 11 | export const WithdrawableLockedColumn: FC = ({ 12 | position, 13 | }) => ( 14 | 15 | 16 | 20 | 21 | 25 | 26 | ); 27 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/columns/PoolsOrPositionsColumns/columns/AprColumn/ErgoAprColumnContent/ErgoAprColumnContent.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { AmmPool } from '../../../../../../../../common/models/AmmPool'; 4 | 5 | export interface ErgoAprColumnContentProps { 6 | readonly ammPool: AmmPool; 7 | } 8 | 9 | export const ErgoAprColumnContent: FC = ({ 10 | ammPool, 11 | }) => <>{ammPool.yearlyFeesPercent ? `${ammPool.yearlyFeesPercent}%` : '—'}; 12 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/components/Apr24InfoTooltip/Apr24InfoTooltip.tsx: -------------------------------------------------------------------------------- 1 | import { Trans } from '@lingui/macro'; 2 | import { FC, ReactNode } from 'react'; 3 | 4 | import { InfoTooltip } from '../../../../../components/InfoTooltip/InfoTooltip.tsx'; 5 | 6 | interface Apr24InfoTooltipProps { 7 | readonly children: ReactNode | ReactNode[] | string; 8 | } 9 | 10 | export const Apr24InfoTooltip: FC = ({ children }) => { 11 | return ( 12 | 17 | 18 | A rough estimate based on the trading volume in a pool for the last 19 | 24 hours. May not correspond to actual gains or losses. 20 | 21 | 22 | } 23 | > 24 | {children} 25 | 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/components/LockLiquidityDatePicker/LiquidityDatePicker.less: -------------------------------------------------------------------------------- 1 | .liquidity-date-picker { 2 | height: 50px; 3 | 4 | &__dropdown { 5 | .ant-picker-footer { 6 | display: none; 7 | } 8 | } 9 | 10 | .ant-picker { 11 | padding: calc(var(--spectrum-base-gutter)*2); 12 | background: none; 13 | transition: all .5s ease; 14 | 15 | .ant-picker-input { 16 | background: 0; 17 | } 18 | 19 | .ant-picker-suffix { 20 | margin: 0; 21 | } 22 | 23 | input { 24 | display: none; 25 | } 26 | 27 | svg { 28 | width: 20px; 29 | height: 20px; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/tableViewStates/LiquiditySearchState/LiquiditySearchState.tsx: -------------------------------------------------------------------------------- 1 | import { SearchDataState } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | import { FC } from 'react'; 4 | 5 | export const LiquiditySearchState: FC = () => ( 6 | 7 | No results was found 8 | 9 | ); 10 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityActiveStateProps.ts: -------------------------------------------------------------------------------- 1 | import { LiquidityState } from './LiquidityState'; 2 | 3 | export interface LiquidityActiveStateProps { 4 | readonly activeState: LiquidityState; 5 | readonly setActiveState: (state: LiquidityState) => void; 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityFilterProps.ts: -------------------------------------------------------------------------------- 1 | import { PoolsOrPositionsFilterValue } from '../components/LiquidityFilter/LiquidityFilter'; 2 | 3 | export interface LiquidityFiltersProps { 4 | readonly filters: Set | undefined; 5 | readonly setFilters: ( 6 | filters: Set | undefined, 7 | ) => void; 8 | } 9 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityLayoutProps.ts: -------------------------------------------------------------------------------- 1 | import { LiquidityActiveStateProps } from './LiquidityActiveStateProps'; 2 | import { LiquidityFiltersProps } from './LiquidityFilterProps'; 3 | import { LiquidityLockedPositionsProps } from './LiquidityLockedPositionsProps'; 4 | import { LiquidityPoolsOverviewProps } from './LiquidityPoolsOverviewProps'; 5 | import { LiquiditySearchProps } from './LiquiditySearchProps'; 6 | import { LiquidityYourPositionsProps } from './LiquidityYourPositionsProps'; 7 | 8 | export type LiquidityLayoutProps = LiquidityPoolsOverviewProps & 9 | LiquidityYourPositionsProps & 10 | LiquidityLockedPositionsProps & 11 | LiquidityFiltersProps & 12 | LiquiditySearchProps & 13 | LiquidityActiveStateProps; 14 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityLockedPositionsProps.ts: -------------------------------------------------------------------------------- 1 | import { Position } from '../../../../common/models/Position'; 2 | 3 | export interface LiquidityLockedPositionsProps { 4 | readonly positionsWithLocks: Position[]; 5 | readonly showLockedPositions: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityPoolOrPositionDetailsProps.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react'; 2 | 3 | import { AmmPool } from '../../../../common/models/AmmPool'; 4 | import { Position } from '../../../../common/models/Position'; 5 | import { ExpandComponentProps } from '../../../../components/TableView/common/Expand'; 6 | 7 | export interface LiquidityPoolOrPositionDetailsProps< 8 | T extends AmmPool | Position, 9 | > extends ExpandComponentProps { 10 | poolMapper: (item: T) => AmmPool; 11 | children?: ReactNode | ReactNode[] | string; 12 | } 13 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityPoolsOverviewProps.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool } from '../../../../common/models/AmmPool'; 2 | 3 | export interface LiquidityPoolsOverviewProps { 4 | readonly ammPools: AmmPool[]; 5 | readonly isAmmPoolsLoading?: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquiditySearchProps.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | export interface LiquiditySearchProps { 4 | readonly term: string; 5 | readonly handleSearchTerm: (e: React.ChangeEvent) => void; 6 | } 7 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityState.ts: -------------------------------------------------------------------------------- 1 | export enum LiquidityState { 2 | POOLS_OVERVIEW = 'positions-overview', 3 | YOUR_POSITIONS = 'your-positions', 4 | LOCKED_POSITIONS = 'locked-positions', 5 | } 6 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/LiquidityYourPositionsProps.ts: -------------------------------------------------------------------------------- 1 | import { Position } from '../../../../common/models/Position'; 2 | 3 | export interface LiquidityYourPositionsProps { 4 | readonly positions: Position[]; 5 | readonly isPositionsLoading?: boolean; 6 | readonly isPositionsEmpty: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /src/pages/Liquidity/common/types/PoolsOrPositionsTableViewProps.ts: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react'; 2 | 3 | import { AmmPool } from '../../../../common/models/AmmPool'; 4 | import { Position } from '../../../../common/models/Position'; 5 | import { ExpandComponentProps } from '../../../../components/TableView/common/Expand'; 6 | 7 | export interface PoolsOrPositionsTableViewProps { 8 | readonly items: T[]; 9 | readonly poolMapper: (item: T) => AmmPool; 10 | readonly expandComponent: FC>; 11 | readonly children?: ReactNode | ReactNode[] | string; 12 | } 13 | -------------------------------------------------------------------------------- /src/pages/Liquidity/default/components/PoolsOverview/PoolDetails/PoolDetails.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { AmmPool } from '../../../../../../common/models/AmmPool'; 4 | import { ExpandComponentProps } from '../../../../../../components/TableView/common/Expand'; 5 | import { PoolOrPositionDetails } from '../../../common/PoolOrPositionDetails/PoolOrPositionDetails'; 6 | 7 | export const PoolDetails: FC> = ({ 8 | item, 9 | ...rest 10 | }) => item} item={item} {...rest} />; 11 | -------------------------------------------------------------------------------- /src/pages/Liquidity/mobile/components/PoolsOverview/PoolDetails/PoolDetails.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react'; 2 | 3 | import { AmmPool } from '../../../../../../common/models/AmmPool'; 4 | import { ExpandComponentProps } from '../../../../../../components/TableView/common/Expand'; 5 | import { PoolOrPositionDetails } from '../../../common/PoolOrPositionDetails/PoolOrPositionDetails'; 6 | 7 | export const PoolDetails: FC> = ({ 8 | item, 9 | ...rest 10 | }) => item} item={item} {...rest} />; 11 | -------------------------------------------------------------------------------- /src/pages/LockLiquidity/LockLiquidityModel.ts: -------------------------------------------------------------------------------- 1 | import { DateTime } from 'luxon'; 2 | 3 | import { AmmPool } from '../../common/models/AmmPool'; 4 | import { Currency } from '../../common/models/Currency'; 5 | 6 | export interface LockLiquidityModel { 7 | xAmount?: Currency; 8 | yAmount?: Currency; 9 | lpAmount?: Currency; 10 | locktime?: DateTime; 11 | percent: number; 12 | pool?: AmmPool; 13 | } 14 | -------------------------------------------------------------------------------- /src/pages/PoolOverview/LockLiquidity/LockLiquidity.less: -------------------------------------------------------------------------------- 1 | .recharts-cartesian-axis tspan { 2 | fill: var(--spectrum-footnote-text); 3 | font: var(--spectrum-footnote-font); 4 | } 5 | 6 | .recharts-rectangle { 7 | fill: linear-gradient(180deg, #FF8C01 -0.57%, #FF5135 100%); 8 | } 9 | 10 | .hidden-tooltip { 11 | display: none; 12 | } 13 | 14 | .recharts-tooltip-cursor { 15 | fill: var(--spectrum-bar-hover-color); 16 | opacity: 0.2; 17 | } 18 | -------------------------------------------------------------------------------- /src/pages/PoolOverview/PoolInfoView/PoolFeeTag/PoolFeeTag.tsx: -------------------------------------------------------------------------------- 1 | import { Box, Typography } from '@ergolabs/ui-kit'; 2 | import { FC } from 'react'; 3 | 4 | import { AmmPool } from '../../../../common/models/AmmPool'; 5 | import { formatToFeePercent } from '../../../../services/number.ts'; 6 | 7 | interface PoolFeeTagProps { 8 | readonly ammPool: AmmPool; 9 | } 10 | 11 | export const PoolFeeTag: FC = ({ ammPool }) => ( 12 | 13 | 14 | {formatToFeePercent(ammPool.poolFee)}% 15 | 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /src/pages/PoolOverview/PriceHistory/PriceHistory.less: -------------------------------------------------------------------------------- 1 | .pool-price-chart { 2 | .recharts-cartesian-axis-line, .recharts-cartesian-axis-tick-line { 3 | stroke: transparent; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/pages/RemoveLiquidity/RemoveLiquidityFormModel.ts: -------------------------------------------------------------------------------- 1 | import { Currency } from '../../common/models/Currency'; 2 | 3 | export interface RemoveLiquidityFormModel { 4 | readonly percent: number; 5 | readonly xAmount?: Currency; 6 | readonly yAmount?: Currency; 7 | readonly lpAmount?: Currency; 8 | } 9 | -------------------------------------------------------------------------------- /src/pages/Rewards/Tags/RewardInfoTag/RewardInfoTag.tsx: -------------------------------------------------------------------------------- 1 | import { Tag } from '@ergolabs/ui-kit'; 2 | 3 | export const RewardInfoTag = () => { 4 | return 🔥 Highest APR; 5 | }; 6 | -------------------------------------------------------------------------------- /src/pages/Rewards/Tags/RewardStatusTag/RewardStatusTag.tsx: -------------------------------------------------------------------------------- 1 | import { CheckCircleOutlined, SyncOutlined, Tag } from '@ergolabs/ui-kit'; 2 | import { Trans } from '@lingui/macro'; 3 | 4 | export const RewardStatusTag = ({ status }) => { 5 | if (status === 'ongoing') { 6 | return ( 7 | }> 8 | {status == 'ongoing' ? 'Ongoing' : 'Finished'} 9 | 10 | ); 11 | } 12 | 13 | return ( 14 | }> 15 | Closed 16 | 17 | ); 18 | }; 19 | -------------------------------------------------------------------------------- /src/pages/Swap/SwapFormModel.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool } from '../../common/models/AmmPool'; 2 | import { AssetInfo } from '../../common/models/AssetInfo'; 3 | import { Currency } from '../../common/models/Currency'; 4 | 5 | export interface SwapFormModel

{ 6 | readonly fromAmount?: Currency; 7 | readonly toAmount?: Currency; 8 | readonly fromAsset?: AssetInfo; 9 | readonly toAsset?: AssetInfo; 10 | readonly pool?: P; 11 | } 12 | -------------------------------------------------------------------------------- /src/pages/Swap/SwapGraph/useAggregatedByDateData.ts: -------------------------------------------------------------------------------- 1 | import { DateTime } from 'luxon'; 2 | import { useMemo } from 'react'; 3 | 4 | import { PoolChartData } from '../../../common/models/PoolChartData'; 5 | 6 | export const useAggregatedByDateData = ( 7 | rawData: PoolChartData[], 8 | ticks: DateTime[], 9 | ): PoolChartData[] => { 10 | return useMemo(() => { 11 | if (rawData.length < 1) { 12 | return []; 13 | } 14 | 15 | let j = -1; 16 | const res = ticks 17 | .filter((lts) => lts.valueOf() > rawData[0].ts) 18 | .map((lts: DateTime) => { 19 | while (rawData[j + 1]?.ts < lts.valueOf()) { 20 | j++; 21 | } 22 | return rawData[j === -1 ? 0 : j].clone({ timestamp: lts.valueOf() }); 23 | }); 24 | res.push(rawData[rawData.length - 1].clone({ timestamp: Date.now() })); 25 | return res; 26 | }, [rawData]); 27 | }; 28 | -------------------------------------------------------------------------------- /src/pages/Swap/SwitchButton/SwitchButton.tsx: -------------------------------------------------------------------------------- 1 | import { Button, ButtonProps } from '@ergolabs/ui-kit'; 2 | import styled from 'styled-components'; 3 | 4 | export type SwitchButtonProps = ButtonProps; 5 | 6 | const _SwitchButton = ({ className, ...rest }: SwitchButtonProps) => ( 7 |

8 |
10 | ); 11 | 12 | export const SwitchButton = styled(_SwitchButton)` 13 | position: relative; 14 | 15 | button { 16 | position: absolute; 17 | z-index: 1; 18 | top: 50%; 19 | left: 50%; 20 | transform: rotate(-90deg) translate(50%, -50%); 21 | } 22 | `; 23 | -------------------------------------------------------------------------------- /src/pages/Swap/YieldFarmingBadge/banner-bg-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/pages/Swap/YieldFarmingBadge/banner-bg-left.png -------------------------------------------------------------------------------- /src/pages/Swap/YieldFarmingBadge/banner-bg-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spectrum-finance/interface/e1af1cf4ee6348350d353fa0952bfa95af7dbb1b/src/pages/Swap/YieldFarmingBadge/banner-bg-right.png -------------------------------------------------------------------------------- /src/pages/Swap/YieldFarmingBadge/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/services/amm.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AmmOrderRefunds, 3 | AmmOrderRefundsWrapper, 4 | DefaultAmmOrdersParser, 5 | DefaultAmmPoolsInfoParser, 6 | } from '@ergolabs/ergo-dex-sdk'; 7 | 8 | import { mainnetTxAssembler } from './defaultTxAssembler'; 9 | import { explorer } from './explorer'; 10 | import yoroiProver from './yoroi/prover'; 11 | 12 | export const ergopayAmmOrderRefunds = new AmmOrderRefunds(explorer); 13 | 14 | export const ammOrderRefunds = new AmmOrderRefundsWrapper( 15 | ergopayAmmOrderRefunds, 16 | yoroiProver, 17 | mainnetTxAssembler, 18 | ); 19 | 20 | export const ordersParser = new DefaultAmmOrdersParser(); 21 | 22 | export const poolsInfoParser = new DefaultAmmPoolsInfoParser(); 23 | -------------------------------------------------------------------------------- /src/services/defaultTxAssembler.ts: -------------------------------------------------------------------------------- 1 | import { DefaultTxAssembler } from '@ergolabs/ergo-sdk'; 2 | 3 | const IS_MAINNET = true; 4 | 5 | export const mainnetTxAssembler = new DefaultTxAssembler(IS_MAINNET); 6 | 7 | export const testnetTxAssembler = new DefaultTxAssembler(!IS_MAINNET); 8 | -------------------------------------------------------------------------------- /src/services/explorer.ts: -------------------------------------------------------------------------------- 1 | import { Explorer } from '@ergolabs/ergo-sdk'; 2 | 3 | import { applicationConfig } from '../applicationConfig'; 4 | 5 | const explorer = new Explorer( 6 | applicationConfig.networksSettings.ergo.networkUrl, 7 | ); 8 | 9 | export { explorer }; 10 | -------------------------------------------------------------------------------- /src/services/locker/parser.ts: -------------------------------------------------------------------------------- 1 | import { mkLockParser } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | export const lockParser = mkLockParser(); 4 | -------------------------------------------------------------------------------- /src/services/networkHistory.ts: -------------------------------------------------------------------------------- 1 | import { NetworkHistory } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { ordersParser, poolsInfoParser } from './amm'; 4 | import { explorer } from './explorer'; 5 | 6 | const networkHistory = new NetworkHistory( 7 | explorer, 8 | ordersParser, 9 | poolsInfoParser, 10 | ); 11 | 12 | export default networkHistory; 13 | -------------------------------------------------------------------------------- /src/services/notifications/CollateralGuideNotification/CollateralGuideNotification.tsx: -------------------------------------------------------------------------------- 1 | import { Button, notification } from '@ergolabs/ui-kit'; 2 | 3 | import { notificationKeys } from '../notificationKeys'; 4 | 5 | export const sendCollateralGuideNotification = () => { 6 | notification.open({ 7 | key: notificationKeys.COLLATERAL_GUIDE, 8 | description: `To perform refund operation you need to provide collateral in your wallet. Go to wallet's settings and search for "Collateral" feature.`, 9 | message: 'Provide collateral', 10 | duration: 0, 11 | type: 'info', 12 | btn: ( 13 | 19 | ), 20 | }); 21 | }; 22 | -------------------------------------------------------------------------------- /src/services/notifications/RefundOperation/RefundOperation.tsx: -------------------------------------------------------------------------------- 1 | import { HistoryOutlined, notification } from '@ergolabs/ui-kit'; 2 | 3 | import { notificationKeys } from '../notificationKeys'; 4 | 5 | export const showRefundOperationNotification = () => { 6 | notification.open({ 7 | key: notificationKeys.REFUND, 8 | description: ( 9 | <> 10 | Some of your funds are locked in smart contracts. Don't worry! To 11 | access them, please click on the Order History button ( 12 | ) to initiate a refund. 13 | 14 | ), 15 | message: 'Refund order', 16 | duration: 0, 17 | type: 'warning', 18 | }); 19 | }; 20 | 21 | export const closeRefundOperationNotification = () => { 22 | notification.close(notificationKeys.REFUND); 23 | }; 24 | -------------------------------------------------------------------------------- /src/services/notifications/notificationKeys.ts: -------------------------------------------------------------------------------- 1 | export const notificationKeys = { 2 | COOKIE_POLICY: 'COOKIE_POLICY', 3 | REFUND: 'REFUND', 4 | COLLATERAL_GUIDE: 'COLLATERAL_GUIDE', 5 | }; 6 | -------------------------------------------------------------------------------- /src/services/poolActions.ts: -------------------------------------------------------------------------------- 1 | import { makeWrappedNativePoolActionsSelector } from '@ergolabs/ergo-dex-sdk'; 2 | 3 | import { UI_REWARD_ADDRESS } from '../common/constants/settings'; 4 | import { mainnetTxAssembler } from './defaultTxAssembler'; 5 | import yoroiProver from './yoroi/prover'; 6 | 7 | export const poolActions = makeWrappedNativePoolActionsSelector( 8 | UI_REWARD_ADDRESS, 9 | yoroiProver, 10 | mainnetTxAssembler, 11 | ); 12 | -------------------------------------------------------------------------------- /src/services/yoroi/index.ts: -------------------------------------------------------------------------------- 1 | import { Address, ErgoTx, ergoTxToProxy } from '@ergolabs/ergo-sdk'; 2 | import { Balance } from '@ergolabs/ergo-sdk/build/main/wallet/entities/balance'; 3 | 4 | import { explorer } from '../explorer'; 5 | // TODO: WALLET_REFACTORING 6 | export const submitTx = async (tx: ErgoTx): Promise => { 7 | try { 8 | return await ergo.submit_tx(ergoTxToProxy(tx)); 9 | } catch { 10 | return ergoConnector.nautilus 11 | .getContext() 12 | .then((context) => context.submit_tx(ergoTxToProxy(tx))); 13 | } 14 | }; 15 | 16 | export const getBalance = async ( 17 | address: Address, 18 | ): Promise => { 19 | return await explorer.getBalanceByAddress(address); 20 | }; 21 | -------------------------------------------------------------------------------- /src/utils/adaHandle.ts: -------------------------------------------------------------------------------- 1 | import { Balance } from '../common/models/Balance.ts'; 2 | import { Currency } from '../common/models/Currency.ts'; 3 | const ADA_HANDLE_POLICY_ID = 4 | 'f0ff48bbb7bbe9d59a40f1ce90e9e9d0ff5002ec48f232b49ca0fb9a'; 5 | export const getAdaHandles = (balance: Balance): Currency[] | undefined => { 6 | const result = balance.values().filter(({ asset, amount }) => { 7 | return asset.id.includes(ADA_HANDLE_POLICY_ID) && amount === 1n; 8 | }); 9 | 10 | if (result.length === 0) { 11 | return undefined; 12 | } 13 | 14 | return result; 15 | }; 16 | -------------------------------------------------------------------------------- /src/utils/ammMath.ts: -------------------------------------------------------------------------------- 1 | import { AssetAmount, isNative, OverallAmount } from '@ergolabs/ergo-sdk'; 2 | 3 | export function makeTarget( 4 | assetsIn: AssetAmount[], 5 | minNErgForFee: bigint, 6 | ): OverallAmount { 7 | const nativeAsset = assetsIn.filter((i) => isNative(i.asset))[0]; 8 | const isNativePool = !!nativeAsset; 9 | 10 | const totalNErgs = isNativePool 11 | ? nativeAsset.amount + minNErgForFee 12 | : minNErgForFee; 13 | 14 | const assets = assetsIn 15 | .filter((i) => !isNative(i.asset)) 16 | .map((ai) => ({ 17 | tokenId: ai.asset.id, 18 | amount: ai.amount, 19 | })); 20 | 21 | return { 22 | nErgs: totalNErgs, 23 | assets, 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/checkPool.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AmmPool, 3 | DefaultAmmPoolValidation, 4 | ValidationResult, 5 | } from '@ergolabs/ergo-dex-sdk'; 6 | 7 | import { explorer } from '../services/explorer'; 8 | 9 | const poolValidation = new DefaultAmmPoolValidation(explorer); 10 | 11 | export const checkPool = async (pool: AmmPool): Promise => { 12 | return poolValidation.validate(pool); 13 | }; 14 | -------------------------------------------------------------------------------- /src/utils/cookies.ts: -------------------------------------------------------------------------------- 1 | import Cookies from 'js-cookie'; 2 | 3 | const WALLET_COOKIE = 'wallet-connected'; 4 | 5 | class WalletCookies { 6 | setConnected() { 7 | Cookies.set(WALLET_COOKIE, 'true', { expires: 1 }); 8 | } 9 | 10 | removeConnected() { 11 | Cookies.remove(WALLET_COOKIE); 12 | } 13 | 14 | isSetConnected() { 15 | return Cookies.get(WALLET_COOKIE) === 'true'; 16 | } 17 | } 18 | 19 | const walletCookies = new WalletCookies(); 20 | 21 | export { walletCookies }; 22 | -------------------------------------------------------------------------------- /src/utils/lbsp.ts: -------------------------------------------------------------------------------- 1 | import { DateTime } from 'luxon'; 2 | 3 | import { applicationConfig } from '../applicationConfig.ts'; 4 | 5 | export const isPreLbspTimeGap = () => { 6 | return applicationConfig.cardanoAmmSwapsOpenTime > DateTime.now(); 7 | }; 8 | 9 | export const isLbspAmmPool = (poolId: string) => { 10 | return applicationConfig.lbspLiquidityPools.some((el) => el === poolId); 11 | }; 12 | 13 | export const isSpfPool = (poolId: string) => { 14 | return applicationConfig.spfPoolId === poolId; 15 | }; 16 | -------------------------------------------------------------------------------- /src/utils/map.ts: -------------------------------------------------------------------------------- 1 | import { TokenId } from '@ergolabs/ergo-sdk'; 2 | 3 | import { TOKEN_MAPPER } from '../mappers/tokenMapper'; 4 | 5 | export const getAssetNameByMappedId = (tokenId: TokenId): string | undefined => 6 | TOKEN_MAPPER.get(tokenId); 7 | -------------------------------------------------------------------------------- /src/utils/network.ts: -------------------------------------------------------------------------------- 1 | export const isCardano = (): boolean => { 2 | return document.location.href.includes('cardano'); 3 | }; 4 | -------------------------------------------------------------------------------- /src/utils/numbers.ts: -------------------------------------------------------------------------------- 1 | export const countDecimals = (value: number): number => 2 | value % 1 != 0 ? value.toString().split('.')[1].length : 0; 3 | 4 | export const isZero = (value: string | number | bigint): boolean => 5 | Number(value) === 0; 6 | -------------------------------------------------------------------------------- /src/utils/osTheme.ts: -------------------------------------------------------------------------------- 1 | export const isDarkOsTheme = (): boolean => 2 | window.matchMedia && 3 | window.matchMedia('(prefers-color-scheme: dark)').matches; 4 | -------------------------------------------------------------------------------- /src/utils/pool/index.ts: -------------------------------------------------------------------------------- 1 | import { evaluate } from 'mathjs'; 2 | 3 | export const getPoolFee = (poolFeeNum: bigint): number => { 4 | return evaluate(`(1 - ${poolFeeNum} / 1000) * 100`).toFixed(1); 5 | }; 6 | -------------------------------------------------------------------------------- /src/utils/price.ts: -------------------------------------------------------------------------------- 1 | import { AmmPool } from '../common/models/AmmPool'; 2 | import { Currency } from '../common/models/Currency'; 3 | import { math, renderFractions } from './math'; 4 | 5 | export function getPoolRatio(pool: AmmPool): Ratio { 6 | return getRatio(pool.x, pool.y); 7 | } 8 | 9 | export function getRatio(x: Currency, y: Currency): Ratio { 10 | const xAmount = renderFractions(x.amount, x.asset.decimals); 11 | const yAmount = renderFractions(y.amount, y.asset.decimals); 12 | 13 | const xPerY = math.evaluate!(`${xAmount} / ${yAmount}`).toFixed( 14 | x.asset.decimals ?? 0, 15 | ); 16 | const yPerX = math.evaluate!(`${yAmount} / ${xAmount}`).toFixed( 17 | y.asset.decimals ?? 0, 18 | ); 19 | 20 | return { xPerY, yPerX }; 21 | } 22 | -------------------------------------------------------------------------------- /src/utils/specialPools.ts: -------------------------------------------------------------------------------- 1 | import { applicationConfig } from '../applicationConfig.ts'; 2 | 3 | export const isSpecialBoostedPool = (poolId: string) => { 4 | return applicationConfig.specialRewards.some((id) => id === poolId); 5 | }; 6 | -------------------------------------------------------------------------------- /src/utils/string/addres.ts: -------------------------------------------------------------------------------- 1 | export const getShortAddress = (address: string): string => { 2 | let shortAddress = address ? address : ''; 3 | shortAddress = 4 | shortAddress.length < 10 5 | ? shortAddress 6 | : shortAddress.substring(0, 6) + 7 | '...' + 8 | shortAddress.substring(shortAddress.length - 4, shortAddress.length); 9 | 10 | return shortAddress; 11 | }; 12 | -------------------------------------------------------------------------------- /src/utils/string/splitStr.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @usage `const [addressBegin, addressSuffix] = splitStr(address);` 3 | */ 4 | export const splitStr = ( 5 | str: string | null | undefined, 6 | end = 6, 7 | ): [string, string] => { 8 | if (!str || str.length < end * 2 - 1) { 9 | return [str!, '']; 10 | } 11 | return [str.substring(0, str.length - end), str.substring(str.length - end)]; 12 | }; 13 | -------------------------------------------------------------------------------- /src/utils/string/txId.ts: -------------------------------------------------------------------------------- 1 | import { TxId } from '@ergolabs/ergo-sdk'; 2 | 3 | import { isHexString } from './string'; 4 | 5 | export const isTxId = (txId: TxId): boolean => 6 | isHexString(txId) && txId.length === 64; 7 | 8 | export const getShortTxId = (txId: TxId): string => 9 | `${txId.slice(0, 16)}...${txId.slice(48)}`; 10 | -------------------------------------------------------------------------------- /src/utils/subjectToId.ts: -------------------------------------------------------------------------------- 1 | export const subjectToId = (subject: string): string => { 2 | return `${subject.slice(0, 56)}.${subject.slice(56)}`; 3 | }; 4 | 5 | export const isSubject = (subject: string): boolean => 6 | subject.indexOf('.') === -1; 7 | -------------------------------------------------------------------------------- /src/utils/transactions.ts: -------------------------------------------------------------------------------- 1 | import { parseUserInputToFractions, renderFractions } from './math'; 2 | 3 | export const calculateTotalFee = ( 4 | fees: number[], 5 | precision: number, 6 | ): string => { 7 | const feeSum = fees.reduce( 8 | (acc: bigint, fee: number) => 9 | parseUserInputToFractions(fee, precision) + acc, 10 | 0n, 11 | ); 12 | 13 | return renderFractions(feeSum, precision); 14 | }; 15 | -------------------------------------------------------------------------------- /src/utils/userAgent.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/utils/verification.ts: -------------------------------------------------------------------------------- 1 | import { VERIFIED_POOLS } from '../mappers/verifiedPoolsMapper'; 2 | 3 | export const getVerifiedPoolByName = (poolId: string) => 4 | VERIFIED_POOLS.get(poolId); 5 | -------------------------------------------------------------------------------- /src/vite-env-override.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | import React = require('react'); 3 | export const ReactComponent: React.FC>; 4 | const src: string; 5 | export default src; 6 | } 7 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | --------------------------------------------------------------------------------