@rango-dev/widget-embedded 0.14.1-next.17 → 0.14.1-next.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/store/settings.d.ts +1 -1
- package/package.json +2 -2
- package/src/constants/languages.ts +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/Wallets.tsx", "../src/hooks/useWalletProviders.ts", "../src/store/wallets.ts", "../src/services/httpService.ts", "../src/constants/index.ts", "../src/utils/configs.ts", "../src/utils/wallets.ts", "../src/constants/numbers.ts", "../src/constants/wallets.ts", "../src/utils/numbers.ts", "../src/store/meta.ts", "../src/store/app.ts", "../src/store/selectors.ts", "../src/store/slices/config.ts", "../src/utils/common.ts", "../src/store/slices/data.ts", "../src/utils/providers.ts", "../src/Widget.tsx", "../src/components/AppRouter.tsx", "../src/constants/navigationRoutes.ts", "../src/pages/Home.tsx", "../src/components/HeaderButtons/BackButton.tsx", "../src/components/HeaderButtons/HeaderButtons.styles.ts", "../src/components/HeaderButtons/CancelButton.tsx", "../src/components/HeaderButtons/WalletButton.tsx", "../src/components/HeaderButtons/HomeButtons.tsx", "../src/components/NotificationContent/NotificationContent.tsx", "../src/store/notification.ts", "../src/store/ui.ts", "../src/components/NotificationContent/NotificationContent.styles.ts", "../src/components/NotificationContent/NotificationNotFound.tsx", "../src/components/HeaderButtons/UnreadNotificationsBadge.tsx", "../src/components/Layout/Layout.tsx", "../src/components/Layout/Layout.styles.ts", "../src/components/NoRoutes/NoRoutes.tsx", "../src/constants/errors.ts", "../src/types/routing.ts", "../src/store/settings.ts", "../src/constants/languages.ts", "../src/constants/swapSettings.ts", "../src/components/NoRoutes/NoRoutes.helper.ts", "../src/components/NoRoutes/NoRoutes.styles.ts", "../src/components/RouteErrors/RouteErrors.tsx", "../src/store/bestRoute.ts", "../src/utils/routing.ts", "../src/utils/meta.ts", "../src/utils/swap.ts", "../src/components/ConfirmWalletsModal/ConfirmWallets.helpers.ts", "../src/constants/messages.ts", "../src/components/RouteErrors/RouteErrors.styles.ts", "../src/components/RouteErrors/RouteErrorsModal.tsx", "../src/components/RouteErrors/RouteErrorsModalItem.tsx", "../src/components/SwitchFromAndTo.tsx", "../src/hooks/useSwapInput.ts", "../src/hooks/useFetchBestRoute.ts", "../src/components/UpdateUrl.tsx", "../src/hooks/useSyncStoresWithConfig.ts", "../src/components/AppRoutes.tsx", "../src/pages/ConfirmSwapPage.tsx", "../src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx", "../src/constants/warnings.ts", "../src/components/ConfirmWalletsModal/ConfirmWallets.styles.ts", "../src/components/ConfirmWalletsModal/WalletList.tsx", "../src/hooks/useWalletList.ts", "../src/pages/WalletsPage.tsx", "../src/components/WalletModal/WalletModal.tsx", "../src/components/WalletModal/WalletModalContent.tsx", "../src/components/WalletModal/WalletModalContent.styles.ts", "../src/hooks/useNavigateBack.ts", "../src/components/ConfirmWalletsModal/WalletList.styles.ts", "../src/hooks/useConfirmSwap.ts", "../src/pages/HistoryPage.tsx", "../src/components/SearchInput/SearchInput.tsx", "../src/components/SearchInput/SearchInput.styles.ts", "../src/components/SwapsGroup/SwapsGroup.tsx", "../src/components/SwapsGroup/SwapsGroup.styles.ts", "../src/utils/date.ts", "../src/utils/queue.ts", "../src/pages/LanguagePage.tsx", "../src/components/SettingsContainer/SettingsContainer.style.ts", "../src/hooks/useLanguage.ts", "../src/pages/LiquiditySourcePage.tsx", "../src/components/LoadingLiquiditySourceList/LoadingLiquiditySourceList.tsx", "../src/components/LoadingLiquiditySourceList/LoadingLiquiditySourceList.styles.ts", "../src/utils/settings.ts", "../src/pages/SelectBlockchainPage.tsx", "../src/components/BlockchainList/BlockchainList.tsx", "../src/components/BlockchainList/BlockchainList.helpers.ts", "../src/components/BlockchainList/BlockchainList.styles.ts", "../src/components/BlockchainList/LoadingBlockchainList.tsx", "../src/pages/SelectSwapItemsPage.tsx", "../src/components/BlockchainsSection/BlockchainsSection.tsx", "../src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.ts", "../src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.constants.ts", "../src/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.ts", "../src/components/BlockchainsSection/BlockchainsSection.styles.ts", "../src/components/TokenList/TokenList.tsx", "../src/utils/colors.ts", "../src/components/TokenList/LoadingTokenList.tsx", "../src/components/TokenList/TokenList.styles.ts", "../src/pages/SettingsPage.tsx", "../src/components/Slippage/Slippage.tsx", "../src/components/Slippage/Slippage.styles.ts", "../src/components/Slippage/SlippageTooltipContent.tsx", "../src/pages/SwapDetailsPage.tsx", "../src/components/SwapDetails/SwapDetails.tsx", "../src/utils/time.ts", "../src/components/SwapDetailsModal/SwapDetailsModal.tsx", "../src/components/SwapDetailsModal/SwapDetailsModal.Cancel.tsx", "../src/components/SwapDetailsModal/SwapDetailsModal.Delete.tsx", "../src/components/SwapDetailsModal/SwapDetailsModal.helpers.tsx", "../src/components/SwapDetailsModal/SwapDetailsModal.WalletState.tsx", "../src/components/SwapDetailsModal/SwapDetailsModal.styles.ts", "../src/components/SwapDetailsModal/SwapDetailsCompleteModal.tsx", "../src/components/SwapDetails/SwapDetails.helpers.tsx", "../src/components/SwapDetailsAlerts/SwapDetailsAlerts.tsx", "../src/components/SwapDetailsAlerts/SwapDetailsAlerts.Failed.tsx", "../src/components/SwapDetailsAlerts/SwapDetailsAlerts.styles.ts", "../src/components/SwapDetailsAlerts/SwapDetailsAlerts.Warning.tsx", "../src/components/SwapDetails/SwapDetails.styles.ts", "../src/components/SwapDetails/SwapDetails.Placeholder.tsx", "../src/components/LoadingSwapDetails/LoadingSwapDetails.tsx", "../src/components/LoadingSwapDetails/LoadingSwapDetails.styles.ts", "../src/components/LoadingSwapDetails/LoadingSwapDetailStep.tsx", "../src/pages/ThemePage.tsx", "../src/components/WidgetEvents.tsx", "../src/types/notification.ts", "../src/globalStyles.ts", "../src/hooks/useTheme.ts", "../src/utils/ui.ts", "../src/utils/hash.ts", "../src/QueueManager.tsx"],
|
|
4
|
-
"sourcesContent": ["import type {\n BlockchainAndTokenConfig,\n WidgetColors,\n WidgetColorsKeys,\n WidgetConfig,\n WidgetTheme,\n} from './types';\nimport type { WidgetProps } from './Widget';\nimport type {\n Route,\n RouteEvent,\n RouteFailedEvent,\n RouteStartedEvent,\n RouteSucceededEvent,\n Step,\n StepApprovalTxSucceededEvent,\n StepCheckStatusEvent,\n StepEvent,\n StepFailedEvent,\n StepOutputRevealedEvent,\n StepStartedEvent,\n StepSucceededEvent,\n StepTxExecutionBlockedEvent,\n StepTxExecutionUpdatedEvent,\n} from '@rango-dev/queue-manager-rango-preset';\nimport type {\n EventHandler as HandleWalletsUpdate,\n ProviderInterface,\n} from '@rango-dev/wallets-react';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport {\n MainEvents,\n RouteEventType,\n StepEventType,\n StepExecutionBlockedEventStatus,\n StepExecutionEventStatus,\n useEvents as useWidgetEvents,\n} from '@rango-dev/queue-manager-rango-preset';\nimport { useWallets } from '@rango-dev/wallets-react';\n\nimport { WidgetWallets } from './Wallets';\nimport { Widget } from './Widget';\n\nexport type {\n WidgetConfig,\n WalletType,\n WidgetTheme,\n WidgetColors,\n WidgetColorsKeys,\n ProviderInterface,\n BlockchainAndTokenConfig,\n WidgetProps,\n RouteEvent,\n StepEvent,\n Route,\n Step,\n RouteStartedEvent,\n RouteSucceededEvent,\n RouteFailedEvent,\n StepStartedEvent,\n StepSucceededEvent,\n StepFailedEvent,\n StepTxExecutionUpdatedEvent,\n StepTxExecutionBlockedEvent,\n StepCheckStatusEvent,\n StepApprovalTxSucceededEvent,\n StepOutputRevealedEvent,\n HandleWalletsUpdate,\n};\nexport {\n Widget,\n WidgetWallets,\n useWallets,\n useWidgetEvents,\n MainEvents,\n RouteEventType,\n StepEventType,\n StepExecutionEventStatus,\n StepExecutionBlockedEventStatus,\n};\n", "import type { WidgetConfig } from './types';\nimport type { ProvidersOptions } from './utils/providers';\nimport type { EventHandler } from '@rango-dev/wallets-react';\nimport type { Network } from '@rango-dev/wallets-shared';\nimport type { PropsWithChildren } from 'react';\n\nimport { Events, Provider } from '@rango-dev/wallets-react';\nimport { isEvmBlockchain } from 'rango-sdk';\nimport React, { createContext, useRef } from 'react';\n\nimport { useWalletProviders } from './hooks/useWalletProviders';\nimport { useMetaStore } from './store/meta';\nimport { useWalletsStore } from './store/wallets';\nimport {\n prepareAccountsForWalletStore,\n walletAndSupportedChainsNames,\n} from './utils/wallets';\n\ntype OnConnectHandler = (key: string) => void;\ninterface WidgetContextInterface {\n onConnectWallet(handler: OnConnectHandler): void;\n}\n\nexport const WidgetContext = createContext<WidgetContextInterface>({\n onConnectWallet: () => {\n return;\n },\n});\n\nexport function WidgetWallets(\n props: PropsWithChildren<{\n providers: WidgetConfig['wallets'];\n options?: ProvidersOptions;\n onUpdateState?: EventHandler;\n }>\n) {\n const { blockchains } = useMetaStore.use.meta();\n const { providers } = useWalletProviders(props.providers, props?.options);\n const disconnectWallet = useWalletsStore.use.disconnectWallet();\n const connectWallet = useWalletsStore.use.connectWallet();\n const onConnectWalletHandler = useRef<OnConnectHandler>();\n\n const evmBasedChainNames = blockchains\n .filter(isEvmBlockchain)\n .map((chain) => chain.name);\n\n const onUpdateState: EventHandler = (\n type,\n event,\n value,\n state,\n supportedBlockchains\n ) => {\n if (event === Events.ACCOUNTS) {\n if (value) {\n const supportedChainNames: Network[] | null =\n walletAndSupportedChainsNames(supportedBlockchains);\n const data = prepareAccountsForWalletStore(\n type,\n value,\n evmBasedChainNames,\n supportedChainNames\n );\n connectWallet(data);\n } else {\n disconnectWallet(type);\n }\n }\n if (event === Events.ACCOUNTS && state.connected) {\n const key = `${type}-${state.network}-${value}`;\n\n if (state.connected) {\n if (!!onConnectWalletHandler.current) {\n onConnectWalletHandler.current(key);\n } else {\n console.warn(\n `onConnectWallet handler hasn't been set. Are you sure?`\n );\n }\n }\n }\n\n if (event === Events.NETWORK && state.network) {\n const key = `${type}-${state.network}`;\n if (!!onConnectWalletHandler.current) {\n onConnectWalletHandler.current(key);\n } else {\n console.warn(`onConnectWallet handler hasn't been set. Are you sure?`);\n }\n }\n\n // propagate updates for Dapps using external wallets\n if (props.onUpdateState) {\n props.onUpdateState(type, event, value, state, supportedBlockchains);\n }\n };\n return (\n <WidgetContext.Provider\n // eslint-disable-next-line react/jsx-no-constructed-context-values\n value={{\n onConnectWallet: (handler) => {\n onConnectWalletHandler.current = handler;\n },\n }}>\n <Provider\n allBlockChains={blockchains}\n providers={providers}\n onUpdateState={onUpdateState}\n autoConnect>\n {props.children}\n </Provider>\n </WidgetContext.Provider>\n );\n}\n", "import type { WidgetConfig } from '../types';\nimport type { ProvidersOptions } from '../utils/providers';\nimport type { ProviderInterface } from '@rango-dev/wallets-react';\n\nimport { useEffect } from 'react';\n\nimport { useWalletsStore } from '../store/wallets';\nimport { matchAndGenerateProviders } from '../utils/providers';\n\nexport function useWalletProviders(\n providers: WidgetConfig['wallets'],\n options?: ProvidersOptions\n) {\n const clearConnectedWallet = useWalletsStore.use.clearConnectedWallet();\n let generateProviders: ProviderInterface[] = matchAndGenerateProviders(\n undefined,\n options\n );\n\n useEffect(() => {\n clearConnectedWallet();\n generateProviders = matchAndGenerateProviders(providers, {\n walletConnectProjectId: options?.walletConnectProjectId,\n });\n }, [providers?.length]);\n\n return {\n providers: generateProviders,\n };\n}\n", "import type { Wallet } from '../types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { create } from 'zustand';\nimport { subscribeWithSelector } from 'zustand/middleware';\n\nimport { httpService } from '../services/httpService';\nimport {\n isAccountAndWalletMatched,\n makeBalanceFor,\n resetConnectedWalletState,\n} from '../utils/wallets';\n\nimport { useMetaStore } from './meta';\nimport createSelectors from './selectors';\n\nexport type TokenBalance = {\n chain: string;\n symbol: string;\n ticker: string;\n address: string | null;\n rawAmount: string;\n decimal: number | null;\n amount: string;\n logo: string | null;\n usdPrice: number | null;\n};\n\nexport interface ConnectedWallet extends Wallet {\n balances: TokenBalance[] | null;\n explorerUrl: string | null;\n selected: boolean;\n loading: boolean;\n error: boolean;\n}\n\ninterface WalletsStore {\n connectedWallets: ConnectedWallet[];\n customDestination: string;\n loading: boolean;\n connectWallet: (accounts: Wallet[]) => void;\n disconnectWallet: (walletType: WalletType) => void;\n selectWallets: (wallets: { walletType: string; chain: string }[]) => void;\n clearConnectedWallet: () => void;\n getWalletsDetails: (accounts: Wallet[], shouldRetry?: boolean) => void;\n}\n\nexport const useWalletsStore = createSelectors(\n create<WalletsStore>()(\n subscribeWithSelector((set, get) => ({\n connectedWallets: [],\n customDestination: '',\n loading: false,\n connectWallet: (accounts) => {\n const getWalletsDetails = get().getWalletsDetails;\n set((state) => ({\n loading: true,\n connectedWallets: state.connectedWallets\n .filter((wallet) => wallet.walletType !== accounts[0].walletType)\n .concat(\n accounts.map((account) => {\n const shouldMarkWalletAsSelected = !state.connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.chain === account.chain &&\n connectedWallet.selected\n );\n return {\n balances: [],\n address: account.address,\n chain: account.chain,\n explorerUrl: null,\n walletType: account.walletType,\n selected: shouldMarkWalletAsSelected,\n loading: true,\n error: false,\n };\n })\n ),\n }));\n getWalletsDetails(accounts);\n },\n disconnectWallet: (walletType) => {\n set((state) => {\n const selectedWallets = state.connectedWallets\n .filter(\n (connectedWallet) =>\n connectedWallet.selected &&\n connectedWallet.walletType !== walletType\n )\n .map((selectedWallet) => selectedWallet.chain);\n return {\n connectedWallets: state.connectedWallets\n .filter(\n (connectedWallet) => connectedWallet.walletType !== walletType\n )\n .map((connectedWallet) => {\n const anyWalletSelectedForBlockchain = selectedWallets.includes(\n connectedWallet.chain\n );\n if (anyWalletSelectedForBlockchain) {\n return connectedWallet;\n }\n selectedWallets.push(connectedWallet.chain);\n return { ...connectedWallet, selected: true };\n }),\n };\n });\n },\n selectWallets: (wallets) =>\n set((state) => ({\n connectedWallets: state.connectedWallets.map((connectedWallet) => {\n const walletSelected = !!wallets.find(\n (wallet) =>\n wallet.chain === connectedWallet.chain &&\n wallet.walletType !== connectedWallet.walletType &&\n connectedWallet.selected\n );\n const walletNotSelected = !!wallets.find(\n (wallet) =>\n wallet.chain === connectedWallet.chain &&\n wallet.walletType === connectedWallet.walletType &&\n !connectedWallet.selected\n );\n if (walletSelected) {\n return { ...connectedWallet, selected: false };\n } else if (walletNotSelected) {\n return { ...connectedWallet, selected: true };\n }\n\n return connectedWallet;\n }),\n })),\n clearConnectedWallet: () =>\n set(() => ({\n connectedWallets: [],\n selectedWallets: [],\n })),\n getWalletsDetails: async (accounts, shouldRetry = true) => {\n const getWalletsDetails = get().getWalletsDetails;\n const { tokens } = useMetaStore.getState().meta;\n set((state) => ({\n loading: true,\n connectedWallets: state.connectedWallets.map((wallet) => {\n return accounts.find((account) =>\n isAccountAndWalletMatched(account, wallet)\n )\n ? { ...wallet, loading: true }\n : wallet;\n }),\n }));\n try {\n const data = accounts.map(({ address, chain }) => ({\n address,\n blockchain: chain,\n }));\n const response = await httpService().getWalletsDetails(data);\n const retrievedBalance = response.wallets;\n if (retrievedBalance) {\n set((state) => ({\n loading: false,\n connectedWallets: state.connectedWallets.map(\n (connectedWallet) => {\n const matchedAccount = accounts.find((account) =>\n isAccountAndWalletMatched(account, connectedWallet)\n );\n const retrievedBalanceAccount = retrievedBalance.find(\n (balance) =>\n balance.address === connectedWallet.address &&\n balance.blockChain === connectedWallet.chain\n );\n if (\n retrievedBalanceAccount?.failed &&\n matchedAccount &&\n shouldRetry\n ) {\n getWalletsDetails([matchedAccount], false);\n }\n return matchedAccount && retrievedBalanceAccount\n ? {\n ...connectedWallet,\n explorerUrl: retrievedBalanceAccount.explorerUrl,\n balances: makeBalanceFor(\n retrievedBalanceAccount,\n tokens\n ),\n }\n : connectedWallet;\n }\n ),\n }));\n } else {\n throw new Error('Wallet not found');\n }\n } catch (error) {\n set((state) => ({\n loading: false,\n connectedWallets: state.connectedWallets.map((balance) => {\n return accounts.find((account) =>\n isAccountAndWalletMatched(account, balance)\n )\n ? resetConnectedWalletState(balance)\n : balance;\n }),\n }));\n }\n },\n }))\n )\n);\n\nexport const fetchingBalanceSelector = (state: WalletsStore) =>\n !!state.connectedWallets.find((wallet) => wallet.loading);\n", "import { RangoClient } from 'rango-sdk';\n\nimport { getConfig } from '../utils/configs';\n\nlet rango: RangoClient | undefined = undefined;\n\nexport const httpService = () => {\n if (rango) {\n return rango;\n }\n rango = new RangoClient(getConfig('API_KEY'));\n return rango;\n};\n", "export const RANGO_PUBLIC_API_KEY = 'c6381a79-2817-4602-83bf-6a641a409e32';\n", "import { RANGO_PUBLIC_API_KEY } from '../constants';\n\nexport interface Configs {\n API_KEY: string;\n}\n\nlet configs: Configs = {\n API_KEY: RANGO_PUBLIC_API_KEY,\n};\n\nexport function getConfig(name: keyof Configs) {\n return configs[name];\n}\n\nexport function setConfig(name: keyof Configs, value: any) {\n configs[name] = value;\n\n return value;\n}\n\n/**\n * Getting new configs from params and reset the value of global `configs` with provided param.\n */\nexport function initConfig(nextConfigs: Configs) {\n let clonedConfigs;\n if (typeof structuredClone === 'function') {\n clonedConfigs = structuredClone(nextConfigs);\n } else {\n clonedConfigs = JSON.parse(JSON.stringify(nextConfigs));\n }\n configs = clonedConfigs;\n return configs;\n}\n\nexport const DEFAULT_PRIMARY_RADIUS = 20;\nexport const DEFAULT_SECONDARY_RADIUS = 25;\nexport const DEFAULT_FONT_FAMILY = 'Roboto';\n\nexport const THEME_CLASS_NAME_PREFIX = `theme-widget`;\n", "import type { TokenWithBalance } from '../components/TokenList';\nimport type { ConnectedWallet, TokenBalance } from '../store/wallets';\nimport type { Wallet } from '../types';\nimport type { WalletInfo as ModalWalletInfo } from '@rango-dev/ui';\nimport type {\n Network,\n WalletInfo,\n WalletState,\n WalletType,\n WalletTypes,\n} from '@rango-dev/wallets-shared';\nimport type {\n BestRouteResponse,\n BlockchainMeta,\n Token,\n WalletDetail,\n} from 'rango-sdk';\n\nimport { WalletState as WalletStatus } from '@rango-dev/ui';\nimport { readAccountAddress } from '@rango-dev/wallets-react';\nimport {\n detectInstallLink,\n getCosmosExperimentalChainInfo,\n isEvmAddress,\n KEPLR_COMPATIBLE_WALLETS,\n Networks,\n} from '@rango-dev/wallets-shared';\nimport BigNumber from 'bignumber.js';\nimport { isCosmosBlockchain } from 'rango-types';\n\nimport { ZERO } from '../constants/numbers';\nimport { EXCLUDED_WALLETS } from '../constants/wallets';\n\nimport { numberToString } from './numbers';\n\nexport function mapStatusToWalletState(state: WalletState): WalletStatus {\n switch (true) {\n case state.connected:\n return WalletStatus.CONNECTED;\n case state.connecting:\n return WalletStatus.CONNECTING;\n case !state.installed:\n return WalletStatus.NOT_INSTALLED;\n default:\n return WalletStatus.DISCONNECTED;\n }\n}\n\nexport function mapWalletTypesToWalletInfo(\n getState: (type: WalletType) => WalletState,\n getWalletInfo: (type: WalletType) => WalletInfo,\n list: WalletType[],\n chain?: string\n): ModalWalletInfo[] {\n return list\n .filter((wallet) => !EXCLUDED_WALLETS.includes(wallet as WalletTypes))\n .filter((wallet) => {\n const { supportedChains, hideWhenNotInstalled } = getWalletInfo(wallet);\n if (hideWhenNotInstalled && !getState(wallet).installed) {\n return false;\n }\n if (chain) {\n return !!supportedChains.find(\n (supportedChain) => supportedChain.name === chain\n );\n }\n return true;\n })\n .map((type) => {\n const { name, img: image, installLink } = getWalletInfo(type);\n const state = mapStatusToWalletState(getState(type));\n return {\n title: name,\n image,\n link: detectInstallLink(installLink),\n state,\n type,\n };\n });\n}\n\nexport function walletAndSupportedChainsNames(\n supportedBlockchains: BlockchainMeta[]\n): Network[] | null {\n if (!supportedBlockchains) {\n return null;\n }\n let walletAndSupportedChainsNames: Network[] = [];\n walletAndSupportedChainsNames = supportedBlockchains.map(\n (blockchainMeta) => blockchainMeta.name\n );\n\n return walletAndSupportedChainsNames;\n}\n\nexport function prepareAccountsForWalletStore(\n wallet: WalletType,\n accounts: string[],\n evmBasedChains: string[],\n supportedChainNames: Network[] | null\n): Wallet[] {\n const result: Wallet[] = [];\n\n function addAccount(network: Network, address: string) {\n const accountForChainAlreadyExists = !!result.find(\n (account) => account.chain === network\n );\n if (!accountForChainAlreadyExists) {\n const newAccount: Wallet = {\n address,\n chain: network,\n walletType: wallet,\n };\n\n result.push(newAccount);\n }\n }\n\n const supportedBlockchains = supportedChainNames || [];\n\n accounts.forEach((account) => {\n const { address, network } = readAccountAddress(account);\n\n const hasLimitation = supportedBlockchains.length > 0;\n const isSupported = supportedBlockchains.includes(network);\n const isUnknown = network === Networks.Unknown;\n const notSupportedNetworkByWallet =\n hasLimitation && !isSupported && !isUnknown;\n\n /*\n * Here we check given `network` is not supported by wallet\n * And also the network is known.\n */\n if (notSupportedNetworkByWallet) {\n return;\n }\n\n /*\n * In some cases we can handle unknown network by checking its address\n * pattern and act on it.\n * Example: showing our evm compatible network when the unknown network is evm.\n * Otherwise, we stop executing this function.\n */\n const isUnknownAndEvmBased =\n network === Networks.Unknown && isEvmAddress(address);\n if (isUnknown && !isUnknownAndEvmBased) {\n return;\n }\n\n const isEvmBasedChain = evmBasedChains.includes(network);\n\n // If it's an evm network, we will add the address to all the evm chains.\n if (isEvmBasedChain || isUnknownAndEvmBased) {\n /*\n * all evm chains are not supported in wallets, so we are adding\n * only to those that are supported by wallet.\n */\n const evmChainsSupportedByWallet = supportedBlockchains.filter((chain) =>\n evmBasedChains.includes(chain)\n );\n\n evmChainsSupportedByWallet.forEach((network) => {\n /*\n * EVM addresses are not case sensitive.\n * Some wallets like Binance-chain return some letters in uppercase which produces bugs in our wallet state.\n */\n addAccount(network, address.toLowerCase());\n });\n } else {\n addAccount(network, address);\n }\n });\n\n return result;\n}\n\nexport function getRequiredChains(route: BestRouteResponse | null) {\n const wallets: string[] = [];\n\n route?.result?.swaps.forEach((swap) => {\n const currentStepFromBlockchain = swap.from.blockchain;\n const currentStepToBlockchain = swap.to.blockchain;\n if (!wallets.includes(currentStepFromBlockchain)) {\n wallets.push(currentStepFromBlockchain);\n }\n if (!wallets.includes(currentStepToBlockchain)) {\n wallets.push(currentStepToBlockchain);\n }\n\n // Check if internalSwaps array exists\n if (swap.internalSwaps && Array.isArray(swap.internalSwaps)) {\n swap.internalSwaps.forEach((internalSwap) => {\n const internalStepFromBlockchain = internalSwap.from.blockchain;\n const internalStepToBlockchain = internalSwap.to.blockchain;\n if (!wallets.includes(internalStepFromBlockchain)) {\n wallets.push(internalStepFromBlockchain);\n }\n if (!wallets.includes(internalStepToBlockchain)) {\n wallets.push(internalStepToBlockchain);\n }\n });\n }\n });\n return wallets;\n}\n\ntype Blockchain = { name: string; accounts: ConnectedWallet[] };\n\nexport function getBalanceFromWallet(\n connectedWallets: ConnectedWallet[],\n chain: string,\n symbol: string,\n address: string | null\n): TokenBalance | null {\n if (connectedWallets.length === 0) {\n return null;\n }\n\n const selectedChainWallets = connectedWallets.filter(\n (wallet) => wallet.chain === chain\n );\n if (selectedChainWallets.length === 0) {\n return null;\n }\n\n return (\n selectedChainWallets\n .map(\n (wallet) =>\n wallet.balances?.find(\n (balance) =>\n (address !== null && balance.address === address) ||\n (address === null &&\n balance.address === address &&\n balance.symbol === symbol)\n ) || null\n )\n .filter((balance) => balance !== null)\n .sort(\n (a, b) => parseFloat(b?.amount || '0') - parseFloat(a?.amount || '1')\n )\n .find(() => true) || null\n );\n}\n\nexport function isAccountAndWalletMatched(\n account: Wallet,\n connectedWallet: ConnectedWallet\n) {\n return (\n account.address === connectedWallet.address &&\n account.chain === connectedWallet.chain &&\n account.walletType === connectedWallet.walletType\n );\n}\n\nexport function makeBalanceFor(\n retrievedBalance: WalletDetail,\n tokens: Token[]\n): TokenBalance[] {\n const { blockChain: chain, balances = [] } = retrievedBalance;\n return (\n balances?.map((tokenBalance) => ({\n chain,\n symbol: tokenBalance.asset.symbol,\n ticker: tokenBalance.asset.symbol,\n address: tokenBalance.asset.address || null,\n rawAmount: tokenBalance.amount.amount,\n decimal: tokenBalance.amount.decimals,\n amount: new BigNumber(tokenBalance.amount.amount)\n .shiftedBy(-tokenBalance.amount.decimals)\n .toFixed(),\n logo: '',\n usdPrice:\n getUsdPrice(\n chain,\n tokenBalance.asset.symbol,\n tokenBalance.asset.address,\n tokens\n ) || null,\n })) || []\n );\n}\n\nexport function resetConnectedWalletState(\n connectedWallet: ConnectedWallet\n): ConnectedWallet {\n return { ...connectedWallet, loading: false, error: true };\n}\n\nexport const calculateWalletUsdValue = (connectedWallet: ConnectedWallet[]) => {\n const uniqueAccountAddresses = new Set<string | null>();\n const uniqueBalance: ConnectedWallet[] = connectedWallet?.reduce(\n (acc: ConnectedWallet[], current: ConnectedWallet) => {\n return acc.findIndex(\n (i) => i.address === current.address && i.chain === current.chain\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n ) === -1\n ? [...acc, current]\n : acc;\n },\n []\n );\n\n const modifiedWalletBlockchains = uniqueBalance?.map((chain) => {\n const modifiedWalletBlockchain: Blockchain = {\n name: chain.chain,\n accounts: [],\n };\n if (!uniqueAccountAddresses.has(chain.address)) {\n uniqueAccountAddresses.add(chain.address);\n }\n uniqueAccountAddresses.forEach((accountAddress) => {\n if (chain.address === accountAddress) {\n modifiedWalletBlockchain.accounts.push(chain);\n }\n });\n return modifiedWalletBlockchain;\n });\n const total = numberToString(\n modifiedWalletBlockchains\n ?.flatMap((b) => b.accounts)\n ?.flatMap((a) => a?.balances)\n ?.map((b) =>\n new BigNumber(b?.amount || ZERO).multipliedBy(b?.usdPrice || 0)\n )\n ?.reduce((a, b) => a.plus(b), ZERO) || ZERO\n ).toString();\n\n return numberWithThousandSeparator(total);\n};\n\nfunction numberWithThousandSeparator(number: string | number): string {\n const parts = number.toString().split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n return parts.join('.');\n}\n\nexport const sortTokens = (tokens: TokenWithBalance[]): TokenWithBalance[] => {\n const walletConnected = !!tokens.some((token) => token.balance);\n if (!walletConnected) {\n return tokens\n .filter((token) => !token.address)\n .concat(\n tokens.filter((token) => token.address && !token.isSecondaryCoin),\n tokens.filter((token) => token.isSecondaryCoin)\n );\n }\n\n return tokens\n .filter((token) => !!token.balance)\n .sort(\n (tokenA, tokenB) =>\n parseFloat(tokenB.balance?.usdValue || '0') -\n parseFloat(tokenA.balance?.usdValue || '0')\n )\n .concat(\n tokens.filter((token) => !token.balance && !token.isSecondaryCoin),\n tokens.filter((token) => !token.balance && token.isSecondaryCoin)\n );\n};\n\nexport const getUsdPrice = (\n blockchain: string,\n symbol: string,\n address: string | null,\n allTokens: Token[]\n): number | null => {\n const token = allTokens?.find(\n (t) =>\n t.blockchain === blockchain &&\n t.symbol?.toUpperCase() === symbol?.toUpperCase() &&\n t.address === address\n );\n return token?.usdPrice || null;\n};\nexport const isExperimentalChain = (\n blockchains: BlockchainMeta[],\n wallet: string\n): boolean => {\n const cosmosExperimentalChainInfo = getCosmosExperimentalChainInfo(\n Object.entries(blockchains)\n .map(([, blockchainMeta]) => blockchainMeta)\n .filter(isCosmosBlockchain)\n );\n return (\n cosmosExperimentalChainInfo &&\n cosmosExperimentalChainInfo[wallet]?.experimental\n );\n};\n\nexport const getKeplrCompatibleConnectedWallets = (\n selectableWallets: Wallet[]\n): WalletType[] => {\n const connectedWalletTypes = new Set(\n selectableWallets.map((wallet) => {\n return wallet.walletType;\n })\n );\n\n return KEPLR_COMPATIBLE_WALLETS.filter((compatibleWallet) =>\n connectedWalletTypes.has(compatibleWallet)\n );\n};\n\nexport function getTokensWithBalance(\n tokens: TokenWithBalance[],\n connectedWallets: ConnectedWallet[]\n): TokenWithBalance[] {\n return tokens.map(({ balance, ...otherProps }) => {\n const tokenAmount = numberToString(\n new BigNumber(\n getBalanceFromWallet(\n connectedWallets,\n otherProps.blockchain,\n otherProps.symbol,\n otherProps.address\n )?.amount || ZERO\n )\n );\n\n let tokenUsdValue = '';\n if (otherProps.usdPrice) {\n tokenUsdValue = numberToString(\n new BigNumber(\n getBalanceFromWallet(\n connectedWallets,\n otherProps.blockchain,\n otherProps.symbol,\n otherProps.address\n )?.amount || ZERO\n ).multipliedBy(otherProps.usdPrice)\n );\n }\n\n return {\n ...otherProps,\n ...(tokenAmount !== '0' && {\n balance: { amount: tokenAmount, usdValue: tokenUsdValue },\n }),\n };\n });\n}\n\nexport function getTokensBalanceFromWalletAndSort(\n tokens: TokenWithBalance[],\n connectedWallets: ConnectedWallet[]\n) {\n const list =\n connectedWallets.length > 0\n ? getTokensWithBalance(tokens, connectedWallets)\n : tokens;\n list.sort((tokenA, tokenB) => {\n if (tokenA.balance?.usdValue && tokenB.balance?.usdValue) {\n return (\n parseFloat(tokenB.balance.usdValue) -\n parseFloat(tokenA.balance.usdValue)\n );\n }\n\n if (!tokenA.balance?.usdValue && tokenB.balance?.usdValue) {\n return 1;\n }\n\n if (tokenA.balance?.usdValue && !tokenB.balance?.usdValue) {\n return -1;\n }\n\n if (!tokenA.balance?.usdValue && !tokenB.balance?.usdValue) {\n return (\n parseFloat(tokenB.balance?.amount || '0') -\n parseFloat(tokenA.balance?.amount || '0')\n );\n }\n\n return 0;\n });\n\n return list;\n}\n\nexport function getSortedTokens(\n chain: BlockchainMeta | null,\n tokens: Token[],\n connectedWallets: ConnectedWallet[],\n otherChainTokens: TokenWithBalance[]\n): TokenWithBalance[] {\n const fromChainEqualsToToBlockchain =\n chain?.name === otherChainTokens[0]?.name;\n if (fromChainEqualsToToBlockchain) {\n return otherChainTokens;\n }\n\n const filteredTokens = tokens.filter(\n (token) => token.blockchain === chain?.name\n );\n return sortTokens(getTokensWithBalance(filteredTokens, connectedWallets));\n}\n\nexport function tokensAreEqual(\n tokenA: Pick<Token, 'blockchain' | 'symbol' | 'address'> | null,\n tokenB: Pick<Token, 'blockchain' | 'symbol' | 'address'> | null\n) {\n return (\n tokenA?.blockchain === tokenB?.blockchain &&\n tokenA?.symbol === tokenB?.symbol &&\n tokenA?.address === tokenB?.address\n );\n}\n\nexport function sortWalletsBasedOnConnectionState(\n wallets: ModalWalletInfo[]\n): ModalWalletInfo[] {\n return wallets.sort(\n (a, b) =>\n Number(b.state === WalletStatus.CONNECTED) -\n Number(a.state === WalletStatus.CONNECTED) ||\n Number(\n b.state === WalletStatus.DISCONNECTED ||\n b.state === WalletStatus.CONNECTING\n ) -\n Number(\n a.state === WalletStatus.DISCONNECTED ||\n a.state === WalletStatus.CONNECTING\n )\n );\n}\n\nexport function getConciseAddress(\n address: string,\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n maxChars = 8,\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n ellipsisLength = 3\n): string {\n if (address.length < 2 * maxChars + ellipsisLength) {\n return address;\n }\n const start = address.slice(0, maxChars);\n const end = address.slice(-maxChars);\n return `${start}${'.'.repeat(ellipsisLength)}${end}`;\n}\n\nexport function getAddress({\n chain,\n connectedWallets,\n walletType,\n}: {\n connectedWallets: ConnectedWallet[];\n walletType: string;\n chain: string;\n}): string | undefined {\n return connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === walletType &&\n connectedWallet.chain === chain\n )?.address;\n}\n", "import BigNumber from 'bignumber.js';\n\nexport const ZERO = new BigNumber(0);\n", "import { WalletTypes } from '@rango-dev/wallets-shared';\n\nexport const EXCLUDED_WALLETS = [WalletTypes.LEAP];\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\n\nimport type { BestRouteResponse } from 'rango-sdk';\n\nimport { BigNumber } from 'bignumber.js';\n\nexport const percentToString = (p: number, fractions = 0): string =>\n (p * 100).toFixed(fractions);\n\nexport const secondsToString = (s: number): string => {\n const seconds = (s % 60).toString().padStart(2, '0');\n const minutes = parseInt((s / 60).toString())\n .toString()\n .padStart(2, '0');\n return `${minutes}:${seconds}`;\n};\n\nexport const numberToString = (\n number: BigNumber | string | null | undefined,\n minDecimals: number | null = null,\n maxDecimals: number | null = null\n): string => {\n if (number === null || number === undefined) {\n return '';\n }\n if (number === '') {\n return '';\n }\n const n = new BigNumber(number);\n const roundingMode = 1;\n let maxI = 1000;\n for (let i = 0; i < 60; i++) {\n if (new BigNumber(n.toFixed(i, roundingMode)).eq(n)) {\n maxI = i;\n break;\n }\n }\n\n if (n.gte(10000)) {\n return n.toFormat(0, roundingMode);\n }\n if (n.gte(1000)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))\n ),\n roundingMode\n );\n }\n if (n.gte(100)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))\n ),\n roundingMode\n );\n }\n if (n.gte(1)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 2))\n ),\n roundingMode\n );\n }\n if (n.gte(0.01)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 4))\n ),\n roundingMode\n );\n }\n for (let i = minDecimals || 4; i < 17; i++) {\n if (n.gte(Math.pow(10, -i))) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, i))\n ),\n roundingMode\n );\n }\n }\n if (n.isEqualTo(0)) {\n return '0';\n }\n\n return n.toFormat(\n Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 8))),\n roundingMode\n );\n};\n\nexport const convertBigNumberToHex = (\n value: BigNumber,\n decimals: number\n): string => {\n return '0x' + value.shiftedBy(decimals).toString(16);\n};\n\nexport const uint8ArrayToHex = (buffer: Uint8Array): string => {\n // buffer is an ArrayBuffer\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return [...buffer].map((x) => x.toString(16).padStart(2, '0')).join('');\n};\n\nexport function dollarToConciseString(num: number | undefined): string {\n if (!num) {\n return '-';\n }\n if (num < 1) {\n return ' < 1$';\n }\n if (num < 1000) {\n return numberToString(new BigNumber(num)) + '$';\n }\n if (num < 10_000) {\n return parseInt((num / 100).toString()) / 10 + 'K';\n }\n if (num < 1_000_000) {\n return parseInt((num / 1000).toString()) + 'K';\n }\n if (num < 100_000_000) {\n return parseInt((num / 100000).toString()) / 10 + 'M';\n }\n return parseInt((num / 1000000).toString()) + 'M';\n}\n\nexport function removeExtraDecimals(num: string, maxDecimals: number): string {\n try {\n if (!num.includes('.')) {\n return num;\n }\n const [b, f] = num.split('.');\n if (f && f.length > maxDecimals) {\n return `${b}.${f.substring(0, maxDecimals)}`;\n }\n return num;\n } catch (e) {\n return num;\n }\n}\n\nexport const totalArrivalTime = (\n data: { estimatedTimeInSeconds: number | null }[] | undefined\n) => data?.reduce((a, b) => a + (b.estimatedTimeInSeconds ?? 0), 0) || 0;\n\nexport const rawFees = (data: BestRouteResponse): string =>\n (\n data?.result?.swaps?.flatMap((s) =>\n s.fee.map((f) => ({ swapperId: s.swapperId, fee: f }))\n ) || []\n )\n .reduce((partialSum, a) => partialSum + parseFloat(a.fee.amount), 0)\n .toFixed(3);\n\nexport const containsText = (text: string, searchText: string) =>\n text.toLowerCase().indexOf(searchText.toLowerCase()) > -1;\n\nexport const isPositiveNumber = (text?: string) =>\n !!text && parseFloat(text) > 0;\n10;\n\nexport function limitDecimalPlaces(\n numberString: string,\n maxDecimalPlaces = 4\n): string {\n const number = parseFloat(numberString);\n if (isNaN(number)) {\n return numberString;\n } // Return the original string if it's not a valid number\n\n const multiplier = Math.pow(10, maxDecimalPlaces);\n const roundedNumber = Math.round(number * multiplier) / multiplier;\n return roundedNumber.toString();\n}\n", "import type { TokenWithBalance } from '../components/TokenList';\nimport type { MetaResponse } from 'rango-sdk';\n\nimport { create } from 'zustand';\n\nimport { useAppStore } from './app';\nimport createSelectors from './selectors';\n\nexport type LoadingStatus = 'loading' | 'success' | 'failed';\n\nexport interface MetaState {\n meta: MetaResponse & { tokens: TokenWithBalance[] };\n loadingStatus: LoadingStatus;\n fetchMeta: () => Promise<void>;\n}\n\nexport const useMetaStore = createSelectors(\n create<MetaState>()((set) => ({\n meta: { blockchains: [], popularTokens: [], swappers: [], tokens: [] },\n loadingStatus: 'loading',\n fetchMeta: async () => {\n try {\n await useAppStore.getState().fetch();\n\n const state = useAppStore.getState();\n const response: MetaResponse = {\n blockchains: state.blockchains(),\n tokens: state.tokens(),\n popularTokens: state._popularTokens,\n swappers: state._swappers,\n };\n\n set({ meta: response, loadingStatus: 'success' });\n } catch (error) {\n set({ loadingStatus: 'failed' });\n }\n },\n }))\n);\n", "import type { ConfigSlice } from './slices/config';\nimport type { DataSlice } from './slices/data';\n\nimport { create } from 'zustand';\n\nimport createSelectors from './selectors';\nimport { createConfigSlice } from './slices/config';\nimport { createDataSlice } from './slices/data';\n\nconst store = create<DataSlice & ConfigSlice>()((...a) => ({\n ...createDataSlice(...a),\n ...createConfigSlice(...a),\n}));\n\nexport const useAppStore = createSelectors(store);\n", "import { StoreApi, UseBoundStore } from 'zustand';\n\ntype State = object;\n\ntype WithSelectors<S> = S extends { getState: () => infer T }\n ? S & { use: { [K in keyof T]: () => T[K] } }\n : never;\n\nconst createSelectors = <S extends UseBoundStore<StoreApi<State>>>(_store: S) => {\n let store = _store as WithSelectors<typeof _store>;\n store.use = {};\n for (let k of Object.keys(store.getState())) {\n (store.use as any)[k] = () => store((s) => s[k as keyof typeof s]);\n }\n\n return store;\n};\n\nexport default createSelectors;\n", "import type { WidgetConfig } from '../../types';\nimport type { StateCreator } from 'zustand';\n\nconst initConfig: WidgetConfig = { apiKey: '' };\n\nexport type ConfigSlice = {\n config: WidgetConfig;\n\n updateConfig: (config: WidgetConfig) => void;\n};\n\nexport const createConfigSlice: StateCreator<ConfigSlice> = (set, get) => ({\n config: initConfig,\n\n // Actions\n updateConfig: (nextConfig: WidgetConfig) => {\n const currentConfig = get().config;\n\n set({\n config: {\n ...currentConfig,\n ...nextConfig,\n },\n });\n },\n});\n", "export function removeDuplicateFrom<T>(array: T[]): T[] {\n return Array.from(new Set(array));\n}\n\nexport function areEqual(\n array1: (number | string)[],\n array2: (number | string)[]\n) {\n return (\n array1.length === array2.length && array1.every((v, i) => v === array2[i])\n );\n}\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function debounce(fn: Function, time: number) {\n let timeoutId: ReturnType<typeof setTimeout> | null;\n return wrapper;\n function wrapper(...args: any) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n timeoutId = null;\n fn(...args);\n }, time);\n }\n}\n\nexport function containsText(text: string, searchText: string): boolean {\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n return text.toLowerCase().indexOf(searchText.toLowerCase()) > -1;\n}\n\nexport const getContainer = () =>\n document.getElementById('swap-box') as HTMLElement;\n", "// We keep all the received data from server in this slice\n\nimport type { ConfigSlice } from './config';\nimport type { BlockchainMeta, SwapperMeta, Token } from 'rango-sdk';\nimport type { StateCreator } from 'zustand';\n\nimport { httpService as sdk } from '../../services/httpService';\nimport { containsText } from '../../utils/common';\nimport { tokensAreEqual } from '../../utils/wallets';\n\ntype BlockchainOptions = {\n type?: 'source' | 'destination';\n};\n\ntype TokenOptions = {\n type?: 'source' | 'destination';\n // filter by an specific blockchain\n blockchain?: string;\n searchFor?: string;\n};\n\nexport interface DataSlice {\n _blockchains: BlockchainMeta[];\n _tokens: Token[];\n _popularTokens: Token[];\n _swappers: SwapperMeta[];\n\n blockchains: (options?: BlockchainOptions) => BlockchainMeta[];\n tokens: (options?: TokenOptions) => Token[];\n isTokenPinned: (token: Token) => boolean;\n\n fetch: () => Promise<void>;\n}\n\nexport const createDataSlice: StateCreator<\n DataSlice & ConfigSlice,\n [],\n [],\n DataSlice\n> = (set, get) => ({\n // State\n _blockchains: [],\n _tokens: [],\n _popularTokens: [],\n _swappers: [],\n\n // Selectors\n blockchains: (options) => {\n const blockchainsFromState = get()._blockchains;\n\n if (!options || !options?.type) {\n return blockchainsFromState;\n }\n\n const config = get().config;\n const supportedBlockchainsFromConfig =\n (options.type === 'source'\n ? config.from?.blockchains\n : config.to?.blockchains) ?? [];\n\n const list = blockchainsFromState.filter((blockchain) => {\n if (\n supportedBlockchainsFromConfig.length > 0 &&\n !supportedBlockchainsFromConfig.includes(blockchain.name)\n ) {\n return false;\n }\n\n return true;\n });\n\n return list;\n },\n tokens: (options) => {\n const tokensFromState = get()._tokens;\n\n if (!options || !options?.type) {\n return tokensFromState;\n }\n\n const config = get().config;\n const supportedTokensFromConfig =\n (options.type === 'source' ? config.from?.tokens : config.to?.tokens) ??\n [];\n const blockchains = get().blockchains({\n type: options.type,\n });\n\n const list = tokensFromState\n .filter((token) => {\n // If there is a list of tokens in config, we only keep them.\n if (\n supportedTokensFromConfig.length > 0 &&\n !supportedTokensFromConfig.some((asset) => {\n return tokensAreEqual(asset, token);\n })\n ) {\n return false;\n }\n\n // If a specific blockchain has passed, we only keep that blockchain's tokens.\n if (!!options.blockchain && token.blockchain !== options.blockchain) {\n return false;\n }\n\n // Check only available blockchains\n if (\n !blockchains.some((blockchain) => {\n return blockchain.name === token.blockchain;\n })\n ) {\n return false;\n }\n\n // Search functionality\n if (options.searchFor) {\n if (\n containsText(token.symbol, options.searchFor) ||\n containsText(token.address || '', options.searchFor) ||\n containsText(token.name || '', options.searchFor)\n ) {\n return true;\n }\n\n return false;\n }\n\n return true;\n })\n .sort((a, b) => {\n // Check pinned tokens\n if (get().isTokenPinned(a)) {\n return -1;\n }\n if (get().isTokenPinned(b)) {\n return 1;\n }\n\n // Check secondary coins\n if (a.isSecondaryCoin) {\n return 1;\n }\n if (b.isSecondaryCoin) {\n return -1;\n }\n\n // Check it has an address or not.\n if (!a.address && b.address) {\n return -1;\n }\n if (a.address && !b.address) {\n return 1;\n }\n\n return 0;\n });\n\n return list;\n },\n isTokenPinned: (token) => {\n const pinned = !!get().config.pinnedTokens?.some((pinnedToken) =>\n tokensAreEqual(pinnedToken, token)\n );\n return pinned;\n },\n\n // Actions\n fetch: async () => {\n const response = await sdk().getAllMetadata();\n\n const blockchains: BlockchainMeta[] = [];\n const tokens: Token[] = [];\n const popularTokens: Token[] = response.popularTokens;\n const swappers: SwapperMeta[] = response.swappers;\n\n const blockchainsWithAtLeastOneToken = new Set();\n\n response.tokens.forEach((token) => {\n blockchainsWithAtLeastOneToken.add(token.blockchain);\n\n tokens.push(token);\n });\n\n response.blockchains.forEach((blockchain) => {\n if (\n blockchain.enabled &&\n blockchainsWithAtLeastOneToken.has(blockchain.name)\n ) {\n blockchains.push(blockchain);\n }\n });\n\n // Sort\n blockchains.sort((a, b) => a.sort - b.sort);\n\n set({\n _blockchains: blockchains,\n _tokens: tokens,\n _popularTokens: popularTokens,\n _swappers: swappers,\n });\n },\n});\n", "import { allProviders } from '@rango-dev/provider-all';\nimport { ProviderInterface } from '@rango-dev/wallets-react';\nimport { WidgetConfig } from '../types';\n\nexport interface ProvidersOptions {\n walletConnectProjectId?: WidgetConfig['walletConnectProjectId'];\n}\n\n/**\n *\n * Generate a list of providers by passing a provider name (e.g. metamask) or a custom provider which implemented ProviderInterface.\n * @returns ProviderInterface[] a list of ProviderInterface\n *\n */\nexport function matchAndGenerateProviders(\n providers: WidgetConfig['wallets'],\n options?: ProvidersOptions\n): ProviderInterface[] {\n const all = allProviders({\n walletconnect2: {\n WC_PROJECT_ID: options?.walletConnectProjectId || '',\n },\n });\n\n if (providers) {\n const selectedProviders: ProviderInterface[] = [];\n\n providers.forEach((requestedProvider) => {\n // There are two types of provider we get, the first one is only passing the wallet name\n // then we will match the wallet name with our providers (@rango-dev/provider-*).\n // The second way is passing a custom provider which implemented ProviderInterface.\n if (typeof requestedProvider === 'string') {\n const result: ProviderInterface | undefined = all.find((provider) => {\n return provider.config.type === requestedProvider;\n });\n if (result) {\n selectedProviders.push(result);\n } else {\n console.warn(\n `Couldn't find ${requestedProvider} provider. Please make sure you are passing the correct name.`\n );\n }\n } else {\n // It's a custom provider so we directly push it to the list.\n selectedProviders.push(requestedProvider);\n }\n });\n return selectedProviders;\n }\n\n return all;\n}\n\nexport function configWalletsToWalletName(\n config: WidgetConfig['wallets'],\n options?: ProvidersOptions\n): string[] {\n const providers = matchAndGenerateProviders(config, options);\n const names = providers.map((provider) => {\n return provider.config.type;\n });\n return names;\n}\n", "import type { WidgetConfig } from './types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\nimport type { PropsWithChildren } from 'react';\n\nimport { I18nManager, styled } from '@rango-dev/ui';\nimport React, { useContext, useEffect, useMemo, useState } from 'react';\n\nimport { AppRouter } from './components/AppRouter';\nimport { AppRoutes } from './components/AppRoutes';\nimport { WidgetEvents } from './components/WidgetEvents';\nimport { globalFont } from './globalStyles';\nimport { useLanguage } from './hooks/useLanguage';\nimport { useTheme } from './hooks/useTheme';\nimport QueueManager from './QueueManager';\nimport { useAppStore } from './store/app';\nimport { useMetaStore } from './store/meta';\nimport { useNotificationStore } from './store/notification';\nimport { useSettingsStore } from './store/settings';\nimport { initConfig } from './utils/configs';\nimport { WidgetContext, WidgetWallets } from './Wallets';\n\nconst MainContainer = styled('div', {\n width: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n fontFamily: '$widget',\n boxSizing: 'border-box',\n '& *, *::before, *::after': {\n boxSizing: 'inherit',\n listStyleType: 'none',\n },\n '& *:focus-visible': {\n outlineColor: '$info500',\n transition: 'none',\n },\n});\n\nexport type WidgetProps = {\n config?: WidgetConfig;\n};\n\nexport function Main(props: PropsWithChildren<WidgetProps>) {\n const { config } = props;\n globalFont();\n\n const { activeTheme } = useTheme(config?.theme || {});\n const { activeLanguage, changeLanguage } = useLanguage();\n\n const [lastConnectedWalletWithNetwork, setLastConnectedWalletWithNetwork] =\n useState<string>('');\n const [disconnectedWallet, setDisconnectedWallet] = useState<WalletType>();\n const widgetContext = useContext(WidgetContext);\n const fetchMeta = useMetaStore.use.fetchMeta();\n\n useMemo(() => {\n if (config?.apiKey) {\n initConfig({\n API_KEY: config?.apiKey,\n });\n }\n }, [config]);\n\n useEffect(() => {\n void fetchMeta();\n void useSettingsStore.persist.rehydrate();\n void useNotificationStore.persist.rehydrate();\n widgetContext.onConnectWallet(setLastConnectedWalletWithNetwork);\n }, []);\n\n useEffect(() => {\n if (config?.language) {\n changeLanguage(config.language);\n }\n }, [config?.language]);\n\n return (\n <I18nManager language={activeLanguage}>\n <MainContainer id=\"swap-container\" className={activeTheme()}>\n <QueueManager>\n <WidgetEvents />\n <AppRouter\n config={config}\n lastConnectedWallet={lastConnectedWalletWithNetwork}\n disconnectedWallet={disconnectedWallet}\n clearDisconnectedWallet={() => {\n setDisconnectedWallet(undefined);\n }}>\n <AppRoutes config={config} />\n </AppRouter>\n </QueueManager>\n </MainContainer>\n </I18nManager>\n );\n}\n\nexport function Widget(props: PropsWithChildren<WidgetProps>) {\n const { updateConfig, config } = useAppStore();\n useEffect(() => {\n if (props.config) {\n updateConfig(props.config);\n }\n }, [props.config]);\n\n if (!props.config?.externalWallets) {\n return (\n <WidgetWallets\n providers={config?.wallets}\n options={{\n walletConnectProjectId:\n config?.walletConnectProjectId ||\n props.config?.walletConnectProjectId,\n }}>\n <Main {...props} />\n </WidgetWallets>\n );\n }\n return <Main {...props} />;\n}\n", "import type { WidgetConfig } from '../types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\nimport type { PropsWithChildren } from 'react';\n\nimport { useQueueManager } from '@rango-dev/queue-manager-rango-preset';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport { isEvmBlockchain } from 'rango-types';\nimport React, { useEffect, useRef } from 'react';\nimport { MemoryRouter, useInRouterContext } from 'react-router';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { Home } from '../pages/Home';\nimport { useMetaStore } from '../store/meta';\n\nimport { UpdateUrl } from './UpdateUrl';\n\nfunction Route(props: PropsWithChildren) {\n const location = useLocation();\n const navigate = useNavigate();\n const firstRender = useRef(true);\n const paths = location.pathname.split('/');\n const pathMatched = paths[paths.length - 1] === navigationRoutes.confirmSwap;\n const shouldRedirectToMainPage = pathMatched && firstRender.current;\n\n useEffect(() => {\n if (shouldRedirectToMainPage) {\n navigate('.');\n }\n firstRender.current = false;\n }, []);\n\n if (shouldRedirectToMainPage) {\n return <Home />;\n }\n\n return <> {props.children}</>;\n}\n\nexport function AppRouter({\n children,\n ...props\n}: PropsWithChildren & {\n lastConnectedWallet: string;\n disconnectedWallet: WalletType | undefined;\n clearDisconnectedWallet: () => void;\n config: WidgetConfig | undefined;\n}) {\n const isRouterInContext = useInRouterContext();\n const Router = isRouterInContext ? Route : MemoryRouter;\n const { blockchains } = useMetaStore.use.meta();\n const { canSwitchNetworkTo } = useWallets();\n\n const evmChains = blockchains.filter(isEvmBlockchain);\n\n useQueueManager({\n lastConnectedWallet: props.lastConnectedWallet,\n clearDisconnectedWallet: props.clearDisconnectedWallet,\n disconnectedWallet: props.disconnectedWallet,\n evmChains,\n canSwitchNetworkTo,\n });\n\n return (\n <>\n <Router>{children}</Router>\n {isRouterInContext && <UpdateUrl config={props.config} />}\n </>\n );\n}\n", "export const navigationRoutes = {\n home: '/',\n fromSwap: 'from-swap',\n fromBlockchain: '/from-swap/blockchains',\n toBlockchain: '/to-swap/blockchains',\n toSwap: 'to-swap',\n settings: 'settings',\n liquiditySources: '/settings/liquidity-sources',\n themes: '/settings/themes',\n bridges: '/settings/bridges',\n exchanges: '/settings/exchanges',\n languages: '/settings/languages',\n swaps: 'swaps',\n wallets: 'wallets',\n confirmSwap: 'confirm-swap',\n swapDetails: 'swaps/:requestId',\n};\n", "import type { SwapResult } from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport {\n Alert,\n BestRoute,\n BestRouteSkeleton,\n Button,\n Divider,\n styled,\n SwapInput,\n Typography,\n WarningIcon,\n} from '@rango-dev/ui';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { HomeButtons } from '../components/HeaderButtons';\nimport { Layout } from '../components/Layout';\nimport { NoRoutes } from '../components/NoRoutes';\nimport { RouteErrors } from '../components/RouteErrors';\nimport { SwitchFromAndToButton } from '../components/SwitchFromAndTo';\nimport { errorMessages } from '../constants/errors';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport {\n BALANCE_MAX_DECIMALS,\n BALANCE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../constants/routing';\nimport { useSwapInput } from '../hooks/useSwapInput';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useUiStore } from '../store/ui';\nimport { useWalletsStore } from '../store/wallets';\nimport { ButtonState } from '../types';\nimport { getContainer } from '../utils/common';\nimport { getBlockchainShortNameFor } from '../utils/meta';\nimport {\n numberToString,\n secondsToString,\n totalArrivalTime,\n} from '../utils/numbers';\nimport { getFormattedBestRoute, getPriceImpactLevel } from '../utils/routing';\nimport {\n canComputePriceImpact,\n getOutputRatio,\n getPercentageChange,\n getSwapButtonState,\n getTotalFeeInUsd,\n hasLimitError,\n LimitErrorMessage,\n outputRatioHasWarning,\n} from '../utils/swap';\nimport { getBalanceFromWallet } from '../utils/wallets';\n\nconst Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n overflowY: 'visible',\n});\n\nconst FromContainer = styled('div', {\n position: 'relative',\n});\n\nconst InputsContainer = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n gap: 5,\n alignSelf: 'stretch',\n});\n\nconst BestRouteContainer = styled('div', {\n width: '100%',\n paddingTop: '$2',\n});\n\nconst FooterStepAlarm = styled('div', {\n paddingBottom: '$15',\n});\n\nconst FooterAlert = styled('div', {\n width: '100%',\n display: 'flex',\n});\n\nexport function Home() {\n const navigate = useNavigate();\n const {\n fetch: refetchBestRoute,\n loading: fetchingBestRoute,\n error: bestRouteError,\n } = useSwapInput();\n const {\n fromToken,\n fromBlockchain,\n toToken,\n toBlockchain,\n setInputAmount,\n inputAmount,\n inputUsdValue,\n outputAmount,\n outputUsdValue,\n bestRoute,\n resetRouteWallets,\n } = useBestRouteStore();\n\n const {\n meta: { tokens, blockchains },\n loadingStatus: loadingMetaStatus,\n } = useMetaStore();\n\n const connectedWallets = useWalletsStore.use.connectedWallets();\n const setCurrentPage = useUiStore.use.setCurrentPage();\n const [openWarningModal, setOpenWarningModal] = useState(false);\n const {\n fromAmountRangeError,\n swap: swapHasError,\n recommendation,\n } = LimitErrorMessage(bestRoute);\n const layoutRef = useRef<HTMLDivElement>(null);\n\n const showBestRoute =\n !!Number(inputAmount) &&\n (!!bestRoute || fetchingBestRoute || !!bestRouteError);\n\n const needsToWarnEthOnPath = false;\n\n const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);\n const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);\n\n const priceImpactInputCanNotBeComputed = !canComputePriceImpact(\n bestRoute,\n inputAmount,\n inputUsdValue\n );\n\n const priceImpactOutputCanNotBeComputed = !canComputePriceImpact(\n bestRoute,\n inputAmount,\n outputUsdValue\n );\n const swapButtonState = getSwapButtonState(\n loadingMetaStatus,\n connectedWallets,\n fetchingBestRoute,\n bestRoute,\n hasLimitError(bestRoute),\n highValueLoss,\n priceImpactInputCanNotBeComputed || priceImpactOutputCanNotBeComputed,\n needsToWarnEthOnPath,\n inputAmount\n );\n\n const tokenBalance =\n !!fromBlockchain && !!fromToken\n ? numberToString(\n getBalanceFromWallet(\n connectedWallets,\n fromBlockchain?.name,\n fromToken?.symbol,\n fromToken?.address\n )?.amount || '0',\n BALANCE_MIN_DECIMALS,\n BALANCE_MAX_DECIMALS\n )\n : '0';\n\n const tokenBalanceReal =\n !!fromBlockchain && !!fromToken\n ? numberToString(\n getBalanceFromWallet(\n connectedWallets,\n fromBlockchain?.name,\n fromToken?.symbol,\n fromToken?.address\n )?.amount || '0',\n getBalanceFromWallet(\n connectedWallets,\n fromBlockchain?.name,\n fromToken?.symbol,\n fromToken?.address\n )?.decimal\n )\n : '0';\n\n useEffect(() => {\n setCurrentPage(navigationRoutes.home);\n resetRouteWallets();\n return setCurrentPage.bind(null, '');\n }, []);\n\n const percentageChange =\n !inputUsdValue || !outputUsdValue || !outputUsdValue.gt(0)\n ? null\n : getPercentageChange(\n inputUsdValue.toNumber(),\n outputUsdValue.toNumber()\n );\n\n const getBestRouteSteps = (swaps: SwapResult[]) => {\n return swaps.map((swap, index) => ({\n swapper: { displayName: swap.swapperId, image: swap.swapperLogo },\n from: {\n token: { displayName: swap.from.symbol, image: swap.from.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.from.blockchain, blockchains) ?? '',\n image: swap.from.blockchainLogo,\n },\n price: {\n value:\n index === 0\n ? numberToString(\n inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n )\n : swap.fromAmount,\n },\n },\n to: {\n token: { displayName: swap.to.symbol, image: swap.to.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.to.blockchain, blockchains) ?? '',\n image: swap.to.blockchainLogo,\n },\n price: {\n value: swap.toAmount,\n },\n },\n alerts:\n swap.swapperId === swapHasError?.swapperId ? (\n <FooterStepAlarm>\n <Alert\n type=\"error\"\n title={recommendation}\n footer={\n <FooterAlert>\n <Typography size=\"xsmall\" variant=\"body\" color=\"neutral700\">\n {fromAmountRangeError}\n </Typography>\n <Divider direction=\"horizontal\" size={8} />\n <Typography size=\"xsmall\" variant=\"body\" color=\"neutral700\">\n |\n </Typography>\n <Divider direction=\"horizontal\" size={8} />\n <Typography size=\"xsmall\" variant=\"body\" color=\"neutral700\">\n {i18n.t({\n id: 'yourSymbol',\n message: 'Yours: {amount} {symbol}',\n values: {\n amount: numberToString(\n swapHasError?.fromAmount || null,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap?.from.symbol,\n },\n })}\n </Typography>\n </FooterAlert>\n }\n />\n </FooterStepAlarm>\n ) : undefined,\n }));\n };\n\n const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);\n\n const bestRouteData = getFormattedBestRoute(bestRoute);\n\n return (\n <Layout\n ref={layoutRef}\n fixedHeight={false}\n hasLogo\n footer={\n <Button\n type=\"primary\"\n size=\"large\"\n disabled={swapButtonState.disabled}\n prefix={\n !swapButtonState.disabled &&\n swapButtonState.hasWarning && <WarningIcon />\n }\n fullWidth\n onClick={() => {\n if (swapButtonState.state === ButtonState.WAITFORCONNECTING) {\n navigate(navigationRoutes.wallets);\n } else if (swapButtonState.state === ButtonState.NEEDTOCONFIRM) {\n setOpenWarningModal(true);\n } else {\n navigate(navigationRoutes.confirmSwap);\n }\n }}>\n {swapButtonState.title}\n </Button>\n }\n header={{\n hasConnectWallet: true,\n title: i18n.t('Swap'),\n suffix: (\n <HomeButtons\n layoutRef={layoutRef.current}\n onClickRefresh={\n !!bestRoute || bestRouteError ? refetchBestRoute : undefined\n }\n onClickHistory={() => navigate(navigationRoutes.swaps)}\n onClickSettings={() => navigate(navigationRoutes.settings)}\n />\n ),\n }}>\n <Container>\n <InputsContainer>\n <FromContainer>\n <SwapInput\n label={i18n.t('From')}\n mode=\"From\"\n onInputChange={setInputAmount}\n balance={tokenBalance}\n chain={{\n displayName: fromBlockchain?.displayName || '',\n image: fromBlockchain?.logo || '',\n }}\n token={{\n displayName: fromToken?.symbol || '',\n image: fromToken?.image || '',\n }}\n onClickToken={() => navigate('from-swap')}\n price={{\n value: inputAmount,\n usdValue: priceImpactInputCanNotBeComputed\n ? undefined\n : numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n error: priceImpactInputCanNotBeComputed\n ? errorMessages().unknownPriceError.impactTitle\n : undefined,\n }}\n disabled={loadingMetaStatus === 'failed'}\n loading={loadingMetaStatus === 'loading'}\n onSelectMaxBalance={() => {\n if (tokenBalance !== '0') {\n setInputAmount(tokenBalanceReal.split(',').join(''));\n }\n }}\n />\n <SwitchFromAndToButton />\n </FromContainer>\n <SwapInput\n sharpBottomStyle={!!bestRoute?.result || fetchingBestRoute}\n label={i18n.t('To')}\n mode=\"To\"\n chain={{\n displayName: toBlockchain?.displayName || '',\n image: toBlockchain?.logo || '',\n }}\n token={{\n displayName: toToken?.symbol || '',\n image: toToken?.image || '',\n }}\n percentageChange={\n !!percentageChange?.lt(0)\n ? numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )\n : null\n }\n warningLevel={getPriceImpactLevel(\n percentageChange?.toNumber() ?? 0\n )}\n price={{\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: priceImpactOutputCanNotBeComputed\n ? undefined\n : numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n error: priceImpactOutputCanNotBeComputed\n ? errorMessages().unknownPriceError.impactTitle\n : undefined,\n }}\n onClickToken={() => navigate('to-swap')}\n disabled={loadingMetaStatus === 'failed'}\n loading={loadingMetaStatus === 'loading'}\n />\n </InputsContainer>\n {fetchingBestRoute && (\n <BestRouteContainer>\n <BestRouteSkeleton type=\"basic\" />\n </BestRouteContainer>\n )}\n {showBestRoute &&\n !fetchingBestRoute &&\n bestRouteData?.result?.swaps?.length ? (\n <BestRouteContainer>\n <BestRoute\n type=\"basic\"\n recommended={true}\n tooltipContainer={getContainer()}\n input={{\n value: numberToString(\n inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n output={{\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n steps={getBestRouteSteps(bestRouteData.result.swaps)}\n percentageChange={numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )}\n totalFee={numberToString(\n totalFeeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n )}\n totalTime={secondsToString(\n totalArrivalTime(bestRoute?.result?.swaps)\n )}\n />\n </BestRouteContainer>\n ) : showBestRoute && !fetchingBestRoute ? (\n <>\n <Divider size={20} />\n <NoRoutes\n diagnosisMessage={bestRouteData?.diagnosisMessages?.[0]}\n fetch={refetchBestRoute}\n error={!!bestRouteError}\n />\n </>\n ) : null}\n </Container>\n <RouteErrors\n openModal={openWarningModal}\n onToggle={setOpenWarningModal}\n totalFeeInUsd={totalFeeInUsd}\n outputUsdValue={outputUsdValue}\n inputUsdValue={inputUsdValue}\n percentageChange={percentageChange}\n highValueLoss={highValueLoss}\n priceImpactCanNotBeComputed={\n priceImpactInputCanNotBeComputed || priceImpactOutputCanNotBeComputed\n }\n loading={fetchingBestRoute || loadingMetaStatus === 'loading'}\n extraSpace={!!bestRoute?.result || !bestRoute}\n />\n </Layout>\n );\n}\n", "import type { PropTypes } from './HeaderButtons.types';\n\nimport { ChevronLeftIcon } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { HeaderButton } from './HeaderButtons.styles';\n\nfunction BackButton(props: PropTypes) {\n return (\n <HeaderButton variant=\"ghost\" size=\"small\" onClick={props.onClick}>\n <ChevronLeftIcon color=\"black\" size={16} />\n </HeaderButton>\n );\n}\n\nexport { BackButton };\n", "import { darkTheme, IconButton, styled } from '@rango-dev/ui';\n\nexport const HeaderButton = styled(IconButton, {\n width: '$24',\n position: 'relative',\n padding: '0',\n overflow: 'unset',\n});\n\nexport const ConnectedIcon = styled('div', {\n position: 'absolute',\n background: '$secondary500',\n [`.${darkTheme} &`]: {\n $$color: '$colors$secondary400',\n },\n width: '$6',\n height: '$6',\n borderRadius: '$lg',\n right: '$4',\n border: '1px solid $surface100',\n});\n\nexport const SuffixContainer = styled('div', {\n display: 'flex',\n justifyContent: 'flex-end',\n width: '$40',\n});\n\nexport const NotificationsBadgeContainer = styled('div', {\n position: 'absolute',\n backgroundColor: '$secondary500',\n width: '14px',\n height: '14px',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: '7px',\n top: '$0',\n right: '$0',\n});\n", "import type { PropTypes } from './HeaderButtons.types';\n\nimport { i18n } from '@lingui/core';\nimport { Button, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { SuffixContainer } from './HeaderButtons.styles';\n\nfunction CancelButton(props: PropTypes) {\n return (\n <SuffixContainer>\n <Button variant=\"ghost\" onClick={props.onClick} size=\"xsmall\">\n <Typography variant=\"label\" size=\"medium\" color=\"error500\">\n {i18n.t('Cancel')}\n </Typography>\n </Button>\n </SuffixContainer>\n );\n}\n\nexport { CancelButton };\n", "import type { PropTypes } from './HeaderButtons.types';\n\nimport { i18n } from '@lingui/core';\nimport { Tooltip, WalletIcon } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { ConnectedIcon, HeaderButton } from './HeaderButtons.styles';\n\nfunction WalletButton(props: PropTypes) {\n return (\n <Tooltip\n container={props.container}\n side=\"top\"\n content={i18n.t('Connect Wallet')}>\n <HeaderButton variant=\"ghost\" size=\"small\" onClick={props.onClick}>\n {props.isConnected && <ConnectedIcon />}\n <WalletIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n );\n}\n\nexport { WalletButton };\n", "import type { HomeButtonsPropTypes } from './HeaderButtons.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n NotificationsIcon,\n Popover,\n RefreshIcon,\n SettingsIcon,\n Tooltip,\n TransactionIcon,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { getContainer } from '../../utils/common';\nimport { NotificationContent } from '../NotificationContent';\n\nimport { HeaderButton } from './HeaderButtons.styles';\nimport { UnreadNotificationsBadge } from './UnreadNotificationsBadge';\n\nexport function HomeButtons(props: HomeButtonsPropTypes) {\n const {\n layoutRef,\n onClickRefresh,\n onClickHistory,\n onClickSettings,\n onClickNotifications,\n } = props;\n\n return (\n <>\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Refresh')}>\n <HeaderButton\n variant=\"ghost\"\n size=\"small\"\n onClick={onClickRefresh}\n disabled={!onClickRefresh}>\n <RefreshIcon size={16} color={!onClickRefresh ? 'gray' : 'black'} />\n </HeaderButton>\n </Tooltip>\n\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Notifications')}>\n <Popover\n align=\"center\"\n collisionBoundary={layoutRef}\n collisionPadding={{ right: 20, left: 20 }}\n container={getContainer()}\n content={<NotificationContent />}>\n <HeaderButton\n size=\"small\"\n variant=\"ghost\"\n onClick={onClickNotifications}>\n <NotificationsIcon size={18} color=\"black\" />\n <UnreadNotificationsBadge />\n </HeaderButton>\n </Popover>\n </Tooltip>\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Settings')}>\n <HeaderButton size=\"small\" variant=\"ghost\" onClick={onClickSettings}>\n <SettingsIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Transactions History')}>\n <HeaderButton size=\"small\" variant=\"ghost\" onClick={onClickHistory}>\n <TransactionIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n </>\n );\n}\n", "import type { Notification } from '../../types/notification';\n\nimport { i18n } from '@lingui/core';\nimport {\n ChainToken,\n ChevronRightIcon,\n ListItemButton,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { useMetaStore } from '../../store/meta';\nimport { useNotificationStore } from '../../store/notification';\nimport { useUiStore } from '../../store/ui';\n\nimport { Container, Images, List } from './NotificationContent.styles';\nimport { NotificationNotFound } from './NotificationNotFound';\n\nconst MAX_NOTIFICATIONS_DISPLAYED = 4;\n\nexport function NotificationContent() {\n const navigate = useNavigate();\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n\n const { getUnreadNotifications } = useNotificationStore();\n\n const notifications: Notification[] = getUnreadNotifications();\n const { tokens, blockchains } = useMetaStore.use.meta();\n const sortedNotification = notifications\n .sort((a, b) => b.creationTime - a.creationTime)\n .slice(0, MAX_NOTIFICATIONS_DISPLAYED);\n\n const handleOnClick = (requestId: Notification['requestId']) => {\n setSelectedSwap(requestId);\n navigate(`/swaps/${requestId}`);\n };\n\n return (\n <Container>\n {sortedNotification.length ? (\n <List>\n {sortedNotification.map((notificationItem) => {\n const fromToken = tokens.find(\n (tokenItem) =>\n tokenItem.address ===\n notificationItem.route.from.tokenAddress &&\n tokenItem.blockchain ===\n notificationItem.route.from.blockchain &&\n tokenItem.symbol === notificationItem.route.from.tokenSymbol\n );\n\n const fromBlockchain = blockchains.find(\n (blockchainItem) =>\n blockchainItem.name === notificationItem.route.from.blockchain\n );\n\n const toToken = tokens.find(\n (tokenItem) =>\n tokenItem.address === notificationItem.route.to.tokenAddress &&\n tokenItem.blockchain === notificationItem.route.to.blockchain &&\n tokenItem.symbol === notificationItem.route.to.tokenSymbol\n );\n\n const toBlockchain = blockchains.find(\n (blockchainItem) =>\n blockchainItem.name === notificationItem.route.to.blockchain\n );\n\n return (\n <ListItemButton\n key={notificationItem.requestId}\n onClick={() => handleOnClick(notificationItem.requestId)}\n title={\n <Typography variant=\"body\" size=\"small\" color=\"$neutral700\">\n {i18n.t(notificationItem.event.message)}\n </Typography>\n }\n id={notificationItem.requestId}\n start={\n <Images>\n <div className=\"from-chain-token\">\n <ChainToken\n tokenImage={fromToken ? fromToken.image : ''}\n chainImage={fromBlockchain ? fromBlockchain.logo : ''}\n size=\"small\"\n />\n </div>\n <div className=\"to-chain-token\">\n <ChainToken\n tokenImage={toToken ? toToken.image : ''}\n chainImage={toBlockchain ? toBlockchain.logo : ''}\n size=\"small\"\n />\n </div>\n </Images>\n }\n end={<ChevronRightIcon size={12} color=\"gray\" />}\n />\n );\n })}\n </List>\n ) : (\n <NotificationNotFound />\n )}\n </Container>\n );\n}\n", "import type { Notification } from '../types/notification';\nimport type {\n Route,\n RouteEvent,\n StepEvent,\n} from '@rango-dev/queue-manager-rango-preset';\n\nimport { create } from 'zustand';\nimport { persist, subscribeWithSelector } from 'zustand/middleware';\n\nimport createSelectors from './selectors';\n\nexport interface NotificationState {\n notifications: Notification[];\n setNotification: (event: RouteEvent | StepEvent, route: Route) => void;\n setAsRead: (requestId: Notification['requestId']) => void;\n getUnreadNotifications: () => Notification[];\n}\n\nexport const useNotificationStore = createSelectors(\n create<NotificationState>()(\n persist(\n subscribeWithSelector((set, get) => ({\n notifications: [],\n setNotification: (event, route) => {\n const fromStep = route.steps[0];\n const toStep = route.steps[route.steps.length - 1];\n\n const notification: Notification = {\n event,\n creationTime: Date.now(),\n read: false,\n requestId: route.requestId,\n route: {\n from: {\n blockchain: fromStep.fromBlockchain,\n tokenAddress: fromStep.fromSymbolAddress,\n tokenSymbol: fromStep.fromSymbol,\n },\n to: {\n blockchain: toStep.toBlockchain,\n tokenSymbol: toStep.toSymbol,\n tokenAddress: toStep.toSymbolAddress,\n },\n },\n };\n\n const excludedList = get().notifications.filter(\n (notificationItem) => notificationItem.requestId !== route.requestId\n );\n\n set(() => ({\n notifications: [...excludedList, notification],\n }));\n },\n setAsRead: (requestId) => {\n set((state) => ({\n notifications: state.notifications.map((notificationItem) =>\n notificationItem.requestId === requestId\n ? { ...notificationItem, read: true }\n : notificationItem\n ),\n }));\n },\n getUnreadNotifications: () => {\n return get().notifications.filter(\n (notificationItem) => !notificationItem.read\n );\n },\n })),\n {\n name: 'notification',\n skipHydration: true,\n }\n )\n )\n);\n", "import { create } from 'zustand';\n\nimport createSelectors from './selectors';\n\ninterface UiState {\n connectWalletsButtonDisabled: boolean;\n selectedSwapRequestId: string | null;\n currentPage: string;\n setSelectedSwap: (requestId: string | null) => void;\n setCurrentPage: (path: string) => void;\n}\n\nexport const useUiStore = createSelectors(\n create<UiState>()((set) => ({\n connectWalletsButtonDisabled: false,\n selectedSwapRequestId: null,\n currentPage: '',\n setSelectedSwap: (requestId) => set({ selectedSwapRequestId: requestId }),\n setCurrentPage: (path) => set({ currentPage: path }),\n }))\n);\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n padding: '$10',\n width: '350px',\n minHeight: '150px',\n});\n\nexport const List = styled('ul', {\n padding: 0,\n margin: 0,\n listStyle: 'none',\n\n '.to-chain-token': {\n transform: 'translateX(-3px)',\n },\n});\n\nexport const Images = styled('div', {\n display: 'flex',\n padding: 0,\n alignItems: 'center',\n alignSelf: 'stretch',\n});\n\nexport const NotFoundContainer = styled('div', {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n flexDirection: 'column',\n padding: '$10',\n width: '100%',\n height: '150px',\n});\n", "import { i18n } from '@lingui/core';\nimport { Divider, NoNotificationIcon, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { NotFoundContainer } from './NotificationContent.styles';\n\nexport function NotificationNotFound() {\n return (\n <NotFoundContainer>\n <NoNotificationIcon color=\"secondary\" size={26} />\n <Divider size={12} />\n <Typography variant=\"body\" size=\"medium\" color=\"neutral700\">\n {i18n.t('You have no notification')}\n </Typography>\n </NotFoundContainer>\n );\n}\n", "import { Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { useNotificationStore } from '../../store/notification';\n\nimport { NotificationsBadgeContainer } from './HeaderButtons.styles';\n\nexport function UnreadNotificationsBadge() {\n const { getUnreadNotifications } = useNotificationStore();\n\n const notificationsCount = getUnreadNotifications().length;\n\n return notificationsCount ? (\n <NotificationsBadgeContainer>\n <Typography variant=\"body\" size=\"xsmall\" color=\"$background\">\n {notificationsCount}\n </Typography>\n </NotificationsBadgeContainer>\n ) : null;\n}\n", "import type { PropTypes, Ref } from './Layout.types';\nimport type { PropsWithChildren } from 'react';\n\nimport { BottomLogo, Divider, Header } from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport { useUiStore } from '../../store/ui';\nimport { useWalletsStore } from '../../store/wallets';\nimport { getContainer } from '../../utils/common';\nimport { BackButton, CancelButton, WalletButton } from '../HeaderButtons';\n\nimport { Container, Content, Footer } from './Layout.styles';\n\nfunction LayoutComponent(props: PropsWithChildren<PropTypes>, ref: Ref) {\n const {\n children,\n header,\n footer,\n noPadding,\n hasLogo = true,\n fixedHeight = true,\n } = props;\n const connectedWallets = useWalletsStore.use.connectedWallets();\n\n const connectWalletsButtonDisabled =\n useUiStore.use.connectWalletsButtonDisabled();\n const navigate = useNavigate();\n\n const onConnectWallet = () => {\n if (!connectWalletsButtonDisabled) {\n navigate('/' + navigationRoutes.wallets);\n }\n };\n return (\n <Container ref={ref} fixedHeight={fixedHeight} id=\"swap-box\">\n <Header\n prefix={<>{header.onBack && <BackButton onClick={header.onBack} />}</>}\n title={header.title}\n suffix={\n <>\n {header.suffix}\n {header.hasConnectWallet && (\n <WalletButton\n container={getContainer()}\n onClick={onConnectWallet}\n isConnected={!!connectedWallets?.length}\n />\n )}\n {header.onCancel && <CancelButton onClick={header.onCancel} />}\n </>\n }\n />\n <Content noPadding={noPadding}>{children}</Content>\n {(hasLogo || footer) && (\n <Footer>\n <div className=\"footer__content\">{footer}</div>\n {hasLogo && (\n <div className=\"footer__logo\">\n <Divider size={12} />\n <BottomLogo />\n </div>\n )}\n </Footer>\n )}\n </Container>\n );\n}\n\nconst Layout = React.forwardRef(LayoutComponent);\nLayout.displayName = 'Layout';\n\nexport { Layout };\n", "import { darkTheme, styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n borderRadius: '$primary',\n overflow: 'hidden !important',\n boxShadow: '15px 15px 15px 0px rgba(0, 0, 0, 0.05)',\n width: '95vw',\n maxWidth: '390px',\n maxHeight: '700px',\n $$color: '$colors$neutral100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral300',\n },\n backgroundColor: '$$color',\n variants: {\n fixedHeight: {\n true: {\n height: '95vh',\n },\n false: {\n height: 'auto',\n },\n },\n },\n});\n\nexport const Content = styled('div', {\n borderTopLeftRadius: '20px',\n borderTopRightRadius: '20px',\n display: 'flex',\n flexDirection: 'column',\n flex: 1,\n padding: '$20 $20 $10 $20',\n backgroundColor: '$background',\n position: 'relative',\n overflowY: 'auto',\n overflowX: 'hidden',\n variants: {\n noPadding: {\n true: {\n padding: '0',\n },\n },\n },\n});\n\nexport const Footer = styled('div', {\n backgroundColor: '$background',\n '& .footer__content': {\n padding: '$0 $20',\n },\n '& .footer__logo': {\n padding: '$0 $20 $10 $20',\n },\n});\n", "import type { PropTypes } from './NoRoutes.types';\n\nimport {\n Alert,\n Button,\n Divider,\n NoRouteIcon,\n RefreshIcon,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { errorMessages } from '../../constants/errors';\nimport { useMetaStore } from '../../store/meta';\nimport { useSettingsStore } from '../../store/settings';\n\nimport { makeInfo } from './NoRoutes.helper';\nimport { Container, Footer, PrefixIcon } from './NoRoutes.styles';\n\nexport function NoRoutes(props: PropTypes) {\n const { diagnosisMessage, fetch, error } = props;\n const disabledLiquiditySources =\n useSettingsStore.use.disabledLiquiditySources();\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n const toggleAllLiquiditySources =\n useSettingsStore.use.toggleAllLiquiditySources();\n\n const hasError = error || loadingMetaStatus === 'failed';\n\n const info = makeInfo(\n diagnosisMessage ?? null,\n disabledLiquiditySources,\n hasError,\n toggleAllLiquiditySources,\n fetch\n );\n\n return (\n <Container>\n <NoRouteIcon size={24} color=\"gray\" />\n <Divider size={4} />\n <Typography variant=\"title\" size=\"small\">\n {errorMessages().noRoutesError.title}\n </Typography>\n {!!info.description && (\n <Typography\n variant=\"body\"\n size=\"small\"\n align=\"center\"\n color=\"neutral700\">\n {info.description}\n </Typography>\n )}\n <Divider size={4} />\n {!!info.alert && (\n <Footer>\n <Alert\n type={info.alert.type}\n title={info.alert.text}\n action={\n info.alert.action && (\n <Button\n size=\"xsmall\"\n type={info.alert.type}\n prefix={\n <PrefixIcon>\n <RefreshIcon size={8} />\n </PrefixIcon>\n }\n onClick={info.alert.action.onClick}>\n {info.alert.action.title}\n </Button>\n )\n }\n variant=\"alarm\"\n />\n </Footer>\n )}\n </Container>\n );\n}\n", "import type { ConfirmSwapError } from '../types';\n\nimport { i18n } from '@lingui/core';\n\nimport { ConfirmSwapErrorTypes } from '../types';\n\nexport const errorMessages = () => {\n return {\n genericServerError: i18n.t('Failed Network, Please retry your swap.'),\n liquiditySourcesError: {\n title: i18n.t('Please reset your liquidity sources.'),\n description: i18n.t(\n 'You have limited the liquidity sources and this might result in Rango finding no routes. Please consider resetting your liquidity sources'\n ),\n },\n noRoutesError: {\n title: i18n.t('No Routes Found'),\n description:\n \"Reasons why Rango couldn't find a route: low liquidity on token, very low input amount or no routes available for the selected input/output token combination.\",\n },\n bridgeLimitErrors: {\n increaseAmount: i18n.t('Bridge Limit Error: Please increase your amount'),\n decreaseAmount: i18n.t('Bridge Limit Error: Please decrease your amount'),\n },\n highValueLossError: {\n impactTitle: i18n.t('High Price Impact'),\n title: i18n.t('Price impact is too high!'),\n description: i18n.t(\n 'The price impact is significantly higher than the allowed amount. If you are sure, continue, otherwise, change the swap.'\n ),\n confirmMessage: i18n.t('Confirm High price impact'),\n },\n routeUpdatedWithHighValueLoss: {\n title: i18n.t(\n 'Route updated and price impact is too high, try again later!'\n ),\n },\n unknownPriceError: {\n impactTitle: i18n.t('USD Price Unknown'),\n title: i18n.t('USD Price Unknown, Cannot calculate Price Impact.'),\n description: i18n.t(\n 'USD Price Unknown, Cannot calculate Price Impact. The price impact may be higher than usual. Are you sure to continue the Swap?'\n ),\n confirmMessage: i18n.t('Confirm USD Price Unknown'),\n },\n };\n};\n\nexport function getConfirmSwapErrorMessage(error: ConfirmSwapError) {\n switch (error.type) {\n case ConfirmSwapErrorTypes.NO_ROUTE:\n return error.diagnosisMessage ?? errorMessages().noRoutesError.title;\n case ConfirmSwapErrorTypes.REQUEST_FAILED:\n return errorMessages().genericServerError;\n case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:\n return errorMessages().routeUpdatedWithHighValueLoss.title;\n default:\n return '';\n }\n}\n", "/* eslint-disable @typescript-eslint/prefer-enum-initializers */\nimport type { RouteState } from '../store/bestRoute';\nimport type { SettingsState } from '../store/settings';\n\ninterface BestRouteStoreParams {\n fromBlockchain?: RouteState['fromBlockchain'];\n toBlockchain?: RouteState['toBlockchain'];\n fromToken?: RouteState['fromToken'];\n toToken?: RouteState['toToken'];\n inputAmount?: RouteState['inputAmount'];\n}\n\ninterface SettingsStoreParams {\n slippage?: SettingsState['slippage'];\n customSlippage?: SettingsState['customSlippage'];\n disabledLiquiditySources?: SettingsState['disabledLiquiditySources'];\n infiniteApprove?: SettingsState['infiniteApprove'];\n}\n\nexport type BestRouteEqualityParams =\n | {\n store: 'bestRoute';\n prevState: BestRouteStoreParams;\n currentState: BestRouteStoreParams;\n }\n | {\n store: 'settings';\n prevState: SettingsStoreParams;\n currentState: SettingsStoreParams;\n };\n\nexport enum ConfirmSwapErrorTypes {\n NO_ROUTE,\n ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,\n REQUEST_FAILED,\n REQUEST_CANCELED,\n}\n\nexport type ConfirmSwapError =\n | {\n type: ConfirmSwapErrorTypes.NO_ROUTE;\n diagnosisMessage?: string;\n }\n | {\n type: Exclude<ConfirmSwapErrorTypes, ConfirmSwapErrorTypes.NO_ROUTE>;\n };\n\nexport enum RouteWarningType {\n ROUTE_UPDATED,\n ROUTE_SWAPPERS_UPDATED,\n ROUTE_COINS_UPDATED,\n ROUTE_AND_OUTPUT_AMOUNT_UPDATED,\n}\n\nexport type RouteWarning =\n | {\n type: RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED;\n newOutputAmount: string;\n percentageChange: string;\n }\n | {\n type: Exclude<\n RouteWarningType,\n RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED\n >;\n };\n\nexport enum SlippageWarningType {\n INSUFFICIENT_SLIPPAGE,\n HIGH_SLIPPAGE,\n}\n\nexport type ConfirmSwapWarnings = {\n route: RouteWarning | null;\n balance: { messages: string[] } | null;\n slippage: { type: SlippageWarningType; slippage: string | null } | null;\n};\n", "import { type Language } from '@rango-dev/ui';\nimport { create } from 'zustand';\nimport { persist, subscribeWithSelector } from 'zustand/middleware';\n\nimport { BLOCKCHAIN_LIST_SIZE } from '../constants/configs';\nimport { DEFAULT_LANGUAGE } from '../constants/languages';\nimport { DEFAULT_SLIPPAGE } from '../constants/swapSettings';\nimport { removeDuplicateFrom } from '../utils/common';\n\nimport { useMetaStore } from './meta';\nimport createSelectors from './selectors';\n\nexport type ThemeMode = 'auto' | 'dark' | 'light';\n\nexport interface SettingsState {\n /** Keeping a history of blockchains that user has selected (in Swap process) */\n preferredBlockchains: string[];\n slippage: number;\n customSlippage: number | null;\n infiniteApprove: boolean;\n disabledLiquiditySources: string[];\n theme: ThemeMode;\n language: Language;\n affiliateRef: string | null;\n affiliatePercent: number | null;\n affiliateWallets: { [key: string]: string } | null;\n\n setSlippage: (slippage: number) => void;\n setCustomSlippage: (customSlippage: number | null) => void;\n toggleInfiniteApprove: () => void;\n toggleLiquiditySource: (name: string) => void;\n setTheme: (theme: ThemeMode) => void;\n setLanguage: (language: Language) => void;\n toggleAllLiquiditySources: (shouldReset?: boolean) => void;\n setAffiliateRef: (affiliateRef: string | null) => void;\n setAffiliatePercent: (affiliatePercent: number | null) => void;\n setAffiliateWallets: (\n affiliateWallets: { [key: string]: string } | null\n ) => void;\n addPreferredBlockchain: (blockchain: string) => void;\n}\n\nexport const useSettingsStore = createSelectors(\n create<SettingsState>()(\n persist(\n subscribeWithSelector((set, get) => ({\n preferredBlockchains: [],\n slippage: DEFAULT_SLIPPAGE,\n customSlippage: null,\n infiniteApprove: false,\n affiliateRef: null,\n affiliatePercent: null,\n affiliateWallets: null,\n disabledLiquiditySources: [],\n theme: 'auto',\n language: DEFAULT_LANGUAGE,\n addPreferredBlockchain: (blockchain) => {\n const currentPreferredBlockchains = get().preferredBlockchains;\n\n const noNeedToDoAnything = currentPreferredBlockchains.find(\n (preferredBlockchain, index) => {\n const isSameBlockchain = preferredBlockchain === blockchain;\n const isInVisibleList = index <= BLOCKCHAIN_LIST_SIZE - 1;\n\n return isSameBlockchain && isInVisibleList;\n }\n );\n\n if (noNeedToDoAnything) {\n return;\n }\n\n const nextPreferredBlockchains: string[] =\n currentPreferredBlockchains.filter((preferredBlockchain) => {\n const isSameBlockchain = preferredBlockchain === blockchain;\n\n return !isSameBlockchain;\n });\n\n set(() => ({\n preferredBlockchains: [blockchain, ...nextPreferredBlockchains],\n }));\n },\n setSlippage: (slippage) =>\n set(() => ({\n slippage: slippage,\n })),\n setCustomSlippage: (customSlippage) =>\n set(() => ({\n customSlippage: customSlippage,\n })),\n setAffiliateRef: (affiliateRef) =>\n set(() => ({\n affiliateRef,\n })),\n setAffiliatePercent: (affiliatePercent) =>\n set(() => ({\n affiliatePercent,\n })),\n\n setAffiliateWallets: (affiliateWallets) =>\n set(() => ({\n affiliateWallets,\n })),\n toggleAllLiquiditySources: (shouldReset?: boolean) =>\n set((state) => {\n if (shouldReset) {\n return { disabledLiquiditySources: [] };\n }\n const { swappers } = useMetaStore.getState().meta;\n const swappersGroup = removeDuplicateFrom(\n swappers.map((swapper) => swapper.swapperGroup)\n );\n\n if (\n swappersGroup.length === state.disabledLiquiditySources.length\n ) {\n return { disabledLiquiditySources: [] };\n }\n\n return {\n disabledLiquiditySources: swappersGroup,\n };\n }),\n toggleInfiniteApprove: () =>\n set((state) => ({\n infiniteApprove: !state.infiniteApprove,\n })),\n toggleLiquiditySource: (name) =>\n set((state) => {\n if (state.disabledLiquiditySources.includes(name)) {\n return {\n disabledLiquiditySources: state.disabledLiquiditySources.filter(\n (liquiditySource) => liquiditySource != name\n ),\n };\n }\n return {\n disabledLiquiditySources:\n state.disabledLiquiditySources.concat(name),\n };\n }),\n setTheme: (theme) =>\n set(() => ({\n theme,\n })),\n setLanguage: (language) =>\n set(() => ({\n language,\n })),\n })),\n {\n name: 'user-settings',\n skipHydration: true,\n }\n )\n )\n);\n", "import type { FlagPropTypes, Language } from '@rango-dev/ui';\n\nimport { English, French, Japanese, Spanish } from '@rango-dev/ui';\n\nexport type LanguageItem = {\n title: string;\n label: string;\n local: Language;\n SVGFlag: React.ComponentType<FlagPropTypes>;\n};\n\nexport const LANGUAGES: LanguageItem[] = [\n { title: 'English', label: 'English', local: 'en', SVGFlag: English },\n { title: 'Spanish', label: 'Espa\u00F1ol', local: 'es', SVGFlag: Spanish },\n { title: 'French', label: 'Fran\u00E7ais', local: 'fr', SVGFlag: French },\n { title: 'Japanese', label: '\u65E5\u672C\u8A9E', local: 'jp', SVGFlag: Japanese },\n];\n\nexport const DEFAULT_LANGUAGE = 'en';\n", "const LOW = 0.5;\nconst MEDIUM = 1;\nconst HIGH = 3;\n\nexport const SLIPPAGES = [LOW, MEDIUM, HIGH];\n\nexport const DEFAULT_SLIPPAGE = 1;\n\nexport const HIGH_SLIPPAGE = 5;\n\nexport const MAX_SLIPPAGE = 100;\n\nexport const MIN_SLIPPGAE = 0;\n", "import type { Info } from './NoRoutes.types';\n\nimport { i18n } from '@lingui/core';\n\nimport { errorMessages } from '../../constants/errors';\n\nexport function makeInfo(\n diagnosisMessage: string | null,\n disabledLiquiditySources: string[],\n hasError: boolean,\n toggleAllLiquiditySources: (shouldReset: boolean) => void,\n refetchBestRoute: () => void\n): Info {\n if (hasError) {\n return {\n alert: {\n type: 'warning',\n text: errorMessages().genericServerError,\n action: {\n onClick: refetchBestRoute,\n title: i18n.t('Retry'),\n },\n },\n description: '',\n };\n } else if (diagnosisMessage) {\n return {\n alert: {\n type: 'error',\n text: diagnosisMessage,\n action: null,\n },\n description: '',\n };\n } else if (disabledLiquiditySources.length) {\n return {\n alert: {\n type: 'warning',\n text: errorMessages().liquiditySourcesError.title,\n action: {\n onClick: () => toggleAllLiquiditySources(true),\n title: i18n.t('Reset'),\n },\n },\n description: errorMessages().liquiditySourcesError.description,\n };\n }\n return {\n alert: null,\n description: errorMessages().noRoutesError.description,\n };\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n});\n\nexport const Footer = styled('div', {\n width: '100%',\n});\n\nexport const PrefixIcon = styled('div', {\n padding: '$6 $0',\n});\n", "import type { PropTypes } from './RouteErrors.types';\n\nimport { Alert, Divider, InfoIcon } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { errorMessages } from '../../constants/errors';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { hasLimitError, LimitErrorMessage } from '../../utils/swap';\n\nimport { Action, Alerts } from './RouteErrors.styles';\nimport { RouteErrorsModal } from './RouteErrorsModal';\n\nconst WARNING_LEVEL_LIMIT = -10;\n\nexport function RouteErrors(props: PropTypes) {\n const { bestRoute } = useBestRouteStore();\n const {\n highValueLoss,\n percentageChange,\n priceImpactCanNotBeComputed,\n openModal,\n onToggle,\n totalFeeInUsd,\n outputUsdValue,\n inputUsdValue,\n loading,\n extraSpace,\n } = props;\n const error = hasLimitError(bestRoute);\n const { recommendation } = LimitErrorMessage(bestRoute);\n\n const showWarnings = !error && (highValueLoss || priceImpactCanNotBeComputed);\n const showAlerts = showWarnings || error;\n\n return (\n <>\n {(loading || (extraSpace && !showAlerts)) && <Divider size={20} />}\n {showAlerts && (\n <Alerts>\n {showWarnings && (\n <>\n <Alert\n title={\n highValueLoss\n ? errorMessages().highValueLossError.title\n : errorMessages().unknownPriceError.title\n }\n type={\n highValueLoss && !!percentageChange?.lt(WARNING_LEVEL_LIMIT)\n ? 'error'\n : 'warning'\n }\n variant=\"alarm\"\n action={\n <Action onClick={() => onToggle(true)}>\n <InfoIcon size={12} color=\"gray\" />\n </Action>\n }\n />\n </>\n )}\n {error && (\n <Alert type=\"error\" variant=\"alarm\" title={recommendation} />\n )}\n </Alerts>\n )}\n\n <RouteErrorsModal\n highValueLoss={highValueLoss}\n open={openModal}\n onToggle={onToggle}\n percentageChange={percentageChange}\n inputUsdValue={inputUsdValue}\n outputUsdValue={outputUsdValue}\n totalFeeInUsd={totalFeeInUsd}\n />\n </>\n );\n}\n", "import type { TokenWithBalance } from '../components/TokenList';\nimport type { Wallet } from '../types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset/dist/shared';\nimport type { BestRouteResponse, BlockchainMeta, Token } from 'rango-sdk';\n\nimport BigNumber from 'bignumber.js';\nimport { create } from 'zustand';\nimport { subscribeWithSelector } from 'zustand/middleware';\n\nimport { ZERO } from '../constants/numbers';\nimport { isPositiveNumber } from '../utils/numbers';\nimport {\n createRetryRoute,\n getBestRouteToTokenUsdPrice,\n} from '../utils/routing';\nimport { calcOutputUsdValue } from '../utils/swap';\n\nimport { useMetaStore } from './meta';\nimport createSelectors from './selectors';\n\nconst getUsdValue = (token: Token | null, amount: string): BigNumber | null =>\n token?.usdPrice\n ? new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0)\n : null;\n\nexport interface RouteState {\n fromBlockchain: BlockchainMeta | null;\n toBlockchain: BlockchainMeta | null;\n inputAmount: string;\n inputUsdValue: BigNumber | null;\n outputAmount: BigNumber | null;\n outputUsdValue: BigNumber | null;\n fromToken: TokenWithBalance | null;\n toToken: TokenWithBalance | null;\n routeWalletsConfirmed: boolean;\n selectedWallets: Wallet[];\n resetRoute: () => void;\n resetToBlockchain: () => void;\n resetFromBlockchain: () => void;\n setFromBlockchain: (chain: BlockchainMeta | null) => void;\n setToBlockchain: (chian: BlockchainMeta | null) => void;\n\n setFromToken: (token: Token | null) => void;\n setToToken: (token: Token | null) => void;\n setInputAmount: (amount: string) => void;\n bestRoute: BestRouteResponse | null;\n setRoute: (bestRoute: BestRouteResponse | null) => void;\n retry: (pendingSwap: PendingSwap) => void;\n switchFromAndTo: () => void;\n setRouteWalletConfirmed: (flag: boolean) => void;\n setSelectedWallets: (wallets: Wallet[]) => void;\n customDestination: string;\n setCustomDestination: (address: string) => void;\n resetRouteWallets: () => void;\n}\n\nexport const useBestRouteStore = createSelectors(\n create<RouteState>()(\n subscribeWithSelector((set) => ({\n fromBlockchain: null,\n fromToken: null,\n inputAmount: '',\n outputAmount: null,\n inputUsdValue: new BigNumber(0),\n outputUsdValue: new BigNumber(0),\n toBlockchain: null,\n toToken: null,\n bestRoute: null,\n routeWalletsConfirmed: false,\n selectedWallets: [],\n customDestination: '',\n setRoute: (bestRoute) =>\n set((state) => {\n let outputAmount: BigNumber | null = null;\n let outputUsdValue: BigNumber = ZERO;\n if (!isPositiveNumber(state.inputAmount)) {\n return {};\n }\n if (!!bestRoute) {\n outputAmount = !!bestRoute.result?.outputAmount\n ? new BigNumber(bestRoute.result?.outputAmount)\n : null;\n outputUsdValue = calcOutputUsdValue(\n bestRoute.result?.outputAmount,\n getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice\n );\n }\n return {\n bestRoute,\n ...(!!bestRoute && {\n outputAmount,\n outputUsdValue,\n }),\n };\n }),\n resetRoute: () =>\n set(() => ({\n bestRoute: null,\n outputAmount: null,\n outputUsdValue: new BigNumber(0),\n })),\n setFromBlockchain: (chain) => {\n set((state) => {\n if (state.fromBlockchain?.name === chain?.name) {\n return {};\n }\n\n return {\n fromBlockchain: chain,\n ...(state.fromToken && {\n bestRoute: null,\n fromToken: null,\n outputAmount: null,\n outputUsdValue: null,\n }),\n };\n });\n },\n setFromToken: (token) => {\n const { blockchains } = useMetaStore.getState().meta;\n return set((state) => ({\n fromToken: token,\n ...(token && {\n fromBlockchain:\n blockchains.find(\n (blockchain) => blockchain.name === token.blockchain\n ) ?? null,\n }),\n ...(!!state.inputAmount && {\n inputUsdValue: getUsdValue(token, state.inputAmount),\n }),\n }));\n },\n setToBlockchain: (chain) => {\n set((state) => {\n if (state.toBlockchain?.name === chain?.name) {\n return {};\n }\n\n return {\n toBlockchain: chain,\n ...(state.toToken && {\n bestRoute: null,\n toToken: null,\n outputAmount: null,\n outputUsdValue: null,\n }),\n };\n });\n },\n setToToken: (token) => {\n const { blockchains } = useMetaStore.getState().meta;\n return set(() => ({\n toToken: token,\n ...(token && {\n toBlockchain:\n blockchains.find(\n (blockchain) => blockchain.name === token.blockchain\n ) ?? null,\n }),\n }));\n },\n setInputAmount: (amount) => {\n set((state) => ({\n inputAmount: amount,\n ...(!amount && {\n outputAmount: new BigNumber(0),\n outputUsdValue: new BigNumber(0),\n bestRoute: null,\n }),\n ...(!!state.fromToken && {\n inputUsdValue: getUsdValue(state.fromToken, amount),\n }),\n }));\n },\n retry: (pendingSwap) => {\n const { tokens, blockchains } = useMetaStore.getState().meta;\n\n const {\n fromBlockchain,\n fromToken,\n toBlockchain,\n toToken,\n inputAmount,\n } = createRetryRoute(pendingSwap, blockchains, tokens);\n\n set({\n fromBlockchain,\n fromToken,\n inputAmount,\n outputAmount: null,\n inputUsdValue: getUsdValue(fromToken ?? null, inputAmount),\n outputUsdValue: new BigNumber(0),\n toBlockchain,\n toToken,\n bestRoute: null,\n });\n },\n switchFromAndTo: () =>\n set((state) => ({\n fromBlockchain: state.toBlockchain,\n fromToken: state.toToken,\n toBlockchain: state.fromBlockchain,\n toToken: state.fromToken,\n inputAmount: state.outputAmount?.toString() || '',\n inputUsdValue: getUsdValue(\n state.toToken,\n state.outputAmount?.toString() || ''\n ),\n })),\n\n resetFromBlockchain: () =>\n set(() => ({\n fromToken: null,\n fromBlockchain: null,\n outputAmount: null,\n outputUsdValue: null,\n bestRoute: null,\n })),\n resetToBlockchain: () =>\n set(() => ({\n toToken: null,\n toBlockchain: null,\n outputAmount: null,\n outputUsdValue: null,\n bestRoute: null,\n })),\n setRouteWalletConfirmed: (flag) =>\n set({\n routeWalletsConfirmed: flag,\n }),\n setSelectedWallets: (wallets) => set({ selectedWallets: wallets }),\n setCustomDestination: (address) => set({ customDestination: address }),\n resetRouteWallets: () =>\n set({\n routeWalletsConfirmed: false,\n selectedWallets: [],\n customDestination: '',\n }),\n }))\n )\n);\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { BestRouteEqualityParams, Wallet } from '../types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport type { PriceImpactWarningLevel } from '@rango-dev/ui';\nimport type {\n SimulationAssetAndAmount,\n SimulationValidationStatus,\n} from '@rango-dev/ui/dist/widget/ui/src/types/swaps';\nimport type {\n Asset,\n BestRouteResponse,\n BlockchainMeta,\n Token,\n} from 'rango-sdk';\n\nimport { getLastSuccessfulStep } from '@rango-dev/queue-manager-rango-preset';\nimport BigNumber from 'bignumber.js';\n\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n HIGHT_PRICE_IMPACT,\n LOW_PRICE_IMPACT,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n} from '../constants/routing';\n\nimport { areEqual } from './common';\nimport { findBlockchain, findToken } from './meta';\nimport { numberToString } from './numbers';\n\nexport function searchParamsToToken(\n tokens: Token[],\n searchParams: string | null,\n chain: BlockchainMeta | null\n): Token | null {\n if (!chain) {\n return null;\n }\n return (\n tokens.find((token) => {\n const symbolAndAddress = searchParams?.split('--');\n if (symbolAndAddress?.length === 1) {\n return (\n token.symbol === symbolAndAddress[0] &&\n token.address === null &&\n token.blockchain === chain.name\n );\n }\n return (\n token.symbol === symbolAndAddress?.[0] &&\n token.address === symbolAndAddress?.[1] &&\n token.blockchain === chain.name\n );\n }) || null\n );\n}\n\nexport function getBestRouteToTokenUsdPrice(\n bestRoute: BestRouteResponse | null\n): number | null | undefined {\n return bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1].to\n .usdPrice;\n}\n\nexport function isNumberOfSwapsChanged(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n) {\n const route1Swaps = route1.result?.swaps || [];\n const route2Swaps = route2.result?.swaps || [];\n return route1Swaps.length !== route2Swaps.length;\n}\n\nexport function isRouteSwappersUpdated(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n) {\n const route1Swappers =\n route1.result?.swaps.map((swap) => swap.swapperId) || [];\n const route2Swappers =\n route2.result?.swaps.map((swap) => swap.swapperId) || [];\n return !areEqual(route1Swappers, route2Swappers);\n}\n\nexport function isRouteInternalCoinsUpdated(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n) {\n const route1InternalCoins =\n route1.result?.swaps.map((swap) => swap.to.symbol) || [];\n const route2InternalCoins =\n route2.result?.swaps.map((swap) => swap.to.symbol) || [];\n return !areEqual(route1InternalCoins, route2InternalCoins);\n}\n\nexport function isRouteChanged(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n): boolean {\n return (\n isNumberOfSwapsChanged(route1, route2) ||\n isRouteSwappersUpdated(route1, route2) ||\n isRouteInternalCoinsUpdated(route1, route2)\n );\n}\n\nexport function outToRatioHasWarning(\n fromUsdValue: BigNumber | null,\n outToInRatio: BigNumber | 0\n) {\n return (\n (parseInt(outToInRatio?.toFixed(2) || '0') <= -10 &&\n (fromUsdValue === null || fromUsdValue.gte(new BigNumber(200)))) ||\n (parseInt(outToInRatio?.toFixed(2) || '0') <= -5 &&\n (fromUsdValue === null || fromUsdValue.gte(new BigNumber(1000))))\n );\n}\n\nexport function getRequiredBalanceOfWallet(\n selectedWallet: Wallet,\n fee: SimulationValidationStatus[] | null\n): SimulationAssetAndAmount[] | null {\n if (fee === null) {\n return null;\n }\n const relatedFeeStatus = fee\n ?.find((item) => item.blockchain === selectedWallet.chain)\n ?.wallets.find(\n (wallet) =>\n wallet.address?.toLowerCase() === selectedWallet.address.toLowerCase()\n );\n if (!relatedFeeStatus) {\n return null;\n }\n return relatedFeeStatus.requiredAssets;\n}\n\nexport function isRouteParametersChanged(params: BestRouteEqualityParams) {\n if (params.store === 'bestRoute') {\n const { prevState, currentState } = params;\n return (\n !!currentState.fromToken &&\n !!currentState.toToken &&\n (prevState.fromBlockchain?.name !== currentState.fromBlockchain?.name ||\n prevState.toBlockchain?.name !== currentState.toBlockchain?.name ||\n prevState.fromToken?.symbol !== currentState.fromToken?.symbol ||\n prevState.toToken?.symbol !== currentState.toToken?.symbol ||\n prevState.fromToken?.blockchain !== prevState.fromToken?.blockchain ||\n prevState.toToken?.blockchain !== currentState.toToken?.blockchain ||\n prevState.fromToken?.address !== currentState.fromToken?.address ||\n prevState.toToken?.address !== currentState.toToken?.address ||\n prevState.inputAmount !== currentState.inputAmount)\n );\n } else if (params.store === 'settings') {\n const { prevState, currentState } = params;\n return (\n prevState.slippage !== currentState.slippage ||\n prevState.customSlippage !== currentState.customSlippage ||\n prevState.disabledLiquiditySources?.length !==\n currentState.disabledLiquiditySources?.length ||\n prevState.infiniteApprove ||\n currentState.infiniteApprove\n );\n }\n return false;\n}\n\nexport function getFormattedBestRoute(\n bestRoute: BestRouteResponse | null\n): BestRouteResponse | null {\n if (!bestRoute) {\n return null;\n }\n\n const formattedSwaps = (bestRoute.result?.swaps || []).map((swap) => ({\n ...swap,\n fromAmount: numberToString(\n swap.fromAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n toAmount: numberToString(\n swap.toAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n }));\n\n return {\n ...bestRoute,\n ...(bestRoute.result && {\n result: { ...bestRoute.result, swaps: formattedSwaps },\n }),\n };\n}\n\nexport function getFormattedPendingSwap(pendingSwap: PendingSwap): PendingSwap {\n const formattedSteps = pendingSwap.steps.map((step) => ({\n ...step,\n feeInUsd: numberToString(\n step.feeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n ),\n outputAmount: numberToString(\n step.outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n expectedOutputAmountHumanReadable: numberToString(\n step.expectedOutputAmountHumanReadable,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n }));\n\n return {\n ...pendingSwap,\n inputAmount: numberToString(\n pendingSwap.inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n steps: formattedSteps,\n };\n}\n\n//todo: refactor bestRoute store and add loadingStatus\nexport const getBestRouteStatus = (loading: boolean, error: boolean) => {\n if (loading) {\n return 'loading';\n }\n if (error) {\n return 'failed';\n }\n return 'success';\n};\n\nexport function getPriceImpactLevel(\n priceImpact: number\n): PriceImpactWarningLevel {\n let warningLevel: PriceImpactWarningLevel = undefined;\n if (priceImpact <= LOW_PRICE_IMPACT && priceImpact > HIGHT_PRICE_IMPACT) {\n warningLevel = 'low';\n } else if (priceImpact <= HIGHT_PRICE_IMPACT) {\n warningLevel = 'high';\n }\n\n return warningLevel;\n}\n\nexport function findCommonTokens<T extends Asset[], R extends Asset[]>(\n listA: T,\n listB: R\n) {\n const tokenToString = (token: Asset): string =>\n `${token.symbol}-${token.blockchain}-${token.address ?? ''}`;\n\n const set = new Set();\n\n listA.forEach((token) => set.add(tokenToString(token)));\n\n return listB.filter((token) => set.has(tokenToString(token))) as R;\n}\n\nexport function createRetryRoute(\n pendingSwap: PendingSwap,\n blockchains: BlockchainMeta[],\n tokens: Token[]\n): {\n fromBlockchain: BlockchainMeta | null;\n fromToken: Token | null;\n toBlockchain: BlockchainMeta | null;\n toToken: Token | null;\n inputAmount: string;\n} {\n const firstStep = pendingSwap.steps[0];\n const lastStep = pendingSwap.steps[pendingSwap.steps.length - 1];\n const lastSuccessfulStep = getLastSuccessfulStep(pendingSwap.steps);\n\n const toToken = {\n blockchain: lastStep.toBlockchain,\n symbol: lastStep.toSymbol,\n address: lastStep.toSymbolAddress,\n };\n\n const fromBlockchainMeta = findBlockchain(\n lastSuccessfulStep\n ? lastSuccessfulStep.toBlockchain\n : firstStep.fromBlockchain,\n blockchains\n );\n const toBlockchainMeta = findBlockchain(lastStep.toBlockchain, blockchains);\n const fromTokenMeta = findToken(\n lastSuccessfulStep\n ? {\n blockchain: fromBlockchainMeta?.name ?? '',\n symbol: lastSuccessfulStep.toSymbol,\n address: lastSuccessfulStep.toSymbolAddress,\n }\n : {\n blockchain: fromBlockchainMeta?.name ?? '',\n symbol: firstStep.fromSymbol,\n address: firstStep.fromSymbolAddress,\n },\n tokens\n );\n const toTokenMeta = findToken(toToken, tokens);\n const inputAmount = lastSuccessfulStep\n ? lastSuccessfulStep.outputAmount ?? ''\n : pendingSwap.inputAmount;\n\n return {\n fromBlockchain: fromBlockchainMeta,\n fromToken: fromTokenMeta,\n toBlockchain: toBlockchainMeta,\n toToken: toTokenMeta,\n inputAmount,\n };\n}\n", "import type { Asset, BlockchainMeta, Token } from 'rango-sdk';\n\nimport { tokensAreEqual } from './wallets';\n\nexport function getBlockchainDisplayNameFor(\n blockchainName: string,\n blockchains: BlockchainMeta[]\n): string | undefined {\n return blockchains.find((blockchain) => blockchain.name === blockchainName)\n ?.displayName;\n}\nexport function getBlockchainShortNameFor(\n blockchainName: string,\n blockchains: BlockchainMeta[]\n): string | undefined {\n return blockchains.find((blockchain) => blockchain.name === blockchainName)\n ?.shortName;\n}\n\nexport function findToken(t: Asset, tokens: Token[]) {\n return tokens.find((token) => tokensAreEqual(token, t)) ?? null;\n}\n\nexport function findBlockchain(name: string, blockchains: BlockchainMeta[]) {\n return blockchains.find((blockchain) => blockchain.name === name) ?? null;\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { LoadingStatus } from '../store/meta';\nimport type { ConnectedWallet } from '../store/wallets';\nimport type { ConvertedToken, SwapButtonState, Wallet } from '../types';\nimport type {\n PendingSwap,\n PendingSwapStep,\n} from '@rango-dev/queue-manager-rango-preset';\nimport type { WalletType } from '@rango-dev/wallets-shared';\nimport type {\n BestRouteRequest,\n BestRouteResponse,\n BlockchainMeta,\n RecommendedSlippage,\n SwapResult,\n Token,\n} from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\nimport BigNumber from 'bignumber.js';\n\nimport { isValidAddress } from '../components/ConfirmWalletsModal/ConfirmWallets.helpers';\nimport { errorMessages } from '../constants/errors';\nimport { swapButtonTitles } from '../constants/messages';\nimport { ZERO } from '../constants/numbers';\nimport {\n BALANCE_MAX_DECIMALS,\n BALANCE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n} from '../constants/routing';\nimport { useMetaStore } from '../store/meta';\nimport { ButtonState } from '../types';\n\nimport { removeDuplicateFrom } from './common';\nimport { numberToString } from './numbers';\nimport { getRequiredBalanceOfWallet } from './routing';\nimport { getRequiredChains } from './wallets';\n\nexport function getOutputRatio(\n inputUsdValue: BigNumber | null,\n outputUsdValue: BigNumber | null\n) {\n if (\n !inputUsdValue ||\n !outputUsdValue ||\n inputUsdValue.lte(ZERO) ||\n outputUsdValue.lte(ZERO)\n ) {\n return 0;\n }\n return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);\n}\n\nexport function outputRatioHasWarning(\n inputUsdValue: BigNumber | null,\n outputRatio: BigNumber | 0\n): boolean {\n return (\n ((parseInt(outputRatio.toFixed(2) || '0') <= -10 &&\n inputUsdValue?.gte(new BigNumber(400))) ||\n (parseInt(outputRatio.toFixed(2) || '0') <= -5 &&\n inputUsdValue?.gte(new BigNumber(1000)))) ??\n false\n );\n}\n\nexport function hasLimitError(bestRoute: BestRouteResponse | null): boolean {\n return (\n (bestRoute?.result?.swaps || []).filter((swap) => {\n const minimum = !!swap.fromAmountMinValue\n ? new BigNumber(swap.fromAmountMinValue)\n : null;\n const maximum = !!swap.fromAmountMaxValue\n ? new BigNumber(swap.fromAmountMaxValue)\n : null;\n const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';\n if (isExclusive) {\n return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);\n }\n return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);\n }).length > 0\n );\n}\n\nexport function LimitErrorMessage(bestRoute: BestRouteResponse | null): {\n swap: SwapResult | null;\n fromAmountRangeError: string;\n recommendation: string;\n} {\n if (!bestRoute) {\n return { swap: null, fromAmountRangeError: '', recommendation: '' };\n }\n const swap = (bestRoute?.result?.swaps || []).filter((swap) => {\n const minimum = !!swap.fromAmountMinValue\n ? new BigNumber(swap.fromAmountMinValue)\n : null;\n const maximum = !!swap.fromAmountMaxValue\n ? new BigNumber(swap.fromAmountMaxValue)\n : null;\n const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';\n if (isExclusive) {\n return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);\n }\n return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);\n })[0];\n if (!swap) {\n return { swap: null, fromAmountRangeError: '', recommendation: '' };\n }\n const minimum = !!swap.fromAmountMinValue\n ? new BigNumber(swap.fromAmountMinValue)\n : null;\n const maximum = !!swap.fromAmountMaxValue\n ? new BigNumber(swap.fromAmountMaxValue)\n : null;\n const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';\n\n let fromAmountRangeError = '';\n let recommendation = '';\n if (!isExclusive && !!minimum && minimum.gt(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredEqualMin',\n message: 'Required: >= {min} {symbol}',\n values: {\n min: numberToString(\n minimum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.increaseAmount;\n } else if (isExclusive && !!minimum && minimum.gte(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredMin',\n message: 'Required: > {min} {symbol}',\n values: {\n min: numberToString(\n minimum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.increaseAmount;\n }\n\n if (!isExclusive && !!maximum && maximum.lt(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredEqualMax',\n message: 'Required: <= {max} {symbol}',\n values: {\n max: numberToString(\n maximum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.decreaseAmount;\n } else if (isExclusive && !!maximum && maximum.lte(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredMax',\n message: 'Required: < {max} {symbol}',\n values: {\n max: numberToString(\n maximum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.decreaseAmount;\n }\n\n return { swap, fromAmountRangeError, recommendation };\n}\n\nexport function getSwapButtonState(\n loadingMetaStatus: LoadingStatus,\n connectedWallets: ConnectedWallet[],\n loading: boolean,\n bestRoute: BestRouteResponse | null,\n hasLimitError: boolean,\n highValueLoss: boolean,\n priceImpactCanNotBeComputed: boolean,\n needsToWarnEthOnPath: boolean,\n inputAmount: string\n): SwapButtonState {\n if (loadingMetaStatus !== 'success') {\n return {\n title: swapButtonTitles().connectWallet,\n state: ButtonState.WAITFORCONNECTING,\n disabled: true,\n };\n }\n if (connectedWallets.length == 0) {\n return {\n title: swapButtonTitles().connectWallet,\n state: ButtonState.WAITFORCONNECTING,\n disabled: false,\n };\n }\n if (\n loading ||\n !bestRoute ||\n !bestRoute.result ||\n hasLimitError ||\n !inputAmount ||\n inputAmount === '0'\n ) {\n return {\n title: swapButtonTitles().swap,\n disabled: true,\n state: ButtonState.SWAP,\n };\n } else if (highValueLoss || priceImpactCanNotBeComputed) {\n return {\n title: swapButtonTitles().swapAnyway,\n disabled: false,\n hasWarning: true,\n state: ButtonState.NEEDTOCONFIRM,\n };\n } else if (needsToWarnEthOnPath) {\n return {\n title: swapButtonTitles().ethRouteWarning,\n disabled: false,\n hasWarning: true,\n state: ButtonState.WARNING,\n };\n }\n return {\n title: swapButtonTitles().swap,\n disabled: false,\n state: ButtonState.SWAP,\n };\n}\n\nexport function canComputePriceImpact(\n bestRoute: BestRouteResponse | null,\n inputAmount: string,\n usdValue: BigNumber | null\n) {\n return !(\n (!usdValue || usdValue.lte(ZERO)) &&\n !!bestRoute?.result &&\n !!inputAmount &&\n inputAmount !== '0' &&\n parseFloat(inputAmount || '0') !== 0 &&\n !!bestRoute.result\n );\n}\n\nexport function requiredWallets(route: BestRouteResponse | null) {\n const wallets: string[] = [];\n\n route?.result?.swaps.forEach((swap) => {\n const currentStepFromBlockchain = swap.from.blockchain;\n const currentStepToBlockchain = swap.to.blockchain;\n let lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepFromBlockchain != lastAddedWallet) {\n wallets.push(currentStepFromBlockchain);\n }\n lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepToBlockchain != lastAddedWallet) {\n wallets.push(currentStepToBlockchain);\n }\n });\n return wallets;\n}\n\nexport const getUsdPrice = (\n blockchain: string,\n symbol: string,\n address: string | null,\n allTokens: Token[]\n): number | null => {\n const token = allTokens?.find(\n (t) =>\n t.blockchain === blockchain &&\n t.symbol?.toUpperCase() === symbol?.toUpperCase() &&\n t.address === address\n );\n return token?.usdPrice || null;\n};\n\nexport function getUsdFeeOfStep(\n step: SwapResult,\n allTokens: Token[]\n): BigNumber {\n let totalFeeInUsd = ZERO;\n for (let i = 0; i < step.fee.length; i++) {\n const fee = step.fee[i];\n if (fee.expenseType === 'DECREASE_FROM_OUTPUT') {\n continue;\n }\n\n const unitPrice = getUsdPrice(\n fee.asset.blockchain,\n fee.asset.symbol,\n fee.asset.address,\n allTokens\n );\n totalFeeInUsd = totalFeeInUsd.plus(\n new BigNumber(fee.amount).multipliedBy(unitPrice || 0)\n );\n }\n\n return totalFeeInUsd;\n}\n\nexport function getTotalFeeInUsd(\n bestRoute: BestRouteResponse | null,\n allTokens: Token[]\n): BigNumber | null {\n return (\n bestRoute?.result?.swaps.reduce(\n (totalFee: BigNumber, step) =>\n totalFee.plus(getUsdFeeOfStep(step, allTokens)),\n ZERO\n ) || null\n );\n}\n\nexport function hasHighFee(totalFeeInUsd: BigNumber | null) {\n if (!totalFeeInUsd) {\n return false;\n }\n return !totalFeeInUsd.lt(new BigNumber(30));\n}\n\nexport function hasSlippageError(\n slippages: (RecommendedSlippage | null)[] | undefined\n) {\n return (slippages?.filter((s) => !!s?.error)?.length || 0) > 0;\n}\n\nexport function getMinRequiredSlippage(\n route: BestRouteResponse\n): string | null {\n const slippages = route.result?.swaps.map(\n (slippage) => slippage.recommendedSlippage\n );\n return (\n slippages\n ?.map((s) => s?.slippage || '0')\n ?.filter((s) => parseFloat(s) > 0)\n ?.sort((a, b) => parseFloat(b) - parseFloat(a))\n ?.find(() => true) || null\n );\n}\n\nexport function hasProperSlippage(\n userSlippage: string,\n minRequiredSlippage: string | null\n) {\n if (!minRequiredSlippage) {\n return true;\n }\n return parseFloat(userSlippage) >= parseFloat(minRequiredSlippage);\n}\n\nexport function hasEnoughBalance(\n route: BestRouteResponse,\n selectedWallets: Wallet[]\n) {\n const fee = route.validationStatus;\n\n if (fee === null || fee.length === 0) {\n return true;\n }\n\n for (const wallet of selectedWallets) {\n const requiredAssets = getRequiredBalanceOfWallet(wallet, fee);\n if (!requiredAssets) {\n continue;\n }\n\n const enoughBalanceInWallet = requiredAssets\n .map((asset) => asset.ok)\n .reduce((previous, current) => previous && current);\n if (!enoughBalanceInWallet) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function hasEnoughBalanceAndProperSlippage(\n route: BestRouteResponse,\n selectedWallets: Wallet[],\n userSlippage: string,\n minRequiredSlippage: string | null\n): boolean {\n return (\n hasEnoughBalance(route, selectedWallets) &&\n hasProperSlippage(userSlippage, minRequiredSlippage)\n );\n}\n\nexport function createBestRouteRequestBody(params: {\n fromToken: Token;\n toToken: Token;\n inputAmount: string;\n wallets?: Wallet[];\n selectedWallets?: Wallet[];\n disabledLiquiditySources: string[];\n slippage: number;\n affiliateRef: string | null;\n affiliatePercent: number | null;\n affiliateWallets: { [key: string]: string } | null;\n initialRoute?: BestRouteResponse;\n destination?: string;\n}): BestRouteRequest {\n const {\n fromToken,\n toToken,\n inputAmount,\n wallets,\n selectedWallets,\n disabledLiquiditySources,\n slippage,\n affiliateRef,\n affiliatePercent,\n affiliateWallets,\n initialRoute,\n destination,\n } = params;\n const selectedWalletsMap = selectedWallets?.reduce(\n (\n selectedWalletsMap: BestRouteRequest['selectedWallets'],\n selectedWallet\n ) => (\n (selectedWalletsMap[selectedWallet.chain] = selectedWallet.address),\n selectedWalletsMap\n ),\n {}\n );\n\n const connectedWallets: BestRouteRequest['connectedWallets'] = [];\n\n wallets?.forEach((wallet) => {\n const chainAndAccounts = connectedWallets.find(\n (connectedWallet) => connectedWallet.blockchain === wallet.chain\n );\n if (!!chainAndAccounts) {\n chainAndAccounts.addresses.push(wallet.address);\n } else {\n connectedWallets.push({\n blockchain: wallet.chain,\n addresses: [wallet.address],\n });\n }\n });\n\n const checkPrerequisites = !!initialRoute;\n\n const filteredBlockchains = removeDuplicateFrom(\n (initialRoute?.result?.swaps || []).reduce(\n (blockchains: string[], swap) => {\n blockchains.push(swap.from.blockchain, swap.to.blockchain);\n // Check if internalSwaps array exists\n if (swap.internalSwaps && Array.isArray(swap.internalSwaps)) {\n swap.internalSwaps.map((internalSwap) => {\n blockchains.push(\n internalSwap.from.blockchain,\n internalSwap.to.blockchain\n );\n });\n }\n return blockchains;\n },\n []\n )\n );\n\n const requestBody: BestRouteRequest = {\n amount: inputAmount.toString(),\n affiliateRef: affiliateRef ?? undefined,\n affiliatePercent: affiliatePercent ?? undefined,\n affiliateWallets: affiliateWallets ?? undefined,\n checkPrerequisites,\n from: {\n address: fromToken.address,\n blockchain: fromToken.blockchain,\n symbol: fromToken.symbol,\n },\n to: {\n address: toToken.address,\n blockchain: toToken.blockchain,\n symbol: toToken.symbol,\n },\n connectedWallets,\n selectedWallets: selectedWalletsMap ?? {},\n slippage: slippage.toString(),\n ...(destination && { destination: destination }),\n ...(disabledLiquiditySources.length > 0 && {\n swapperGroups: disabledLiquiditySources,\n swappersGroupsExclude: true,\n }),\n ...(checkPrerequisites && { blockchains: filteredBlockchains }),\n };\n\n return requestBody;\n}\n\nexport function getWalletsForNewSwap(selectedWallets: Wallet[]) {\n const wallets = selectedWallets.reduce(\n (\n selectedWalletsMap: {\n [p: string]: { address: string; walletType: WalletType };\n },\n selectedWallet\n ) => (\n (selectedWalletsMap[selectedWallet.chain] = {\n address: selectedWallet.address,\n walletType: selectedWallet.walletType,\n }),\n selectedWalletsMap\n ),\n {}\n );\n\n return wallets;\n}\n\nexport function getRouteOutputAmount(route: BestRouteResponse | null) {\n return route?.result?.outputAmount || null;\n}\n\nexport function getPercentageChange(\n inputUsdValue: string | number | null,\n outputUsdValue: string | number | null\n) {\n if (!inputUsdValue || !outputUsdValue) {\n return null;\n }\n return new BigNumber(outputUsdValue)\n .div(new BigNumber(inputUsdValue))\n .minus(1)\n .multipliedBy(100);\n}\n\nexport function isOutputAmountChangedALot(\n oldRoute: BestRouteResponse,\n newRoute: BestRouteResponse\n) {\n const oldOutputAmount = getRouteOutputAmount(oldRoute);\n const newOutputAmount = getRouteOutputAmount(newRoute);\n if (!oldOutputAmount || !newOutputAmount) {\n return false;\n }\n const percentageChange = getPercentageChange(\n oldOutputAmount,\n newOutputAmount\n );\n if (!percentageChange) {\n return true;\n }\n\n return percentageChange.toNumber() <= -1;\n}\n\nexport function getBalanceWarnings(\n route: BestRouteResponse,\n selectedWallets: Wallet[]\n) {\n const fee = route.validationStatus;\n const requiredWallets = getRequiredChains(route);\n const walletsSortedByRequiredWallets = selectedWallets.sort(\n (selectedWallet1, selectedWallet2) =>\n requiredWallets.indexOf(selectedWallet1.chain) -\n requiredWallets.indexOf(selectedWallet2.chain)\n );\n return walletsSortedByRequiredWallets\n .flatMap((wallet) => getRequiredBalanceOfWallet(wallet, fee) || [])\n .filter((asset) => !asset.ok)\n .map((asset) => {\n const symbol = asset.asset.symbol;\n const currentAmount = numberToString(\n new BigNumber(asset.currentAmount.amount).shiftedBy(\n -asset.currentAmount.decimals\n ),\n BALANCE_MIN_DECIMALS,\n BALANCE_MAX_DECIMALS\n );\n const requiredAmount = numberToString(\n new BigNumber(asset.requiredAmount.amount).shiftedBy(\n -asset.requiredAmount.decimals\n ),\n BALANCE_MIN_DECIMALS,\n BALANCE_MAX_DECIMALS\n );\n let reason = '';\n if (asset.reason === 'FEE') {\n reason = i18n.t(' for network fee');\n }\n if (asset.reason === 'INPUT_ASSET') {\n reason = i18n.t(' for swap');\n }\n if (asset.reason === 'FEE_AND_INPUT_ASSET') {\n reason = i18n.t(' for input and network fee');\n }\n const warningMessage = i18n.t({\n id: 'balanceWarningMessage',\n message: `Needs \u2248 {requiredAmount} {symbol}{reason}, but you have {currentAmount} {symbol} in your {blockchain} wallet.`,\n values: {\n requiredAmount,\n symbol,\n reason,\n currentAmount,\n blockchain: asset.asset.blockchain,\n },\n });\n return warningMessage;\n });\n}\n\nexport function calcOutputUsdValue(\n outputAmount?: string,\n tokenPrice?: number | null\n) {\n const amount = !!outputAmount ? new BigNumber(outputAmount) : ZERO;\n\n return amount.multipliedBy(tokenPrice || 0);\n}\n\nexport function isNetworkStatusInWarningState(\n pendingSwapStep: PendingSwapStep | null\n): boolean {\n return (\n !!pendingSwapStep &&\n pendingSwapStep.networkStatus !== null &&\n pendingSwapStep.networkStatus !== PendingSwapNetworkStatus.NetworkChanged\n );\n}\n\nexport function getSwapMessages(\n pendingSwap: PendingSwap,\n currentStep: PendingSwapStep | null\n): {\n shortMessage: string;\n detailedMessage: { content: string; long: boolean };\n} {\n const textForRemove = 'bellow button or';\n let message = pendingSwap.extraMessage;\n let detailedMessage = pendingSwap.extraMessageDetail;\n\n if (pendingSwap.networkStatusExtraMessageDetail?.includes(textForRemove)) {\n pendingSwap.networkStatusExtraMessageDetail =\n pendingSwap.networkStatusExtraMessageDetail.replace(textForRemove, '');\n }\n\n const networkWarningState = isNetworkStatusInWarningState(currentStep);\n\n if (networkWarningState) {\n message = pendingSwap.networkStatusExtraMessage || '';\n detailedMessage = pendingSwap.networkStatusExtraMessageDetail || '';\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check\n switch (currentStep?.networkStatus) {\n case PendingSwapNetworkStatus.WaitingForConnectingWallet:\n message = message || i18n.t('Waiting for connecting wallet');\n break;\n case PendingSwapNetworkStatus.WaitingForQueue:\n message =\n message || i18n.t('Waiting for other running tasks to be finished');\n break;\n case PendingSwapNetworkStatus.WaitingForNetworkChange:\n message = message || i18n.t('Waiting for changing wallet network');\n break;\n default:\n message = message || '';\n break;\n }\n }\n detailedMessage = detailedMessage || '';\n message = message || '';\n const isRpc =\n message?.indexOf('code') !== -1 && message?.indexOf('reason') !== -1;\n\n return {\n shortMessage: message,\n detailedMessage: { content: detailedMessage, long: isRpc },\n };\n}\n\nexport function getLastConvertedTokenInFailedSwap(\n pendingSwap: PendingSwap\n): ConvertedToken {\n let resultToken: ConvertedToken = null;\n if (pendingSwap.status === 'failed') {\n const lastSuccessStep = pendingSwap.steps\n .slice()\n .reverse()\n .filter((step) => step.status === 'success')[0];\n\n if (lastSuccessStep) {\n resultToken = {\n blockchain: lastSuccessStep.toBlockchain,\n symbol: lastSuccessStep.toSymbol,\n outputAmount: lastSuccessStep.outputAmount,\n address: lastSuccessStep.toSymbolAddress,\n };\n }\n }\n return resultToken;\n}\n\nexport function shouldRetrySwap(pendingSwap: PendingSwap) {\n return (\n pendingSwap.status === 'failed' &&\n !!pendingSwap.finishTime &&\n new Date().getTime() - parseInt(pendingSwap.finishTime) < 4 * 3600 * 1000\n );\n}\nexport function isValidCustomDestination(\n blockchain: string,\n address: string\n): boolean {\n const blockchains = useMetaStore.getState().meta.blockchains;\n const regex =\n blockchains.find((chain) => chain.name === blockchain)?.addressPatterns ||\n [];\n return regex.filter((r) => new RegExp(r).test(address)).length > 0;\n}\n\nexport function confirmSwapDisabled(\n fetching: boolean,\n showCustomDestination: boolean,\n customDestination: string,\n bestRoute: BestRouteResponse | null,\n selectedWallets: { walletType: string; chain: string }[],\n lastStepToBlockchain?: BlockchainMeta\n) {\n return (\n fetching ||\n (!showCustomDestination &&\n !requiredWallets(bestRoute).every((chain) =>\n selectedWallets.map((wallet) => wallet.chain).includes(chain)\n )) ||\n (!!showCustomDestination && !customDestination) ||\n (!!showCustomDestination &&\n !!customDestination &&\n lastStepToBlockchain &&\n !isValidAddress(lastStepToBlockchain, customDestination))\n );\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { Step } from '@rango-dev/ui/dist/widget/ui/src/components/BestRoute/BestRoute.types';\nimport type { BestRouteResponse, BlockchainMeta } from 'rango-sdk';\n\nimport {\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { getBlockchainShortNameFor } from '../../utils/meta';\nimport { numberToString } from '../../utils/numbers';\n\nexport function formatBestRoute(\n bestRoute: BestRouteResponse,\n blockchains: BlockchainMeta[]\n): Step[] | undefined {\n return bestRoute.result?.swaps.map((swap) => {\n return {\n swapper: { displayName: swap.swapperId, image: swap.swapperLogo },\n from: {\n token: { displayName: swap.from.symbol, image: swap.from.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.from.blockchain, blockchains) ?? '',\n image: swap.from.blockchainLogo,\n },\n price: {\n value: numberToString(\n swap.fromAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n swap.from.usdPrice?.toString(),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n },\n to: {\n token: { displayName: swap.to.symbol, image: swap.to.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.to.blockchain, blockchains) ?? '',\n image: swap.to.blockchainLogo,\n },\n price: {\n value: numberToString(\n swap.toAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n swap.to.usdPrice?.toString(),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n },\n };\n });\n}\n\nexport function getRequiredWallets(route: BestRouteResponse | null): string[] {\n const wallets: string[] = [];\n\n route?.result?.swaps.forEach((swap) => {\n const currentStepFromBlockchain = swap.from.blockchain;\n const currentStepToBlockchain = swap.to.blockchain;\n let lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepFromBlockchain != lastAddedWallet) {\n wallets.push(currentStepFromBlockchain);\n }\n lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepToBlockchain != lastAddedWallet) {\n wallets.push(currentStepToBlockchain);\n }\n });\n return wallets;\n}\n\nexport function isValidAddress(\n chain: BlockchainMeta,\n address: string\n): boolean {\n const regex = chain.addressPatterns;\n const valid = regex.filter((r) => new RegExp(r).test(address)).length > 0;\n return valid;\n}\n", "import { i18n } from '@lingui/core';\n\nexport const swapButtonTitles = () => {\n return {\n connectWallet: i18n.t('Connect Wallet'),\n swap: i18n.t('Swap'),\n swapAnyway: i18n.t('Swap anyway'),\n ethRouteWarning: i18n.t('The route goes through Ethereum. Continue?'),\n };\n};\n", "import { styled } from '@rango-dev/ui';\n\nexport const Alerts = styled('div', {\n width: '100%',\n paddingTop: '$10',\n});\n\nexport const Flex = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n gap: 10,\n width: '100%',\n});\n\nexport const Item = styled('div', {\n display: 'flex',\n padding: '$5 0',\n justifyContent: 'space-between',\n alignItems: 'center',\n width: '100%',\n});\n\nexport const Action = styled('div', {\n padding: '$2',\n alignSelf: 'flex-start',\n cursor: 'pointer',\n});\n", "import type { ModalPropTypes } from './RouteErrors.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Divider,\n MessageBox,\n Modal,\n Typography,\n WarningIcon,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { errorMessages } from '../../constants/errors';\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n HIGHT_PRICE_IMPACT,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { numberToString } from '../../utils/numbers';\n\nimport { Flex } from './RouteErrors.styles';\nimport { RouteErrorsModalItem } from './RouteErrorsModalItem';\n\nexport function RouteErrorsModal(props: ModalPropTypes) {\n const {\n highValueLoss,\n open,\n onToggle,\n percentageChange,\n inputUsdValue,\n outputUsdValue,\n totalFeeInUsd,\n } = props;\n const navigate = useNavigate();\n const type =\n highValueLoss && !!percentageChange?.lt(HIGHT_PRICE_IMPACT)\n ? 'error'\n : 'warning';\n const highValueLossData = [\n {\n title: i18n.t('Swapping'),\n value: numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n {\n title: i18n.t('Gas cost'),\n value: numberToString(\n totalFeeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n ),\n },\n {\n title: i18n.t('Receiving'),\n value: numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n {\n title: i18n.t('Price impact'),\n value: numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n ),\n valueColor: `${type}500`,\n },\n ];\n\n return (\n <Modal\n open={open}\n onClose={() => onToggle(false)}\n container={document.getElementById('swap-box') || document.body}>\n {highValueLoss ? (\n <MessageBox\n type={type}\n title={errorMessages().highValueLossError.impactTitle}\n description={errorMessages().highValueLossError.description}\n />\n ) : (\n <MessageBox\n type={type}\n title={errorMessages().unknownPriceError.impactTitle}\n description={errorMessages().unknownPriceError.description}\n />\n )}\n {highValueLoss && (\n <Flex>\n <Divider size={20} />\n <Typography size=\"small\" variant=\"title\">\n {i18n.t('Details')}\n </Typography>\n <Flex>\n {highValueLossData.map((item, index) => {\n const key = index;\n return <RouteErrorsModalItem key={key} {...item} />;\n })}\n </Flex>\n </Flex>\n )}\n <Divider size={32} />\n <Button\n type=\"primary\"\n size=\"large\"\n prefix={<WarningIcon />}\n fullWidth\n onClick={() => {\n navigate(navigationRoutes.confirmSwap);\n }}>\n {highValueLoss\n ? errorMessages().highValueLossError.confirmMessage\n : errorMessages().unknownPriceError.confirmMessage}\n </Button>\n </Modal>\n );\n}\n", "import type { ModalContentData } from './RouteErrors.types';\n\nimport { Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Item } from './RouteErrors.styles';\n\nexport function RouteErrorsModalItem(props: ModalContentData) {\n const { title, value, valueColor } = props;\n\n return (\n <Item>\n <Typography size=\"medium\" variant=\"label\" color=\"neutral600\">\n {title}\n </Typography>\n <Typography\n size=\"large\"\n variant=\"label\"\n color={valueColor || 'foreground'}>\n {`${valueColor ? '%' : '$'}${value}`}\n </Typography>\n </Item>\n );\n}\n", "import { ReverseIcon, styled } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { useBestRouteStore } from '../store/bestRoute';\n\nconst SwitchButtonContainer = styled('div', {\n position: 'absolute',\n bottom: '-12px',\n left: '50%',\n transform: 'translate(-50%, 10%)',\n cursor: 'pointer',\n});\n\nconst StyledButton = styled('div', {\n borderRadius: '$md',\n border: '3px solid $background',\n background: '$neutral100',\n width: '$24',\n height: '$24',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n color: '$foreground',\n '&:hover': {\n color: '$secondary500',\n },\n});\n\nexport function SwitchFromAndToButton() {\n const switchFromAndTo = useBestRouteStore.use.switchFromAndTo();\n\n return (\n <SwitchButtonContainer>\n <StyledButton\n onClick={() => {\n switchFromAndTo();\n }}>\n <ReverseIcon size={12} />\n </StyledButton>\n </SwitchButtonContainer>\n );\n}\n", "import { useEffect, useRef, useState } from 'react';\n\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useSettingsStore } from '../store/settings';\nimport { debounce } from '../utils/common';\nimport { isPositiveNumber } from '../utils/numbers';\nimport { createBestRouteRequestBody } from '../utils/swap';\nimport { tokensAreEqual } from '../utils/wallets';\n\nimport { useFetchBestRoute } from './useFetchBestRoute';\n\nconst DEBOUNCE_DELAY = 600;\n\ntype UseSwapInput = {\n fetch: () => void;\n loading: boolean;\n error: string;\n};\n\n/**\n * a hook for fetching best route based on from and to input values\n * we use this hook in home page\n */\nexport function useSwapInput(): UseSwapInput {\n const { fetch: fetchBestRoute, cancelFetch } = useFetchBestRoute();\n const [loading, setLoading] = useState(false);\n const {\n fromToken,\n toToken,\n inputAmount,\n inputUsdValue,\n resetRoute,\n setRoute,\n } = useBestRouteStore();\n const {\n slippage,\n customSlippage,\n affiliatePercent,\n affiliateRef,\n affiliateWallets,\n disabledLiquiditySources,\n } = useSettingsStore();\n const [error, setError] = useState('');\n const prevDisabledLiquiditySources = useRef(disabledLiquiditySources);\n const userSlippage = customSlippage ?? slippage;\n const hasTokensValue = !fromToken || !toToken;\n const shouldSkipRequest =\n hasTokensValue ||\n tokensAreEqual(fromToken, toToken) ||\n !isPositiveNumber(inputAmount);\n\n const fetch: UseSwapInput['fetch'] = () => {\n if (!loading) {\n setLoading(true);\n }\n if (!shouldSkipRequest) {\n resetRoute();\n const requestBody = createBestRouteRequestBody({\n fromToken,\n toToken,\n inputAmount,\n disabledLiquiditySources,\n slippage: userSlippage,\n affiliateRef,\n affiliatePercent,\n affiliateWallets,\n });\n fetchBestRoute(requestBody)\n .then((res) => {\n setLoading(false);\n setRoute(res);\n })\n .catch((error) => {\n resetRoute();\n if (error?.code !== 'ERR_CANCELED') {\n setError(error.message);\n setLoading(false);\n }\n });\n }\n };\n\n const debouncedFetch = debounce(() => {\n if (!shouldSkipRequest) {\n fetch();\n }\n }, DEBOUNCE_DELAY);\n\n useEffect(() => {\n if (!isPositiveNumber(inputAmount) || inputUsdValue?.eq(0)) {\n setLoading(false);\n cancelFetch();\n return;\n }\n if (shouldSkipRequest) {\n return;\n }\n resetRoute();\n setLoading(true);\n debouncedFetch();\n return cancelFetch;\n }, [inputAmount, shouldSkipRequest]);\n\n useEffect(() => {\n const disabledLiquiditySourceReset =\n !!prevDisabledLiquiditySources.current.length &&\n !disabledLiquiditySources.length;\n if (!shouldSkipRequest && disabledLiquiditySourceReset) {\n fetch();\n }\n prevDisabledLiquiditySources.current = disabledLiquiditySources;\n return cancelFetch;\n }, [disabledLiquiditySources.length]);\n\n return { fetch, loading, error };\n}\n", "import type { BestRouteRequest, BestRouteResponse } from 'rango-sdk';\n\nimport { useRef, useState } from 'react';\n\nimport { httpService } from '../services/httpService';\n\ninterface UseFetchBestRoute {\n fetch: (requestBody: BestRouteRequest) => Promise<BestRouteResponse>;\n cancelFetch: () => void;\n loading: boolean;\n}\n\nexport function useFetchBestRoute(): UseFetchBestRoute {\n const [loading, setLoading] = useState(false);\n const abortController = useRef<AbortController | null>(null);\n const cancel = () => abortController.current?.abort();\n\n const fetch: UseFetchBestRoute['fetch'] = async (requestBody) => {\n cancel();\n abortController.current = new AbortController();\n\n setLoading(true);\n\n try {\n const res = await httpService().getBestRoute(requestBody, {\n signal: abortController.current.signal,\n });\n abortController.current = null;\n return res;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-useless-catch\n } catch (error: any) {\n throw error;\n } finally {\n setLoading(false);\n }\n };\n return { fetch, loading, cancelFetch: cancel };\n}\n", "import type { WidgetConfig } from '../types';\n\nimport { useEffect, useRef } from 'react';\nimport {\n createSearchParams,\n useLocation,\n useSearchParams,\n} from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { SearchParams } from '../constants/searchParams';\nimport { useSyncStoresWithConfig } from '../hooks/useSyncStoresWithConfig';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useUiStore } from '../store/ui';\nimport { searchParamsToToken } from '../utils/routing';\n\ntype Props = { config: WidgetConfig | undefined };\n\nexport function UpdateUrl(props: Props) {\n const firstRender = useRef(true);\n const [searchParams, setSearchParams] = useSearchParams();\n const location = useLocation();\n const firstRenderSearchParams = useRef(location.search);\n const searchParamsRef = useRef<Record<string, string>>({});\n const fromBlockchain = useBestRouteStore.use.fromBlockchain();\n const toBlockchain = useBestRouteStore.use.toBlockchain();\n const fromToken = useBestRouteStore.use.fromToken();\n const toToken = useBestRouteStore.use.toToken();\n const setFromBlockchain = useBestRouteStore.use.setFromBlockchain();\n const setFromToken = useBestRouteStore.use.setFromToken();\n const setToBlockchain = useBestRouteStore.use.setToBlockchain();\n const setToToken = useBestRouteStore.use.setToToken();\n const inputAmount = useBestRouteStore.use.inputAmount();\n const setInputAmount = useBestRouteStore.use.setInputAmount();\n const loadingStatus = useMetaStore.use.loadingStatus();\n const { blockchains, tokens } = useMetaStore.use.meta();\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n useSyncStoresWithConfig(props.config);\n\n useEffect(() => {\n const params: Record<string, string> = {};\n createSearchParams(firstRenderSearchParams.current).forEach(\n (value, key) => {\n params[key] = value;\n }\n );\n searchParamsRef.current = params;\n const requestId =\n location.pathname.split(navigationRoutes.swaps + '/')[1] || null;\n if (requestId) {\n setSelectedSwap(requestId);\n }\n }, []);\n\n useEffect(() => {\n if (!firstRender.current) {\n let fromChainString = '',\n fromTokenString = '',\n toChainString = '',\n toTokenString = '',\n fromAmount = '';\n if (loadingStatus !== 'success') {\n fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];\n fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];\n toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];\n toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];\n fromAmount =\n searchParamsRef.current[SearchParams.FROM_AMOUNT] || inputAmount;\n } else {\n if (location.state === 'redirect') {\n return;\n }\n fromChainString = fromBlockchain?.name || '';\n fromTokenString =\n (fromToken?.symbol || '') +\n (fromToken?.address ? `--${fromToken?.address}` : '');\n toChainString = toBlockchain?.name || '';\n toTokenString =\n (toToken?.symbol || '') +\n (toToken?.address ? `--${toToken?.address}` : '');\n fromAmount = inputAmount;\n }\n setSearchParams(\n {\n ...(fromChainString && {\n [SearchParams.FROM_CHAIN]: fromChainString,\n }),\n ...(fromTokenString && {\n [SearchParams.FROM_TOKEN]: fromTokenString,\n }),\n ...(toChainString && { [SearchParams.TO_CHAIN]: toChainString }),\n ...(toTokenString && { [SearchParams.TO_TOKEN]: toTokenString }),\n ...(fromAmount && {\n [SearchParams.FROM_AMOUNT]: fromAmount.toString(),\n }),\n },\n { replace: true }\n );\n }\n firstRender.current = false;\n }, [\n location.pathname,\n inputAmount,\n fromBlockchain,\n fromToken,\n toBlockchain,\n toToken,\n ]);\n\n useEffect(() => {\n if (loadingStatus === 'success') {\n const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);\n const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);\n const toChainString = searchParams.get(SearchParams.TO_CHAIN);\n const toTokenString = searchParams.get(SearchParams.TO_TOKEN);\n const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);\n const fromBlockchain = blockchains.find(\n (blockchain) => blockchain.name === fromChainString\n );\n const fromToken = searchParamsToToken(\n tokens,\n fromTokenString,\n fromBlockchain || null\n );\n const toBlockchain = blockchains.find(\n (blockchain) => blockchain.name === toChainString\n );\n const toToken = searchParamsToToken(\n tokens,\n toTokenString,\n toBlockchain || null\n );\n if (!!fromBlockchain) {\n setFromBlockchain(fromBlockchain);\n if (!!fromToken) {\n setFromToken(fromToken);\n }\n }\n if (!!toBlockchain) {\n setToBlockchain(toBlockchain);\n if (!!toToken) {\n setToToken(toToken);\n }\n }\n if (fromAmount) {\n setInputAmount(fromAmount);\n }\n }\n }, [loadingStatus]);\n\n return null;\n}\n", "import type { WidgetConfig } from '../types';\nimport type { Asset } from 'rango-sdk';\n\nimport { useEffect, useMemo, useRef } from 'react';\n\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { tokensAreEqual } from '../utils/wallets';\n\nexport function useSyncStoresWithConfig(config: WidgetConfig | undefined) {\n const {\n setInputAmount,\n setToToken,\n setToBlockchain,\n setFromBlockchain,\n setFromToken,\n fromToken,\n toToken,\n fromBlockchain,\n toBlockchain,\n } = useBestRouteStore();\n\n const {\n meta: { tokens, blockchains },\n loadingStatus: loadingMetaStatus,\n } = useMetaStore();\n\n const { setAffiliateRef, setAffiliatePercent, setAffiliateWallets } =\n useSettingsStore();\n\n const fromTokensConfig = useMemo(\n () => config?.from?.tokens,\n [config?.from?.tokens]\n );\n const fromBlockchainsConfig = useMemo(\n () => config?.from?.blockchains,\n [config?.from?.blockchains]\n );\n const toTokensConfig = useMemo(\n () => config?.to?.tokens,\n [config?.to?.tokens]\n );\n const toBlockchainsConfig = useMemo(\n () => config?.to?.blockchains,\n [config?.to?.blockchains]\n );\n const prevConfigFromToken = useRef<Asset | undefined>(undefined);\n const prevConfigToToken = useRef<Asset | undefined>(undefined);\n const prevConfigFromBlockchain = useRef<string | undefined>(undefined);\n const prevConfigToBlockchain = useRef<string | undefined>(undefined);\n\n useEffect(() => {\n setInputAmount(config?.amount?.toString() || '');\n }, [config?.amount]);\n\n useEffect(() => {\n if (loadingMetaStatus === 'success') {\n const chain = blockchains.find(\n (chain) => chain.name === config?.from?.blockchain\n );\n const token = tokens.find((t) =>\n tokensAreEqual(t, config?.from?.token || null)\n );\n\n if (chain || (!chain && prevConfigFromBlockchain.current)) {\n setFromBlockchain(chain ?? null);\n }\n\n if (token || (!token && prevConfigFromToken.current)) {\n setFromToken(token ?? null);\n }\n\n prevConfigFromBlockchain.current = config?.from?.blockchain;\n prevConfigFromToken.current = config?.from?.token;\n }\n }, [\n config?.from?.token?.symbol,\n config?.from?.token?.address,\n config?.from?.token?.blockchain,\n config?.from?.blockchain,\n loadingMetaStatus,\n ]);\n\n useEffect(() => {\n if (fromToken && fromTokensConfig) {\n if (!fromTokensConfig.some((token) => tokensAreEqual(token, fromToken))) {\n setFromToken(null);\n }\n }\n\n if (fromBlockchain && fromBlockchainsConfig) {\n if (!fromBlockchainsConfig.includes(fromBlockchain.name)) {\n setFromBlockchain(null);\n }\n }\n }, [fromTokensConfig, fromBlockchainsConfig]);\n\n useEffect(() => {\n if (toToken && toTokensConfig) {\n if (!toTokensConfig.some((token) => tokensAreEqual(token, toToken))) {\n setToToken(null);\n }\n }\n\n if (toBlockchain && toBlockchainsConfig) {\n if (!toBlockchainsConfig.includes(toBlockchain.name)) {\n setToBlockchain(null);\n }\n }\n }, [toTokensConfig, toBlockchainsConfig]);\n\n useEffect(() => {\n if (loadingMetaStatus === 'success') {\n const chain = blockchains.find(\n (chain) => chain.name === config?.to?.blockchain\n );\n const token = tokens.find((t) =>\n tokensAreEqual(t, config?.to?.token || null)\n );\n\n if (chain || (!chain && prevConfigToBlockchain.current)) {\n setToBlockchain(chain ?? null);\n }\n\n if (token || (!token && prevConfigToToken.current)) {\n setToToken(token ?? null);\n }\n\n prevConfigToBlockchain.current = config?.to?.blockchain;\n prevConfigToToken.current = config?.to?.token;\n }\n }, [\n config?.to?.token?.symbol,\n config?.to?.token?.address,\n config?.to?.token?.blockchain,\n config?.to?.blockchain,\n loadingMetaStatus,\n ]);\n\n useEffect(() => {\n setAffiliateRef(config?.affiliate?.ref ?? null);\n setAffiliatePercent(config?.affiliate?.percent ?? null);\n setAffiliateWallets(config?.affiliate?.wallets ?? null);\n }, [\n config?.affiliate?.ref,\n config?.affiliate?.percent,\n config?.affiliate?.wallets,\n ]);\n}\n", "import type { WidgetConfig } from '../types';\n\nimport React from 'react';\nimport { useRoutes } from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { ConfirmSwapPage } from '../pages/ConfirmSwapPage';\nimport { HistoryPage } from '../pages/HistoryPage';\nimport { Home } from '../pages/Home';\nimport { LanguagePage } from '../pages/LanguagePage';\nimport { LiquiditySourcePage } from '../pages/LiquiditySourcePage';\nimport { SelectBlockchainPage } from '../pages/SelectBlockchainPage';\nimport { SelectSwapItemsPage } from '../pages/SelectSwapItemsPage';\nimport { SettingsPage } from '../pages/SettingsPage';\nimport { SwapDetailsPage } from '../pages/SwapDetailsPage';\nimport { ThemePage } from '../pages/ThemePage';\nimport { WalletsPage } from '../pages/WalletsPage';\n\nconst getAbsolutePath = (path: string) => path.replace('/', '');\n\ninterface PropTypes {\n config?: WidgetConfig;\n}\n\nexport function AppRoutes(props: PropTypes) {\n const { config } = props;\n\n return useRoutes([\n {\n path: navigationRoutes.home,\n element: <Home />,\n },\n {\n path: navigationRoutes.fromSwap,\n element: <SelectSwapItemsPage type=\"source\" />,\n },\n {\n path: navigationRoutes.toSwap,\n element: <SelectSwapItemsPage type=\"destination\" />,\n },\n {\n path: navigationRoutes.fromBlockchain,\n element: <SelectBlockchainPage type=\"source\" />,\n },\n {\n path: navigationRoutes.toBlockchain,\n element: <SelectBlockchainPage type=\"destination\" />,\n },\n {\n path: navigationRoutes.settings,\n element: (\n <SettingsPage\n singleTheme={config?.theme?.singleTheme}\n supportedSwappers={config?.liquiditySources}\n />\n ),\n },\n {\n path: navigationRoutes.themes,\n element: <ThemePage />,\n },\n {\n path: navigationRoutes.languages,\n element: <LanguagePage />,\n },\n {\n path: navigationRoutes.exchanges,\n element: (\n <LiquiditySourcePage\n sourceType=\"Exchanges\"\n supportedSwappers={config?.liquiditySources}\n />\n ),\n },\n {\n path: navigationRoutes.bridges,\n element: (\n <LiquiditySourcePage\n sourceType=\"Bridges\"\n supportedSwappers={config?.liquiditySources}\n />\n ),\n },\n { path: navigationRoutes.swaps, element: <HistoryPage /> },\n {\n path: navigationRoutes.swapDetails,\n element: <SwapDetailsPage />,\n },\n {\n path: navigationRoutes.wallets,\n element: (\n <WalletsPage\n supportedWallets={config?.wallets}\n multiWallets={\n typeof config?.multiWallets === 'undefined'\n ? true\n : config.multiWallets\n }\n config={config}\n />\n ),\n },\n {\n path: getAbsolutePath(navigationRoutes.confirmSwap),\n element: <ConfirmSwapPage config={config} />,\n },\n ]);\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type {\n ConfirmSwap,\n ConfirmSwapFetchResult,\n} from '../hooks/useConfirmSwap';\nimport type { WidgetConfig } from '../types';\n\nimport { i18n } from '@lingui/core';\nimport { useManager } from '@rango-dev/queue-manager-react';\nimport {\n Alert,\n BestRoute,\n BestRouteSkeleton,\n Button,\n Divider,\n IconButton,\n MessageBox,\n Modal,\n RefreshIcon,\n SettingsIcon,\n styled,\n Tooltip,\n Typography,\n WalletIcon,\n} from '@rango-dev/ui';\nimport React, { useEffect, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useNavigate } from 'react-router-dom';\n\nimport {\n formatBestRoute,\n getRequiredWallets,\n} from '../components/ConfirmWalletsModal/ConfirmWallets.helpers';\nimport { ConfirmWalletsModal } from '../components/ConfirmWalletsModal/ConfirmWalletsModal';\nimport { HeaderButton } from '../components/HeaderButtons/HeaderButtons.styles';\nimport { Layout } from '../components/Layout';\nimport { NoRoutes } from '../components/NoRoutes';\nimport { getConfirmSwapErrorMessage } from '../constants/errors';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../constants/routing';\nimport { getRouteWarningMessage } from '../constants/warnings';\nimport { useConfirmSwap } from '../hooks/useConfirmSwap';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { useUiStore } from '../store/ui';\nimport { useWalletsStore } from '../store/wallets';\nimport {\n ConfirmSwapErrorTypes,\n RouteWarningType,\n SlippageWarningType,\n} from '../types';\nimport { getContainer } from '../utils/common';\nimport {\n numberToString,\n secondsToString,\n totalArrivalTime,\n} from '../utils/numbers';\nimport { getPriceImpactLevel } from '../utils/routing';\nimport { getPercentageChange, getTotalFeeInUsd } from '../utils/swap';\n\nconst Container = styled('div', {\n position: 'relative',\n width: '100%',\n '& .description': {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n paddingBottom: '$10',\n },\n '& .icon': {\n width: '$24',\n height: '$24',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n },\n});\n\nconst Buttons = styled('div', {\n width: '100%',\n display: 'flex',\n justifyContent: 'space-between',\n '& .confirm-button': {\n flexGrow: 1,\n paddingRight: '$10',\n },\n [`& ${IconButton}`]: {\n width: '$48',\n height: '$48',\n },\n});\n\ntype PropTypes = {\n config?: WidgetConfig;\n};\n\nexport function ConfirmSwapPage(props: PropTypes) {\n //TODO: move component's logics to a custom hook\n const { config } = props;\n const {\n bestRoute,\n inputAmount,\n outputAmount,\n inputUsdValue,\n outputUsdValue,\n setInputAmount,\n selectedWallets,\n routeWalletsConfirmed,\n setRouteWalletConfirmed,\n customDestination,\n } = useBestRouteStore();\n const navigate = useNavigate();\n const [dbErrorMessage, setDbErrorMessage] = useState<string>('');\n const [showSlippageWarning, setShowSlippageWarning] = useState(false);\n\n const { connectedWallets } = useWalletsStore();\n const showWalletsOnInit = !routeWalletsConfirmed;\n const [showWallets, setShowWallets] = useState(false);\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n const {\n meta: { tokens, blockchains },\n loadingStatus: loadingMetaStatus,\n } = useMetaStore();\n const slippage = useSettingsStore.use.slippage();\n const customSlippage = useSettingsStore.use.customSlippage();\n const { manager } = useManager();\n const selectedSlippage = customSlippage || slippage;\n const {\n fetch: confirmSwap,\n loading: fetchingConfirmationRoute,\n cancelFetch,\n } = useConfirmSwap();\n const [confirmSwapResult, setConfirmSwapResult] =\n useState<ConfirmSwapFetchResult>({\n swap: null,\n error: null,\n warnings: null,\n });\n const showSkeleton =\n fetchingConfirmationRoute || loadingMetaStatus === 'loading';\n const showNoRouteFound =\n !fetchingConfirmationRoute &&\n confirmSwapResult.error &&\n [\n ConfirmSwapErrorTypes.NO_ROUTE,\n ConfirmSwapErrorTypes.REQUEST_FAILED,\n ].includes(confirmSwapResult.error.type);\n const showBestRoute =\n !showNoRouteFound &&\n !fetchingConfirmationRoute &&\n bestRoute &&\n bestRoute.result;\n\n const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);\n const percentageChange = numberToString(\n getPercentageChange(\n inputUsdValue?.toNumber() ?? 0,\n outputUsdValue?.toNumber() ?? 0\n ),\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n );\n\n const warningLevel = getPriceImpactLevel(parseFloat(percentageChange));\n\n const onConfirmSwap: ConfirmSwap['fetch'] = async ({\n selectedWallets,\n customDestination,\n }) => {\n const result = await confirmSwap?.({ selectedWallets, customDestination });\n setConfirmSwapResult(result);\n return result;\n };\n\n const addNewSwap = async () => {\n if (confirmSwapResult.swap && routeWalletsConfirmed) {\n try {\n await manager?.create(\n 'swap',\n { swapDetails: confirmSwapResult.swap },\n { id: confirmSwapResult.swap.requestId }\n );\n setSelectedSwap(confirmSwapResult.swap.requestId);\n navigate(\n '/' + navigationRoutes.swaps + `/${confirmSwapResult.swap.requestId}`,\n {\n replace: true,\n }\n );\n setTimeout(() => {\n setInputAmount('');\n }, 0);\n } catch (e) {\n setDbErrorMessage('Error: ' + (e as any)?.message);\n }\n }\n };\n\n const onConfirm = async () => {\n await addNewSwap();\n };\n\n const onStartConfirmSwap = async () => {\n if (confirmSwapResult?.warnings?.slippage) {\n setShowSlippageWarning(true);\n } else {\n await onConfirm();\n }\n };\n\n const onRefresh = async () => {\n setConfirmSwapResult({\n error: null,\n swap: null,\n warnings: null,\n });\n confirmSwap({ selectedWallets })\n .then((res) => {\n setConfirmSwapResult(res);\n })\n .catch((error) => console.error(error));\n };\n\n useEffect(() => {\n if (showWalletsOnInit) {\n cancelFetch();\n }\n }, [showWalletsOnInit]);\n\n useEffect(() => {\n if (showWalletsOnInit) {\n setShowWallets(showWalletsOnInit);\n }\n }, [showWalletsOnInit]);\n\n useEffect(() => {\n if (!showWalletsOnInit) {\n confirmSwap({ selectedWallets, customDestination })\n .then((result) => setConfirmSwapResult(result))\n .catch((error) => console.error(error));\n }\n }, []);\n\n useEffect(() => {\n const routeChanged =\n confirmSwapResult.warnings?.route?.type &&\n Object.values(RouteWarningType).includes(\n confirmSwapResult.warnings?.route?.type\n );\n\n const selectedWalletDisconnected =\n selectedWallets.length < 1 ||\n !selectedWallets.every((selectedWallet) =>\n connectedWallets.find(\n (connectedWallet) =>\n selectedWallet.address === connectedWallet.address &&\n selectedWallet.walletType === connectedWallet.walletType &&\n selectedWallet.chain === connectedWallet.chain\n )\n );\n\n let routeWalletsChanged = false;\n\n if (routeChanged) {\n let requiredWallets = getRequiredWallets(bestRoute);\n\n const lastStepToBlockchain =\n bestRoute?.result?.swaps[bestRoute.result.swaps.length - 1].to\n .blockchain;\n\n const isLastWalletRequired = !!bestRoute?.result?.swaps.find(\n (swap) => swap.from.blockchain === lastStepToBlockchain\n );\n\n if (!isLastWalletRequired) {\n requiredWallets = requiredWallets.slice(\n -requiredWallets.length,\n requiredWallets.length - 1\n );\n }\n\n const allRequiredWalletsSelected = requiredWallets.every(\n (requiredWallet) =>\n selectedWallets.find(\n (selectedWallet) => selectedWallet.chain === requiredWallet\n )\n );\n\n if (!allRequiredWalletsSelected) {\n routeWalletsChanged = true;\n }\n }\n\n if (bestRoute && (selectedWalletDisconnected || routeWalletsChanged)) {\n queueMicrotask(() => flushSync(setShowWallets.bind(null, true)));\n setRouteWalletConfirmed(false);\n }\n }, [\n confirmSwapResult.warnings?.route,\n selectedWallets.length,\n connectedWallets.length,\n ]);\n\n return (\n <Layout\n header={{\n title: i18n.t('Confirm Swap'),\n onBack: navigate.bind(null, -1),\n hasConnectWallet: true,\n suffix: (\n <Tooltip\n container={getContainer()}\n side=\"bottom\"\n content={i18n.t('Settings')}>\n <HeaderButton\n size=\"small\"\n variant=\"ghost\"\n onClick={() => navigate('/' + navigationRoutes.settings)}>\n <SettingsIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n ),\n }}\n footer={\n <Buttons>\n <div className=\"confirm-button\">\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n fullWidth\n loading={fetchingConfirmationRoute}\n disabled={!!confirmSwapResult.error}\n onClick={onStartConfirmSwap}>\n {i18n.t('Start Swap')}\n </Button>\n </div>\n <IconButton\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n loading={fetchingConfirmationRoute}\n onClick={setShowWallets.bind(null, true)}>\n <WalletIcon size={24} />\n </IconButton>\n </Buttons>\n }>\n <Modal\n anchor=\"bottom\"\n open={showSlippageWarning}\n prefix={\n <Button\n size=\"small\"\n variant=\"ghost\"\n onClick={() => navigate('/' + navigationRoutes.settings)}>\n <Typography variant=\"label\" size=\"medium\" color=\"$neutral700\">\n {i18n.t('Change settings')}\n </Typography>\n </Button>\n }\n container={document.querySelector('#swap-box') as HTMLDivElement}\n onClose={setShowSlippageWarning.bind(null, (prevState) => !prevState)}>\n {confirmSwapResult.warnings?.slippage && (\n <MessageBox\n type=\"warning\"\n title={\n confirmSwapResult.warnings.slippage.type ===\n SlippageWarningType.HIGH_SLIPPAGE\n ? i18n.t('High slippage')\n : i18n.t('Low slippage')\n }\n description={\n confirmSwapResult.warnings.slippage.type ===\n SlippageWarningType.HIGH_SLIPPAGE\n ? i18n.t(\n 'highSlippage',\n { selectedSlippage },\n {\n message:\n ' Caution, your slippage is high (={selectedSlippage}). Your trade may be front run.',\n }\n )\n : i18n.t(\n 'increaseSlippage',\n\n {\n minRequiredSlippage:\n confirmSwapResult.warnings.slippage.slippage,\n },\n {\n message:\n 'We recommend you to increase slippage to at least {minRequiredSlippage} for this route.',\n }\n )\n }>\n <Divider size={18} />\n <Divider size={32} />\n <Button\n size=\"large\"\n type=\"primary\"\n variant=\"contained\"\n fullWidth\n onClick={onConfirm}>\n {i18n.t('Confirm anyway')}\n </Button>\n </MessageBox>\n )}\n </Modal>\n {showWallets && (\n <ConfirmWalletsModal\n open={showWallets}\n onClose={() => setShowWallets(false)}\n onCancel={cancelFetch}\n loading={fetchingConfirmationRoute}\n onCheckBalance={onConfirmSwap}\n config={config}\n />\n )}\n\n <Container>\n <div className=\"description\">\n <Typography variant=\"title\" size=\"small\">\n {i18n.t('You get')}\n </Typography>\n <Button\n style={{ padding: '0' }}\n variant=\"ghost\"\n disabled={fetchingConfirmationRoute}\n onClick={onRefresh}>\n <div className=\"icon\">\n <RefreshIcon size={16} />\n </div>\n </Button>\n </div>\n {dbErrorMessage && (\n <>\n <Alert type=\"error\" variant=\"alarm\" title={dbErrorMessage} />\n <Divider size={12} />\n </>\n )}\n {confirmSwapResult.warnings?.route && (\n <>\n <Alert\n variant=\"alarm\"\n type=\"warning\"\n title={getRouteWarningMessage(confirmSwapResult.warnings.route)}\n />\n <Divider size={12} />\n </>\n )}\n {showSkeleton && <BestRouteSkeleton type=\"swap-preview\" expanded />}\n {showBestRoute && (\n <BestRoute\n expanded={true}\n tooltipContainer={getContainer()}\n steps={formatBestRoute(bestRoute, blockchains) ?? []}\n input={{\n value: numberToString(\n inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n output={{\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n totalFee={numberToString(\n totalFeeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n )}\n totalTime={secondsToString(\n totalArrivalTime(bestRoute.result?.swaps)\n )}\n recommended={true}\n type=\"swap-preview\"\n percentageChange={percentageChange}\n warningLevel={warningLevel}\n />\n )}\n {showNoRouteFound && (\n <>\n <Divider size={12} />\n <NoRoutes\n diagnosisMessage={\n confirmSwapResult.error?.type === ConfirmSwapErrorTypes.NO_ROUTE\n ? confirmSwapResult.error.diagnosisMessage\n : undefined\n }\n error={\n confirmSwapResult.error?.type ===\n ConfirmSwapErrorTypes.REQUEST_FAILED\n }\n fetch={onRefresh}\n />\n </>\n )}\n {confirmSwapResult.error?.type ===\n ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS && (\n <>\n <Alert\n variant=\"alarm\"\n type=\"error\"\n title={getConfirmSwapErrorMessage(confirmSwapResult.error)}\n />\n <Divider size={12} />\n </>\n )}\n </Container>\n </Layout>\n );\n}\n", "import type { PropTypes } from './ConfirmWalletsModal.types';\nimport type { ConnectedWallet } from '../../store/wallets';\nimport type { ConfirmSwapWarnings, Wallet } from '../../types';\n\nimport { i18n } from '@lingui/core';\nimport {\n Alert,\n BalanceErrors,\n Button,\n ChevronDownIcon,\n ChevronLeftIcon,\n Divider,\n MessageBox,\n Modal,\n Typography,\n WalletIcon,\n} from '@rango-dev/ui';\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { getConfirmSwapErrorMessage } from '../../constants/errors';\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport { getRouteWarningMessage } from '../../constants/warnings';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { useMetaStore } from '../../store/meta';\nimport { useWalletsStore } from '../../store/wallets';\nimport { confirmSwapDisabled } from '../../utils/swap';\n\nimport { getRequiredWallets, isValidAddress } from './ConfirmWallets.helpers';\nimport {\n CollapsibleContent,\n CollapsibleRoot,\n ConfirmButton,\n CustomDestination,\n CustomDestinationButton,\n EXPANDABLE_TRANSITION_DURATION,\n ExpandedIcon,\n ListContainer,\n NavigateBack,\n ShowMoreHeader,\n StyledTextField,\n Title,\n Trigger,\n Wallets,\n WalletsContainer,\n} from './ConfirmWallets.styles';\nimport { WalletList } from './WalletList';\n\nconst NUMBER_OF_WALLETS_TO_DISPLAY = 2;\n\nexport function ConfirmWalletsModal(props: PropTypes) {\n //TODO: move component's logics to a custom hook\n const { open, onClose, onCancel, onCheckBalance, config, loading } = props;\n const { blockchains } = useMetaStore.use.meta();\n const {\n bestRoute,\n setSelectedWallets: selectRouteWallets,\n routeWalletsConfirmed,\n setRouteWalletConfirmed,\n customDestination,\n setCustomDestination,\n } = useBestRouteStore();\n const { connectedWallets, selectWallets } = useWalletsStore();\n\n const [showMoreWalletFor, setShowMoreWalletFor] = useState('');\n const [balanceWarnings, setBalanceWarnings] = useState<string[]>([]);\n const [error, setError] = useState('');\n const [routeWarning, setRouteWarning] = useState<\n ConfirmSwapWarnings['route'] | null\n >(null);\n const [destination, setDestination] = useState(customDestination);\n const [showCustomDestination, setShowCustomDestination] = useState(\n !!customDestination\n );\n const customDestinationRef = useRef<HTMLDivElement | null>(null);\n\n const requiredWallets = getRequiredWallets(bestRoute);\n const customDestinationEnabled =\n typeof config?.customDestination === 'undefined'\n ? true\n : config.customDestination;\n\n const lastStepToBlockchain = blockchains.find(\n (blockchain) =>\n blockchain.name ===\n bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1].to\n .blockchain\n );\n const isWalletRequiredFor = (blockchain: string) =>\n !!bestRoute?.result?.swaps.find(\n (swap) => swap.from.blockchain === blockchain\n );\n\n const [selectableWallets, setSelectableWallets] = useState<ConnectedWallet[]>(\n connectedWallets.filter((connectedWallet) => {\n return (\n connectedWallet.selected &&\n requiredWallets.includes(connectedWallet.chain)\n );\n })\n );\n const lastStepToBlockchainMeta = blockchains.find(\n (chain) => chain.name === lastStepToBlockchain?.name\n );\n\n const isSelected = (walletType: string, chain: string) =>\n !!selectableWallets.find(\n (selectableWallet) =>\n selectableWallet.walletType === walletType &&\n selectableWallet.chain === chain &&\n selectableWallet.selected &&\n (isWalletRequiredFor(chain) ||\n (!isWalletRequiredFor(chain) && !destination))\n );\n\n const isAddressMatched =\n !!destination &&\n showCustomDestination &&\n lastStepToBlockchainMeta &&\n !isValidAddress(lastStepToBlockchainMeta, destination);\n\n const resetCustomDestination = () => {\n setShowCustomDestination(false);\n setDestination('');\n setSelectableWallets((selectableWallets) => {\n let anyWalletSelected = false;\n return selectableWallets.map((selectableWallet) => {\n if (\n !anyWalletSelected &&\n selectableWallet.chain === lastStepToBlockchain?.name\n ) {\n anyWalletSelected = true;\n return {\n ...selectableWallet,\n selected: true,\n };\n }\n return selectableWallet;\n });\n });\n };\n\n const onChange = (wallet: Wallet) => {\n if (showMoreWalletFor) {\n setShowMoreWalletFor('');\n }\n const selected = isSelected(wallet.walletType, wallet.chain);\n if (selected) {\n return;\n }\n const connectedWallet = connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === wallet.walletType &&\n connectedWallet.chain === wallet.chain\n );\n\n if (!connectedWallet) {\n return;\n }\n\n onCancel();\n if (wallet.chain === lastStepToBlockchain?.name && showCustomDestination) {\n setShowCustomDestination(false);\n setDestination('');\n }\n setSelectableWallets((selectableWallets) =>\n selectableWallets\n .filter((selectableWallet) => selectableWallet.chain !== wallet.chain)\n .concat({ ...connectedWallet, selected: true })\n );\n };\n\n const onConfirmBalance = () => {\n const lastSelectedWallets = selectableWallets.filter(\n (wallet) => wallet.selected\n );\n selectWallets(lastSelectedWallets);\n selectRouteWallets(lastSelectedWallets);\n setCustomDestination(destination);\n setRouteWalletConfirmed(true);\n onClose();\n };\n\n const onConfirmWallets = async () => {\n setBalanceWarnings([]);\n setError('');\n setRouteWarning(null);\n const selectedWallets = connectedWallets.filter((connectedWallet) =>\n selectableWallets.find(\n (selectableWallet) =>\n selectableWallet.chain === connectedWallet.chain &&\n selectableWallet.walletType === connectedWallet.walletType\n )\n );\n const result = await onCheckBalance?.({\n selectedWallets,\n customDestination: destination,\n });\n\n const warnings = result.warnings;\n if (warnings?.balance?.messages) {\n setBalanceWarnings(warnings.balance.messages);\n }\n if (warnings?.route) {\n setRouteWarning(warnings.route);\n }\n if (result.error) {\n setError(getConfirmSwapErrorMessage(result.error));\n }\n\n if (!result.error && (!warnings?.balance?.messages.length || 0 > 0)) {\n onConfirmBalance();\n } else {\n setBalanceWarnings(warnings?.balance?.messages ?? []);\n }\n };\n\n useEffect(() => {\n setSelectableWallets((selectableWallets) =>\n selectableWallets.concat(\n connectedWallets.filter((connectedWallet) => {\n const anyWalletSelected = !!selectableWallets.find(\n (selectableWallet) =>\n selectableWallet.chain === connectedWallet.chain\n );\n\n return (\n !anyWalletSelected &&\n connectedWallet.selected &&\n requiredWallets.includes(connectedWallet.chain)\n );\n })\n )\n );\n }, [connectedWallets.length]);\n\n useLayoutEffect(() => {\n if (showCustomDestination && customDestinationRef.current) {\n setTimeout(() => {\n customDestinationRef?.current?.scrollIntoView({ behavior: 'smooth' });\n }, EXPANDABLE_TRANSITION_DURATION);\n }\n }, [showCustomDestination]);\n\n const modalContainer = document.querySelector('#swap-box') as HTMLDivElement;\n\n const navigate = useNavigate();\n return (\n <Modal\n open={open}\n onClose={() => {\n if (!routeWalletsConfirmed) {\n navigate(navigationRoutes.home, { replace: true });\n }\n onClose();\n }}\n dismissible={!showMoreWalletFor}\n container={modalContainer}\n {...(!showMoreWalletFor && {\n footer: (\n <ConfirmButton>\n <Button\n loading={loading}\n disabled={confirmSwapDisabled(\n loading,\n showCustomDestination,\n destination,\n bestRoute,\n selectableWallets,\n lastStepToBlockchain\n )}\n onClick={onConfirmWallets}\n variant=\"contained\"\n type=\"primary\"\n fullWidth\n size=\"large\">\n Confirm\n </Button>\n </ConfirmButton>\n ),\n })}\n {...(showMoreWalletFor && {\n containerStyle: { padding: '$0' },\n header: (\n <ShowMoreHeader>\n <NavigateBack\n variant=\"ghost\"\n onClick={setShowMoreWalletFor.bind(null, '')}>\n <ChevronLeftIcon size={16} />\n </NavigateBack>\n <Typography variant=\"headline\" size=\"small\">\n {i18n.t({\n id: 'yourWallets',\n message: 'Your {blockchainName} wallets',\n values: { blockchainName: showMoreWalletFor },\n })}\n </Typography>\n </ShowMoreHeader>\n ),\n })}\n anchor=\"center\">\n <Modal\n open={balanceWarnings.length > 0}\n onClose={setBalanceWarnings.bind(null, [])}\n container={modalContainer}>\n <MessageBox\n title={i18n.t('Insufficient account balance')}\n type=\"error\"\n description={<BalanceErrors messages={balanceWarnings ?? []} />}>\n <Button\n variant=\"outlined\"\n size=\"large\"\n type=\"primary\"\n fullWidth\n onClick={onConfirmBalance}>\n {i18n.t('Proceed anyway')}\n </Button>\n </MessageBox>\n </Modal>\n {showMoreWalletFor && (\n <WalletsContainer>\n <div className=\"wallets-list\">\n <WalletList\n chain={showMoreWalletFor}\n isSelected={isSelected}\n selectWallet={onChange}\n multiWallets={config?.multiWallets ?? true}\n supportedWallets={config?.wallets ?? []}\n config={config}\n onShowMore={setShowMoreWalletFor.bind(null, showMoreWalletFor)}\n />\n </div>\n </WalletsContainer>\n )}\n {!showMoreWalletFor && (\n <>\n {error && (\n <>\n <Alert variant=\"alarm\" type=\"error\" title={i18n.t(error)} />\n <Divider size={12} />\n </>\n )}\n {routeWarning && (\n <>\n <Alert\n variant=\"alarm\"\n type=\"warning\"\n title={getRouteWarningMessage(routeWarning)}\n />\n <Divider size={12} />\n </>\n )}\n <Wallets>\n {requiredWallets.map((requiredWallet, index) => {\n const blockchain = blockchains.find(\n (blockchain) => blockchain.name === requiredWallet\n );\n\n const key = `wallet-${index}`;\n const isLastWallet = index === requiredWallets.length - 1;\n\n return (\n <div key={key}>\n <Title>\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t({\n id: 'yourWallets',\n message: 'Your {blockchainName} wallets',\n values: { blockchainName: blockchain?.displayName },\n })}\n </Typography>\n <Typography\n variant=\"label\"\n color=\"$neutral700\"\n size=\"medium\">\n {i18n.t({\n id: 'needConnect',\n message:\n 'You need to connect a {blockchainName} wallet.',\n values: { blockchainName: blockchain?.displayName },\n })}\n </Typography>\n </Title>\n <Divider size={24} />\n <ListContainer>\n <WalletList\n chain={requiredWallet}\n isSelected={isSelected}\n selectWallet={onChange}\n multiWallets={config?.multiWallets ?? true}\n supportedWallets={config?.wallets ?? []}\n config={config}\n limit={NUMBER_OF_WALLETS_TO_DISPLAY}\n onShowMore={() =>\n setShowMoreWalletFor(blockchain?.name ?? '')\n }\n />\n </ListContainer>\n {!isLastWallet && <Divider size={32} />}\n {isLastWallet && customDestinationEnabled && (\n <CustomDestination>\n <CollapsibleRoot\n ref={customDestinationRef}\n selected={showCustomDestination}\n open={showCustomDestination}\n onOpenChange={(checked) => {\n if (!checked) {\n resetCustomDestination();\n } else {\n if (\n !isWalletRequiredFor(\n lastStepToBlockchain?.name ?? ''\n )\n ) {\n setSelectableWallets((selectableWallets) =>\n selectableWallets.map((selectableWallet) => {\n if (\n selectableWallet.chain ===\n lastStepToBlockchain?.name\n ) {\n return {\n ...selectableWallet,\n selected: false,\n };\n }\n return selectableWallet;\n })\n );\n }\n }\n }}>\n <Trigger\n onClick={() =>\n setShowCustomDestination((prevState) => !prevState)\n }>\n <CustomDestinationButton\n fullWidth\n variant=\"default\"\n suffix={\n <ExpandedIcon\n orientation={\n showCustomDestination ? 'up' : 'down'\n }>\n <ChevronDownIcon size={10} color=\"gray\" />\n </ExpandedIcon>\n }>\n <div className=\"button__content\">\n <WalletIcon size={18} color=\"info\" />\n <Divider size={4} direction=\"horizontal\" />\n <Typography variant=\"label\" size=\"medium\">\n {i18n.t('Send to a different address')}\n </Typography>\n </div>\n </CustomDestinationButton>\n </Trigger>\n <CollapsibleContent open={showCustomDestination}>\n <>\n <Divider size={4} />\n <StyledTextField\n autoFocus\n placeholder={i18n.t('Your destination address')}\n value={destination}\n onChange={(e) => {\n setDestination(e.target.value);\n }}\n />\n </>\n </CollapsibleContent>\n </CollapsibleRoot>\n {isAddressMatched && (\n <div className=\"alarms\">\n <Alert\n variant=\"alarm\"\n type=\"error\"\n title={i18n.t({\n id: 'addressMatch',\n values: { destination },\n message:\n \"Address {destination} doesn't match the blockchain address pattern.\",\n })}\n />\n </div>\n )}\n </CustomDestination>\n )}\n </div>\n );\n })}\n </Wallets>\n </>\n )}\n </Modal>\n );\n}\n", "import type { RouteWarning } from '../types';\n\nimport { i18n } from '@lingui/core';\n\nimport { RouteWarningType } from '../types';\n\nexport function getRouteWarningMessage(warning: RouteWarning) {\n switch (warning.type) {\n case RouteWarningType.ROUTE_UPDATED:\n return i18n.t('Route has been updated.');\n case RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:\n return i18n.t(\n 'Output amount changed to {newOutputAmount} ({percentageChange}% change).',\n {\n newOutputAmount: warning.newOutputAmount,\n percentageChange: warning.percentageChange,\n }\n );\n case RouteWarningType.ROUTE_SWAPPERS_UPDATED:\n return i18n.t('Route swappers has been updated.');\n case RouteWarningType.ROUTE_COINS_UPDATED:\n return i18n.t('Route internal coins has been updated.');\n default:\n return '';\n }\n}\n", "import * as Collapsible from '@radix-ui/react-collapsible';\nimport {\n Button,\n darkTheme,\n IconButton,\n keyframes,\n styled,\n TextField,\n} from '@rango-dev/ui';\n\nexport const EXPANDABLE_TRANSITION_DURATION = 300;\n\nconst slideDown = keyframes({\n from: {\n height: 0,\n },\n to: {\n height: 'var(--radix-collapsible-content-height)',\n },\n});\n\nconst slideUp = keyframes({\n from: {\n height: 'var(--radix-collapsible-content-height)',\n },\n to: {\n height: 0,\n },\n});\n\nexport const Title = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n});\n\nexport const ListContainer = styled('div', {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: ' repeat(3, minmax(0, 1fr))',\n alignContent: 'baseline',\n});\n\nexport const WalletButton = styled('button', {\n borderRadius: '$xm',\n padding: '$10',\n border: '0',\n display: 'flex',\n justifyContent: 'center',\n $$color: '$colors$neutral100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral300',\n },\n backgroundColor: '$$color',\n alignItems: 'center',\n cursor: 'pointer',\n width: 110,\n position: 'relative',\n\n '&:hover': {\n $$color: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral100',\n },\n backgroundColor: '$$color',\n },\n\n '&:focus-visible': {\n $$color: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$info700',\n },\n backgroundColor: '$$color',\n outline: 0,\n },\n variants: {\n selected: {\n true: {\n outlineWidth: 1,\n outlineColor: '$secondary',\n outlineStyle: 'solid',\n },\n },\n },\n});\nexport const Trigger = styled(Collapsible.Trigger, {\n padding: '$0',\n border: 'none',\n outline: 'none',\n width: '100%',\n backgroundColor: 'transparent',\n fontFamily: 'inherit',\n});\n\nexport const ShowMoreHeader = styled('div', {\n padding: '$20',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: '$neutral200',\n position: 'relative',\n width: '100%',\n});\n\nexport const NavigateBack = styled(IconButton, {\n position: 'absolute',\n left: '$20',\n});\n\nexport const WalletsContainer = styled('div', {\n paddingTop: '$20',\n '& .wallets-list': {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: ' repeat(3, minmax(0, 1fr))',\n alignContent: 'baseline',\n },\n});\n\nexport const CollapsibleRoot = styled(Collapsible.Root, {\n backgroundColor: '$neutral200',\n borderRadius: '$sm',\n variants: {\n selected: {\n true: {\n outlineWidth: 1,\n outlineColor: '$secondary500',\n outlineStyle: 'solid',\n },\n },\n },\n});\n\nexport const CustomDestinationButton = styled(Button, {\n width: '100%',\n borderRadius: '$sm !important',\n padding: '$15 !important',\n justifyContent: 'space-between',\n alignItems: 'center',\n $$color: '$colors$neutral100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral300',\n },\n backgroundColor: '$$color',\n\n '&:hover': {\n $$color: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral100',\n },\n backgroundColor: '$$color',\n },\n '&:focus-visible': {\n $$background: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$background: '$colors$info700',\n },\n backgroundColor: '$$background',\n outline: 0,\n },\n});\n\nexport const CustomDestination = styled('div', {\n padding: '$10 $0',\n '& .button__content': {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n },\n '& .alarms': { paddingTop: '5px' },\n});\n\nexport const ExpandedIcon = styled('div', {\n transition: `all ${EXPANDABLE_TRANSITION_DURATION}ms ease`,\n variants: {\n orientation: {\n down: {\n transform: 'rotate(0)',\n },\n up: {\n transform: 'rotate(180deg)',\n },\n },\n },\n});\n\nexport const ConfirmButton = styled('div', {\n display: 'flex',\n});\n\nexport const StyledTextField = styled(TextField, {\n padding: '$0 $15 $15 $15',\n});\n\nexport const CollapsibleContent = styled(Collapsible.Content, {\n overflow: 'hidden',\n variants: {\n open: {\n true: {\n animation: `${slideDown} ${EXPANDABLE_TRANSITION_DURATION}ms ease-out`,\n },\n false: {\n animation: `${slideUp} ${EXPANDABLE_TRANSITION_DURATION}ms ease-out`,\n },\n },\n },\n});\n\nexport const Wallets = styled('div', { overflow: 'visible', width: '100%' });\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { PropTypes } from './WalletList.type';\nimport type { Wallet } from '../../types';\nimport type { WalletInfo } from '@rango-dev/ui';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Divider,\n Image,\n MessageBox,\n Modal,\n SelectableWallet,\n Typography,\n WalletState,\n} from '@rango-dev/ui';\nimport React, { useEffect, useState } from 'react';\n\nimport { useWallets } from '../..';\nimport { useWalletList } from '../../hooks/useWalletList';\nimport {\n TIME_TO_CLOSE_MODAL,\n TIME_TO_IGNORE_MODAL,\n} from '../../pages/WalletsPage';\nimport { useMetaStore } from '../../store/meta';\nimport { useWalletsStore } from '../../store/wallets';\nimport { getBlockchainDisplayNameFor } from '../../utils/meta';\nimport {\n getAddress,\n getConciseAddress,\n isExperimentalChain,\n} from '../../utils/wallets';\nimport { WalletModal } from '../WalletModal';\n\nimport { WalletButton } from './ConfirmWallets.styles';\nimport {\n LogoContainer,\n Spinner,\n WalletImageContainer,\n} from './WalletList.styles';\n\nexport function WalletList(props: PropTypes) {\n const { config, chain, isSelected, selectWallet, limit, onShowMore } = props;\n\n const connectedWallets = useWalletsStore.use.connectedWallets();\n const { blockchains } = useMetaStore.use.meta();\n const [openWalletStateModal, setOpenWalletStateModal] =\n useState<WalletType>('');\n const [experimentalChainWallet, setExperimentalChainWallet] =\n useState<Wallet | null>(null);\n const [showExperimentalChainModal, setShowExperimentalChainModal] =\n useState(false);\n const [addingExperimentalChainStatus, setAddingExperimentalChainStatus] =\n useState<'in-progress' | 'completed' | null>(null);\n const { connect } = useWallets();\n let modalTimerId: ReturnType<typeof setTimeout> | null = null;\n const { list, error, handleClick } = useWalletList({\n config,\n chain,\n onBeforeConnect: (type) => {\n modalTimerId = setTimeout(() => {\n setOpenWalletStateModal(type);\n }, TIME_TO_IGNORE_MODAL);\n },\n onConnect: () => {\n if (modalTimerId) {\n clearTimeout(modalTimerId);\n }\n setTimeout(() => {\n setOpenWalletStateModal('');\n }, TIME_TO_CLOSE_MODAL);\n },\n });\n const [sortedList, setSortedList] = useState<WalletInfo[]>(list);\n const numberOfSupportedWallets = list.length;\n const shouldShowMoreWallets = limit && numberOfSupportedWallets - limit > 0;\n\n const addExperimentalChain = async (wallet: Wallet) => {\n setShowExperimentalChainModal(false);\n setAddingExperimentalChainStatus('in-progress');\n await connect(wallet.walletType, wallet.chain);\n setAddingExperimentalChainStatus('completed');\n };\n\n useEffect(() => {\n setSortedList((sortedList) => {\n const selectedWalletIndex = list.findIndex((wallet) =>\n isSelected(wallet.type, chain)\n );\n\n if (shouldShowMoreWallets && selectedWalletIndex > 1) {\n return [list[selectedWalletIndex]].concat(\n list.filter((_, index) => index !== selectedWalletIndex)\n );\n }\n return sortedList.map(\n (sortedItem) =>\n list.find((listItem) => listItem.type === sortedItem.type) ??\n sortedItem\n );\n });\n }, [JSON.stringify(list)]);\n\n const modalContainer = document.querySelector('#swap-box') as HTMLDivElement;\n\n useEffect(() => {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n if (addingExperimentalChainStatus === 'completed') {\n timeout = setTimeout(\n () => setAddingExperimentalChainStatus(null),\n TIME_TO_CLOSE_MODAL\n );\n }\n\n return () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n };\n }, [addingExperimentalChainStatus]);\n\n return (\n <>\n {sortedList.slice(0, limit).map((wallet) => {\n const address = getAddress({\n connectedWallets,\n walletType: wallet.type,\n chain,\n });\n const conciseAddress = address ? getConciseAddress(address) : '';\n\n const experimentalChain = isExperimentalChain(blockchains, chain);\n\n const experimentalChainNotAdded = !connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === wallet.type &&\n connectedWallet.chain === chain\n );\n\n const couldAddExperimentalChain =\n experimentalChain &&\n experimentalChainNotAdded &&\n wallet.state === WalletState.CONNECTED;\n\n const connectedWalletDescription = couldAddExperimentalChain\n ? i18n.t({\n id: 'addChain',\n message: 'Add {chain} chain',\n values: { chain },\n })\n : conciseAddress;\n\n const onClick = () => {\n if (wallet.state === WalletState.DISCONNECTED) {\n void handleClick(wallet.type);\n } else if (couldAddExperimentalChain) {\n setExperimentalChainWallet({\n walletType: wallet.type,\n chain,\n address: address ?? '',\n });\n setShowExperimentalChainModal(true);\n } else {\n selectWallet({\n walletType: wallet.type,\n chain,\n address: address ?? '',\n });\n }\n };\n\n const blockchainDisplayName: string | undefined =\n experimentalChainWallet?.chain\n ? getBlockchainDisplayNameFor(\n experimentalChainWallet.chain,\n blockchains\n )\n : undefined;\n return (\n <>\n <WalletModal\n open={openWalletStateModal === wallet.type}\n onClose={() => setOpenWalletStateModal('')}\n image={wallet.image}\n state={wallet.state}\n error={error}\n />\n {!!experimentalChainWallet && (\n <Modal\n open={!!experimentalChainWallet && showExperimentalChainModal}\n container={modalContainer}\n onClose={() => {\n setExperimentalChainWallet(null);\n }}>\n <MessageBox\n title={i18n.t({\n id: 'addBlockchain',\n message: 'Add {blockchainDisplayName} Chain',\n values: { blockchainDisplayName },\n })}\n type=\"warning\"\n description={i18n.t({\n id: 'addBlockchainDescription',\n message:\n 'You should connect a {blockchainDisplayName} supported wallet or choose a different {blockchainDisplayName} address',\n values: { blockchainDisplayName },\n })}>\n <Divider size={18} />\n <Divider size={32} />\n <Button\n onClick={addExperimentalChain.bind(\n null,\n experimentalChainWallet\n )}\n variant=\"outlined\"\n type=\"primary\"\n fullWidth\n size=\"large\">\n {i18n.t('Confirm')}\n </Button>\n </MessageBox>\n </Modal>\n )}\n {addingExperimentalChainStatus && (\n <Modal\n open={!!addingExperimentalChainStatus}\n onClose={setAddingExperimentalChainStatus.bind(null, null)}\n container={modalContainer}>\n {addingExperimentalChainStatus === 'in-progress' ? (\n <MessageBox\n type=\"loading\"\n title={i18n.t({\n id: 'addBlockchain',\n message: 'Add {blockchainDisplayName} Chain',\n values: { blockchainDisplayName },\n })}\n description={i18n.t({\n id: 'addBlockchainDescription',\n message:\n 'You should connect a {blockchainDisplayName} supported wallet or choose a different {blockchainDisplayName} address',\n values: { blockchainDisplayName },\n })}\n icon={\n <LogoContainer>\n <WalletImageContainer>\n <Image src={wallet.image} size={45} />\n </WalletImageContainer>\n <Spinner />\n </LogoContainer>\n }\n />\n ) : (\n <MessageBox\n type=\"success\"\n title={i18n.t({\n id: 'blockchainAdded',\n message: '{blockchainDisplayName} Chain Added',\n values: { blockchainDisplayName },\n })}\n description={i18n.t({\n id: 'blockchainAddedDescription',\n message:\n '{blockchainDisplayName} is added to your wallet, you can use it to swap.',\n values: { blockchainDisplayName },\n })}\n />\n )}\n <Divider direction=\"vertical\" size={32} />\n </Modal>\n )}\n <SelectableWallet\n key={wallet.type}\n description={connectedWalletDescription}\n onClick={onClick}\n selected={isSelected(wallet.type, chain)}\n {...wallet}\n />\n </>\n );\n })}\n {shouldShowMoreWallets && (\n <WalletButton selected={false} onClick={onShowMore.bind(null)}>\n <Typography variant=\"label\" size=\"medium\">\n {i18n.t('Show more wallets')}\n <Typography variant=\"label\" size=\"medium\" color=\"$primary\">\n +{numberOfSupportedWallets - (limit ?? 0)}\n </Typography>\n </Typography>\n </WalletButton>\n )}\n </>\n );\n}\n", "import type { WidgetConfig } from '../types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { WalletState } from '@rango-dev/ui';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport {\n KEPLR_COMPATIBLE_WALLETS,\n type WalletType,\n WalletTypes,\n} from '@rango-dev/wallets-shared';\nimport { useEffect, useState } from 'react';\n\nimport { useMetaStore } from '../store/meta';\nimport { useWalletsStore } from '../store/wallets';\nimport { configWalletsToWalletName } from '../utils/providers';\nimport {\n isExperimentalChain,\n mapWalletTypesToWalletInfo,\n sortWalletsBasedOnConnectionState,\n} from '../utils/wallets';\n\nconst ALL_SUPPORTED_WALLETS = Object.values(WalletTypes);\n\ninterface Params {\n config?: WidgetConfig;\n chain?: string;\n onBeforeConnect?: (walletType: string) => void;\n onConnect?: (walletType: string) => void;\n}\n\n/**\n * gets list of wallets with their information and an action for handling click callback fo UI\n * we need to share the logic of rendering list of wallets and handle clicking on them in different places\n * you can use this list whenever you need to show the list of wallets and needed callbacks\n */\nexport function useWalletList(params: Params) {\n const { config, chain, onBeforeConnect, onConnect } = params;\n const { state, disconnect, getWalletInfo, connect } = useWallets();\n const { connectedWallets } = useWalletsStore();\n const { blockchains } = useMetaStore().meta;\n const multiWallets =\n typeof config?.multiWallets === 'undefined' ? true : config.multiWallets;\n\n /** It can be what has been set by widget config or as a fallback we use all the supported wallets by our library */\n const listAvailableWalletTypes =\n configWalletsToWalletName(config?.wallets, {\n walletConnectProjectId: config?.walletConnectProjectId,\n }) || ALL_SUPPORTED_WALLETS;\n\n const wallets = mapWalletTypesToWalletInfo(\n state,\n getWalletInfo,\n listAvailableWalletTypes,\n chain\n );\n\n const sortedWallets = sortWalletsBasedOnConnectionState(wallets);\n const [error, setError] = useState('');\n\n const isExperimentalChainNotAdded = (walletType: string) =>\n !connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === walletType &&\n connectedWallet.chain === chain\n );\n\n const handleClick = async (type: WalletType) => {\n const wallet = state(type);\n try {\n if (error) {\n setError('');\n }\n if (wallet.connected) {\n await disconnect(type);\n } else {\n const atLeastOneWalletIsConnected = !!wallets.find(\n (w) => w.state === WalletState.CONNECTED\n );\n if (!multiWallets && atLeastOneWalletIsConnected) {\n return;\n }\n onBeforeConnect?.(type);\n await connect(type);\n onConnect?.(type);\n }\n } catch (e) {\n setError('Error: ' + (e as any)?.message);\n }\n };\n\n const disconnectConnectingWallets = () => {\n const connectingWallets =\n wallets?.filter((wallet) => wallet.state === WalletState.CONNECTING) ||\n [];\n for (const wallet of connectingWallets) {\n void disconnect(wallet.type);\n }\n };\n\n useEffect(() => {\n return () => {\n disconnectConnectingWallets();\n };\n }, []);\n\n const shouldExcludeWallet = (\n walletType: string,\n chain: string,\n blockchains: BlockchainMeta[]\n ) => {\n return (\n isExperimentalChain(blockchains, chain) &&\n isExperimentalChainNotAdded(walletType) &&\n !KEPLR_COMPATIBLE_WALLETS.includes(walletType)\n );\n };\n\n return {\n list: sortedWallets.filter(\n (wallet) => !shouldExcludeWallet(wallet.type, chain ?? '', blockchains)\n ),\n error,\n handleClick,\n };\n}\n", "import type { WidgetConfig } from '../types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { i18n } from '@lingui/core';\nimport { styled, Typography, Wallet, WalletState } from '@rango-dev/ui';\nimport React, { Fragment, useState } from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { WalletModal } from '../components/WalletModal';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useWalletList } from '../hooks/useWalletList';\nimport { useMetaStore } from '../store/meta';\nimport { getContainer } from '../utils/common';\n\ninterface PropTypes {\n supportedWallets: WidgetConfig['wallets'];\n multiWallets: boolean;\n config?: WidgetConfig;\n}\n\nconst ListContainer = styled('div', {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: ' repeat(3, minmax(0, 1fr))',\n alignContent: 'baseline',\n paddingTop: '$15',\n height: '100%',\n});\n\nconst Container = styled('div', {\n textAlign: 'center',\n});\n\nexport const TIME_TO_CLOSE_MODAL = 3_000;\nexport const TIME_TO_IGNORE_MODAL = 300;\n\nexport function WalletsPage({ config }: PropTypes) {\n const { navigateBackFrom } = useNavigateBack();\n const [openModal, setOpenModal] = useState(false);\n const [selectedWalletType, setSelectedWalletType] = useState<WalletType>('');\n let modalTimerId: ReturnType<typeof setTimeout> | null = null;\n\n const { list, handleClick, error } = useWalletList({\n config,\n onBeforeConnect: (type) => {\n modalTimerId = setTimeout(() => {\n setOpenModal(true);\n setSelectedWalletType(type);\n }, TIME_TO_IGNORE_MODAL);\n },\n onConnect: () => {\n if (modalTimerId) {\n clearTimeout(modalTimerId);\n }\n setTimeout(() => {\n setOpenModal(false);\n }, TIME_TO_CLOSE_MODAL);\n },\n });\n\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n const selectedWallet = list.find(\n (wallet) => wallet.type === selectedWalletType\n );\n const selectedWalletImage = selectedWallet?.image || '';\n const selectedWalletState =\n selectedWallet?.state || WalletState.NOT_INSTALLED;\n\n return (\n <Layout\n header={{\n title: i18n.t('Connect Wallets'),\n onBack: navigateBackFrom.bind(null, navigationRoutes.wallets),\n }}>\n <Container>\n <Typography variant=\"title\" size=\"xmedium\" align=\"center\">\n {i18n.t('Choose a wallet to connect.')}\n </Typography>\n <ListContainer>\n {list.map((wallet, index) => {\n const key = `wallet-${index}-${wallet.type}`;\n return (\n <Fragment key={key}>\n <Wallet\n {...wallet}\n container={getContainer()}\n onClick={(type) => {\n void handleClick(type);\n }}\n isLoading={loadingMetaStatus === 'loading'}\n />\n </Fragment>\n );\n })}\n <WalletModal\n open={!!openModal}\n onClose={() => setOpenModal(false)}\n image={selectedWalletImage}\n state={selectedWalletState}\n error={error}\n />\n </ListContainer>\n </Container>\n </Layout>\n );\n}\n", "import type { PropTypes } from './WalletModal.types';\n\nimport { Divider, Modal } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { ModalContent } from './WalletModalContent';\n\nexport function WalletModal(props: PropTypes) {\n const { open, onClose, ...otherProps } = props;\n\n return (\n <Modal\n open={open}\n onClose={onClose}\n container={document.getElementById('swap-box') || document.body}>\n <ModalContent {...otherProps} />\n <Divider direction=\"vertical\" size={32} />\n </Modal>\n );\n}\n", "import type { ModalContentProps } from './WalletModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { Image, MessageBox, WalletState } from '@rango-dev/ui';\nimport React from 'react';\n\nimport {\n LogoContainer,\n Spinner,\n WalletImageContainer,\n} from './WalletModalContent.styles';\n\nexport function ModalContent(props: ModalContentProps) {\n const { state, image, error } = props;\n if (state === WalletState.CONNECTED) {\n return (\n <MessageBox\n type=\"success\"\n title={i18n.t('Wallet Connected')}\n description={i18n.t(\n 'Your wallet is connected, you can use it to swap.'\n )}\n />\n );\n }\n\n if (error) {\n return (\n <MessageBox\n type=\"error\"\n title={i18n.t('Failed to Connect')}\n description={\n error || i18n.t('Your wallet is not connected. Please try again.')\n }\n />\n );\n }\n\n return (\n <MessageBox\n type=\"loading\"\n title={i18n.t('Connecting to your wallet')}\n description={i18n.t('Click connect in your wallet popup.')}\n icon={\n <LogoContainer>\n <WalletImageContainer>\n <Image src={image} size={45} />\n </WalletImageContainer>\n <Spinner />\n </LogoContainer>\n }\n />\n );\n}\n", "import { keyframes, styled } from '@rango-dev/ui';\n\nexport const IconContainer = styled('div', {\n borderRadius: '$lg',\n width: '$45',\n height: '$45',\n backgroundColor: '$success300',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n});\n\nexport const LogoContainer = styled('div', {\n position: 'relative',\n});\n\nconst spin = keyframes({\n '0%': {\n transform: 'rotate(0deg)',\n },\n '100%': {\n transform: 'rotate(360deg)',\n },\n});\n\nexport const Spinner = styled('div', {\n position: 'absolute',\n border: '2px solid rgba(0, 0, 0, 0.1)',\n borderTop: '2px solid $info500',\n borderRadius: '$lg',\n width: '$45',\n height: '$45',\n animation: `${spin} 1s linear infinite`,\n top: 0,\n bottom: 0,\n right: 0,\n left: 0,\n});\n\nexport const WalletImageContainer = styled('div', {\n '& img': {\n borderRadius: '50%',\n },\n});\n", "import { useInRouterContext, useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useBestRouteStore } from '../store/bestRoute';\n\nexport function useNavigateBack() {\n const isRouterInContext = useInRouterContext();\n const navigate = useNavigate();\n const routeWalletsConfirmed = useBestRouteStore.use.routeWalletsConfirmed();\n\n navigationRoutes;\n\n const navigateBackFrom = (currentRoute: string) => {\n if (currentRoute === navigationRoutes.swapDetails) {\n return navigate('/' + navigationRoutes.swaps, { replace: true });\n }\n\n if (\n !isRouterInContext ||\n (window.history.state && window.history.state.idx > 0)\n ) {\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n navigate(-1);\n } else {\n if (\n [navigationRoutes.settings, navigationRoutes.wallets].includes(\n currentRoute\n ) &&\n routeWalletsConfirmed\n ) {\n return navigate('/' + navigationRoutes.confirmSwap, { replace: true });\n }\n if (\n [\n navigationRoutes.fromSwap,\n navigationRoutes.toSwap,\n navigationRoutes.settings,\n navigationRoutes.wallets,\n navigationRoutes.swaps,\n navigationRoutes.confirmSwap,\n ].includes(currentRoute)\n ) {\n navigate(navigationRoutes.home, { replace: true });\n } else if (currentRoute === navigationRoutes.fromBlockchain) {\n navigate('/' + navigationRoutes.fromSwap, { replace: true });\n } else if (currentRoute === navigationRoutes.toBlockchain) {\n navigate('/' + navigationRoutes.fromSwap, { replace: true });\n } else if (currentRoute === navigationRoutes.liquiditySources) {\n navigate('/' + navigationRoutes.settings, { replace: true });\n }\n }\n };\n\n return { navigateBackFrom };\n}\n", "import { keyframes, styled } from '@rango-dev/ui';\n\nexport const LogoContainer = styled('div', {\n position: 'relative',\n});\n\nconst SpinAnimation = keyframes({\n '0%': {\n transform: 'rotate(0deg)',\n },\n '100%': {\n transform: 'rotate(360deg)',\n },\n});\n\nexport const Spinner = styled('div', {\n position: 'absolute',\n border: '2px solid rgba(0, 0, 0, 0.1)',\n borderTop: '2px solid $info500',\n borderRadius: '$lg',\n width: '$45',\n height: '$45',\n animation: `${SpinAnimation} 1s linear infinite`,\n top: 0,\n bottom: 0,\n right: 0,\n left: 0,\n});\n\nexport const WalletImageContainer = styled('div', {\n '& img': {\n borderRadius: '50%',\n },\n});\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type {\n ConfirmSwapError,\n ConfirmSwapWarnings,\n PendingSwapSettings,\n Wallet,\n} from '../types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport type { BestRouteResponse } from 'rango-sdk';\n\nimport { calculatePendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport BigNumber from 'bignumber.js';\nimport { useEffect } from 'react';\n\nimport { errorMessages } from '../constants/errors';\nimport { HIGH_SLIPPAGE } from '../constants/swapSettings';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { useWalletsStore } from '../store/wallets';\nimport {\n ConfirmSwapErrorTypes,\n RouteWarningType,\n SlippageWarningType,\n} from '../types';\nimport { numberToString } from '../utils/numbers';\nimport {\n isNumberOfSwapsChanged,\n isRouteChanged,\n isRouteInternalCoinsUpdated,\n isRouteSwappersUpdated,\n} from '../utils/routing';\nimport {\n createBestRouteRequestBody,\n getBalanceWarnings,\n getMinRequiredSlippage,\n getOutputRatio,\n getPercentageChange,\n getRouteOutputAmount,\n getWalletsForNewSwap,\n hasProperSlippage,\n isOutputAmountChangedALot,\n outputRatioHasWarning,\n} from '../utils/swap';\n\nimport { useFetchBestRoute } from './useFetchBestRoute';\n\nexport type ConfirmSwapFetchResult = {\n swap: PendingSwap | null;\n error: ConfirmSwapError | null;\n warnings: ConfirmSwapWarnings | null;\n};\n\nexport type ConfirmSwap = {\n loading: boolean;\n fetch: (params: Params) => Promise<ConfirmSwapFetchResult>;\n cancelFetch: () => void;\n};\n\ntype Params = {\n selectedWallets: Wallet[];\n customDestination?: string;\n};\n\n/**\n * A request can be successful but in body of the response, it can be some case which is considered as failed.\n */\nfunction throwErrorIfResponseIsNotValid(\n response: BestRouteResponse,\n params: { inputUsdValue: BigNumber | null; outputUsdValue: number | null }\n) {\n if (!response.result) {\n throw new Error(errorMessages().noRoutesError.title, {\n cause: {\n type: ConfirmSwapErrorTypes.NO_ROUTE,\n diagnosisMessage: response.diagnosisMessages?.[0],\n },\n });\n }\n\n const newRouteOutputUsdValue = new BigNumber(\n response.result?.outputAmount || '0'\n ).multipliedBy(params.outputUsdValue || 0);\n\n const outputRatio = getOutputRatio(\n params.inputUsdValue,\n newRouteOutputUsdValue\n );\n const highValueLoss = outputRatioHasWarning(\n params.inputUsdValue,\n outputRatio\n );\n\n if (highValueLoss) {\n throw new Error('High value loss for route', {\n cause: {\n type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,\n },\n });\n }\n\n return response;\n}\n\nfunction generateWarnings(\n previousRoute: BestRouteResponse,\n currentRoute: BestRouteResponse,\n params: {\n selectedWallets: Wallet[];\n userSlippage: number;\n }\n): ConfirmSwapWarnings {\n const routeChanged = isRouteChanged(previousRoute, currentRoute);\n const output: ConfirmSwapWarnings = {\n balance: null,\n route: null,\n slippage: null,\n };\n\n if (routeChanged) {\n if (isOutputAmountChangedALot(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,\n newOutputAmount: numberToString(getRouteOutputAmount(currentRoute)),\n percentageChange: numberToString(\n getPercentageChange(\n getRouteOutputAmount(previousRoute),\n getRouteOutputAmount(currentRoute)\n ),\n null,\n 2\n ),\n };\n } else if (isNumberOfSwapsChanged(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_UPDATED,\n };\n } else if (isRouteSwappersUpdated(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_SWAPPERS_UPDATED,\n };\n } else if (isRouteInternalCoinsUpdated(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_COINS_UPDATED,\n };\n }\n }\n\n const balanceWarnings = getBalanceWarnings(\n currentRoute,\n params.selectedWallets\n );\n const enoughBalance = balanceWarnings.length === 0;\n\n if (!enoughBalance) {\n output.balance = {\n messages: balanceWarnings,\n };\n }\n\n const minRequiredSlippage = getMinRequiredSlippage(previousRoute);\n const highSlippage = params.userSlippage > HIGH_SLIPPAGE;\n\n if (!hasProperSlippage(params.userSlippage.toString(), minRequiredSlippage)) {\n output.slippage = {\n type: SlippageWarningType.INSUFFICIENT_SLIPPAGE,\n slippage: minRequiredSlippage,\n };\n } else if (highSlippage) {\n output.slippage = {\n type: SlippageWarningType.HIGH_SLIPPAGE,\n slippage: params.userSlippage.toString(),\n };\n }\n\n return output;\n}\n\nexport function useConfirmSwap(): ConfirmSwap {\n const {\n fromToken,\n toToken,\n inputAmount,\n inputUsdValue,\n setRoute,\n bestRoute: initialRoute,\n customDestination: customDestinationFromStore,\n } = useBestRouteStore();\n\n const {\n slippage,\n customSlippage,\n affiliatePercent,\n affiliateRef,\n affiliateWallets,\n disabledLiquiditySources,\n } = useSettingsStore();\n const { connectedWallets } = useWalletsStore();\n\n const { meta } = useMetaStore();\n\n const userSlippage = customSlippage || slippage;\n\n const { fetch: fetchBestRoute, cancelFetch, loading } = useFetchBestRoute();\n\n useEffect(() => cancelFetch, []);\n\n const fetch: ConfirmSwap['fetch'] = async (params: Params) => {\n const selectedWallets = params.selectedWallets;\n const customDestination =\n params?.customDestination ?? customDestinationFromStore;\n\n if (!fromToken || !toToken || !inputAmount || !initialRoute) {\n return {\n route: null,\n swap: null,\n error: null,\n warnings: null,\n };\n }\n\n const requestBody = createBestRouteRequestBody({\n fromToken,\n toToken,\n inputAmount,\n wallets: connectedWallets,\n selectedWallets,\n disabledLiquiditySources,\n slippage: userSlippage,\n affiliateRef,\n affiliatePercent,\n affiliateWallets,\n initialRoute,\n destination: customDestination,\n });\n\n let currentRoute: BestRouteResponse;\n try {\n currentRoute = await fetchBestRoute(requestBody).then((response) =>\n throwErrorIfResponseIsNotValid(response, {\n outputUsdValue: toToken.usdPrice,\n inputUsdValue,\n })\n );\n setRoute(currentRoute);\n } catch (error: any) {\n if (error?.code === 'ERR_CANCELED') {\n return {\n swap: null,\n error: {\n type: ConfirmSwapErrorTypes.REQUEST_CANCELED,\n },\n warnings: null,\n };\n }\n\n if (error.cause) {\n return {\n swap: null,\n error: error.cause,\n warnings: null,\n };\n }\n\n return {\n swap: null,\n error: {\n type: ConfirmSwapErrorTypes.REQUEST_FAILED,\n },\n warnings: null,\n };\n }\n\n const swapSettings: PendingSwapSettings = {\n slippage: userSlippage.toString(),\n disabledSwappersGroups: disabledLiquiditySources,\n };\n const swap = calculatePendingSwap(\n inputAmount.toString(),\n currentRoute,\n getWalletsForNewSwap(selectedWallets),\n swapSettings,\n false,\n meta\n );\n\n return {\n route: currentRoute,\n swap,\n error: null,\n warnings: generateWarnings(initialRoute, currentRoute, {\n selectedWallets,\n userSlippage,\n }),\n };\n };\n\n return {\n loading,\n fetch,\n cancelFetch,\n };\n}\n", "import type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport type { PendingSwapStep } from 'rango-types';\n\nimport { i18n } from '@lingui/core';\nimport { useManager } from '@rango-dev/queue-manager-react';\nimport { Divider, NotFound, styled } from '@rango-dev/ui';\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { Layout } from '../components/Layout';\nimport { SearchInput } from '../components/SearchInput';\nimport { SwapsGroup } from '../components/SwapsGroup';\nimport { NotFoundContainer } from '../components/SwapsGroup/SwapsGroup.styles';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useUiStore } from '../store/ui';\nimport { groupSwapsByDate } from '../utils/date';\nimport { containsText } from '../utils/numbers';\nimport { getPendingSwaps } from '../utils/queue';\n\nconst Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n height: '100%',\n gap: 15,\n});\n\nconst SwapsGroupContainer = styled('div', {\n overflowY: 'visible',\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n gap: 15,\n height: '100%',\n});\n\nconst isStepContainsText = (steps: PendingSwapStep[], value: string) => {\n if (!steps?.length) {\n return false;\n }\n return steps.filter(\n (step) =>\n containsText(step.fromBlockchain, value) ||\n containsText(step.toBlockchain, value) ||\n containsText(step.toSymbol, value) ||\n containsText(step.fromSymbol, value)\n ).length;\n};\n\nexport function HistoryPage() {\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n const { manager, state } = useManager();\n const list: PendingSwap[] = getPendingSwaps(manager).map(({ swap }) => swap);\n const [searchedFor, setSearchedFor] = useState<string>('');\n const loading = !state.loadedFromPersistor;\n\n const searchHandler = (event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n setSearchedFor(value);\n };\n\n let filteredList = list;\n if (searchedFor) {\n filteredList = list.filter(\n (swap) =>\n containsText(swap.inputAmount, searchedFor) ||\n containsText(swap.status, searchedFor) ||\n isStepContainsText(swap.steps, searchedFor) ||\n containsText(swap.requestId, searchedFor)\n );\n }\n\n const isEmpty = !filteredList?.length && !loading;\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.swaps),\n title: i18n.t('History'),\n }}>\n <Container>\n <SearchInput\n setValue={setSearchedFor}\n fullWidth\n variant=\"contained\"\n placeholder={i18n.t('Search Transaction')}\n autoFocus\n onChange={searchHandler}\n value={searchedFor}\n />\n <SwapsGroupContainer>\n {isEmpty && (\n <NotFoundContainer>\n <Divider size={32} />\n <NotFound\n title={i18n.t('No results found')}\n description={\n searchedFor ? i18n.t('Try using different keywords') : ''\n }\n />\n </NotFoundContainer>\n )}\n {!isEmpty && (\n <SwapsGroup\n list={filteredList}\n onSwapClick={(requestId) => {\n setSelectedSwap(requestId);\n navigate(`${requestId}`, { replace: true });\n }}\n groupBy={groupSwapsByDate}\n isLoading={loading}\n />\n )}\n </SwapsGroupContainer>\n </Container>\n </Layout>\n );\n}\n", "import type { PropTypes } from './SearchInput.types';\n\nimport { CloseIcon, IconButton, SearchIcon, TextField } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { IconWrapper } from './SearchInput.styles';\n\nexport function SearchInput(props: PropTypes) {\n const {\n variant,\n fullWidth,\n color,\n size,\n onChange,\n value,\n setValue,\n ...inputAttributes\n } = props;\n\n return (\n <TextField\n prefix={\n <IconWrapper>\n <SearchIcon color=\"black\" />\n </IconWrapper>\n }\n suffix={\n !!value.length && (\n <IconButton\n variant=\"ghost\"\n onClick={() => setValue?.('')}\n size=\"small\">\n <CloseIcon color=\"gray\" size={10} />\n </IconButton>\n )\n }\n fullWidth={fullWidth}\n color={color}\n variant={variant}\n style={{\n padding: 10,\n borderRadius: 25,\n alignItems: 'center',\n }}\n size={size}\n value={value}\n onChange={onChange}\n {...inputAttributes}\n />\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const IconWrapper = styled('div', {\n width: '$24',\n height: '$24',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n});\n", "import type { PropTypes } from './SwapsGroup.types';\n\nimport { i18n } from '@lingui/core';\nimport { Divider, SwapListItem, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { limitDecimalPlaces } from '../../utils/numbers';\n\nimport { Group, SwapList, Time } from './SwapsGroup.styles';\n\nexport function SwapsGroup(props: PropTypes) {\n const { list, onSwapClick, groupBy, isLoading } = props;\n const groups = groupBy ? groupBy(list) : [{ title: 'History', swaps: list }];\n\n if (isLoading) {\n const swaps = [{}, {}];\n\n const loadingGroups = [\n {\n title: 'Today',\n swaps,\n },\n {\n title: 'Last month',\n swaps,\n },\n ];\n return (\n <>\n {loadingGroups.map((group) => (\n <React.Fragment key={group.title}>\n <Group>\n <Time>\n <Typography\n variant=\"label\"\n size=\"medium\"\n color=\"neutral600\"\n className=\"group-title\">\n {i18n.t(group.title)}\n </Typography>\n </Time>\n <Divider size={4} />\n <SwapList>\n {group.swaps.map((_, index) => {\n const key = index + group.title;\n return (\n <React.Fragment key={key}>\n <SwapListItem isLoading={true} />\n </React.Fragment>\n );\n })}\n </SwapList>\n </Group>\n </React.Fragment>\n ))}\n </>\n );\n }\n\n return (\n <>\n {groups\n .filter((group) => group.swaps.length > 0)\n .map((group) => (\n <React.Fragment key={group.title}>\n <Group>\n <Time>\n <Typography\n variant=\"label\"\n size=\"medium\"\n color=\"neutral600\"\n className=\"group-title\">\n {i18n.t(group.title)}\n </Typography>\n </Time>\n <Divider size={4} />\n <SwapList>\n {group.swaps.map((swap) => {\n const firstStep = swap.steps[0];\n const lastStep = swap.steps[swap.steps.length - 1];\n return (\n <React.Fragment key={swap.requestId}>\n <SwapListItem\n requestId={swap.requestId}\n creationTime={swap.creationTime}\n status={swap.status}\n onClick={onSwapClick}\n onlyShowTime={group.title === 'Today'}\n swapTokenData={{\n from: {\n token: {\n image: firstStep.fromLogo,\n displayName: firstStep.fromSymbol,\n },\n blockchain: {\n image: firstStep.fromBlockchainLogo || '',\n },\n amount: limitDecimalPlaces(swap.inputAmount),\n },\n to: {\n token: {\n image: lastStep.toLogo,\n displayName: lastStep.toSymbol,\n },\n blockchain: {\n image: lastStep.toBlockchainLogo || '',\n },\n amount: limitDecimalPlaces(\n lastStep.outputAmount || ''\n ),\n estimatedAmount: limitDecimalPlaces(\n lastStep.expectedOutputAmountHumanReadable || ''\n ),\n },\n }}\n />\n </React.Fragment>\n );\n })}\n </SwapList>\n </Group>\n </React.Fragment>\n ))}\n </>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Group = styled('div', {\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n});\n\nexport const Time = styled('div', {\n display: 'flex',\n justifyContent: 'flex-start',\n padding: '$2',\n});\n\nexport const SwapList = styled('div', {\n gap: '$10',\n display: 'flex',\n flexDirection: 'column',\n});\n\nexport const NotFoundContainer = styled('div', {\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n});\n", "import type { GroupBy } from '../components/SwapsGroup/SwapsGroup.types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\n\nimport dayjs from 'dayjs';\n\nexport const groupSwapsByDate: GroupBy = (swaps) => {\n const output: Map<\n string,\n {\n title: string;\n swaps: PendingSwap[];\n }\n > = new Map([\n [\n 'today',\n {\n title: 'Today',\n swaps: [],\n },\n ],\n [\n 'month',\n {\n title: 'Last month',\n swaps: [],\n },\n ],\n [\n 'year',\n {\n title: 'Last year',\n swaps: [],\n },\n ],\n [\n 'history',\n {\n title: 'History',\n swaps: [],\n },\n ],\n ]);\n\n const now = dayjs();\n swaps.forEach((swap) => {\n const swapDate = dayjs(Number(swap.creationTime));\n if (now.isSame(swapDate, 'day')) {\n output.get('today')?.swaps.push(swap);\n } else if (now.isSame(swapDate, 'month')) {\n output.get('month')?.swaps.push(swap);\n } else if (now.isSame(swapDate, 'year')) {\n output.get('year')?.swaps.push(swap);\n } else {\n output.get('history')?.swaps.push(swap);\n }\n });\n\n return Array.from(output.values());\n};\n", "import { Manager } from '@rango-dev/queue-manager-core';\nimport {\n PendingSwapWithQueueID,\n SwapStorage,\n} from '@rango-dev/queue-manager-rango-preset';\n\nexport const getPendingSwaps = (manager: Manager | undefined) => {\n const result: PendingSwapWithQueueID[] = [];\n\n manager?.getAll().forEach((q, id) => {\n const storage = q.list.getStorage() as SwapStorage;\n\n if (storage?.swapDetails) {\n result.push({\n id,\n swap: storage?.swapDetails,\n });\n }\n });\n\n return result.sort(\n (a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime)\n );\n};\n", "import { i18n } from '@lingui/core';\nimport {\n List,\n ListItemButton,\n Radio,\n RadioRoot,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { SettingsContainer } from '../components/SettingsContainer';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useLanguage } from '../hooks/useLanguage';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\n\nexport function LanguagePage() {\n const { navigateBackFrom } = useNavigateBack();\n\n const { activeLanguage, changeLanguage, languages } = useLanguage();\n\n const languageList = languages.map((languageItem) => {\n const { local, label, SVGFlag } = languageItem;\n return {\n id: local,\n value: local,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {label}\n </Typography>\n ),\n onClick: () => changeLanguage(languageItem.local),\n end: <Radio value={local} />,\n start: <SVGFlag />,\n };\n });\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t('Language'),\n }}>\n <SettingsContainer>\n <RadioRoot value={activeLanguage}>\n <List\n type={\n <ListItemButton\n title={i18n.t('language')}\n id=\"_\"\n onClick={() => console.log()}\n />\n }\n items={languageList}\n />\n </RadioRoot>\n </SettingsContainer>\n </Layout>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const SettingsContainer = styled('div', {\n height: '100%',\n overflow: 'hidden',\n});\n\nexport const LiquiditySourceList = styled('ul', {\n padding: '$15 $5 0',\n margin: 0,\n listStyle: 'none',\n height: '100%',\n overflowY: 'auto',\n});\n\nexport const LiquiditySourceSuffix = styled('div', {\n width: 80,\n display: 'flex',\n justifyContent: 'flex-end',\n});\n\nexport const NotFoundContainer = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n});\n", "import type { LanguageItem } from '../constants/languages';\n\nimport { type Language } from '@rango-dev/ui';\n\nimport { DEFAULT_LANGUAGE, LANGUAGES } from '../constants/languages';\nimport { useSettingsStore } from '../store/settings';\n\ninterface UseLanguage {\n languages: LanguageItem[];\n defaultLanguage: Language;\n activeLanguage: Language;\n changeLanguage: (language: Language) => void;\n}\n\nexport function useLanguage(): UseLanguage {\n const language = useSettingsStore.use.language();\n const setLanguage = useSettingsStore.use.setLanguage();\n const languages = LANGUAGES;\n const defaultLanguage = DEFAULT_LANGUAGE;\n\n return {\n activeLanguage: language,\n languages,\n defaultLanguage,\n changeLanguage: setLanguage,\n };\n}\n", "import type {\n LiquiditySourceType,\n UniqueSwappersGroupType,\n} from '../utils/settings';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Checkbox,\n Image,\n ListItemButton,\n NotFound,\n Typography,\n} from '@rango-dev/ui';\nimport React, { useState } from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { LoadingLiquiditySourceList } from '../components/LoadingLiquiditySourceList';\nimport { SearchInput } from '../components/SearchInput';\nimport {\n LiquiditySourceList,\n LiquiditySourceSuffix,\n NotFoundContainer,\n SettingsContainer,\n} from '../components/SettingsContainer';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { containsText } from '../utils/numbers';\nimport {\n getUniqueSwappersGroups,\n sortLiquiditySourcesByGroupTitle,\n} from '../utils/settings';\n\ninterface PropTypes {\n supportedSwappers?: string[];\n sourceType: 'Exchanges' | 'Bridges';\n}\n\nexport function LiquiditySourcePage({\n supportedSwappers,\n sourceType,\n}: PropTypes) {\n const [searchedFor, setSearchedFor] = useState<string>('');\n const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();\n const { navigateBackFrom } = useNavigateBack();\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n\n const supportedUniqueSwappersGroups: Array<UniqueSwappersGroupType> =\n getUniqueSwappersGroups(supportedSwappers);\n\n const validTypes: Array<LiquiditySourceType> = [];\n if (sourceType === 'Exchanges') {\n validTypes.push('DEX');\n }\n if (sourceType === 'Bridges') {\n validTypes.push('BRIDGE');\n validTypes.push('AGGREGATOR');\n }\n\n const liquiditySources = supportedUniqueSwappersGroups.filter((uniqueItem) =>\n validTypes.includes(uniqueItem.type)\n );\n\n const hasSelectAll =\n liquiditySources.length ===\n liquiditySources.filter((sourceItem) => sourceItem.selected).length;\n\n const toggleAllSources = () => {\n liquiditySources.forEach((sourceItem) => {\n if (hasSelectAll) {\n toggleLiquiditySource(sourceItem.groupTitle);\n } else {\n if (!sourceItem.selected) {\n toggleLiquiditySource(sourceItem.groupTitle);\n }\n }\n });\n };\n\n const list = liquiditySources\n .sort(sortLiquiditySourcesByGroupTitle)\n .map((sourceItem) => {\n const { selected, groupTitle, logo } = sourceItem;\n return {\n start: <Image src={logo} size={22} type=\"circular\" />,\n onClick: () => toggleLiquiditySource(groupTitle),\n end: <Checkbox checked={selected} />,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t(groupTitle)}\n </Typography>\n ),\n ...sourceItem,\n };\n });\n\n const searchHandler = (event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n setSearchedFor(value);\n };\n\n let filteredList = list;\n if (searchedFor) {\n filteredList = list.filter((sourceItem) =>\n containsText(sourceItem.groupTitle, searchedFor)\n );\n }\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t(sourceType),\n suffix: (\n <LiquiditySourceSuffix>\n <Button variant=\"ghost\" size=\"xsmall\" onClick={toggleAllSources}>\n {i18n.t(hasSelectAll ? 'Deselect all' : 'Select all')}\n </Button>\n </LiquiditySourceSuffix>\n ),\n }}>\n <SettingsContainer>\n <SearchInput\n value={searchedFor}\n setValue={setSearchedFor}\n fullWidth\n color=\"light\"\n variant=\"contained\"\n placeholder={i18n.t('Search {sourceType}', { sourceType })}\n onChange={searchHandler}\n />\n {loadingMetaStatus === 'loading' && <LoadingLiquiditySourceList />}\n\n {!filteredList.length && !!searchedFor ? (\n <NotFoundContainer>\n <NotFound\n title={i18n.t('No results found')}\n description={i18n.t('Try using different keywords')}\n />\n </NotFoundContainer>\n ) : (\n loadingMetaStatus === 'success' && (\n <LiquiditySourceList>\n {filteredList.map((sourceItem) => {\n return (\n <React.Fragment key={sourceItem.id}>\n <ListItemButton\n style={{ height: '61px' }}\n {...sourceItem}\n selected={false}\n hasDivider\n />\n </React.Fragment>\n );\n })}\n </LiquiditySourceList>\n )\n )}\n </SettingsContainer>\n </Layout>\n );\n}\n", "import { Checkbox, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { LiquiditySourceList } from '../SettingsContainer';\n\nimport { CustomeListItem } from './LoadingLiquiditySourceList.styles';\n\nconst ITEM_SKELETON_COUNT = 30;\nexport function LoadingLiquiditySourceList() {\n return (\n <LiquiditySourceList>\n {Array.from(Array(ITEM_SKELETON_COUNT), (e) => (\n <CustomeListItem\n hasDivider\n key={e}\n start={<Skeleton variant=\"circular\" width={35} height={35} />}\n title={<Skeleton variant=\"text\" size=\"large\" width={90} />}\n end={<Checkbox checked={false} />}\n />\n ))}\n </LiquiditySourceList>\n );\n}\n", "import { ListItem, styled } from '@rango-dev/ui';\n\nexport const CustomeListItem = styled(ListItem, {\n height: 61,\n});\n", "import { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\n\nimport { removeDuplicateFrom } from './common';\n\nexport type LiquiditySourceType = 'BRIDGE' | 'AGGREGATOR' | 'DEX';\n\nexport type UniqueSwappersGroupType = {\n id: string;\n groupTitle: string;\n logo: string;\n type: LiquiditySourceType;\n selected: boolean;\n};\n\nexport function getUniqueSwappersGroups(\n supportedSwappers?: string[]\n): UniqueSwappersGroupType[] {\n const swappers = useMetaStore.use.meta().swappers;\n const disabledLiquiditySources =\n useSettingsStore.use.disabledLiquiditySources();\n\n const uniqueSupportedSwappersGroups: Array<UniqueSwappersGroupType> = [];\n\n const uniqueGroup = removeDuplicateFrom(swappers.map((s) => s.swapperGroup));\n\n uniqueGroup.map((uniqueGroupItem) => {\n const swapperItem = swappers.find(\n (swapper) => swapper.swapperGroup === uniqueGroupItem\n );\n\n if (swapperItem) {\n let isSupportedSwapper = true;\n if (supportedSwappers) {\n isSupportedSwapper = supportedSwappers.some(\n (supportedItem) => supportedItem === swapperItem.swapperGroup\n );\n }\n\n if (isSupportedSwapper) {\n swapperItem.types.map((swapperTypeItem) => {\n uniqueSupportedSwappersGroups.push({\n id: swapperItem.swapperGroup,\n groupTitle: swapperItem.swapperGroup,\n logo: swapperItem.logo,\n type: swapperTypeItem,\n selected: !disabledLiquiditySources.includes(\n swapperItem.swapperGroup\n ),\n });\n });\n }\n }\n });\n\n return uniqueSupportedSwappersGroups;\n}\n\nexport function sortLiquiditySourcesByGroupTitle(\n a: UniqueSwappersGroupType,\n b: UniqueSwappersGroupType\n) {\n if (a.groupTitle < b.groupTitle) {\n return -1;\n }\n\n if (a.groupTitle > b.groupTitle) {\n return 1;\n }\n\n return 0;\n}\n", "import { i18n } from '@lingui/core';\nimport { Divider, SelectableCategoryList } from '@rango-dev/ui';\nimport React, { useState } from 'react';\n\nimport { BlockchainList } from '../components/BlockchainList';\nimport { Layout } from '../components/Layout';\nimport { SearchInput } from '../components/SearchInput';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useAppStore } from '../store/app';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\n\ninterface PropTypes {\n type: 'source' | 'destination';\n}\n\nexport function SelectBlockchainPage(props: PropTypes) {\n const { type } = props;\n const { navigateBackFrom } = useNavigateBack();\n const [searchedFor, setSearchedFor] = useState<string>('');\n const [blockchainCategory, setBlockchainCategory] = useState<string>('ALL');\n const setToBlockchain = useBestRouteStore.use.setToBlockchain();\n const setFromBlockchain = useBestRouteStore.use.setFromBlockchain();\n const { loadingStatus } = useMetaStore();\n\n const blockchains = useAppStore().blockchains({\n type: type,\n });\n const routeKey = type === 'source' ? 'fromBlockchain' : 'toBlockchain';\n\n return (\n <Layout\n header={{\n onBack: () => {\n navigateBackFrom(navigationRoutes[routeKey]);\n },\n title: i18n.t(`Select Blockchain`),\n }}>\n <Divider size={12} />\n <SelectableCategoryList\n setCategory={setBlockchainCategory}\n category={blockchainCategory}\n blockchains={blockchains}\n isLoading={loadingStatus === 'loading'}\n />\n <Divider size={24} />\n <SearchInput\n value={searchedFor}\n autoFocus\n placeholder={i18n.t('Search Blockchain')}\n color=\"light\"\n variant=\"contained\"\n size=\"large\"\n setValue={() => setSearchedFor('')}\n onChange={(event) => setSearchedFor(event.target.value)}\n />\n <Divider size={16} />\n\n <BlockchainList\n list={blockchains}\n searchedFor={searchedFor}\n blockchainCategory={blockchainCategory}\n onChange={(blockchain) => {\n if (type === 'source') {\n setFromBlockchain(blockchain);\n } else {\n setToBlockchain(blockchain);\n }\n\n navigateBackFrom(navigationRoutes[routeKey]);\n }}\n />\n </Layout>\n );\n}\n", "import type { PropTypes } from './BlockchainList.types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport {\n Divider,\n Image,\n ListItemButton,\n NotFound,\n Typography,\n} from '@rango-dev/ui';\nimport React, { useEffect, useState } from 'react';\n\nimport { useMetaStore } from '../../store/meta';\n\nimport { filterBlockchains } from './BlockchainList.helpers';\nimport { Container, List } from './BlockchainList.styles';\nimport { LoadingBlockchainList } from './LoadingBlockchainList';\n\nexport function BlockchainList(props: PropTypes) {\n const { list, searchedFor, onChange, blockchainCategory } = props;\n const [blockchains, setBlockchains] = useState<BlockchainMeta[]>(list);\n const loadingStatus = useMetaStore.use.loadingStatus();\n\n useEffect(() => {\n setBlockchains([\n ...filterBlockchains(list, searchedFor, blockchainCategory),\n ]);\n }, [list, searchedFor, blockchainCategory]);\n\n const renderList = () => {\n if (!blockchains.length && !!searchedFor) {\n return (\n <>\n <Divider size={32} />\n <NotFound\n title={i18n.t('No results found')}\n description={i18n.t('Try using different keywords')}\n />\n </>\n );\n }\n return (\n <List key={`${blockchainCategory}-${searchedFor}`}>\n {blockchains.map((item) => (\n <ListItemButton\n key={`${item.name}-${item.chainId}`}\n hasDivider\n onClick={() => onChange(item)}\n start={<Image src={item.logo} size={30} />}\n title={\n <Typography variant=\"title\" size=\"medium\">\n {item.displayName}\n </Typography>\n }\n id={item.chainId as string}\n />\n ))}\n </List>\n );\n };\n\n return (\n <Container>\n <Typography variant=\"label\" size=\"large\">\n {i18n.t('Select Blockchain')}\n </Typography>\n <Divider size={4} />\n {loadingStatus === 'loading' && <LoadingBlockchainList />}\n {loadingStatus === 'success' && renderList()}\n </Container>\n );\n}\n", "import { BlockchainCategories } from '@rango-dev/ui';\nimport { type BlockchainMeta, TransactionType } from 'rango-sdk';\n\nimport { containsText } from '../../utils/common';\n\nexport const filterByType = (\n blockchain: BlockchainMeta,\n type: string\n): boolean => {\n switch (type) {\n case BlockchainCategories.ALL:\n return true;\n case BlockchainCategories.UTXO:\n return blockchain.type === TransactionType.TRANSFER;\n case BlockchainCategories.OTHER:\n return (\n blockchain.type !== TransactionType.TRANSFER &&\n blockchain.type !== TransactionType.COSMOS &&\n blockchain.type !== TransactionType.EVM\n );\n default:\n return blockchain.type === type;\n }\n};\n\nexport const filterBlockchains = (\n list: BlockchainMeta[],\n searchedFor: string,\n blockchainType: string\n) =>\n list\n .filter((blockchain) => filterByType(blockchain, blockchainType))\n .filter(\n (blockchain) =>\n containsText(blockchain.name, searchedFor) ||\n containsText(blockchain.displayName, searchedFor)\n );\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n});\n\nexport const List = styled('ul', {\n padding: 0,\n margin: 0,\n listStyle: 'none',\n overflowY: 'auto',\n paddingRight: '$5',\n '.image-container': {\n borderRadius: '$xm',\n overflow: 'hidden',\n },\n});\n", "import { ListItem, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { List } from './BlockchainList.styles';\n\nconst ITEM_SKELETON_COUNT = 20;\nexport function LoadingBlockchainList() {\n return (\n <List>\n {Array.from(Array(ITEM_SKELETON_COUNT), (e) => (\n <ListItem\n key={e}\n hasDivider\n start={<Skeleton variant=\"circular\" width={35} height={35} />}\n title={<Skeleton variant=\"text\" size=\"large\" width={90} />}\n />\n ))}\n </List>\n );\n}\n", "import type { BlockchainMeta, Token } from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport { Divider } from '@rango-dev/ui';\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { BlockchainsSection } from '../components/BlockchainsSection';\nimport { Layout } from '../components/Layout';\nimport { SearchInput } from '../components/SearchInput';\nimport { TokenList } from '../components/TokenList/TokenList';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useAppStore } from '../store/app';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useWalletsStore } from '../store/wallets';\nimport { getTokensBalanceFromWalletAndSort } from '../utils/wallets';\n\ninterface PropTypes {\n type: 'source' | 'destination';\n}\n\nexport function SelectSwapItemsPage(props: PropTypes) {\n const { type } = props;\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n const {\n fromBlockchain,\n toBlockchain,\n setFromToken,\n setToToken,\n setFromBlockchain,\n setToBlockchain,\n } = useBestRouteStore();\n const { connectedWallets } = useWalletsStore();\n const [searchedFor, setSearchedFor] = useState<string>('');\n\n const selectedBlockchain = type === 'source' ? fromBlockchain : toBlockchain;\n const selectedBlockchainName = selectedBlockchain?.name ?? '';\n\n // Tokens & Blockchains list\n const blockchains = useAppStore().blockchains({\n type: type,\n });\n const tokens = useAppStore().tokens({\n type,\n blockchain: selectedBlockchainName,\n searchFor: searchedFor,\n });\n const tokensList = getTokensBalanceFromWalletAndSort(\n tokens,\n connectedWallets\n );\n\n // Actions\n const updateBlockchain = (blockchain: BlockchainMeta) => {\n if (type === 'source') {\n setFromBlockchain(blockchain);\n } else {\n setToBlockchain(blockchain);\n }\n };\n\n const updateToken = (token: Token) => {\n if (type === 'source') {\n setFromToken(token);\n } else {\n setToToken(token);\n }\n };\n\n return (\n <Layout\n header={{\n onBack: () =>\n navigateBackFrom(\n type === 'source'\n ? navigationRoutes.fromSwap\n : navigationRoutes.toSwap\n ),\n title: i18n.t('Swap {type}', {\n type: type === 'source' ? 'from' : 'to',\n }),\n }}>\n <BlockchainsSection\n blockchains={blockchains}\n type={type == 'source' ? 'from' : 'to'}\n blockchain={type === 'source' ? fromBlockchain : toBlockchain}\n onMoreClick={() =>\n navigate(\n type === 'source'\n ? navigationRoutes.fromBlockchain\n : navigationRoutes.toBlockchain\n )\n }\n onChange={(blockchain) => {\n updateBlockchain(blockchain);\n }}\n />\n <Divider size={24} />\n <SearchInput\n value={searchedFor}\n autoFocus\n placeholder={i18n.t('Search Token')}\n color=\"light\"\n variant=\"contained\"\n size=\"large\"\n setValue={() => setSearchedFor('')}\n onChange={(event) => setSearchedFor(event.target.value)}\n />\n <Divider size={16} />\n <TokenList\n list={tokensList}\n selectedBlockchain={selectedBlockchainName}\n searchedFor={searchedFor}\n onChange={(token) => {\n updateToken(token);\n\n const tokenBlockchain = blockchains.find(\n (chain) => token.blockchain === chain.name\n );\n if (tokenBlockchain) {\n updateBlockchain(tokenBlockchain);\n }\n\n navigateBackFrom(navigationRoutes.fromSwap);\n }}\n />\n </Layout>\n );\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { PropTypes } from './BlockchainsSection.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n BlockchainsChip,\n Divider,\n Image,\n Skeleton,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { BLOCKCHAIN_LIST_SIZE } from '../../constants/configs';\nimport { usePrepareBlockchainList } from '../../hooks/usePrepareBlockchainList';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { useMetaStore } from '../../store/meta';\n\nimport { Container } from './BlockchainsSection.styles';\n\nconst NUMBER_OF_LOADING = 12;\n\nexport function BlockchainsSection(props: PropTypes) {\n const { blockchains, type, blockchain, onChange, onMoreClick } = props;\n const blockchainsList = usePrepareBlockchainList(blockchains, {\n limit: BLOCKCHAIN_LIST_SIZE,\n selected: blockchain?.name,\n });\n\n const loadingStatus = useMetaStore.use.loadingStatus();\n const resetToBlockchain = useBestRouteStore.use.resetToBlockchain();\n const resetFromBlockchain = useBestRouteStore.use.resetFromBlockchain();\n const hasMoreItemsInList = blockchainsList.more.length > 0;\n /**\n * When only one item is left on list, we will not show the `More` button and will show the item itself instead.\n */\n const onlyOneItemInList = blockchainsList.more.length === 1;\n const showMoreButton = !onlyOneItemInList && hasMoreItemsInList;\n\n return (\n <div>\n <Divider size={12} />\n <Typography variant=\"label\" size=\"large\">\n {i18n.t('Select Blockchain')}\n </Typography>\n <Divider size={12} />\n <Container>\n {loadingStatus === 'loading' &&\n Array.from(Array(NUMBER_OF_LOADING), (e) => (\n <Skeleton key={e} variant=\"rounded\" height={50} />\n ))}\n {loadingStatus === 'success' && (\n <>\n <BlockchainsChip\n selected={!blockchain}\n onClick={() => {\n if (type === 'from') {\n resetFromBlockchain();\n } else {\n resetToBlockchain();\n }\n }}>\n <Typography variant=\"body\" size=\"xsmall\" color=\"secondary500\">\n {i18n.t('All')}\n </Typography>\n </BlockchainsChip>\n {blockchainsList.list.map((item) => (\n <BlockchainsChip\n key={item.name}\n selected={!!blockchain && blockchain.name === item.name}\n onClick={() => onChange(item)}>\n <Image src={item.logo} size={30} />\n </BlockchainsChip>\n ))}\n\n {onlyOneItemInList ? (\n <BlockchainsChip\n key={blockchainsList.more[0].name}\n selected={\n !!blockchain &&\n blockchain.name === blockchainsList.more[0].name\n }\n onClick={() => onChange(blockchainsList.more[0])}>\n <Image src={blockchainsList.more[0].logo} size={30} />\n </BlockchainsChip>\n ) : null}\n\n {showMoreButton ? (\n <BlockchainsChip onClick={onMoreClick} key=\"more-blockchains\">\n <Typography variant=\"body\" size=\"xsmall\" color=\"secondary500\">\n {i18n._('More +{count}', {\n count: blockchainsList.more.length,\n })}\n </Typography>\n </BlockchainsChip>\n ) : null}\n </>\n )}\n </Container>\n </div>\n );\n}\n", "import type {\n PrepareListOptions,\n PrepareListOutput,\n} from './usePrepareBlockchainList.types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { useEffect } from 'react';\n\nimport { useSettingsStore } from '../../store/settings';\n\nimport { prepare } from './usePrepareBlockchainList.helpers';\n\n/**\n *\n * UI needs some specific logics like limiting the list and sorting,\n * this function is getting the raw blockchains list and return a list for showing in UI.\n *\n */\nexport function usePrepareBlockchainList(\n blockchains: BlockchainMeta[],\n options?: PrepareListOptions\n): PrepareListOutput {\n const { preferredBlockchains, addPreferredBlockchain } = useSettingsStore();\n\n useEffect(() => {\n if (options?.selected) {\n addPreferredBlockchain(options?.selected);\n }\n }, [options?.selected]);\n\n const output = prepare(blockchains, preferredBlockchains, options);\n\n return {\n list: output.list,\n more: output.more,\n history: [],\n };\n}\n", "export const MOST_USED_BLOCKChAINS = ['ETH', 'COSMOS', 'OSMOSIS'];\n", "import type { PrepareListOptions } from './usePrepareBlockchainList.types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { MOST_USED_BLOCKChAINS } from './usePrepareBlockchainList.constants';\n\nexport function prepare(\n blockchains: BlockchainMeta[],\n preferredBlockchains: string[],\n options?: PrepareListOptions\n) {\n /*\n * TODO:\n * We copying the `blockchains` which can causes performance penalties but we should because we are mutating the original object.\n * A better way to solve the problem maybe is using new JS features like Use toSpliced() but\n * we can not use it right now because we need to upgrade our toolings first.\n */\n const list: BlockchainMeta[] = JSON.parse(JSON.stringify(blockchains));\n let more: BlockchainMeta[] = [];\n\n list.sort(sortByMostUsedBlockchains);\n\n // Checking `limit` has set and it should be more than of the list items.\n if (!!options?.limit && blockchains.length > options.limit) {\n const start = options.limit;\n let preferredBlockchainsWithoutMainList = preferredBlockchains;\n\n if (preferredBlockchains.length <= options.limit) {\n /*\n * For first X (limit) numbers, we need to remove them from preferred if exists.\n */\n for (let i = 0; i < options.limit; i++) {\n const blockchain = list[i];\n preferredBlockchainsWithoutMainList =\n preferredBlockchainsWithoutMainList.filter((preferredBlockchain) => {\n return blockchain.name !== preferredBlockchain;\n });\n }\n }\n list.sort(\n generateSortByPreferredBlockchainsFor(preferredBlockchainsWithoutMainList)\n );\n\n /*\n * Splice will modify the original list and returns the deleted items\n * We use the deleted items as `more`\n */\n more = list.splice(start);\n }\n return {\n list,\n more,\n };\n}\n\n/** There is a hardcoded list of blockchains that we want to show them first in the list. */\nexport function sortByMostUsedBlockchains(\n a: BlockchainMeta,\n b: BlockchainMeta\n) {\n const mostUsed = MOST_USED_BLOCKChAINS;\n const aIndexInMostUsed = mostUsed.findIndex((token) => token === a.name);\n const bIndexInMostUsed = mostUsed.findIndex((token) => token === b.name);\n const aIsMostUsed = aIndexInMostUsed > -1;\n const bIsMostUsed = bIndexInMostUsed > -1;\n\n if (aIsMostUsed && bIsMostUsed) {\n return aIndexInMostUsed > bIndexInMostUsed ? 1 : -1;\n }\n\n if (aIsMostUsed) {\n return -1;\n }\n\n if (bIsMostUsed) {\n return 1;\n }\n\n return 0;\n}\n\nexport function generateSortByPreferredBlockchainsFor(\n preferredBlockchains: string[]\n) {\n return function sortByPreferred(a: BlockchainMeta, b: BlockchainMeta) {\n const aIndexInPreferred = preferredBlockchains.findIndex(\n (blockchain) => blockchain === a.name\n );\n const bIndexInPreferred = preferredBlockchains.findIndex(\n (blockchain) => blockchain === b.name\n );\n\n const aIsPreferred = aIndexInPreferred > -1;\n const bIsPreferred = bIndexInPreferred > -1;\n\n if (aIsPreferred && bIsPreferred) {\n return aIndexInPreferred > bIndexInPreferred ? 1 : -1;\n }\n\n if (preferredBlockchains.includes(a.name)) {\n return -1;\n }\n if (preferredBlockchains.includes(b.name)) {\n return 1;\n }\n\n return 0;\n };\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: 'repeat(6, minmax(0, 1fr))',\n});\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type {\n PropTypes,\n RenderDescProps,\n TokenWithBalance,\n} from './TokenList.types';\nimport type { CommonProps } from 'react-window';\n\nimport { i18n } from '@lingui/core';\nimport {\n darkTheme,\n Divider,\n ExternalLinkIcon,\n Image,\n ListItemButton,\n NotFound,\n PinIcon,\n Skeleton,\n Typography,\n VirtualizedList,\n} from '@rango-dev/ui';\nimport React, { forwardRef, useEffect, useState } from 'react';\n\nimport { useAppStore } from '../../store/app';\nimport { useMetaStore } from '../../store/meta';\nimport { useWalletsStore } from '../../store/wallets';\nimport { generateRangeColors } from '../../utils/colors';\n\nimport { LoadingTokenList } from './LoadingTokenList';\nimport {\n BalanceContainer,\n Container,\n End,\n ImageSection,\n List,\n Pin,\n Tag,\n TagTitle,\n Title,\n} from './TokenList.styles';\n\nconst PAGE_SIZE = 20;\n\nconst renderDesc = (props: RenderDescProps) => {\n const { address, name, url, token, customCssForTag, customCssForTagTitle } =\n props;\n const length = address.length;\n\n return (\n <div className=\"description\">\n {name ? (\n <div className=\"token-name\">{name}</div>\n ) : (\n <Title className=\"token-title\">\n <Typography variant=\"title\" size=\"xmedium\">\n {token.symbol}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tag css={customCssForTag}>\n <TagTitle variant=\"body\" size=\"xsmall\" css={customCssForTagTitle}>\n {token.blockchain}\n </TagTitle>\n </Tag>\n </Title>\n )}\n\n {!!address && (\n <div\n className={`token-address ${!name && 'token-address-without-name'}`}>\n <a\n href={url}\n target=\"_blank\"\n rel=\"nofollow noreferrer\"\n onClick={(e) => e.stopPropagation()}>\n {length > 10\n ? `${address.slice(0, 5)}...${address.slice(length - 6, length)}`\n : address}{' '}\n <ExternalLinkIcon color=\"gray\" size={12} />\n </a>\n </div>\n )}\n </div>\n );\n};\n\nexport function TokenList(props: PropTypes) {\n const { list, searchedFor = '', onChange, selectedBlockchain } = props;\n\n const [tokens, setTokens] = useState<TokenWithBalance[]>(list);\n const loadingStatus = useMetaStore.use.loadingStatus();\n const [hasNextPage, setHasNextPage] = useState<boolean>(true);\n const loadingWallet = useWalletsStore.use.loading();\n const { blockchains } = useMetaStore.use.meta();\n const { isTokenPinned } = useAppStore();\n\n // eslint-disable-next-line react/display-name\n const innerElementType: React.FC<CommonProps> = forwardRef((render, ref) => {\n return (\n <div\n {...render}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref={ref as any}\n style={{\n ...render.style,\n height: `${parseFloat(render.style?.height as string) + 8 * 2}px`,\n }}\n />\n );\n });\n const loadNextPage = () => {\n setTokens(list.slice(0, tokens.length + PAGE_SIZE));\n };\n\n useEffect(() => {\n setHasNextPage(list.length > tokens.length);\n }, [tokens.length]);\n\n useEffect(() => {\n setTokens(list.slice(0, PAGE_SIZE));\n }, [list]);\n\n const renderList = () => {\n if (!tokens.length && !!searchedFor) {\n return (\n <>\n <Divider size={32} />\n <NotFound\n title={i18n.t('No results found')}\n description={i18n.t('Try using different keywords')}\n />\n </>\n );\n }\n return (\n <VirtualizedList\n Item={({ index, style }) => {\n const token = tokens[index];\n\n const address = token.address || '';\n const blockchain = blockchains.find(\n (blockchain) => blockchain.name === token.blockchain\n );\n const color = generateRangeColors(\n token.symbol,\n blockchain?.color || ''\n );\n\n const customCssForTag = {\n $$color: color[`${token.symbol}100`],\n [`.${darkTheme} &`]: {\n $$color: color[`${token.symbol}900`],\n },\n backgroundColor: '$$color',\n };\n\n const customCssForTagTitle = {\n $$color: color[`${token.symbol}700`],\n [`.${darkTheme} &`]: {\n $$color: color[`${token.symbol}100`],\n },\n color: '$$color',\n };\n\n return (\n <div\n style={{\n ...style,\n paddingRight: 5,\n }}>\n <ListItemButton\n style={{\n height: style?.height,\n }}\n tab-index={index}\n key={`${token.symbol}${token.address}`}\n id={`${token.symbol}${token.address}`}\n hasDivider\n onClick={() => onChange(tokens[index])}\n start={\n <ImageSection>\n <Image src={token.image} size={30} />\n {isTokenPinned(token) && (\n <Pin>\n <PinIcon size={12} color=\"gray\" />\n </Pin>\n )}\n </ImageSection>\n }\n title={\n blockchain?.type === 'COSMOS' ||\n !!token.name ||\n (!token.name && !address) ? (\n <Title>\n <Typography variant=\"title\" size=\"xmedium\">\n {token.symbol}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tag css={customCssForTag}>\n <TagTitle\n variant=\"body\"\n size=\"xsmall\"\n css={customCssForTagTitle}>\n {token.blockchain}\n </TagTitle>\n </Tag>\n </Title>\n ) : undefined\n }\n description={\n !!blockchain?.info &&\n !!address &&\n blockchain.type !== 'COSMOS'\n ? renderDesc({\n address,\n token: tokens[index],\n customCssForTag,\n customCssForTagTitle,\n name: token.name,\n url: blockchain.info.addressUrl\n .split('{wallet}')\n .join(address),\n })\n : token.name || undefined\n }\n end={\n loadingWallet ? (\n <End>\n <Skeleton variant=\"text\" size=\"large\" width={70} />\n <Divider size={4} />\n <Skeleton variant=\"text\" size=\"medium\" width={50} />\n </End>\n ) : (\n tokens[index]?.balance && (\n <BalanceContainer>\n <Typography variant=\"title\" size=\"small\">\n {token.balance?.amount}\n </Typography>\n <div />\n {token.balance?.usdValue && (\n <Typography\n variant=\"body\"\n color=\"neutral600\"\n size=\"xsmall\">\n {`$${token.balance?.usdValue}`}\n </Typography>\n )}\n </BalanceContainer>\n )\n )\n }\n />\n </div>\n );\n }}\n hasNextPage={hasNextPage}\n itemCount={tokens.length}\n loadNextPage={loadNextPage}\n innerElementType={innerElementType}\n size={60}\n key={`${selectedBlockchain}-${searchedFor}`}\n />\n );\n };\n\n return (\n <Container>\n <Typography variant=\"label\" size=\"large\">\n {i18n.t('Select Token')}\n </Typography>\n <Divider size={4} />\n {loadingStatus === 'loading' && <LoadingTokenList size={PAGE_SIZE} />}\n {loadingStatus === 'success' && <List>{renderList()}</List>}\n </Container>\n );\n}\n", "import type { WidgetColors, WidgetColorsKeys } from '../types';\n\nexport const colorShade = (col: string, amt: number) => {\n const RANGE = 255;\n const COL = 3;\n const RADIX = 16;\n\n col = col.replace(/^#/, '');\n if (col.length === COL) {\n col = col[0] + col[0] + col[1] + col[1] + col[2] + col[2];\n }\n let [r, g, b]: any = col.match(/.{2}/g);\n [r, g, b] = [\n parseInt(r, RADIX) + amt,\n parseInt(g, RADIX) + amt,\n parseInt(b, RADIX) + amt,\n ];\n\n r = Math.max(Math.min(RANGE, r), 0).toString(RADIX);\n g = Math.max(Math.min(RANGE, g), 0).toString(RADIX);\n b = Math.max(Math.min(RANGE, b), 0).toString(RADIX);\n\n const rr = (r.length < 2 ? '0' : '') + r;\n const gg = (g.length < 2 ? '0' : '') + g;\n const bb = (b.length < 2 ? '0' : '') + b;\n\n return `#${rr}${gg}${bb}`;\n};\n\nexport const generateRangeColors = (name: string, color: string) => {\n const NUMBER_OF_COLORS = 10;\n const HALF_NUMBER_OF_COLORS = 5;\n const COLOR_SUFFIX = 100;\n const AMT = 32;\n\n let colors = { [name]: color };\n for (let i = 1; i < NUMBER_OF_COLORS; i++) {\n if (i < HALF_NUMBER_OF_COLORS) {\n colors = {\n ...colors,\n [name + i * COLOR_SUFFIX]: colorShade(\n color,\n (HALF_NUMBER_OF_COLORS - i) * AMT\n ),\n };\n }\n if (i === HALF_NUMBER_OF_COLORS) {\n colors = {\n ...colors,\n [name + i * COLOR_SUFFIX]: color,\n };\n }\n if (i > HALF_NUMBER_OF_COLORS) {\n colors = {\n ...colors,\n [name + i * COLOR_SUFFIX]: colorShade(\n color,\n -((i - HALF_NUMBER_OF_COLORS) * AMT)\n ),\n };\n }\n }\n return colors;\n};\nexport const generateColors = (\n mainColors: { [x: string]: string },\n reverseNeutralRange: boolean,\n colors?: WidgetColors\n) => {\n if (!colors || !Object.entries(colors).length) {\n return {};\n }\n let changeColors = false;\n let listOfColors = { ...mainColors };\n for (const colorKey in colors) {\n const color = colors[colorKey as WidgetColorsKeys];\n\n if (!!color && color !== mainColors[colorKey]) {\n changeColors = true;\n if (colorKey === 'background' || colorKey === 'foreground') {\n listOfColors = {\n ...listOfColors,\n [colorKey]: color,\n };\n } else if (colorKey === 'neutral' && reverseNeutralRange) {\n const range = generateRangeColors(colorKey, color);\n listOfColors = {\n ...listOfColors,\n // Reverse the neutral shade\n [`${colorKey}100`]: range[`${colorKey}900`],\n [`${colorKey}200`]: range[`${colorKey}800`],\n [`${colorKey}300`]: range[`${colorKey}700`],\n [`${colorKey}400`]: range[`${colorKey}600`],\n [`${colorKey}500`]: range[`${colorKey}500`],\n [`${colorKey}600`]: range[`${colorKey}400`],\n [`${colorKey}700`]: range[`${colorKey}300`],\n [`${colorKey}800`]: range[`${colorKey}200`],\n [`${colorKey}900`]: range[`${colorKey}100`],\n };\n } else {\n listOfColors = {\n ...listOfColors,\n ...generateRangeColors(colorKey, color),\n };\n }\n }\n }\n return changeColors ? listOfColors : {};\n};\n", "import type { LoadingTokenListProps } from './TokenList.types';\n\nimport { Divider, ListItem, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { End, List } from './TokenList.styles';\n\nexport function LoadingTokenList(props: LoadingTokenListProps) {\n return (\n <List>\n {Array.from(Array(props.size), (e) => (\n <ListItem\n key={e}\n hasDivider\n start={<Skeleton variant=\"circular\" width={35} height={35} />}\n end={\n <End>\n <Skeleton variant=\"text\" size=\"large\" width={70} />\n <Divider size={4} />\n <Skeleton variant=\"text\" size=\"medium\" width={50} />\n </End>\n }\n title={\n <div>\n <Skeleton variant=\"text\" size=\"large\" width={90} />\n <Divider size={4} />\n <Skeleton variant=\"text\" size=\"medium\" width={90} />\n </div>\n }\n />\n ))}\n </List>\n );\n}\n", "import { styled, Typography } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n flexGrow: 1,\n});\n\nexport const Title = styled('div', {\n display: 'flex',\n alignItems: 'center',\n '._typography': {\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: 100,\n overflow: 'hidden',\n },\n});\nexport const List = styled('ul', {\n flexGrow: 1,\n padding: 0,\n margin: 0,\n listStyle: 'none',\n '& li': {\n alignItems: 'none',\n '.description': {\n position: 'relative',\n height: 12,\n width: 150,\n '.token-title': {\n position: 'absolute',\n transform: 'none',\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms',\n bottom: '-8px',\n },\n\n '.token-address': {\n transform: 'translateY(12px)',\n visibility: 'hidden',\n '& a': {\n fontSize: '$12',\n lineHeight: '$16',\n color: '$neutral600',\n textDecoration: 'none',\n },\n },\n '.token-name': {\n position: 'absolute',\n transform: 'none',\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: 100,\n overflow: 'hidden',\n },\n },\n '&:hover': {\n '.description': {\n '.token-address': {\n position: 'absolute',\n transform: 'none',\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms',\n visibility: 'visible',\n },\n '.token-address-without-name': {\n bottom: '-15px',\n },\n '.token-name': {\n position: 'absolute',\n transform: 'translateY(-12px)',\n visibility: 'hidden',\n },\n '.token-title': {\n position: 'absolute',\n transform: 'translateY(-12px)',\n bottom: '-10px',\n },\n },\n },\n },\n});\n\nexport const Tag = styled('div', {\n paddingLeft: '$5',\n paddingRight: '$5',\n borderRadius: '$md',\n display: 'flex',\n alignItems: 'center',\n});\n\nexport const TagTitle = styled(Typography, {});\n\nexport const BalanceContainer = styled('div', {\n textAlign: 'right',\n});\n\nexport const End = styled('ul', {\n display: 'flex',\n alignItems: 'end',\n flexDirection: 'column',\n});\n\nexport const Description = styled('div', {\n display: 'flex',\n alignItems: 'center',\n});\nexport const ImageSection = styled('div', {\n position: 'relative',\n '.image-container': {\n borderRadius: '$xm',\n overflow: 'hidden',\n },\n});\nexport const Pin = styled('div', {\n position: 'absolute',\n backgroundColor: '$neutral100',\n padding: '$4',\n borderRadius: '50%',\n bottom: -6,\n right: -6,\n});\n", "import { i18n } from '@lingui/core';\nimport {\n ChevronRightIcon,\n Divider,\n InfoIcon,\n List,\n ListItemButton,\n Skeleton,\n Switch,\n Tooltip,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { Layout } from '../components/Layout';\nimport { SettingsContainer } from '../components/SettingsContainer';\nimport { Slippage } from '../components/Slippage';\nimport { SlippageTooltipContainer as TooltipContainer } from '../components/Slippage/Slippage.styles';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { getContainer } from '../utils/common';\nimport { getUniqueSwappersGroups } from '../utils/settings';\n\ninterface PropTypes {\n supportedSwappers?: string[];\n singleTheme?: boolean;\n}\n\nexport function SettingsPage({ supportedSwappers, singleTheme }: PropTypes) {\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n\n const infiniteApprove = useSettingsStore.use.infiniteApprove();\n const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n\n const supportedUniqueSwappersGroups =\n getUniqueSwappersGroups(supportedSwappers);\n\n const bridgeSources = supportedUniqueSwappersGroups.filter(\n (uniqueItem) =>\n uniqueItem.type === 'BRIDGE' || uniqueItem.type === 'AGGREGATOR'\n );\n const totalBridgeSources = bridgeSources.length;\n const totalSelectedBridgeSources = bridgeSources.filter(\n (uniqueItem) => uniqueItem.selected\n ).length;\n\n const exchangeSources = supportedUniqueSwappersGroups.filter(\n (uniqueItem) => uniqueItem.type === 'DEX'\n );\n const totalExchangeSources = exchangeSources.length;\n const totalSelectedExchangeSources = exchangeSources.filter(\n (uniqueItem) => uniqueItem.selected\n ).length;\n\n const handleEndItem = (totalSelected: number, total: number) => {\n switch (loadingMetaStatus) {\n case 'loading':\n return <Skeleton variant=\"text\" size=\"medium\" width={50} />;\n case 'failed':\n return (\n <Typography variant=\"body\" size=\"medium\" color=\"$error500\">\n {i18n.t('Loading failed')}\n </Typography>\n );\n default:\n return (\n <Typography variant=\"body\" size=\"medium\">\n {`${totalSelected} / ${total}`}\n </Typography>\n );\n }\n };\n\n const bridgeItem = {\n id: 'bridge-item',\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Enabled bridges')}\n </Typography>\n ),\n end: (\n <>\n {handleEndItem(totalSelectedBridgeSources, totalBridgeSources)}\n <Divider direction=\"horizontal\" size={8} />\n <ChevronRightIcon color=\"black\" />\n </>\n ),\n onClick: () => navigate(navigationRoutes.bridges),\n };\n\n const exchangeItem = {\n id: 'exchange-item',\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Enabled exchanges')}\n </Typography>\n ),\n end: (\n <>\n {handleEndItem(totalSelectedExchangeSources, totalExchangeSources)}\n <Divider direction=\"horizontal\" size={8} />\n <ChevronRightIcon color=\"gray\" />\n </>\n ),\n onClick: () => navigate(navigationRoutes.exchanges),\n };\n\n /*\n * const languageItem = {\n * id: 'language-item',\n * title: (\n * <Typography variant=\"title\" size=\"xmedium\">\n * {i18n.t('Language')}\n * </Typography>\n * ),\n * end: <ChevronRightIcon color=\"gray\" />,\n * onClick: () => navigate(navigationRoutes.languages),\n * };\n */\n\n const themeItem = {\n id: 'theme-item',\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Theme')}\n </Typography>\n ),\n end: <ChevronRightIcon color=\"gray\" />,\n onClick: () => navigate(navigationRoutes.themes),\n };\n\n const infiniteApprovalItem = {\n id: 'infinite-approval-item',\n title: (\n <>\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Infinite Approval')}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tooltip\n side=\"top\"\n container={getContainer()}\n content={\n <TooltipContainer>\n <Typography variant=\"label\" size=\"medium\" color=\"neutral700\">\n {i18n.t(\n \"Enabling the 'Infinite Approval' mode grants unrestricted access to smart contracts of DEXes/Bridges, allowing them to utilize the approved token amount without limitations.\"\n )}\n </Typography>\n </TooltipContainer>\n }>\n <InfoIcon color=\"gray\" />\n </Tooltip>\n </>\n ),\n end: <Switch checked={infiniteApprove} />,\n onClick: toggleInfiniteApprove,\n };\n\n const settingItems = [\n bridgeItem,\n exchangeItem,\n // languageItem\n ];\n if (!singleTheme) {\n settingItems.push(themeItem);\n }\n settingItems.push(infiniteApprovalItem);\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t('Setting'),\n }}>\n <SettingsContainer>\n <Slippage />\n <List\n type={\n <ListItemButton title=\"_\" id=\"_\" onClick={() => console.log()} />\n }\n items={settingItems}\n />\n </SettingsContainer>\n </Layout>\n );\n}\n", "import { i18n } from '@lingui/core';\nimport {\n Chip,\n Divider,\n InfoIcon,\n TextField,\n Tooltip,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport {\n MAX_SLIPPAGE,\n MIN_SLIPPGAE,\n SLIPPAGES,\n} from '../../constants/swapSettings';\nimport { useSettingsStore } from '../../store/settings';\nimport { getContainer } from '../../utils/common';\n\nimport { BaseContainer, Head, SlippageChipsContainer } from './Slippage.styles';\nimport { SlippageTooltipContent } from './SlippageTooltipContent';\n\nexport function Slippage() {\n const slippage = useSettingsStore.use.slippage();\n const setSlippage = useSettingsStore.use.setSlippage();\n const customSlippage = useSettingsStore.use.customSlippage();\n const setCustomSlippage = useSettingsStore.use.setCustomSlippage();\n\n return (\n <BaseContainer>\n <Head>\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Slippage tolerance per swap')}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={<SlippageTooltipContent />}>\n <InfoIcon color=\"gray\" />\n </Tooltip>\n </Head>\n <SlippageChipsContainer>\n {SLIPPAGES.map((slippageItem, index) => {\n const key = `slippage-${index}`;\n return (\n <>\n <Chip\n style={{ width: '64px', flexShrink: 0 }}\n key={key}\n onClick={() => {\n if (customSlippage) {\n setCustomSlippage(null);\n }\n setSlippage(slippageItem);\n }}\n selected={!customSlippage && slippageItem === slippage}\n label={`${slippageItem.toString()}%`}\n />\n <Divider direction=\"horizontal\" size={8} />\n </>\n );\n })}\n <TextField\n type=\"number\"\n min=\"0.01\"\n max=\"30\"\n step=\"0.01\"\n fullWidth\n variant=\"contained\"\n value={customSlippage || ''}\n color=\"dark\"\n onChange={(event) => {\n const parsedValue = parseFloat(event.target.value);\n if (\n !parsedValue ||\n (parsedValue >= MIN_SLIPPGAE && parsedValue <= MAX_SLIPPAGE)\n ) {\n setCustomSlippage(parsedValue);\n }\n }}\n suffix={\n customSlippage && (\n <Typography variant=\"body\" size=\"small\">\n %\n </Typography>\n )\n }\n placeholder={i18n.t('Custom')}\n />\n </SlippageChipsContainer>\n </BaseContainer>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const BaseContainer = styled('div', {\n paddingTop: '$5',\n paddingBottom: '30px',\n});\n\nexport const SlippageChipsContainer = styled('div', {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'start',\n});\n\nexport const Head = styled('div', {\n display: 'flex',\n justifyContent: 'start',\n alignItems: 'center',\n paddingBottom: '$10',\n});\n\nexport const SlippageTooltipContainer = styled('div', {\n maxWidth: '300px',\n padding: '$10',\n});\n", "import { i18n } from '@lingui/core';\nimport { Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { SlippageTooltipContainer } from './Slippage.styles';\n\nexport function SlippageTooltipContent() {\n return (\n <SlippageTooltipContainer>\n <Typography variant=\"label\" size=\"medium\" color=\"neutral700\">\n {i18n.t(\n 'Your transaction will be reverted if the price changes unfavorably by more than this percentage'\n )}\n <br />\n <br />\n <b>{i18n.t('Warning')}</b>:\n {i18n.t(\n 'This setting is applied per step, e.g. 1Inch, Thorchain, etc. and only that step will be reverted, not the whole transaction'\n )}\n </Typography>\n </SlippageTooltipContainer>\n );\n}\n", "import { cancelSwap } from '@rango-dev/queue-manager-rango-preset';\nimport { useManager } from '@rango-dev/queue-manager-react';\nimport React from 'react';\n\nimport { SwapDetails } from '../components/SwapDetails';\nimport { SwapDetailsPlaceholder } from '../components/SwapDetails/SwapDetails.Placeholder';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useMetaStore } from '../store/meta';\nimport { useUiStore } from '../store/ui';\nimport { getPendingSwaps } from '../utils/queue';\n\nexport function SwapDetailsPage() {\n const { manager, state } = useManager();\n const loading = !state.loadedFromPersistor;\n const pendingSwaps = getPendingSwaps(manager);\n const requestId = useUiStore.use.selectedSwapRequestId();\n const { navigateBackFrom } = useNavigateBack();\n const { loadingStatus } = useMetaStore();\n\n const showSkeleton = loading || loadingStatus === 'loading';\n\n const selectedSwap = pendingSwaps.find(\n ({ swap }) => swap.requestId === requestId\n );\n\n const onCancel = () => {\n if (selectedSwap?.id) {\n const swap = manager?.get(selectedSwap.id);\n if (swap) {\n cancelSwap(swap);\n }\n }\n };\n\n const onDelete = async () => {\n if (selectedSwap?.id) {\n try {\n await manager?.deleteQueue(selectedSwap.id);\n navigateBackFrom(navigationRoutes.swapDetails);\n } catch (e) {\n console.log(e);\n }\n }\n };\n const swap = selectedSwap?.swap;\n\n if (!swap || showSkeleton) {\n return (\n <SwapDetailsPlaceholder\n requestId={requestId || ''}\n showSkeleton={showSkeleton}\n />\n );\n }\n\n return (\n <SwapDetails\n swap={swap}\n requestId={requestId || ''}\n onCancel={onCancel}\n onDelete={onDelete}\n />\n );\n}\n", "import type { SwapDetailsProps } from './SwapDetails.types';\nimport type { ModalState } from '../SwapDetailsModal';\n\nimport { i18n } from '@lingui/core';\nimport {\n getCurrentBlockchainOfOrNull,\n getCurrentStep,\n getRelatedWalletOrNull,\n PendingSwapNetworkStatus,\n} from '@rango-dev/queue-manager-rango-preset';\nimport {\n Button,\n CopyIcon,\n Divider,\n IconButton,\n RouteCost,\n RouteSummary,\n StepDetails,\n Typography,\n useCopyToClipboard,\n} from '@rango-dev/ui';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { useNavigateBack } from '../../hooks/useNavigateBack';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { useMetaStore } from '../../store/meta';\nimport { useNotificationStore } from '../../store/notification';\nimport {\n numberToString,\n secondsToString,\n totalArrivalTime,\n} from '../../utils/numbers';\nimport { getPriceImpactLevel } from '../../utils/routing';\nimport {\n getLastConvertedTokenInFailedSwap,\n getPercentageChange,\n getSwapMessages,\n shouldRetrySwap,\n} from '../../utils/swap';\nimport { getSwapDate } from '../../utils/time';\nimport { getConciseAddress, getUsdPrice } from '../../utils/wallets';\nimport { SuffixContainer } from '../HeaderButtons/HeaderButtons.styles';\nimport { Layout } from '../Layout';\nimport {\n SwapDetailsCompleteModal,\n SwapDetailsModal,\n} from '../SwapDetailsModal';\n\nimport { getSteps, getStepState, RESET_INTERVAL } from './SwapDetails.helpers';\nimport { Container, HeaderDetails, StepsList } from './SwapDetails.styles';\n\nexport function SwapDetails(props: SwapDetailsProps) {\n const { swap, requestId, onDelete, onCancel: onCancelProps } = props;\n const { canSwitchNetworkTo, connect, getWalletInfo } = useWallets();\n const retry = useBestRouteStore.use.retry();\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n const [_, handleCopy] = useCopyToClipboard(RESET_INTERVAL);\n const listRef = useRef<HTMLDivElement | null>(null);\n const [modalState, setModalState] = useState<ModalState>(null);\n const [showCompletedModal, setShowCompletedModal] = useState<\n 'success' | 'failed' | null\n >(null);\n const {\n meta: { tokens, blockchains },\n } = useMetaStore();\n\n const onCancel = () => {\n onCancelProps();\n setModalState(null);\n };\n\n const getUnreadNotifications =\n useNotificationStore.use.getUnreadNotifications();\n const setAsRead = useNotificationStore.use.setAsRead();\n const unreadNotifications = getUnreadNotifications();\n const currentStep = getCurrentStep(swap);\n const currentStepNetworkStatus = currentStep?.networkStatus;\n\n useEffect(() => {\n const existNotification = unreadNotifications.find(\n (n) => n.requestId === swap.requestId\n );\n if (existNotification) {\n if (swap.status === 'success' || swap.status === 'failed') {\n setShowCompletedModal(swap.status);\n setAsRead(swap.requestId);\n }\n }\n }, [swap.status]);\n\n useEffect(() => {\n if (showSwitchNetwork) {\n setModalState(PendingSwapNetworkStatus.WaitingForNetworkChange);\n } else if (\n currentStepNetworkStatus ===\n PendingSwapNetworkStatus.WaitingForConnectingWallet ||\n currentStepNetworkStatus === PendingSwapNetworkStatus.NetworkChanged\n ) {\n setModalState(currentStepNetworkStatus);\n } else {\n setModalState(null);\n }\n }, [currentStepNetworkStatus]);\n\n const lastConvertedTokenInFailedSwap =\n getLastConvertedTokenInFailedSwap(swap);\n\n const currentStepBlockchain = currentStep\n ? getCurrentBlockchainOfOrNull(swap, currentStep)\n : null;\n const currentStepWallet = currentStep\n ? getRelatedWalletOrNull(swap, currentStep)\n : null;\n\n const swapDate = getSwapDate(swap);\n const shouldRetry = shouldRetrySwap(swap);\n\n const isMobileWallet = (walletType: string): boolean =>\n !!getWalletInfo(walletType)?.mobileWallet;\n\n const showSwitchNetwork =\n currentStepNetworkStatus ===\n PendingSwapNetworkStatus.WaitingForNetworkChange &&\n !!currentStepBlockchain &&\n !!currentStepWallet?.walletType &&\n (isMobileWallet(currentStepWallet.walletType) ||\n canSwitchNetworkTo(currentStepWallet.walletType, currentStepBlockchain));\n\n const switchNetwork = showSwitchNetwork\n ? connect.bind(null, currentStepWallet.walletType, currentStepBlockchain)\n : undefined;\n\n const stepMessage = getSwapMessages(swap, currentStep);\n const steps = getSteps({\n swap,\n switchNetwork,\n showNetworkModal: currentStepNetworkStatus,\n setNetworkModal: setModalState,\n message: stepMessage,\n blockchains,\n });\n const numberOfSteps = steps.length;\n const [firstStep, lastStep] = [swap.steps[0], swap.steps[numberOfSteps - 1]];\n const outputAmount =\n lastStep.outputAmount || lastStep.expectedOutputAmountHumanReadable;\n\n const totalFee = swap.steps.reduce(\n (totalFee, steps) => totalFee + parseFloat(steps.feeInUsd || ''),\n 0\n );\n\n const diagnosisUrl = swap.steps.find(\n (step) => step.diagnosisUrl\n )?.diagnosisUrl;\n\n const outputUsdValue = numberToString(\n String(\n parseFloat(\n numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n )\n ) *\n (getUsdPrice(\n lastStep.toBlockchain,\n lastStep.toSymbol,\n lastStep.toSymbolAddress,\n tokens\n ) || 0)\n ),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n );\n\n const inputUsdValue = numberToString(\n String(\n parseFloat(swap.inputAmount) *\n (getUsdPrice(\n firstStep.fromBlockchain,\n firstStep.fromSymbol,\n firstStep.fromSymbolAddress,\n tokens\n ) || 0)\n ),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n );\n\n const percentageChange = getPercentageChange(inputUsdValue, outputUsdValue);\n\n const completeModalDesc =\n swap.status === 'success'\n ? i18n.t({\n id: 'receivedMessage',\n message:\n 'You have received {amount} {token} in {conciseAddress} wallet on {chain} chain.',\n values: {\n amount: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n token: steps[numberOfSteps - 1].to.token.displayName,\n conciseAddress: getConciseAddress(\n swap.wallets[steps[numberOfSteps - 1].to.chain.displayName]\n ?.address || ''\n ),\n chain: steps[numberOfSteps - 1].to.chain.displayName,\n },\n })\n : `${i18n.t('Transaction was not sent.')} ${\n lastConvertedTokenInFailedSwap\n ? i18n.t({\n id: 'remainSymbol',\n message:\n '{amount} {symbol} on {blockchain} remain in your wallet',\n values: {\n amount: lastConvertedTokenInFailedSwap.outputAmount,\n symbol: lastConvertedTokenInFailedSwap.symbol,\n blockchain: lastConvertedTokenInFailedSwap.blockchain,\n },\n })\n : ''\n }`;\n\n return (\n <Layout\n noPadding\n header={{\n title: i18n.t('Swap and Bridge'),\n onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),\n onCancel:\n swap.status === 'running' ? () => setModalState('cancel') : undefined,\n suffix: swap.status !== 'running' && (\n <SuffixContainer>\n <Button\n variant=\"ghost\"\n type=\"error\"\n size=\"xsmall\"\n onClick={() => setModalState('delete')}>\n <Typography size=\"medium\" variant=\"label\" color=\"error\">\n {i18n.t('Delete')}\n </Typography>\n </Button>\n </SuffixContainer>\n ),\n }}\n footer={\n shouldRetry &&\n !showCompletedModal && (\n <Button\n fullWidth\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={() => {\n retry(swap);\n setTimeout(() => {\n navigate(navigationRoutes.home);\n }, 0);\n }}>\n {i18n.t('Try again')}\n </Button>\n )\n }>\n <Container>\n <HeaderDetails>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Request ID')}:`}\n </Typography>\n <div className=\"request-id\">\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n {requestId}\n </Typography>\n <IconButton\n variant=\"ghost\"\n onClick={handleCopy.bind(null, requestId || '')}>\n <CopyIcon size={16} color=\"gray\" />\n </IconButton>\n </div>\n </div>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Created at')}:`}\n </Typography>\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n {swapDate}\n </Typography>\n </div>\n </HeaderDetails>\n\n <div className=\"output\">\n <RouteCost\n fee={numberToString(\n String(totalFee),\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n )}\n time={secondsToString(totalArrivalTime(swap.steps))}\n steps={numberOfSteps}\n />\n <RouteSummary\n from={{\n price: {\n value: numberToString(\n swap.inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: inputUsdValue,\n },\n token: {\n displayName: steps[0].from.token.displayName,\n image: steps[0].from.token.image,\n },\n chain: {\n image: steps[0].from.chain.image,\n displayName: steps[0].from.chain.displayName,\n },\n }}\n to={{\n price: {\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: outputUsdValue,\n },\n token: {\n displayName: steps[numberOfSteps - 1].to.token.displayName,\n image: steps[numberOfSteps - 1].to.token.image,\n },\n chain: {\n image: steps[numberOfSteps - 1].to.chain.image,\n displayName: steps[numberOfSteps - 1].to.chain.displayName,\n },\n }}\n percentageChange={numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )}\n warningLevel={getPriceImpactLevel(\n percentageChange?.toNumber() ?? 0\n )}\n />\n </div>\n <div className=\"title-steps\">\n <Typography variant=\"title\" size=\"small\">\n {i18n.t('Swaps steps')}\n </Typography>\n </div>\n <Divider size={8} />\n <StepsList ref={listRef}>\n {steps.map((step, index) => {\n const key = index;\n const state = getStepState(swap.steps[index]);\n const isFocused =\n state === 'error' ||\n state === 'in-progress' ||\n state === 'warning' ||\n (state === 'completed' && index === steps.length - 1);\n return (\n <StepDetails\n key={key}\n step={step}\n type=\"route-progress\"\n ref={listRef}\n state={state}\n hasSeparator={index !== 0}\n tabIndex={key}\n isFocused={isFocused}\n />\n );\n })}\n </StepsList>\n </Container>\n\n <SwapDetailsModal\n state={modalState}\n onClose={() => setModalState(null)}\n onCancel={onCancel}\n onDelete={onDelete}\n message={stepMessage.detailedMessage.content}\n currentStepWallet={currentStepWallet}\n />\n <SwapDetailsCompleteModal\n open={!!showCompletedModal}\n diagnosisUrl={diagnosisUrl}\n onClose={() => setShowCompletedModal(null)}\n status={swap.status === 'success' ? 'success' : 'failed'}\n priceValue={numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n )}\n usdValue={outputUsdValue}\n percentageChange={numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )}\n token={{\n displayName: steps[numberOfSteps - 1].to.token.displayName,\n image: steps[numberOfSteps - 1].to.token.image,\n }}\n chain={{ image: steps[numberOfSteps - 1].to.chain.image }}\n description={completeModalDesc}\n />\n </Layout>\n );\n}\n", "import type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\n\nimport { i18n } from '@lingui/core';\n\nconst MILLISECOND_PER_SECOND = 1000;\nconst SECONDS_PER_YEAR = 31536000;\nconst SECONDS_PER_MONTH = 2592000;\nconst SECONDS_PER_DAY = 86400;\nconst SECONDS_PER_HOUR = 3600;\nconst SECONDS_PER_MINUTE = 60;\n\nexport function timeSince(millisecond: number): string {\n const seconds = Math.floor(\n (Date.now() - millisecond) / MILLISECOND_PER_SECOND\n );\n\n const intervals = [\n {\n turningPoint: SECONDS_PER_YEAR,\n label: i18n.t('year'),\n pluralLabel: i18n.t('years'),\n },\n {\n turningPoint: SECONDS_PER_MONTH,\n label: i18n.t('month'),\n pluralLabel: i18n.t('months'),\n },\n {\n turningPoint: SECONDS_PER_DAY,\n label: i18n.t('day'),\n pluralLabel: i18n.t('days'),\n },\n {\n turningPoint: SECONDS_PER_HOUR,\n label: i18n.t('hour'),\n pluralLabel: i18n.t('hours'),\n },\n {\n turningPoint: SECONDS_PER_MINUTE,\n label: i18n.t('minute'),\n pluralLabel: i18n.t('minutes'),\n },\n ];\n\n const sortedIntervals = intervals.sort(\n (a, b) => b.turningPoint - a.turningPoint\n );\n\n for (const interval of sortedIntervals) {\n const { turningPoint, label, pluralLabel } = interval;\n const intervalCount = Math.floor(seconds / turningPoint);\n if (intervalCount > 1) {\n return `${intervalCount} ${pluralLabel}`;\n }\n if (intervalCount === 1) {\n return `${intervalCount} ${label}`;\n }\n }\n\n if (seconds > 1) {\n return `${seconds} ${i18n.t('seconds')}`;\n }\n\n return `${seconds} ${i18n.t('second')}`;\n}\n\nexport function getSwapDate(pendingSwap: PendingSwap) {\n return pendingSwap.finishTime\n ? i18n.t({\n id: 'timeAgo',\n message: '{time} ago',\n values: { time: timeSince(parseInt(pendingSwap.finishTime)) },\n })\n : i18n.t({\n id: 'timeAgo',\n message: '{time} ago',\n values: { time: timeSince(parseInt(pendingSwap.creationTime)) },\n });\n}\n", "import type { ModalPropTypes } from './SwapDetailsModal.types';\n\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\nimport { Modal } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { CancelContent } from './SwapDetailsModal.Cancel';\nimport { DeleteContent } from './SwapDetailsModal.Delete';\nimport { modalNetworkValues } from './SwapDetailsModal.helpers';\nimport { WalletStateContent } from './SwapDetailsModal.WalletState';\n\nexport function SwapDetailsModal(props: ModalPropTypes) {\n const { state, onClose, onDelete, onCancel, currentStepWallet, message } =\n props;\n\n const showWalletStateContent =\n state === PendingSwapNetworkStatus.WaitingForNetworkChange ||\n state === PendingSwapNetworkStatus.WaitingForConnectingWallet ||\n state === PendingSwapNetworkStatus.NetworkChanged;\n\n return (\n <Modal\n open={!!state}\n onClose={onClose}\n container={document.getElementById('swap-box') || document.body}>\n {showWalletStateContent && (\n <WalletStateContent\n type={modalNetworkValues[state].type}\n title={modalNetworkValues[state].title}\n currentStepWallet={currentStepWallet}\n message={message}\n showWalletButton={\n state !== PendingSwapNetworkStatus.WaitingForNetworkChange\n }\n />\n )}\n {state === 'delete' && (\n <DeleteContent onClose={onClose} onDelete={onDelete} />\n )}\n {state === 'cancel' && (\n <CancelContent onClose={onClose} onCancel={onCancel} />\n )}\n </Modal>\n );\n}\n", "import type { CancelContentProps } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { Button, Divider, MessageBox, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nexport const CancelContent = ({ onCancel, onClose }: CancelContentProps) => {\n return (\n <>\n <Divider size={20} />\n <MessageBox\n type=\"error\"\n title={i18n.t('Transaction Cancel')}\n description={i18n.t('Are you sure you want to Cancel this swap?')}\n />\n <Divider size={32} />\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={onCancel}>\n <Typography variant=\"title\" size=\"medium\" color=\"neutral100\">\n {i18n.t('Yes, Cancel it')}\n </Typography>\n </Button>\n <Divider size={12} />\n <Button variant=\"outlined\" type=\"primary\" size=\"large\" onClick={onClose}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('No, Continue')}\n </Typography>\n </Button>\n </>\n );\n};\n", "import type { DeleteContentProps } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { Button, Divider, MessageBox, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nexport const DeleteContent = ({ onDelete, onClose }: DeleteContentProps) => {\n return (\n <>\n <Divider size={20} />\n <MessageBox\n type=\"error\"\n title={i18n.t('Delete Transaction')}\n description={i18n.t('Are you sure you want to delete this swap?')}\n />\n <Divider size={32} />\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={onDelete}>\n <Typography variant=\"title\" size=\"medium\" color=\"neutral100\">\n {i18n.t('Yes, Delete it')}\n </Typography>\n </Button>\n <Divider size={12} />\n <Button variant=\"outlined\" type=\"primary\" size=\"large\" onClick={onClose}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('No, Cancel')}\n </Typography>\n </Button>\n </>\n );\n};\n", "import type { ModalNetworkValueTypes } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\n\nexport const modalNetworkValues: Record<\n Exclude<PendingSwapNetworkStatus, PendingSwapNetworkStatus.WaitingForQueue>,\n ModalNetworkValueTypes\n> = {\n [PendingSwapNetworkStatus.WaitingForNetworkChange]: {\n type: 'loading',\n title: i18n.t('Change Network'),\n },\n [PendingSwapNetworkStatus.WaitingForConnectingWallet]: {\n type: 'warning',\n title: i18n.t('Connect Wallet'),\n },\n [PendingSwapNetworkStatus.NetworkChanged]: {\n type: 'success',\n title: i18n.t('Network Changed'),\n },\n};\n", "import type { WalletStateContentProps } from './SwapDetailsModal.types';\n\nimport { MessageBox, Wallet, WalletState } from '@rango-dev/ui';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport React from 'react';\n\nimport { getContainer } from '../../utils/common';\n\nimport { WalletContainer } from './SwapDetailsModal.styles';\n\nexport const WalletStateContent = (props: WalletStateContentProps) => {\n const { type, title, currentStepWallet, message, showWalletButton } = props;\n const { connect, getWalletInfo, state: walletState } = useWallets();\n const walletType = currentStepWallet?.walletType;\n const isConnected = walletType && walletState(walletType).connected;\n const state = isConnected ? WalletState.CONNECTED : WalletState.DISCONNECTED;\n return (\n <>\n <MessageBox type={type} title={title} description={message} />\n {showWalletButton && walletType && (\n <WalletContainer>\n <Wallet\n container={getContainer()}\n title={getWalletInfo(walletType).name}\n image={getWalletInfo(walletType).img}\n type={walletType}\n state={state}\n onClick={async () => connect(walletType)}\n />\n </WalletContainer>\n )}\n </>\n );\n};\n", "import { styled } from '@rango-dev/ui';\n\nexport const WalletContainer = styled('div', {\n display: 'flex',\n justifyContent: 'center',\n});\n", "import type { CompleteModalPropTypes } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Divider,\n MessageBox,\n Modal,\n TokenAmount,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\n\nexport function SwapDetailsCompleteModal(props: CompleteModalPropTypes) {\n const {\n open,\n onClose,\n status,\n priceValue,\n usdValue,\n token,\n chain,\n percentageChange,\n description,\n diagnosisUrl,\n } = props;\n const navigate = useNavigate();\n\n return (\n <Modal\n open={open}\n onClose={onClose}\n container={document.getElementById('swap-box') || document.body}>\n {status === 'success' ? (\n <MessageBox type=\"success\" title={i18n.t('Swap Successful')}>\n <TokenAmount\n direction=\"vertical\"\n type=\"output\"\n centerAlign={true}\n price={{\n value: priceValue,\n usdValue,\n }}\n token={token}\n chain={chain}\n percentageChange={percentageChange}\n />\n <Divider size={12} />\n <Typography\n variant=\"body\"\n size=\"medium\"\n color=\"neutral700\"\n align=\"center\">\n {description}\n </Typography>\n </MessageBox>\n ) : (\n <MessageBox\n type=\"error\"\n title={i18n.t('Transaction Failed')}\n description={description}\n />\n )}\n <Divider size={32} />\n {status === 'success' && (\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={() => navigate(navigationRoutes.home)}>\n <Typography variant=\"title\" size=\"medium\" color=\"neutral100\">\n {i18n.t('Done')}\n </Typography>\n </Button>\n )}\n <Divider size={12} />\n {diagnosisUrl && (\n <>\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={() => window.open(diagnosisUrl, '_blank')}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('Diagnosis')}\n </Typography>\n </Button>\n <Divider size={12} />\n </>\n )}\n <Button variant=\"outlined\" type=\"primary\" size=\"large\" onClick={onClose}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('See Details')}\n </Typography>\n </Button>\n </Modal>\n );\n}\n", "import type { GetStep } from '../SwapDetailsAlerts';\nimport type { PendingSwapStep } from '@rango-dev/queue-manager-rango-preset';\nimport type { Step, StepDetailsProps } from '@rango-dev/ui';\n\nimport React from 'react';\n\nimport {\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { getBlockchainShortNameFor } from '../../utils/meta';\nimport { numberToString } from '../../utils/numbers';\nimport { isNetworkStatusInWarningState } from '../../utils/swap';\nimport { SwapDetailsAlerts } from '../SwapDetailsAlerts';\n\nexport const RESET_INTERVAL = 2_000;\nexport const SECONDS = 60;\n\nexport const getSteps = ({ swap, blockchains, ...args }: GetStep): Step[] => {\n const hasAlreadyProceededToSign = swap.hasAlreadyProceededToSign !== false;\n return swap.steps.map((step, index) => {\n const amountToConvert =\n index === 0 ? swap.inputAmount : swap.steps[index - 1].outputAmount;\n return {\n from: {\n token: { displayName: step.fromSymbol, image: step.fromLogo ?? '' },\n chain: {\n displayName:\n getBlockchainShortNameFor(step.fromBlockchain, blockchains) ?? '',\n image: step.fromBlockchainLogo ?? '',\n },\n price: {\n value: numberToString(\n amountToConvert,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n },\n },\n to: {\n token: { displayName: step.toSymbol, image: step.toLogo },\n chain: {\n displayName:\n getBlockchainShortNameFor(step.toBlockchain, blockchains) ?? '',\n image: step.toBlockchainLogo ?? '',\n },\n price: {\n value: numberToString(\n step.outputAmount || step.expectedOutputAmountHumanReadable,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n },\n },\n swapper: { displayName: step.swapperId, image: step.swapperLogo ?? '' },\n alerts: (\n <SwapDetailsAlerts\n step={step}\n hasAlreadyProceededToSign={hasAlreadyProceededToSign}\n {...args}\n />\n ),\n };\n });\n};\n\nexport function getStepState(step: PendingSwapStep): StepDetailsProps['state'] {\n if (\n isNetworkStatusInWarningState(step) &&\n step.status !== 'failed' &&\n step.status !== 'success'\n ) {\n return 'warning';\n }\n\n switch (step.status) {\n case 'created':\n return 'default';\n case 'approved':\n case 'waitingForApproval':\n case 'running':\n return 'in-progress';\n case 'failed':\n return 'error';\n case 'success':\n return 'completed';\n }\n}\n", "import type { SwapAlertsProps } from './SwapDetailsAlerts.types';\n\nimport { i18n } from '@lingui/core';\nimport { Alert, IconButton, LinkIcon } from '@rango-dev/ui';\nimport React, { Fragment } from 'react';\n\nimport { isNetworkStatusInWarningState } from '../../utils/swap';\n\nimport { FailedAlert } from './SwapDetailsAlerts.Failed';\nimport { Alerts } from './SwapDetailsAlerts.styles';\nimport { WarningAlert } from './SwapDetailsAlerts.Warning';\n\nexport function SwapDetailsAlerts(props: SwapAlertsProps) {\n const {\n switchNetwork,\n showNetworkModal,\n setNetworkModal,\n message,\n step,\n hasAlreadyProceededToSign,\n } = props;\n\n const hasWarning = isNetworkStatusInWarningState(step);\n const waitingForApproval =\n step.status === 'waitingForApproval' && !hasWarning;\n const inProgress = step.status === 'running' && !hasWarning;\n return (\n <Alerts>\n {step.explorerUrl?.map((explorerUrl, index, urls) => {\n const key = index + explorerUrl.url;\n const lastUrl = index === urls.length - 1;\n const loading = (lastUrl && inProgress) || waitingForApproval;\n const error = lastUrl && step.status === 'failed';\n\n return (\n <Fragment key={key}>\n <Alert\n type={(loading && 'loading') || (error && 'error') || 'success'}\n title={\n !explorerUrl.description\n ? i18n.t('View transaction')\n : `${explorerUrl.description} Tx`\n }\n action={\n explorerUrl.url && (\n <IconButton\n variant=\"ghost\"\n size=\"xsmall\"\n onClick={() => window.open(explorerUrl.url, '_blank')}>\n <LinkIcon size={16} />\n </IconButton>\n )\n }\n />\n </Fragment>\n );\n })}\n {((inProgress && !hasAlreadyProceededToSign) ||\n (waitingForApproval && !step.explorerUrl?.length)) && (\n <Alert type=\"loading\" title={message.shortMessage} />\n )}\n {step.status !== 'failed' && hasWarning && (\n <WarningAlert\n switchNetwork={switchNetwork}\n showNetworkModal={showNetworkModal}\n setNetworkModal={setNetworkModal}\n message={message}\n />\n )}\n\n {step.status === 'failed' && <FailedAlert message={message} />}\n </Alerts>\n );\n}\n", "import type { FailedAlertsProps } from './SwapDetailsAlerts.types';\n\nimport {\n Alert,\n ChevronDownIcon,\n ChevronUpIcon,\n IconButton,\n} from '@rango-dev/ui';\nimport React, { useState } from 'react';\n\nexport function FailedAlert(props: FailedAlertsProps) {\n const { message } = props;\n const [showContentError, setShowContentError] = useState(false);\n\n return (\n <Alert\n type=\"error\"\n title={message.shortMessage}\n action={\n message.detailedMessage.content && (\n <IconButton\n onClick={() => setShowContentError((prev) => !prev)}\n variant=\"ghost\"\n size=\"xsmall\">\n {showContentError ? (\n <ChevronUpIcon size={12} color=\"gray\" />\n ) : (\n <ChevronDownIcon size={12} color=\"gray\" />\n )}\n </IconButton>\n )\n }\n footer={showContentError ? message.detailedMessage.content : undefined}\n />\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Alerts = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n gap: '$10',\n});\n", "import type { WaningAlertsProps } from './SwapDetailsAlerts.types';\n\nimport { i18n } from '@lingui/core';\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\nimport { Alert, Button } from '@rango-dev/ui';\nimport React from 'react';\n\nexport function WarningAlert(props: WaningAlertsProps) {\n const { switchNetwork, setNetworkModal, message, showNetworkModal } = props;\n if (!!switchNetwork) {\n return (\n <Alert\n type=\"warning\"\n title={message.shortMessage}\n action={\n <Button\n size=\"xxsmall\"\n type=\"warning\"\n onClick={() => {\n setNetworkModal(PendingSwapNetworkStatus.WaitingForNetworkChange);\n switchNetwork().catch((e) => {\n console.log(e);\n });\n }}>\n {i18n.t('Change')}\n </Button>\n }\n />\n );\n }\n if (\n showNetworkModal === PendingSwapNetworkStatus.WaitingForConnectingWallet\n ) {\n return (\n <Alert\n type=\"warning\"\n title={message.shortMessage}\n action={\n <Button\n size=\"xxsmall\"\n type=\"warning\"\n onClick={() => {\n setNetworkModal(\n PendingSwapNetworkStatus.WaitingForConnectingWallet\n );\n }}>\n {i18n.t('Connect')}\n </Button>\n }\n />\n );\n }\n\n return <Alert type=\"warning\" title={message.shortMessage} />;\n}\n", "import { darkTheme, styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n width: '100%',\n flexDirection: 'column',\n alignItems: 'center',\n height: '0',\n flexGrow: 1,\n '& .row': {\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '$10 $20',\n borderBottom: '1px solid',\n $$color: '$colors$neutral300',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral400',\n },\n borderColor: '$$color',\n color: '$neutral500',\n },\n '& .request-id': {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '$24',\n },\n '& .output': {\n display: 'flex',\n width: '100%',\n padding: '$15 $20 $20',\n flexDirection: 'column',\n alignItems: 'start',\n },\n '& .title-steps': {\n textAlign: 'left',\n width: '100%',\n padding: '0 $20 $10',\n },\n});\n\nexport const HeaderDetails = styled('div', {\n width: '100%',\n});\n\nexport const StepsList = styled('div', {\n padding: '$0 $20 $20 $20',\n width: '100%',\n overflow: 'auto',\n});\nexport const Alerts = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n gap: '$10',\n});\n\nexport const PlaceholderContainer = styled('div', {\n height: '450px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n});\n\nexport const LoaderContainer = styled('div', {\n display: 'flex',\n justifyContent: 'center',\n width: '100%',\n paddingTop: '33%',\n flex: 1,\n});\n", "import type { SwapDetailsPlaceholderPropTypes } from './SwapDetails.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n CopyIcon,\n IconButton,\n NotFound,\n Skeleton,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport { useNavigateBack } from '../../hooks/useNavigateBack';\nimport { SuffixContainer } from '../HeaderButtons/HeaderButtons.styles';\nimport { Layout } from '../Layout';\nimport { LoadingSwapDetails } from '../LoadingSwapDetails';\n\nimport {\n Container,\n HeaderDetails,\n PlaceholderContainer,\n} from './SwapDetails.styles';\n\nexport function SwapDetailsPlaceholder(props: SwapDetailsPlaceholderPropTypes) {\n const { requestId, showSkeleton } = props;\n const { navigateBackFrom } = useNavigateBack();\n\n return (\n <Layout\n noPadding\n header={{\n title: i18n.t('Swap and Bridge'),\n onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),\n suffix: <SuffixContainer />,\n }}>\n {showSkeleton && (\n <Container>\n <HeaderDetails>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Request ID')}:`}\n </Typography>\n <div className=\"request-id\">\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n <Skeleton width={60} height={10} variant=\"rounded\" />\n </Typography>\n <IconButton variant=\"ghost\">\n <CopyIcon size={16} color=\"gray\" />\n </IconButton>\n </div>\n </div>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Created at')}:`}\n </Typography>\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n <Skeleton width={60} height={10} variant=\"rounded\" />\n </Typography>\n </div>\n </HeaderDetails>\n <LoadingSwapDetails />\n </Container>\n )}\n {!showSkeleton && (\n <PlaceholderContainer>\n <NotFound\n title={i18n.t('Not found')}\n description={i18n.t({\n id: 'swapNotFound',\n values: { requestId },\n message: 'Swap with request ID = {requestId} not found.',\n })}\n />\n </PlaceholderContainer>\n )}\n </Layout>\n );\n}\n", "import { i18n } from '@lingui/core';\nimport { ChainToken, Divider, Skeleton, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Container, StepSeparator } from './LoadingSwapDetails.styles';\nimport { LoadingSwapDetailStep } from './LoadingSwapDetailStep';\n\nexport function LoadingSwapDetails() {\n const routeSummary = (\n <div className=\"route-summary-item\">\n <div className=\"token-amount\">\n <ChainToken loading size=\"medium\" chainImage=\"\" tokenImage=\"\" />\n <Divider size={8} direction=\"horizontal\" />\n <Skeleton height={15} width={148} variant=\"rounded\" />\n </div>\n <Skeleton height={12} width={64} variant=\"rounded\" />\n </div>\n );\n\n return (\n <Container>\n <div className=\"cost\">\n <Skeleton width={60} height={10} variant=\"rounded\" />\n <Divider size={4} direction=\"horizontal\" />\n <Skeleton width={60} height={10} variant=\"rounded\" />\n <Divider size={4} direction=\"horizontal\" />\n <Skeleton width={60} height={10} variant=\"rounded\" />\n </div>\n\n <div className=\"route-summary\">\n {routeSummary}\n <div className=\"route-summary-separator\"></div>\n {routeSummary}\n </div>\n\n <div className=\"swaps-steps\">\n <Typography variant=\"title\" size=\"small\">\n {i18n.t('Swaps steps')}\n </Typography>\n </div>\n\n <div className=\"step-container\">\n <LoadingSwapDetailStep extraInfo />\n <StepSeparator />\n <LoadingSwapDetailStep />\n <StepSeparator />\n <LoadingSwapDetailStep />\n <StepSeparator />\n <LoadingSwapDetailStep />\n </div>\n </Container>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n width: '100%',\n height: '100%',\n padding: '$0 $20',\n\n '.cost': {\n paddingTop: '$15',\n display: 'flex',\n },\n\n '.route-summary': {\n padding: '$15 $0',\n },\n\n '.route-summary-item': {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n\n '.token-amount': {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n\n '.route-summary-separator': {\n width: '0px',\n height: '$16',\n borderLeft: '1px solid $neutral400',\n marginLeft: '13px',\n },\n\n '.swaps-steps': {\n paddingBottom: '$10',\n },\n});\n\nexport const StepContainer = styled('div', {\n backgroundColor: '$neutral100',\n borderRadius: '$xm',\n padding: '$10 $15',\n\n '.step-title': {\n display: 'flex',\n justifyContent: 'start',\n alignItems: 'center',\n },\n '.step-tokens': {\n paddingTop: '$5',\n display: 'flex',\n alignItems: 'center',\n },\n '.step-token-info': {\n display: 'flex',\n alignItems: 'center',\n },\n '.step-icon-container': {\n padding: '$4 $6',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n },\n\n '.extra-info': {\n display: 'flex',\n paddingTop: '$10',\n paddingBottom: '$5',\n },\n});\nexport const StepSeparator = styled('div', {\n width: '0px',\n height: '$20',\n borderLeft: '1px dashed $neutral700',\n marginLeft: '25px',\n});\n", "import type { StepSkeletonPropsTypes } from './LoadingSwapDetails.types';\n\nimport { ChainToken, Divider, NextIcon, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { StepContainer } from './LoadingSwapDetails.styles';\n\nexport function LoadingSwapDetailStep(props: StepSkeletonPropsTypes) {\n const { extraInfo } = props;\n return (\n <StepContainer>\n <div className=\"step-title\">\n <Skeleton height={28} width={28} variant=\"circular\" />\n <Divider direction=\"horizontal\" size={8} />\n <Skeleton height={15} width={148} variant=\"rounded\" />\n </div>\n <div className=\"step-tokens\">\n <Divider direction=\"horizontal\" size={20} />\n <div className=\"step-token-info\">\n <ChainToken size=\"small\" loading chainImage=\"\" tokenImage=\"\" />\n <Divider direction=\"horizontal\" size={8} />\n <Skeleton height={12} width={76} variant=\"rounded\" />\n </div>\n <div className=\"step-icon-container\">\n <NextIcon color=\"gray\" size={16} />\n </div>\n <div className=\"step-token-info\">\n <ChainToken size=\"small\" loading chainImage=\"\" tokenImage=\"\" />\n <Divider direction=\"horizontal\" size={8} />\n <Skeleton height={12} width={76} variant=\"rounded\" />\n </div>\n </div>\n {extraInfo && (\n <div className=\"extra-info\">\n <Divider direction=\"horizontal\" size={20} />\n <Skeleton height={22} width={297} variant=\"rectangular\" />\n </div>\n )}\n </StepContainer>\n );\n}\n", "import { i18n } from '@lingui/core';\nimport {\n AutoThemeIcon,\n DarkModeIcon,\n LightModeIcon,\n List,\n ListItemButton,\n Radio,\n RadioRoot,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { SettingsContainer } from '../components/SettingsContainer';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useSettingsStore } from '../store/settings';\n\ntype Theme = 'dark' | 'light' | 'auto';\n\nenum Mode {\n DARK = 'dark',\n LIGHT = 'light',\n AUTO = 'auto',\n}\n\nexport function ThemePage() {\n const { navigateBackFrom } = useNavigateBack();\n const theme = useSettingsStore.use.theme();\n const setTheme = useSettingsStore.use.setTheme();\n\n const themesList = [\n {\n id: Mode.LIGHT,\n value: Mode.LIGHT,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Light')}\n </Typography>\n ),\n onClick: () => setTheme(Mode.LIGHT as Theme),\n start: <LightModeIcon color=\"gray\" />,\n end: <Radio value={Mode.LIGHT} />,\n },\n {\n id: Mode.DARK,\n value: Mode.DARK,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Dark')}\n </Typography>\n ),\n onClick: () => setTheme(Mode.DARK as Theme),\n start: <DarkModeIcon color=\"gray\" />,\n end: <Radio value={Mode.DARK} />,\n },\n {\n id: Mode.AUTO,\n value: Mode.AUTO,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Auto')}\n </Typography>\n ),\n onClick: () => setTheme(Mode.AUTO as Theme),\n start: <AutoThemeIcon color=\"gray\" />,\n end: <Radio value={Mode.AUTO} />,\n },\n ];\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t('Theme'),\n }}>\n <SettingsContainer>\n <RadioRoot\n onValueChange={(value) => setTheme(value as Theme)}\n value={theme}>\n <List\n type={\n <ListItemButton\n title={i18n.t('Theme')}\n id=\"_\"\n onClick={() => console.log()}\n />\n }\n items={themesList}\n />\n </RadioRoot>\n </SettingsContainer>\n </Layout>\n );\n}\n", "import {\n isApprovalTX,\n MainEvents,\n RouteEventType,\n StepEventType,\n StepExecutionEventStatus,\n useEvents,\n} from '@rango-dev/queue-manager-rango-preset';\nimport { useEffect } from 'react';\n\nimport { useNotificationStore } from '../store/notification';\nimport { useWalletsStore } from '../store/wallets';\nimport { validBlockedStatuses } from '../types/notification';\n\nexport function WidgetEvents() {\n const connectedWallets = useWalletsStore.use.connectedWallets();\n const getWalletsDetails = useWalletsStore.use.getWalletsDetails();\n const setNotification = useNotificationStore.use.setNotification();\n const setAsRead = useNotificationStore.use.setAsRead();\n const widgetEvents = useEvents();\n\n useEffect(() => {\n widgetEvents.on(MainEvents.StepEvent, (widgetEvent) => {\n const { event, step, route } = widgetEvent;\n const shouldRefetchBalance =\n (event.type === StepEventType.TX_EXECUTION &&\n event.status === StepExecutionEventStatus.TX_SENT &&\n !isApprovalTX(step)) ||\n event.type === StepEventType.SUCCEEDED;\n\n if (shouldRefetchBalance) {\n const fromAccount = connectedWallets.find(\n (account) => account.chain === step?.fromBlockchain\n );\n const toAccount =\n step?.fromBlockchain !== step?.toBlockchain &&\n connectedWallets.find(\n (wallet) => wallet.chain === step?.toBlockchain\n );\n\n fromAccount && getWalletsDetails([fromAccount]);\n toAccount && getWalletsDetails([toAccount]);\n }\n if (\n (event.type === StepEventType.TX_EXECUTION_BLOCKED &&\n validBlockedStatuses.includes(event.status)) ||\n event.type === StepEventType.FAILED\n ) {\n setNotification(event, route);\n } else if (\n event.type === StepEventType.TX_EXECUTION ||\n event.type === StepEventType.CHECK_STATUS\n ) {\n setAsRead(route.requestId);\n }\n });\n\n return () => widgetEvents.all.clear();\n }, [widgetEvents, connectedWallets.length]);\n\n useEffect(() => {\n widgetEvents.on(MainEvents.RouteEvent, (widgetEvent) => {\n const { event, route } = widgetEvent;\n\n if (\n event.type === RouteEventType.FAILED ||\n event.type === RouteEventType.SUCCEEDED\n ) {\n setNotification(event, route);\n }\n });\n\n return () => widgetEvents.all.clear();\n }, [widgetEvents, connectedWallets.length]);\n\n return null;\n}\n", "import {\n type Route,\n type RouteEvent,\n type Step,\n type StepEvent,\n StepExecutionBlockedEventStatus,\n} from '@rango-dev/queue-manager-rango-preset';\n\ntype NotificationRoute = {\n from: {\n blockchain: Step['fromBlockchain'];\n tokenSymbol: Step['fromSymbol'];\n tokenAddress: Step['fromSymbolAddress'];\n };\n to: {\n blockchain: Step['toBlockchain'];\n tokenSymbol: Step['toSymbol'];\n tokenAddress: Step['toSymbolAddress'];\n };\n};\n\nexport type Notification = Pick<Route, 'requestId'> & {\n event: RouteEvent | StepEvent;\n creationTime: number;\n read: boolean;\n route: NotificationRoute;\n};\n\nexport const validBlockedStatuses: StepExecutionBlockedEventStatus[] = [\n StepExecutionBlockedEventStatus.WAITING_FOR_CHANGE_WALLET_ACCOUNT,\n StepExecutionBlockedEventStatus.WAITING_FOR_NETWORK_CHANGE,\n StepExecutionBlockedEventStatus.WAITING_FOR_WALLET_CONNECT,\n];\n", "import { globalCss } from '@rango-dev/ui';\n\nexport const globalFont = () =>\n globalCss({\n '@import': [\n \"url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')\",\n \"url('https://fonts.cdnfonts.com/css/times-new-roman')\",\n ],\n })();\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { WidgetTheme } from '../types';\n\nimport {\n createTheme,\n darkTheme as defaultDarkTheme,\n lightTheme as defaultLightTheme,\n} from '@rango-dev/ui';\nimport { useEffect, useState } from 'react';\n\nimport { useSettingsStore } from '../store/settings';\nimport {\n DEFAULT_FONT_FAMILY,\n DEFAULT_PRIMARY_RADIUS,\n DEFAULT_SECONDARY_RADIUS,\n} from '../utils/configs';\nimport { customizedThemeTokens } from '../utils/ui';\n\nexport function useTheme(props: WidgetTheme) {\n const {\n colors,\n fontFamily = DEFAULT_FONT_FAMILY,\n borderRadius = DEFAULT_PRIMARY_RADIUS,\n secondaryBorderRadius = DEFAULT_SECONDARY_RADIUS,\n mode = 'auto',\n } = props;\n\n const [OSTheme, setOSTheme] = useState('light');\n const theme = useSettingsStore.use.theme();\n const setTheme = useSettingsStore.use.setTheme();\n\n const { dark, light } = customizedThemeTokens(colors);\n\n const baseTheme = createTheme({\n radii: {\n primary: `${borderRadius}px`,\n secondary: `${secondaryBorderRadius}px`,\n },\n fonts: {\n widget: fontFamily,\n },\n });\n const lightThemeClasses = [baseTheme.className, defaultLightTheme.className];\n const darkThemeClasses = [baseTheme.className, defaultDarkTheme.className];\n\n /*\n * If theme has been customized, we will push the customized theme to override the default themes.\n * To be overridden, it should be last thing that has been pushed.\n */\n if (light) {\n const customizedLightTheme = createTheme(light.id, light.tokens);\n lightThemeClasses.push(customizedLightTheme.className);\n }\n if (dark) {\n const customizedDarkTheme = createTheme(dark.id, dark.tokens);\n darkThemeClasses.push(customizedDarkTheme.className);\n }\n\n useEffect(() => {\n const switchThemeListener = (event: MediaQueryListEvent) => {\n if (event.matches) {\n setOSTheme('dark');\n } else {\n setOSTheme('light');\n }\n };\n\n if (\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ) {\n setOSTheme('dark');\n }\n\n window\n .matchMedia('(prefers-color-scheme: dark)')\n .addEventListener('change', switchThemeListener);\n return () => {\n window\n .matchMedia('(prefers-color-scheme: dark)')\n .removeEventListener('change', switchThemeListener);\n };\n }, []);\n\n useEffect(() => {\n if (mode !== 'auto') {\n setTheme(mode);\n }\n }, [mode]);\n\n const getActiveTheme = () => {\n const lightClassNames = lightThemeClasses.join(' ');\n const darkClassNames = darkThemeClasses.join(' ');\n if (theme === 'auto') {\n return OSTheme === 'dark' ? darkClassNames : lightClassNames;\n }\n return theme === 'dark' ? darkClassNames : lightClassNames;\n };\n\n return { activeTheme: getActiveTheme };\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { WidgetTheme } from '../types';\nimport type { createTheme } from '@rango-dev/ui';\n\nimport {\n theme as baseThemeTokens,\n darkColors as defaultDarkColors,\n} from '@rango-dev/ui';\n\nimport { generateColors } from '../utils/colors';\nimport { toHash } from '../utils/hash';\n\nimport { THEME_CLASS_NAME_PREFIX } from './configs';\n\ninterface CustomizedThemeValues {\n id: string;\n tokens: Parameters<typeof createTheme>[0];\n}\n\ninterface CustomizedTheme {\n light: undefined | CustomizedThemeValues;\n dark: undefined | CustomizedThemeValues;\n}\n\nexport function customizedThemeTokens(\n colors: WidgetTheme['colors']\n): CustomizedTheme {\n const baseColors = baseThemeTokens.colors;\n\n const darkColorsWithDefaults = generateColors(\n {\n ...baseColors,\n ...defaultDarkColors,\n },\n true,\n colors?.dark\n );\n const lightColorsWithDefaults = generateColors(\n baseColors,\n false,\n colors?.light\n );\n const hasDefaultDarkColors = Object.keys(darkColorsWithDefaults).length > 0;\n const hasDefaultLightColors = Object.keys(lightColorsWithDefaults).length > 0;\n\n let light: CustomizedTheme['light'] = undefined;\n let dark: CustomizedTheme['dark'] = undefined;\n\n if (hasDefaultLightColors) {\n const tokens = { colors: lightColorsWithDefaults };\n const id = `${THEME_CLASS_NAME_PREFIX}-light-${toHash(tokens)}`;\n light = {\n id,\n tokens,\n };\n }\n if (hasDefaultDarkColors) {\n const tokens = {\n colors: darkColorsWithDefaults,\n };\n const id = `${THEME_CLASS_NAME_PREFIX}-dark-${toHash(tokens)}`;\n dark = {\n id,\n tokens,\n };\n }\n\n return {\n light,\n dark,\n };\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\n// Original Code: https://github.com/stitchesjs/stitches/blob/canary/packages/core/src/convert/toHash.js\n\nconst toAlphabeticChar = (code: number) =>\n String.fromCharCode(code + (code > 25 ? 39 : 97));\n\nconst toAlphabeticName = (code: number) => {\n let name = '';\n let x;\n\n for (x = Math.abs(code); x > 52; x = (x / 52) | 0) {\n name = toAlphabeticChar(x % 52) + name;\n }\n\n return toAlphabeticChar(x % 52) + name;\n};\n\nconst toPhash = (h: number, x: string) => {\n let i = x.length;\n while (i) {\n h = (h * 33) ^ x.charCodeAt(--i);\n }\n return h;\n};\n\nexport const toHash = (value: object) =>\n toAlphabeticName(toPhash(5381, JSON.stringify(value)) >>> 0);\n", "import React, { PropsWithChildren, useMemo } from 'react';\nimport { Provider as ManagerProvider } from '@rango-dev/queue-manager-react';\nimport {\n makeQueueDefinition,\n SwapQueueContext,\n checkWaitingForNetworkChange,\n} from '@rango-dev/queue-manager-rango-preset';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport {\n convertEvmBlockchainMetaToEvmChainInfo,\n Network,\n WalletType,\n} from '@rango-dev/wallets-shared';\nimport { useMetaStore } from './store/meta';\nimport { useWalletsStore } from './store/wallets';\nimport { walletAndSupportedChainsNames } from './utils/wallets';\nimport { getConfig } from './utils/configs';\nimport { isEvmBlockchain } from 'rango-types';\n\nfunction QueueManager(props: PropsWithChildren) {\n const {\n providers,\n getSigners,\n state,\n connect,\n canSwitchNetworkTo,\n getWalletInfo,\n } = useWallets();\n\n const swapQueueDef = useMemo(() => {\n return makeQueueDefinition({\n API_KEY: getConfig('API_KEY'),\n });\n }, []);\n\n const { blockchains } = useMetaStore.use.meta();\n const connectedWallets = useWalletsStore.use.connectedWallets();\n\n const wallets = {\n blockchains: connectedWallets.map((wallet) => ({\n accounts: [wallet],\n name: wallet.chain,\n })),\n };\n\n const switchNetwork = (wallet: WalletType, network: Network) => {\n if (!canSwitchNetworkTo(wallet, network)) {\n return undefined;\n }\n return connect(wallet, network);\n };\n\n const isMobileWallet = (walletType: WalletType): boolean =>\n !!getWalletInfo(walletType).mobileWallet;\n\n // TODO: this code copy & pasted from rango, should be refactored.\n const allBlockchains = blockchains\n .filter((blockchain) => blockchain.enabled)\n .reduce(\n (blockchainsObj: any, blockchain) => (\n (blockchainsObj[blockchain.name] = blockchain), blockchainsObj\n ),\n {}\n );\n const evmBasedChains = blockchains.filter(isEvmBlockchain);\n const getSupportedChainNames = (type: WalletType) => {\n const { supportedChains } = getWalletInfo(type);\n return walletAndSupportedChainsNames(supportedChains);\n };\n const allProviders = providers();\n\n const context: SwapQueueContext = {\n meta: {\n blockchains: allBlockchains,\n evmBasedChains: evmBasedChains,\n evmNetworkChainInfo:\n convertEvmBlockchainMetaToEvmChainInfo(evmBasedChains),\n getSupportedChainNames,\n },\n getSigners,\n //todo: remove Network type\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n wallets,\n providers: allProviders,\n switchNetwork,\n canSwitchNetworkTo,\n connect,\n state,\n isMobileWallet,\n };\n\n return (\n <ManagerProvider\n queuesDefs={[swapQueueDef]}\n context={context}\n onPersistedDataLoaded={(manager) => {\n checkWaitingForNetworkChange(manager);\n }}\n isPaused={false}>\n {props.children}\n </ManagerProvider>\n );\n}\n\nexport default QueueManager;\n"],
|
|
4
|
+
"sourcesContent": ["import type {\n BlockchainAndTokenConfig,\n WidgetColors,\n WidgetColorsKeys,\n WidgetConfig,\n WidgetTheme,\n} from './types';\nimport type { WidgetProps } from './Widget';\nimport type {\n Route,\n RouteEvent,\n RouteFailedEvent,\n RouteStartedEvent,\n RouteSucceededEvent,\n Step,\n StepApprovalTxSucceededEvent,\n StepCheckStatusEvent,\n StepEvent,\n StepFailedEvent,\n StepOutputRevealedEvent,\n StepStartedEvent,\n StepSucceededEvent,\n StepTxExecutionBlockedEvent,\n StepTxExecutionUpdatedEvent,\n} from '@rango-dev/queue-manager-rango-preset';\nimport type {\n EventHandler as HandleWalletsUpdate,\n ProviderInterface,\n} from '@rango-dev/wallets-react';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport {\n MainEvents,\n RouteEventType,\n StepEventType,\n StepExecutionBlockedEventStatus,\n StepExecutionEventStatus,\n useEvents as useWidgetEvents,\n} from '@rango-dev/queue-manager-rango-preset';\nimport { useWallets } from '@rango-dev/wallets-react';\n\nimport { WidgetWallets } from './Wallets';\nimport { Widget } from './Widget';\n\nexport type {\n WidgetConfig,\n WalletType,\n WidgetTheme,\n WidgetColors,\n WidgetColorsKeys,\n ProviderInterface,\n BlockchainAndTokenConfig,\n WidgetProps,\n RouteEvent,\n StepEvent,\n Route,\n Step,\n RouteStartedEvent,\n RouteSucceededEvent,\n RouteFailedEvent,\n StepStartedEvent,\n StepSucceededEvent,\n StepFailedEvent,\n StepTxExecutionUpdatedEvent,\n StepTxExecutionBlockedEvent,\n StepCheckStatusEvent,\n StepApprovalTxSucceededEvent,\n StepOutputRevealedEvent,\n HandleWalletsUpdate,\n};\nexport {\n Widget,\n WidgetWallets,\n useWallets,\n useWidgetEvents,\n MainEvents,\n RouteEventType,\n StepEventType,\n StepExecutionEventStatus,\n StepExecutionBlockedEventStatus,\n};\n", "import type { WidgetConfig } from './types';\nimport type { ProvidersOptions } from './utils/providers';\nimport type { EventHandler } from '@rango-dev/wallets-react';\nimport type { Network } from '@rango-dev/wallets-shared';\nimport type { PropsWithChildren } from 'react';\n\nimport { Events, Provider } from '@rango-dev/wallets-react';\nimport { isEvmBlockchain } from 'rango-sdk';\nimport React, { createContext, useRef } from 'react';\n\nimport { useWalletProviders } from './hooks/useWalletProviders';\nimport { useMetaStore } from './store/meta';\nimport { useWalletsStore } from './store/wallets';\nimport {\n prepareAccountsForWalletStore,\n walletAndSupportedChainsNames,\n} from './utils/wallets';\n\ntype OnConnectHandler = (key: string) => void;\ninterface WidgetContextInterface {\n onConnectWallet(handler: OnConnectHandler): void;\n}\n\nexport const WidgetContext = createContext<WidgetContextInterface>({\n onConnectWallet: () => {\n return;\n },\n});\n\nexport function WidgetWallets(\n props: PropsWithChildren<{\n providers: WidgetConfig['wallets'];\n options?: ProvidersOptions;\n onUpdateState?: EventHandler;\n }>\n) {\n const { blockchains } = useMetaStore.use.meta();\n const { providers } = useWalletProviders(props.providers, props?.options);\n const disconnectWallet = useWalletsStore.use.disconnectWallet();\n const connectWallet = useWalletsStore.use.connectWallet();\n const onConnectWalletHandler = useRef<OnConnectHandler>();\n\n const evmBasedChainNames = blockchains\n .filter(isEvmBlockchain)\n .map((chain) => chain.name);\n\n const onUpdateState: EventHandler = (\n type,\n event,\n value,\n state,\n supportedBlockchains\n ) => {\n if (event === Events.ACCOUNTS) {\n if (value) {\n const supportedChainNames: Network[] | null =\n walletAndSupportedChainsNames(supportedBlockchains);\n const data = prepareAccountsForWalletStore(\n type,\n value,\n evmBasedChainNames,\n supportedChainNames\n );\n connectWallet(data);\n } else {\n disconnectWallet(type);\n }\n }\n if (event === Events.ACCOUNTS && state.connected) {\n const key = `${type}-${state.network}-${value}`;\n\n if (state.connected) {\n if (!!onConnectWalletHandler.current) {\n onConnectWalletHandler.current(key);\n } else {\n console.warn(\n `onConnectWallet handler hasn't been set. Are you sure?`\n );\n }\n }\n }\n\n if (event === Events.NETWORK && state.network) {\n const key = `${type}-${state.network}`;\n if (!!onConnectWalletHandler.current) {\n onConnectWalletHandler.current(key);\n } else {\n console.warn(`onConnectWallet handler hasn't been set. Are you sure?`);\n }\n }\n\n // propagate updates for Dapps using external wallets\n if (props.onUpdateState) {\n props.onUpdateState(type, event, value, state, supportedBlockchains);\n }\n };\n return (\n <WidgetContext.Provider\n // eslint-disable-next-line react/jsx-no-constructed-context-values\n value={{\n onConnectWallet: (handler) => {\n onConnectWalletHandler.current = handler;\n },\n }}>\n <Provider\n allBlockChains={blockchains}\n providers={providers}\n onUpdateState={onUpdateState}\n autoConnect>\n {props.children}\n </Provider>\n </WidgetContext.Provider>\n );\n}\n", "import type { WidgetConfig } from '../types';\nimport type { ProvidersOptions } from '../utils/providers';\nimport type { ProviderInterface } from '@rango-dev/wallets-react';\n\nimport { useEffect } from 'react';\n\nimport { useWalletsStore } from '../store/wallets';\nimport { matchAndGenerateProviders } from '../utils/providers';\n\nexport function useWalletProviders(\n providers: WidgetConfig['wallets'],\n options?: ProvidersOptions\n) {\n const clearConnectedWallet = useWalletsStore.use.clearConnectedWallet();\n let generateProviders: ProviderInterface[] = matchAndGenerateProviders(\n undefined,\n options\n );\n\n useEffect(() => {\n clearConnectedWallet();\n generateProviders = matchAndGenerateProviders(providers, {\n walletConnectProjectId: options?.walletConnectProjectId,\n });\n }, [providers?.length]);\n\n return {\n providers: generateProviders,\n };\n}\n", "import type { Wallet } from '../types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { create } from 'zustand';\nimport { subscribeWithSelector } from 'zustand/middleware';\n\nimport { httpService } from '../services/httpService';\nimport {\n isAccountAndWalletMatched,\n makeBalanceFor,\n resetConnectedWalletState,\n} from '../utils/wallets';\n\nimport { useMetaStore } from './meta';\nimport createSelectors from './selectors';\n\nexport type TokenBalance = {\n chain: string;\n symbol: string;\n ticker: string;\n address: string | null;\n rawAmount: string;\n decimal: number | null;\n amount: string;\n logo: string | null;\n usdPrice: number | null;\n};\n\nexport interface ConnectedWallet extends Wallet {\n balances: TokenBalance[] | null;\n explorerUrl: string | null;\n selected: boolean;\n loading: boolean;\n error: boolean;\n}\n\ninterface WalletsStore {\n connectedWallets: ConnectedWallet[];\n customDestination: string;\n loading: boolean;\n connectWallet: (accounts: Wallet[]) => void;\n disconnectWallet: (walletType: WalletType) => void;\n selectWallets: (wallets: { walletType: string; chain: string }[]) => void;\n clearConnectedWallet: () => void;\n getWalletsDetails: (accounts: Wallet[], shouldRetry?: boolean) => void;\n}\n\nexport const useWalletsStore = createSelectors(\n create<WalletsStore>()(\n subscribeWithSelector((set, get) => ({\n connectedWallets: [],\n customDestination: '',\n loading: false,\n connectWallet: (accounts) => {\n const getWalletsDetails = get().getWalletsDetails;\n set((state) => ({\n loading: true,\n connectedWallets: state.connectedWallets\n .filter((wallet) => wallet.walletType !== accounts[0].walletType)\n .concat(\n accounts.map((account) => {\n const shouldMarkWalletAsSelected = !state.connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.chain === account.chain &&\n connectedWallet.selected\n );\n return {\n balances: [],\n address: account.address,\n chain: account.chain,\n explorerUrl: null,\n walletType: account.walletType,\n selected: shouldMarkWalletAsSelected,\n loading: true,\n error: false,\n };\n })\n ),\n }));\n getWalletsDetails(accounts);\n },\n disconnectWallet: (walletType) => {\n set((state) => {\n const selectedWallets = state.connectedWallets\n .filter(\n (connectedWallet) =>\n connectedWallet.selected &&\n connectedWallet.walletType !== walletType\n )\n .map((selectedWallet) => selectedWallet.chain);\n return {\n connectedWallets: state.connectedWallets\n .filter(\n (connectedWallet) => connectedWallet.walletType !== walletType\n )\n .map((connectedWallet) => {\n const anyWalletSelectedForBlockchain = selectedWallets.includes(\n connectedWallet.chain\n );\n if (anyWalletSelectedForBlockchain) {\n return connectedWallet;\n }\n selectedWallets.push(connectedWallet.chain);\n return { ...connectedWallet, selected: true };\n }),\n };\n });\n },\n selectWallets: (wallets) =>\n set((state) => ({\n connectedWallets: state.connectedWallets.map((connectedWallet) => {\n const walletSelected = !!wallets.find(\n (wallet) =>\n wallet.chain === connectedWallet.chain &&\n wallet.walletType !== connectedWallet.walletType &&\n connectedWallet.selected\n );\n const walletNotSelected = !!wallets.find(\n (wallet) =>\n wallet.chain === connectedWallet.chain &&\n wallet.walletType === connectedWallet.walletType &&\n !connectedWallet.selected\n );\n if (walletSelected) {\n return { ...connectedWallet, selected: false };\n } else if (walletNotSelected) {\n return { ...connectedWallet, selected: true };\n }\n\n return connectedWallet;\n }),\n })),\n clearConnectedWallet: () =>\n set(() => ({\n connectedWallets: [],\n selectedWallets: [],\n })),\n getWalletsDetails: async (accounts, shouldRetry = true) => {\n const getWalletsDetails = get().getWalletsDetails;\n const { tokens } = useMetaStore.getState().meta;\n set((state) => ({\n loading: true,\n connectedWallets: state.connectedWallets.map((wallet) => {\n return accounts.find((account) =>\n isAccountAndWalletMatched(account, wallet)\n )\n ? { ...wallet, loading: true }\n : wallet;\n }),\n }));\n try {\n const data = accounts.map(({ address, chain }) => ({\n address,\n blockchain: chain,\n }));\n const response = await httpService().getWalletsDetails(data);\n const retrievedBalance = response.wallets;\n if (retrievedBalance) {\n set((state) => ({\n loading: false,\n connectedWallets: state.connectedWallets.map(\n (connectedWallet) => {\n const matchedAccount = accounts.find((account) =>\n isAccountAndWalletMatched(account, connectedWallet)\n );\n const retrievedBalanceAccount = retrievedBalance.find(\n (balance) =>\n balance.address === connectedWallet.address &&\n balance.blockChain === connectedWallet.chain\n );\n if (\n retrievedBalanceAccount?.failed &&\n matchedAccount &&\n shouldRetry\n ) {\n getWalletsDetails([matchedAccount], false);\n }\n return matchedAccount && retrievedBalanceAccount\n ? {\n ...connectedWallet,\n explorerUrl: retrievedBalanceAccount.explorerUrl,\n balances: makeBalanceFor(\n retrievedBalanceAccount,\n tokens\n ),\n }\n : connectedWallet;\n }\n ),\n }));\n } else {\n throw new Error('Wallet not found');\n }\n } catch (error) {\n set((state) => ({\n loading: false,\n connectedWallets: state.connectedWallets.map((balance) => {\n return accounts.find((account) =>\n isAccountAndWalletMatched(account, balance)\n )\n ? resetConnectedWalletState(balance)\n : balance;\n }),\n }));\n }\n },\n }))\n )\n);\n\nexport const fetchingBalanceSelector = (state: WalletsStore) =>\n !!state.connectedWallets.find((wallet) => wallet.loading);\n", "import { RangoClient } from 'rango-sdk';\n\nimport { getConfig } from '../utils/configs';\n\nlet rango: RangoClient | undefined = undefined;\n\nexport const httpService = () => {\n if (rango) {\n return rango;\n }\n rango = new RangoClient(getConfig('API_KEY'));\n return rango;\n};\n", "export const RANGO_PUBLIC_API_KEY = 'c6381a79-2817-4602-83bf-6a641a409e32';\n", "import { RANGO_PUBLIC_API_KEY } from '../constants';\n\nexport interface Configs {\n API_KEY: string;\n}\n\nlet configs: Configs = {\n API_KEY: RANGO_PUBLIC_API_KEY,\n};\n\nexport function getConfig(name: keyof Configs) {\n return configs[name];\n}\n\nexport function setConfig(name: keyof Configs, value: any) {\n configs[name] = value;\n\n return value;\n}\n\n/**\n * Getting new configs from params and reset the value of global `configs` with provided param.\n */\nexport function initConfig(nextConfigs: Configs) {\n let clonedConfigs;\n if (typeof structuredClone === 'function') {\n clonedConfigs = structuredClone(nextConfigs);\n } else {\n clonedConfigs = JSON.parse(JSON.stringify(nextConfigs));\n }\n configs = clonedConfigs;\n return configs;\n}\n\nexport const DEFAULT_PRIMARY_RADIUS = 20;\nexport const DEFAULT_SECONDARY_RADIUS = 25;\nexport const DEFAULT_FONT_FAMILY = 'Roboto';\n\nexport const THEME_CLASS_NAME_PREFIX = `theme-widget`;\n", "import type { TokenWithBalance } from '../components/TokenList';\nimport type { ConnectedWallet, TokenBalance } from '../store/wallets';\nimport type { Wallet } from '../types';\nimport type { WalletInfo as ModalWalletInfo } from '@rango-dev/ui';\nimport type {\n Network,\n WalletInfo,\n WalletState,\n WalletType,\n WalletTypes,\n} from '@rango-dev/wallets-shared';\nimport type {\n BestRouteResponse,\n BlockchainMeta,\n Token,\n WalletDetail,\n} from 'rango-sdk';\n\nimport { WalletState as WalletStatus } from '@rango-dev/ui';\nimport { readAccountAddress } from '@rango-dev/wallets-react';\nimport {\n detectInstallLink,\n getCosmosExperimentalChainInfo,\n isEvmAddress,\n KEPLR_COMPATIBLE_WALLETS,\n Networks,\n} from '@rango-dev/wallets-shared';\nimport BigNumber from 'bignumber.js';\nimport { isCosmosBlockchain } from 'rango-types';\n\nimport { ZERO } from '../constants/numbers';\nimport { EXCLUDED_WALLETS } from '../constants/wallets';\n\nimport { numberToString } from './numbers';\n\nexport function mapStatusToWalletState(state: WalletState): WalletStatus {\n switch (true) {\n case state.connected:\n return WalletStatus.CONNECTED;\n case state.connecting:\n return WalletStatus.CONNECTING;\n case !state.installed:\n return WalletStatus.NOT_INSTALLED;\n default:\n return WalletStatus.DISCONNECTED;\n }\n}\n\nexport function mapWalletTypesToWalletInfo(\n getState: (type: WalletType) => WalletState,\n getWalletInfo: (type: WalletType) => WalletInfo,\n list: WalletType[],\n chain?: string\n): ModalWalletInfo[] {\n return list\n .filter((wallet) => !EXCLUDED_WALLETS.includes(wallet as WalletTypes))\n .filter((wallet) => {\n const { supportedChains, hideWhenNotInstalled } = getWalletInfo(wallet);\n if (hideWhenNotInstalled && !getState(wallet).installed) {\n return false;\n }\n if (chain) {\n return !!supportedChains.find(\n (supportedChain) => supportedChain.name === chain\n );\n }\n return true;\n })\n .map((type) => {\n const { name, img: image, installLink } = getWalletInfo(type);\n const state = mapStatusToWalletState(getState(type));\n return {\n title: name,\n image,\n link: detectInstallLink(installLink),\n state,\n type,\n };\n });\n}\n\nexport function walletAndSupportedChainsNames(\n supportedBlockchains: BlockchainMeta[]\n): Network[] | null {\n if (!supportedBlockchains) {\n return null;\n }\n let walletAndSupportedChainsNames: Network[] = [];\n walletAndSupportedChainsNames = supportedBlockchains.map(\n (blockchainMeta) => blockchainMeta.name\n );\n\n return walletAndSupportedChainsNames;\n}\n\nexport function prepareAccountsForWalletStore(\n wallet: WalletType,\n accounts: string[],\n evmBasedChains: string[],\n supportedChainNames: Network[] | null\n): Wallet[] {\n const result: Wallet[] = [];\n\n function addAccount(network: Network, address: string) {\n const accountForChainAlreadyExists = !!result.find(\n (account) => account.chain === network\n );\n if (!accountForChainAlreadyExists) {\n const newAccount: Wallet = {\n address,\n chain: network,\n walletType: wallet,\n };\n\n result.push(newAccount);\n }\n }\n\n const supportedBlockchains = supportedChainNames || [];\n\n accounts.forEach((account) => {\n const { address, network } = readAccountAddress(account);\n\n const hasLimitation = supportedBlockchains.length > 0;\n const isSupported = supportedBlockchains.includes(network);\n const isUnknown = network === Networks.Unknown;\n const notSupportedNetworkByWallet =\n hasLimitation && !isSupported && !isUnknown;\n\n /*\n * Here we check given `network` is not supported by wallet\n * And also the network is known.\n */\n if (notSupportedNetworkByWallet) {\n return;\n }\n\n /*\n * In some cases we can handle unknown network by checking its address\n * pattern and act on it.\n * Example: showing our evm compatible network when the unknown network is evm.\n * Otherwise, we stop executing this function.\n */\n const isUnknownAndEvmBased =\n network === Networks.Unknown && isEvmAddress(address);\n if (isUnknown && !isUnknownAndEvmBased) {\n return;\n }\n\n const isEvmBasedChain = evmBasedChains.includes(network);\n\n // If it's an evm network, we will add the address to all the evm chains.\n if (isEvmBasedChain || isUnknownAndEvmBased) {\n /*\n * all evm chains are not supported in wallets, so we are adding\n * only to those that are supported by wallet.\n */\n const evmChainsSupportedByWallet = supportedBlockchains.filter((chain) =>\n evmBasedChains.includes(chain)\n );\n\n evmChainsSupportedByWallet.forEach((network) => {\n /*\n * EVM addresses are not case sensitive.\n * Some wallets like Binance-chain return some letters in uppercase which produces bugs in our wallet state.\n */\n addAccount(network, address.toLowerCase());\n });\n } else {\n addAccount(network, address);\n }\n });\n\n return result;\n}\n\nexport function getRequiredChains(route: BestRouteResponse | null) {\n const wallets: string[] = [];\n\n route?.result?.swaps.forEach((swap) => {\n const currentStepFromBlockchain = swap.from.blockchain;\n const currentStepToBlockchain = swap.to.blockchain;\n if (!wallets.includes(currentStepFromBlockchain)) {\n wallets.push(currentStepFromBlockchain);\n }\n if (!wallets.includes(currentStepToBlockchain)) {\n wallets.push(currentStepToBlockchain);\n }\n\n // Check if internalSwaps array exists\n if (swap.internalSwaps && Array.isArray(swap.internalSwaps)) {\n swap.internalSwaps.forEach((internalSwap) => {\n const internalStepFromBlockchain = internalSwap.from.blockchain;\n const internalStepToBlockchain = internalSwap.to.blockchain;\n if (!wallets.includes(internalStepFromBlockchain)) {\n wallets.push(internalStepFromBlockchain);\n }\n if (!wallets.includes(internalStepToBlockchain)) {\n wallets.push(internalStepToBlockchain);\n }\n });\n }\n });\n return wallets;\n}\n\ntype Blockchain = { name: string; accounts: ConnectedWallet[] };\n\nexport function getBalanceFromWallet(\n connectedWallets: ConnectedWallet[],\n chain: string,\n symbol: string,\n address: string | null\n): TokenBalance | null {\n if (connectedWallets.length === 0) {\n return null;\n }\n\n const selectedChainWallets = connectedWallets.filter(\n (wallet) => wallet.chain === chain\n );\n if (selectedChainWallets.length === 0) {\n return null;\n }\n\n return (\n selectedChainWallets\n .map(\n (wallet) =>\n wallet.balances?.find(\n (balance) =>\n (address !== null && balance.address === address) ||\n (address === null &&\n balance.address === address &&\n balance.symbol === symbol)\n ) || null\n )\n .filter((balance) => balance !== null)\n .sort(\n (a, b) => parseFloat(b?.amount || '0') - parseFloat(a?.amount || '1')\n )\n .find(() => true) || null\n );\n}\n\nexport function isAccountAndWalletMatched(\n account: Wallet,\n connectedWallet: ConnectedWallet\n) {\n return (\n account.address === connectedWallet.address &&\n account.chain === connectedWallet.chain &&\n account.walletType === connectedWallet.walletType\n );\n}\n\nexport function makeBalanceFor(\n retrievedBalance: WalletDetail,\n tokens: Token[]\n): TokenBalance[] {\n const { blockChain: chain, balances = [] } = retrievedBalance;\n return (\n balances?.map((tokenBalance) => ({\n chain,\n symbol: tokenBalance.asset.symbol,\n ticker: tokenBalance.asset.symbol,\n address: tokenBalance.asset.address || null,\n rawAmount: tokenBalance.amount.amount,\n decimal: tokenBalance.amount.decimals,\n amount: new BigNumber(tokenBalance.amount.amount)\n .shiftedBy(-tokenBalance.amount.decimals)\n .toFixed(),\n logo: '',\n usdPrice:\n getUsdPrice(\n chain,\n tokenBalance.asset.symbol,\n tokenBalance.asset.address,\n tokens\n ) || null,\n })) || []\n );\n}\n\nexport function resetConnectedWalletState(\n connectedWallet: ConnectedWallet\n): ConnectedWallet {\n return { ...connectedWallet, loading: false, error: true };\n}\n\nexport const calculateWalletUsdValue = (connectedWallet: ConnectedWallet[]) => {\n const uniqueAccountAddresses = new Set<string | null>();\n const uniqueBalance: ConnectedWallet[] = connectedWallet?.reduce(\n (acc: ConnectedWallet[], current: ConnectedWallet) => {\n return acc.findIndex(\n (i) => i.address === current.address && i.chain === current.chain\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n ) === -1\n ? [...acc, current]\n : acc;\n },\n []\n );\n\n const modifiedWalletBlockchains = uniqueBalance?.map((chain) => {\n const modifiedWalletBlockchain: Blockchain = {\n name: chain.chain,\n accounts: [],\n };\n if (!uniqueAccountAddresses.has(chain.address)) {\n uniqueAccountAddresses.add(chain.address);\n }\n uniqueAccountAddresses.forEach((accountAddress) => {\n if (chain.address === accountAddress) {\n modifiedWalletBlockchain.accounts.push(chain);\n }\n });\n return modifiedWalletBlockchain;\n });\n const total = numberToString(\n modifiedWalletBlockchains\n ?.flatMap((b) => b.accounts)\n ?.flatMap((a) => a?.balances)\n ?.map((b) =>\n new BigNumber(b?.amount || ZERO).multipliedBy(b?.usdPrice || 0)\n )\n ?.reduce((a, b) => a.plus(b), ZERO) || ZERO\n ).toString();\n\n return numberWithThousandSeparator(total);\n};\n\nfunction numberWithThousandSeparator(number: string | number): string {\n const parts = number.toString().split('.');\n parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n return parts.join('.');\n}\n\nexport const sortTokens = (tokens: TokenWithBalance[]): TokenWithBalance[] => {\n const walletConnected = !!tokens.some((token) => token.balance);\n if (!walletConnected) {\n return tokens\n .filter((token) => !token.address)\n .concat(\n tokens.filter((token) => token.address && !token.isSecondaryCoin),\n tokens.filter((token) => token.isSecondaryCoin)\n );\n }\n\n return tokens\n .filter((token) => !!token.balance)\n .sort(\n (tokenA, tokenB) =>\n parseFloat(tokenB.balance?.usdValue || '0') -\n parseFloat(tokenA.balance?.usdValue || '0')\n )\n .concat(\n tokens.filter((token) => !token.balance && !token.isSecondaryCoin),\n tokens.filter((token) => !token.balance && token.isSecondaryCoin)\n );\n};\n\nexport const getUsdPrice = (\n blockchain: string,\n symbol: string,\n address: string | null,\n allTokens: Token[]\n): number | null => {\n const token = allTokens?.find(\n (t) =>\n t.blockchain === blockchain &&\n t.symbol?.toUpperCase() === symbol?.toUpperCase() &&\n t.address === address\n );\n return token?.usdPrice || null;\n};\nexport const isExperimentalChain = (\n blockchains: BlockchainMeta[],\n wallet: string\n): boolean => {\n const cosmosExperimentalChainInfo = getCosmosExperimentalChainInfo(\n Object.entries(blockchains)\n .map(([, blockchainMeta]) => blockchainMeta)\n .filter(isCosmosBlockchain)\n );\n return (\n cosmosExperimentalChainInfo &&\n cosmosExperimentalChainInfo[wallet]?.experimental\n );\n};\n\nexport const getKeplrCompatibleConnectedWallets = (\n selectableWallets: Wallet[]\n): WalletType[] => {\n const connectedWalletTypes = new Set(\n selectableWallets.map((wallet) => {\n return wallet.walletType;\n })\n );\n\n return KEPLR_COMPATIBLE_WALLETS.filter((compatibleWallet) =>\n connectedWalletTypes.has(compatibleWallet)\n );\n};\n\nexport function getTokensWithBalance(\n tokens: TokenWithBalance[],\n connectedWallets: ConnectedWallet[]\n): TokenWithBalance[] {\n return tokens.map(({ balance, ...otherProps }) => {\n const tokenAmount = numberToString(\n new BigNumber(\n getBalanceFromWallet(\n connectedWallets,\n otherProps.blockchain,\n otherProps.symbol,\n otherProps.address\n )?.amount || ZERO\n )\n );\n\n let tokenUsdValue = '';\n if (otherProps.usdPrice) {\n tokenUsdValue = numberToString(\n new BigNumber(\n getBalanceFromWallet(\n connectedWallets,\n otherProps.blockchain,\n otherProps.symbol,\n otherProps.address\n )?.amount || ZERO\n ).multipliedBy(otherProps.usdPrice)\n );\n }\n\n return {\n ...otherProps,\n ...(tokenAmount !== '0' && {\n balance: { amount: tokenAmount, usdValue: tokenUsdValue },\n }),\n };\n });\n}\n\nexport function getTokensBalanceFromWalletAndSort(\n tokens: TokenWithBalance[],\n connectedWallets: ConnectedWallet[]\n) {\n const list =\n connectedWallets.length > 0\n ? getTokensWithBalance(tokens, connectedWallets)\n : tokens;\n list.sort((tokenA, tokenB) => {\n if (tokenA.balance?.usdValue && tokenB.balance?.usdValue) {\n return (\n parseFloat(tokenB.balance.usdValue) -\n parseFloat(tokenA.balance.usdValue)\n );\n }\n\n if (!tokenA.balance?.usdValue && tokenB.balance?.usdValue) {\n return 1;\n }\n\n if (tokenA.balance?.usdValue && !tokenB.balance?.usdValue) {\n return -1;\n }\n\n if (!tokenA.balance?.usdValue && !tokenB.balance?.usdValue) {\n return (\n parseFloat(tokenB.balance?.amount || '0') -\n parseFloat(tokenA.balance?.amount || '0')\n );\n }\n\n return 0;\n });\n\n return list;\n}\n\nexport function getSortedTokens(\n chain: BlockchainMeta | null,\n tokens: Token[],\n connectedWallets: ConnectedWallet[],\n otherChainTokens: TokenWithBalance[]\n): TokenWithBalance[] {\n const fromChainEqualsToToBlockchain =\n chain?.name === otherChainTokens[0]?.name;\n if (fromChainEqualsToToBlockchain) {\n return otherChainTokens;\n }\n\n const filteredTokens = tokens.filter(\n (token) => token.blockchain === chain?.name\n );\n return sortTokens(getTokensWithBalance(filteredTokens, connectedWallets));\n}\n\nexport function tokensAreEqual(\n tokenA: Pick<Token, 'blockchain' | 'symbol' | 'address'> | null,\n tokenB: Pick<Token, 'blockchain' | 'symbol' | 'address'> | null\n) {\n return (\n tokenA?.blockchain === tokenB?.blockchain &&\n tokenA?.symbol === tokenB?.symbol &&\n tokenA?.address === tokenB?.address\n );\n}\n\nexport function sortWalletsBasedOnConnectionState(\n wallets: ModalWalletInfo[]\n): ModalWalletInfo[] {\n return wallets.sort(\n (a, b) =>\n Number(b.state === WalletStatus.CONNECTED) -\n Number(a.state === WalletStatus.CONNECTED) ||\n Number(\n b.state === WalletStatus.DISCONNECTED ||\n b.state === WalletStatus.CONNECTING\n ) -\n Number(\n a.state === WalletStatus.DISCONNECTED ||\n a.state === WalletStatus.CONNECTING\n )\n );\n}\n\nexport function getConciseAddress(\n address: string,\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n maxChars = 8,\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n ellipsisLength = 3\n): string {\n if (address.length < 2 * maxChars + ellipsisLength) {\n return address;\n }\n const start = address.slice(0, maxChars);\n const end = address.slice(-maxChars);\n return `${start}${'.'.repeat(ellipsisLength)}${end}`;\n}\n\nexport function getAddress({\n chain,\n connectedWallets,\n walletType,\n}: {\n connectedWallets: ConnectedWallet[];\n walletType: string;\n chain: string;\n}): string | undefined {\n return connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === walletType &&\n connectedWallet.chain === chain\n )?.address;\n}\n", "import BigNumber from 'bignumber.js';\n\nexport const ZERO = new BigNumber(0);\n", "import { WalletTypes } from '@rango-dev/wallets-shared';\n\nexport const EXCLUDED_WALLETS = [WalletTypes.LEAP];\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\n\nimport type { BestRouteResponse } from 'rango-sdk';\n\nimport { BigNumber } from 'bignumber.js';\n\nexport const percentToString = (p: number, fractions = 0): string =>\n (p * 100).toFixed(fractions);\n\nexport const secondsToString = (s: number): string => {\n const seconds = (s % 60).toString().padStart(2, '0');\n const minutes = parseInt((s / 60).toString())\n .toString()\n .padStart(2, '0');\n return `${minutes}:${seconds}`;\n};\n\nexport const numberToString = (\n number: BigNumber | string | null | undefined,\n minDecimals: number | null = null,\n maxDecimals: number | null = null\n): string => {\n if (number === null || number === undefined) {\n return '';\n }\n if (number === '') {\n return '';\n }\n const n = new BigNumber(number);\n const roundingMode = 1;\n let maxI = 1000;\n for (let i = 0; i < 60; i++) {\n if (new BigNumber(n.toFixed(i, roundingMode)).eq(n)) {\n maxI = i;\n break;\n }\n }\n\n if (n.gte(10000)) {\n return n.toFormat(0, roundingMode);\n }\n if (n.gte(1000)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))\n ),\n roundingMode\n );\n }\n if (n.gte(100)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 1))\n ),\n roundingMode\n );\n }\n if (n.gte(1)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 2))\n ),\n roundingMode\n );\n }\n if (n.gte(0.01)) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 4))\n ),\n roundingMode\n );\n }\n for (let i = minDecimals || 4; i < 17; i++) {\n if (n.gte(Math.pow(10, -i))) {\n return n.toFormat(\n Math.min(\n maxI,\n Math.min(maxDecimals || 100, Math.max(minDecimals || 0, i))\n ),\n roundingMode\n );\n }\n }\n if (n.isEqualTo(0)) {\n return '0';\n }\n\n return n.toFormat(\n Math.min(maxI, Math.min(maxDecimals || 100, Math.max(minDecimals || 0, 8))),\n roundingMode\n );\n};\n\nexport const convertBigNumberToHex = (\n value: BigNumber,\n decimals: number\n): string => {\n return '0x' + value.shiftedBy(decimals).toString(16);\n};\n\nexport const uint8ArrayToHex = (buffer: Uint8Array): string => {\n // buffer is an ArrayBuffer\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return [...buffer].map((x) => x.toString(16).padStart(2, '0')).join('');\n};\n\nexport function dollarToConciseString(num: number | undefined): string {\n if (!num) {\n return '-';\n }\n if (num < 1) {\n return ' < 1$';\n }\n if (num < 1000) {\n return numberToString(new BigNumber(num)) + '$';\n }\n if (num < 10_000) {\n return parseInt((num / 100).toString()) / 10 + 'K';\n }\n if (num < 1_000_000) {\n return parseInt((num / 1000).toString()) + 'K';\n }\n if (num < 100_000_000) {\n return parseInt((num / 100000).toString()) / 10 + 'M';\n }\n return parseInt((num / 1000000).toString()) + 'M';\n}\n\nexport function removeExtraDecimals(num: string, maxDecimals: number): string {\n try {\n if (!num.includes('.')) {\n return num;\n }\n const [b, f] = num.split('.');\n if (f && f.length > maxDecimals) {\n return `${b}.${f.substring(0, maxDecimals)}`;\n }\n return num;\n } catch (e) {\n return num;\n }\n}\n\nexport const totalArrivalTime = (\n data: { estimatedTimeInSeconds: number | null }[] | undefined\n) => data?.reduce((a, b) => a + (b.estimatedTimeInSeconds ?? 0), 0) || 0;\n\nexport const rawFees = (data: BestRouteResponse): string =>\n (\n data?.result?.swaps?.flatMap((s) =>\n s.fee.map((f) => ({ swapperId: s.swapperId, fee: f }))\n ) || []\n )\n .reduce((partialSum, a) => partialSum + parseFloat(a.fee.amount), 0)\n .toFixed(3);\n\nexport const containsText = (text: string, searchText: string) =>\n text.toLowerCase().indexOf(searchText.toLowerCase()) > -1;\n\nexport const isPositiveNumber = (text?: string) =>\n !!text && parseFloat(text) > 0;\n10;\n\nexport function limitDecimalPlaces(\n numberString: string,\n maxDecimalPlaces = 4\n): string {\n const number = parseFloat(numberString);\n if (isNaN(number)) {\n return numberString;\n } // Return the original string if it's not a valid number\n\n const multiplier = Math.pow(10, maxDecimalPlaces);\n const roundedNumber = Math.round(number * multiplier) / multiplier;\n return roundedNumber.toString();\n}\n", "import type { TokenWithBalance } from '../components/TokenList';\nimport type { MetaResponse } from 'rango-sdk';\n\nimport { create } from 'zustand';\n\nimport { useAppStore } from './app';\nimport createSelectors from './selectors';\n\nexport type LoadingStatus = 'loading' | 'success' | 'failed';\n\nexport interface MetaState {\n meta: MetaResponse & { tokens: TokenWithBalance[] };\n loadingStatus: LoadingStatus;\n fetchMeta: () => Promise<void>;\n}\n\nexport const useMetaStore = createSelectors(\n create<MetaState>()((set) => ({\n meta: { blockchains: [], popularTokens: [], swappers: [], tokens: [] },\n loadingStatus: 'loading',\n fetchMeta: async () => {\n try {\n await useAppStore.getState().fetch();\n\n const state = useAppStore.getState();\n const response: MetaResponse = {\n blockchains: state.blockchains(),\n tokens: state.tokens(),\n popularTokens: state._popularTokens,\n swappers: state._swappers,\n };\n\n set({ meta: response, loadingStatus: 'success' });\n } catch (error) {\n set({ loadingStatus: 'failed' });\n }\n },\n }))\n);\n", "import type { ConfigSlice } from './slices/config';\nimport type { DataSlice } from './slices/data';\n\nimport { create } from 'zustand';\n\nimport createSelectors from './selectors';\nimport { createConfigSlice } from './slices/config';\nimport { createDataSlice } from './slices/data';\n\nconst store = create<DataSlice & ConfigSlice>()((...a) => ({\n ...createDataSlice(...a),\n ...createConfigSlice(...a),\n}));\n\nexport const useAppStore = createSelectors(store);\n", "import { StoreApi, UseBoundStore } from 'zustand';\n\ntype State = object;\n\ntype WithSelectors<S> = S extends { getState: () => infer T }\n ? S & { use: { [K in keyof T]: () => T[K] } }\n : never;\n\nconst createSelectors = <S extends UseBoundStore<StoreApi<State>>>(_store: S) => {\n let store = _store as WithSelectors<typeof _store>;\n store.use = {};\n for (let k of Object.keys(store.getState())) {\n (store.use as any)[k] = () => store((s) => s[k as keyof typeof s]);\n }\n\n return store;\n};\n\nexport default createSelectors;\n", "import type { WidgetConfig } from '../../types';\nimport type { StateCreator } from 'zustand';\n\nconst initConfig: WidgetConfig = { apiKey: '' };\n\nexport type ConfigSlice = {\n config: WidgetConfig;\n\n updateConfig: (config: WidgetConfig) => void;\n};\n\nexport const createConfigSlice: StateCreator<ConfigSlice> = (set, get) => ({\n config: initConfig,\n\n // Actions\n updateConfig: (nextConfig: WidgetConfig) => {\n const currentConfig = get().config;\n\n set({\n config: {\n ...currentConfig,\n ...nextConfig,\n },\n });\n },\n});\n", "export function removeDuplicateFrom<T>(array: T[]): T[] {\n return Array.from(new Set(array));\n}\n\nexport function areEqual(\n array1: (number | string)[],\n array2: (number | string)[]\n) {\n return (\n array1.length === array2.length && array1.every((v, i) => v === array2[i])\n );\n}\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport function debounce(fn: Function, time: number) {\n let timeoutId: ReturnType<typeof setTimeout> | null;\n return wrapper;\n function wrapper(...args: any) {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(() => {\n timeoutId = null;\n fn(...args);\n }, time);\n }\n}\n\nexport function containsText(text: string, searchText: string): boolean {\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n return text.toLowerCase().indexOf(searchText.toLowerCase()) > -1;\n}\n\nexport const getContainer = () =>\n document.getElementById('swap-box') as HTMLElement;\n", "// We keep all the received data from server in this slice\n\nimport type { ConfigSlice } from './config';\nimport type { BlockchainMeta, SwapperMeta, Token } from 'rango-sdk';\nimport type { StateCreator } from 'zustand';\n\nimport { httpService as sdk } from '../../services/httpService';\nimport { containsText } from '../../utils/common';\nimport { tokensAreEqual } from '../../utils/wallets';\n\ntype BlockchainOptions = {\n type?: 'source' | 'destination';\n};\n\ntype TokenOptions = {\n type?: 'source' | 'destination';\n // filter by an specific blockchain\n blockchain?: string;\n searchFor?: string;\n};\n\nexport interface DataSlice {\n _blockchains: BlockchainMeta[];\n _tokens: Token[];\n _popularTokens: Token[];\n _swappers: SwapperMeta[];\n\n blockchains: (options?: BlockchainOptions) => BlockchainMeta[];\n tokens: (options?: TokenOptions) => Token[];\n isTokenPinned: (token: Token) => boolean;\n\n fetch: () => Promise<void>;\n}\n\nexport const createDataSlice: StateCreator<\n DataSlice & ConfigSlice,\n [],\n [],\n DataSlice\n> = (set, get) => ({\n // State\n _blockchains: [],\n _tokens: [],\n _popularTokens: [],\n _swappers: [],\n\n // Selectors\n blockchains: (options) => {\n const blockchainsFromState = get()._blockchains;\n\n if (!options || !options?.type) {\n return blockchainsFromState;\n }\n\n const config = get().config;\n const supportedBlockchainsFromConfig =\n (options.type === 'source'\n ? config.from?.blockchains\n : config.to?.blockchains) ?? [];\n\n const list = blockchainsFromState.filter((blockchain) => {\n if (\n supportedBlockchainsFromConfig.length > 0 &&\n !supportedBlockchainsFromConfig.includes(blockchain.name)\n ) {\n return false;\n }\n\n return true;\n });\n\n return list;\n },\n tokens: (options) => {\n const tokensFromState = get()._tokens;\n\n if (!options || !options?.type) {\n return tokensFromState;\n }\n\n const config = get().config;\n const supportedTokensFromConfig =\n (options.type === 'source' ? config.from?.tokens : config.to?.tokens) ??\n [];\n const blockchains = get().blockchains({\n type: options.type,\n });\n\n const list = tokensFromState\n .filter((token) => {\n // If there is a list of tokens in config, we only keep them.\n if (\n supportedTokensFromConfig.length > 0 &&\n !supportedTokensFromConfig.some((asset) => {\n return tokensAreEqual(asset, token);\n })\n ) {\n return false;\n }\n\n // If a specific blockchain has passed, we only keep that blockchain's tokens.\n if (!!options.blockchain && token.blockchain !== options.blockchain) {\n return false;\n }\n\n // Check only available blockchains\n if (\n !blockchains.some((blockchain) => {\n return blockchain.name === token.blockchain;\n })\n ) {\n return false;\n }\n\n // Search functionality\n if (options.searchFor) {\n if (\n containsText(token.symbol, options.searchFor) ||\n containsText(token.address || '', options.searchFor) ||\n containsText(token.name || '', options.searchFor)\n ) {\n return true;\n }\n\n return false;\n }\n\n return true;\n })\n .sort((a, b) => {\n // Check pinned tokens\n if (get().isTokenPinned(a)) {\n return -1;\n }\n if (get().isTokenPinned(b)) {\n return 1;\n }\n\n // Check secondary coins\n if (a.isSecondaryCoin) {\n return 1;\n }\n if (b.isSecondaryCoin) {\n return -1;\n }\n\n // Check it has an address or not.\n if (!a.address && b.address) {\n return -1;\n }\n if (a.address && !b.address) {\n return 1;\n }\n\n return 0;\n });\n\n return list;\n },\n isTokenPinned: (token) => {\n const pinned = !!get().config.pinnedTokens?.some((pinnedToken) =>\n tokensAreEqual(pinnedToken, token)\n );\n return pinned;\n },\n\n // Actions\n fetch: async () => {\n const response = await sdk().getAllMetadata();\n\n const blockchains: BlockchainMeta[] = [];\n const tokens: Token[] = [];\n const popularTokens: Token[] = response.popularTokens;\n const swappers: SwapperMeta[] = response.swappers;\n\n const blockchainsWithAtLeastOneToken = new Set();\n\n response.tokens.forEach((token) => {\n blockchainsWithAtLeastOneToken.add(token.blockchain);\n\n tokens.push(token);\n });\n\n response.blockchains.forEach((blockchain) => {\n if (\n blockchain.enabled &&\n blockchainsWithAtLeastOneToken.has(blockchain.name)\n ) {\n blockchains.push(blockchain);\n }\n });\n\n // Sort\n blockchains.sort((a, b) => a.sort - b.sort);\n\n set({\n _blockchains: blockchains,\n _tokens: tokens,\n _popularTokens: popularTokens,\n _swappers: swappers,\n });\n },\n});\n", "import { allProviders } from '@rango-dev/provider-all';\nimport { ProviderInterface } from '@rango-dev/wallets-react';\nimport { WidgetConfig } from '../types';\n\nexport interface ProvidersOptions {\n walletConnectProjectId?: WidgetConfig['walletConnectProjectId'];\n}\n\n/**\n *\n * Generate a list of providers by passing a provider name (e.g. metamask) or a custom provider which implemented ProviderInterface.\n * @returns ProviderInterface[] a list of ProviderInterface\n *\n */\nexport function matchAndGenerateProviders(\n providers: WidgetConfig['wallets'],\n options?: ProvidersOptions\n): ProviderInterface[] {\n const all = allProviders({\n walletconnect2: {\n WC_PROJECT_ID: options?.walletConnectProjectId || '',\n },\n });\n\n if (providers) {\n const selectedProviders: ProviderInterface[] = [];\n\n providers.forEach((requestedProvider) => {\n // There are two types of provider we get, the first one is only passing the wallet name\n // then we will match the wallet name with our providers (@rango-dev/provider-*).\n // The second way is passing a custom provider which implemented ProviderInterface.\n if (typeof requestedProvider === 'string') {\n const result: ProviderInterface | undefined = all.find((provider) => {\n return provider.config.type === requestedProvider;\n });\n if (result) {\n selectedProviders.push(result);\n } else {\n console.warn(\n `Couldn't find ${requestedProvider} provider. Please make sure you are passing the correct name.`\n );\n }\n } else {\n // It's a custom provider so we directly push it to the list.\n selectedProviders.push(requestedProvider);\n }\n });\n return selectedProviders;\n }\n\n return all;\n}\n\nexport function configWalletsToWalletName(\n config: WidgetConfig['wallets'],\n options?: ProvidersOptions\n): string[] {\n const providers = matchAndGenerateProviders(config, options);\n const names = providers.map((provider) => {\n return provider.config.type;\n });\n return names;\n}\n", "import type { WidgetConfig } from './types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\nimport type { PropsWithChildren } from 'react';\n\nimport { I18nManager, styled } from '@rango-dev/ui';\nimport React, { useContext, useEffect, useMemo, useState } from 'react';\n\nimport { AppRouter } from './components/AppRouter';\nimport { AppRoutes } from './components/AppRoutes';\nimport { WidgetEvents } from './components/WidgetEvents';\nimport { globalFont } from './globalStyles';\nimport { useLanguage } from './hooks/useLanguage';\nimport { useTheme } from './hooks/useTheme';\nimport QueueManager from './QueueManager';\nimport { useAppStore } from './store/app';\nimport { useMetaStore } from './store/meta';\nimport { useNotificationStore } from './store/notification';\nimport { useSettingsStore } from './store/settings';\nimport { initConfig } from './utils/configs';\nimport { WidgetContext, WidgetWallets } from './Wallets';\n\nconst MainContainer = styled('div', {\n width: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n fontFamily: '$widget',\n boxSizing: 'border-box',\n '& *, *::before, *::after': {\n boxSizing: 'inherit',\n listStyleType: 'none',\n },\n '& *:focus-visible': {\n outlineColor: '$info500',\n transition: 'none',\n },\n});\n\nexport type WidgetProps = {\n config?: WidgetConfig;\n};\n\nexport function Main(props: PropsWithChildren<WidgetProps>) {\n const { config } = props;\n globalFont();\n\n const { activeTheme } = useTheme(config?.theme || {});\n const { activeLanguage, changeLanguage } = useLanguage();\n\n const [lastConnectedWalletWithNetwork, setLastConnectedWalletWithNetwork] =\n useState<string>('');\n const [disconnectedWallet, setDisconnectedWallet] = useState<WalletType>();\n const widgetContext = useContext(WidgetContext);\n const fetchMeta = useMetaStore.use.fetchMeta();\n\n useMemo(() => {\n if (config?.apiKey) {\n initConfig({\n API_KEY: config?.apiKey,\n });\n }\n }, [config]);\n\n useEffect(() => {\n void fetchMeta();\n void useSettingsStore.persist.rehydrate();\n void useNotificationStore.persist.rehydrate();\n widgetContext.onConnectWallet(setLastConnectedWalletWithNetwork);\n }, []);\n\n useEffect(() => {\n if (config?.language) {\n changeLanguage(config.language);\n }\n }, [config?.language]);\n\n return (\n <I18nManager language={activeLanguage}>\n <MainContainer id=\"swap-container\" className={activeTheme()}>\n <QueueManager>\n <WidgetEvents />\n <AppRouter\n config={config}\n lastConnectedWallet={lastConnectedWalletWithNetwork}\n disconnectedWallet={disconnectedWallet}\n clearDisconnectedWallet={() => {\n setDisconnectedWallet(undefined);\n }}>\n <AppRoutes config={config} />\n </AppRouter>\n </QueueManager>\n </MainContainer>\n </I18nManager>\n );\n}\n\nexport function Widget(props: PropsWithChildren<WidgetProps>) {\n const { updateConfig, config } = useAppStore();\n useEffect(() => {\n if (props.config) {\n updateConfig(props.config);\n }\n }, [props.config]);\n\n if (!props.config?.externalWallets) {\n return (\n <WidgetWallets\n providers={config?.wallets}\n options={{\n walletConnectProjectId:\n config?.walletConnectProjectId ||\n props.config?.walletConnectProjectId,\n }}>\n <Main {...props} />\n </WidgetWallets>\n );\n }\n return <Main {...props} />;\n}\n", "import type { WidgetConfig } from '../types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\nimport type { PropsWithChildren } from 'react';\n\nimport { useQueueManager } from '@rango-dev/queue-manager-rango-preset';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport { isEvmBlockchain } from 'rango-types';\nimport React, { useEffect, useRef } from 'react';\nimport { MemoryRouter, useInRouterContext } from 'react-router';\nimport { useLocation, useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { Home } from '../pages/Home';\nimport { useMetaStore } from '../store/meta';\n\nimport { UpdateUrl } from './UpdateUrl';\n\nfunction Route(props: PropsWithChildren) {\n const location = useLocation();\n const navigate = useNavigate();\n const firstRender = useRef(true);\n const paths = location.pathname.split('/');\n const pathMatched = paths[paths.length - 1] === navigationRoutes.confirmSwap;\n const shouldRedirectToMainPage = pathMatched && firstRender.current;\n\n useEffect(() => {\n if (shouldRedirectToMainPage) {\n navigate('.');\n }\n firstRender.current = false;\n }, []);\n\n if (shouldRedirectToMainPage) {\n return <Home />;\n }\n\n return <> {props.children}</>;\n}\n\nexport function AppRouter({\n children,\n ...props\n}: PropsWithChildren & {\n lastConnectedWallet: string;\n disconnectedWallet: WalletType | undefined;\n clearDisconnectedWallet: () => void;\n config: WidgetConfig | undefined;\n}) {\n const isRouterInContext = useInRouterContext();\n const Router = isRouterInContext ? Route : MemoryRouter;\n const { blockchains } = useMetaStore.use.meta();\n const { canSwitchNetworkTo } = useWallets();\n\n const evmChains = blockchains.filter(isEvmBlockchain);\n\n useQueueManager({\n lastConnectedWallet: props.lastConnectedWallet,\n clearDisconnectedWallet: props.clearDisconnectedWallet,\n disconnectedWallet: props.disconnectedWallet,\n evmChains,\n canSwitchNetworkTo,\n });\n\n return (\n <>\n <Router>{children}</Router>\n {isRouterInContext && <UpdateUrl config={props.config} />}\n </>\n );\n}\n", "export const navigationRoutes = {\n home: '/',\n fromSwap: 'from-swap',\n fromBlockchain: '/from-swap/blockchains',\n toBlockchain: '/to-swap/blockchains',\n toSwap: 'to-swap',\n settings: 'settings',\n liquiditySources: '/settings/liquidity-sources',\n themes: '/settings/themes',\n bridges: '/settings/bridges',\n exchanges: '/settings/exchanges',\n languages: '/settings/languages',\n swaps: 'swaps',\n wallets: 'wallets',\n confirmSwap: 'confirm-swap',\n swapDetails: 'swaps/:requestId',\n};\n", "import type { SwapResult } from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport {\n Alert,\n BestRoute,\n BestRouteSkeleton,\n Button,\n Divider,\n styled,\n SwapInput,\n Typography,\n WarningIcon,\n} from '@rango-dev/ui';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { HomeButtons } from '../components/HeaderButtons';\nimport { Layout } from '../components/Layout';\nimport { NoRoutes } from '../components/NoRoutes';\nimport { RouteErrors } from '../components/RouteErrors';\nimport { SwitchFromAndToButton } from '../components/SwitchFromAndTo';\nimport { errorMessages } from '../constants/errors';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport {\n BALANCE_MAX_DECIMALS,\n BALANCE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../constants/routing';\nimport { useSwapInput } from '../hooks/useSwapInput';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useUiStore } from '../store/ui';\nimport { useWalletsStore } from '../store/wallets';\nimport { ButtonState } from '../types';\nimport { getContainer } from '../utils/common';\nimport { getBlockchainShortNameFor } from '../utils/meta';\nimport {\n numberToString,\n secondsToString,\n totalArrivalTime,\n} from '../utils/numbers';\nimport { getFormattedBestRoute, getPriceImpactLevel } from '../utils/routing';\nimport {\n canComputePriceImpact,\n getOutputRatio,\n getPercentageChange,\n getSwapButtonState,\n getTotalFeeInUsd,\n hasLimitError,\n LimitErrorMessage,\n outputRatioHasWarning,\n} from '../utils/swap';\nimport { getBalanceFromWallet } from '../utils/wallets';\n\nconst Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n overflowY: 'visible',\n});\n\nconst FromContainer = styled('div', {\n position: 'relative',\n});\n\nconst InputsContainer = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n gap: 5,\n alignSelf: 'stretch',\n});\n\nconst BestRouteContainer = styled('div', {\n width: '100%',\n paddingTop: '$2',\n});\n\nconst FooterStepAlarm = styled('div', {\n paddingBottom: '$15',\n});\n\nconst FooterAlert = styled('div', {\n width: '100%',\n display: 'flex',\n});\n\nexport function Home() {\n const navigate = useNavigate();\n const {\n fetch: refetchBestRoute,\n loading: fetchingBestRoute,\n error: bestRouteError,\n } = useSwapInput();\n const {\n fromToken,\n fromBlockchain,\n toToken,\n toBlockchain,\n setInputAmount,\n inputAmount,\n inputUsdValue,\n outputAmount,\n outputUsdValue,\n bestRoute,\n resetRouteWallets,\n } = useBestRouteStore();\n\n const {\n meta: { tokens, blockchains },\n loadingStatus: loadingMetaStatus,\n } = useMetaStore();\n\n const connectedWallets = useWalletsStore.use.connectedWallets();\n const setCurrentPage = useUiStore.use.setCurrentPage();\n const [openWarningModal, setOpenWarningModal] = useState(false);\n const {\n fromAmountRangeError,\n swap: swapHasError,\n recommendation,\n } = LimitErrorMessage(bestRoute);\n const layoutRef = useRef<HTMLDivElement>(null);\n\n const showBestRoute =\n !!Number(inputAmount) &&\n (!!bestRoute || fetchingBestRoute || !!bestRouteError);\n\n const needsToWarnEthOnPath = false;\n\n const outToInRatio = getOutputRatio(inputUsdValue, outputUsdValue);\n const highValueLoss = outputRatioHasWarning(inputUsdValue, outToInRatio);\n\n const priceImpactInputCanNotBeComputed = !canComputePriceImpact(\n bestRoute,\n inputAmount,\n inputUsdValue\n );\n\n const priceImpactOutputCanNotBeComputed = !canComputePriceImpact(\n bestRoute,\n inputAmount,\n outputUsdValue\n );\n const swapButtonState = getSwapButtonState(\n loadingMetaStatus,\n connectedWallets,\n fetchingBestRoute,\n bestRoute,\n hasLimitError(bestRoute),\n highValueLoss,\n priceImpactInputCanNotBeComputed || priceImpactOutputCanNotBeComputed,\n needsToWarnEthOnPath,\n inputAmount\n );\n\n const tokenBalance =\n !!fromBlockchain && !!fromToken\n ? numberToString(\n getBalanceFromWallet(\n connectedWallets,\n fromBlockchain?.name,\n fromToken?.symbol,\n fromToken?.address\n )?.amount || '0',\n BALANCE_MIN_DECIMALS,\n BALANCE_MAX_DECIMALS\n )\n : '0';\n\n const tokenBalanceReal =\n !!fromBlockchain && !!fromToken\n ? numberToString(\n getBalanceFromWallet(\n connectedWallets,\n fromBlockchain?.name,\n fromToken?.symbol,\n fromToken?.address\n )?.amount || '0',\n getBalanceFromWallet(\n connectedWallets,\n fromBlockchain?.name,\n fromToken?.symbol,\n fromToken?.address\n )?.decimal\n )\n : '0';\n\n useEffect(() => {\n setCurrentPage(navigationRoutes.home);\n resetRouteWallets();\n return setCurrentPage.bind(null, '');\n }, []);\n\n const percentageChange =\n !inputUsdValue || !outputUsdValue || !outputUsdValue.gt(0)\n ? null\n : getPercentageChange(\n inputUsdValue.toNumber(),\n outputUsdValue.toNumber()\n );\n\n const getBestRouteSteps = (swaps: SwapResult[]) => {\n return swaps.map((swap, index) => ({\n swapper: { displayName: swap.swapperId, image: swap.swapperLogo },\n from: {\n token: { displayName: swap.from.symbol, image: swap.from.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.from.blockchain, blockchains) ?? '',\n image: swap.from.blockchainLogo,\n },\n price: {\n value:\n index === 0\n ? numberToString(\n inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n )\n : swap.fromAmount,\n },\n },\n to: {\n token: { displayName: swap.to.symbol, image: swap.to.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.to.blockchain, blockchains) ?? '',\n image: swap.to.blockchainLogo,\n },\n price: {\n value: swap.toAmount,\n },\n },\n alerts:\n swap.swapperId === swapHasError?.swapperId ? (\n <FooterStepAlarm>\n <Alert\n type=\"error\"\n title={recommendation}\n footer={\n <FooterAlert>\n <Typography size=\"xsmall\" variant=\"body\" color=\"neutral700\">\n {fromAmountRangeError}\n </Typography>\n <Divider direction=\"horizontal\" size={8} />\n <Typography size=\"xsmall\" variant=\"body\" color=\"neutral700\">\n |\n </Typography>\n <Divider direction=\"horizontal\" size={8} />\n <Typography size=\"xsmall\" variant=\"body\" color=\"neutral700\">\n {i18n.t({\n id: 'yourSymbol',\n message: 'Yours: {amount} {symbol}',\n values: {\n amount: numberToString(\n swapHasError?.fromAmount || null,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap?.from.symbol,\n },\n })}\n </Typography>\n </FooterAlert>\n }\n />\n </FooterStepAlarm>\n ) : undefined,\n }));\n };\n\n const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);\n\n const bestRouteData = getFormattedBestRoute(bestRoute);\n\n return (\n <Layout\n ref={layoutRef}\n fixedHeight={false}\n hasLogo\n footer={\n <Button\n type=\"primary\"\n size=\"large\"\n disabled={swapButtonState.disabled}\n prefix={\n !swapButtonState.disabled &&\n swapButtonState.hasWarning && <WarningIcon />\n }\n fullWidth\n onClick={() => {\n if (swapButtonState.state === ButtonState.WAITFORCONNECTING) {\n navigate(navigationRoutes.wallets);\n } else if (swapButtonState.state === ButtonState.NEEDTOCONFIRM) {\n setOpenWarningModal(true);\n } else {\n navigate(navigationRoutes.confirmSwap);\n }\n }}>\n {swapButtonState.title}\n </Button>\n }\n header={{\n hasConnectWallet: true,\n title: i18n.t('Swap'),\n suffix: (\n <HomeButtons\n layoutRef={layoutRef.current}\n onClickRefresh={\n !!bestRoute || bestRouteError ? refetchBestRoute : undefined\n }\n onClickHistory={() => navigate(navigationRoutes.swaps)}\n onClickSettings={() => navigate(navigationRoutes.settings)}\n />\n ),\n }}>\n <Container>\n <InputsContainer>\n <FromContainer>\n <SwapInput\n label={i18n.t('From')}\n mode=\"From\"\n onInputChange={setInputAmount}\n balance={tokenBalance}\n chain={{\n displayName: fromBlockchain?.displayName || '',\n image: fromBlockchain?.logo || '',\n }}\n token={{\n displayName: fromToken?.symbol || '',\n image: fromToken?.image || '',\n }}\n onClickToken={() => navigate('from-swap')}\n price={{\n value: inputAmount,\n usdValue: priceImpactInputCanNotBeComputed\n ? undefined\n : numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n error: priceImpactInputCanNotBeComputed\n ? errorMessages().unknownPriceError.impactTitle\n : undefined,\n }}\n disabled={loadingMetaStatus === 'failed'}\n loading={loadingMetaStatus === 'loading'}\n onSelectMaxBalance={() => {\n if (tokenBalance !== '0') {\n setInputAmount(tokenBalanceReal.split(',').join(''));\n }\n }}\n />\n <SwitchFromAndToButton />\n </FromContainer>\n <SwapInput\n sharpBottomStyle={!!bestRoute?.result || fetchingBestRoute}\n label={i18n.t('To')}\n mode=\"To\"\n chain={{\n displayName: toBlockchain?.displayName || '',\n image: toBlockchain?.logo || '',\n }}\n token={{\n displayName: toToken?.symbol || '',\n image: toToken?.image || '',\n }}\n percentageChange={\n !!percentageChange?.lt(0)\n ? numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )\n : null\n }\n warningLevel={getPriceImpactLevel(\n percentageChange?.toNumber() ?? 0\n )}\n price={{\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: priceImpactOutputCanNotBeComputed\n ? undefined\n : numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n error: priceImpactOutputCanNotBeComputed\n ? errorMessages().unknownPriceError.impactTitle\n : undefined,\n }}\n onClickToken={() => navigate('to-swap')}\n disabled={loadingMetaStatus === 'failed'}\n loading={loadingMetaStatus === 'loading'}\n />\n </InputsContainer>\n {fetchingBestRoute && (\n <BestRouteContainer>\n <BestRouteSkeleton type=\"basic\" />\n </BestRouteContainer>\n )}\n {showBestRoute &&\n !fetchingBestRoute &&\n bestRouteData?.result?.swaps?.length ? (\n <BestRouteContainer>\n <BestRoute\n type=\"basic\"\n recommended={true}\n tooltipContainer={getContainer()}\n input={{\n value: numberToString(\n inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n output={{\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n steps={getBestRouteSteps(bestRouteData.result.swaps)}\n percentageChange={numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )}\n totalFee={numberToString(\n totalFeeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n )}\n totalTime={secondsToString(\n totalArrivalTime(bestRoute?.result?.swaps)\n )}\n />\n </BestRouteContainer>\n ) : showBestRoute && !fetchingBestRoute ? (\n <>\n <Divider size={20} />\n <NoRoutes\n diagnosisMessage={bestRouteData?.diagnosisMessages?.[0]}\n fetch={refetchBestRoute}\n error={!!bestRouteError}\n />\n </>\n ) : null}\n </Container>\n <RouteErrors\n openModal={openWarningModal}\n onToggle={setOpenWarningModal}\n totalFeeInUsd={totalFeeInUsd}\n outputUsdValue={outputUsdValue}\n inputUsdValue={inputUsdValue}\n percentageChange={percentageChange}\n highValueLoss={highValueLoss}\n priceImpactCanNotBeComputed={\n priceImpactInputCanNotBeComputed || priceImpactOutputCanNotBeComputed\n }\n loading={fetchingBestRoute || loadingMetaStatus === 'loading'}\n extraSpace={!!bestRoute?.result || !bestRoute}\n />\n </Layout>\n );\n}\n", "import type { PropTypes } from './HeaderButtons.types';\n\nimport { ChevronLeftIcon } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { HeaderButton } from './HeaderButtons.styles';\n\nfunction BackButton(props: PropTypes) {\n return (\n <HeaderButton variant=\"ghost\" size=\"small\" onClick={props.onClick}>\n <ChevronLeftIcon color=\"black\" size={16} />\n </HeaderButton>\n );\n}\n\nexport { BackButton };\n", "import { darkTheme, IconButton, styled } from '@rango-dev/ui';\n\nexport const HeaderButton = styled(IconButton, {\n width: '$24',\n position: 'relative',\n padding: '0',\n overflow: 'unset',\n});\n\nexport const ConnectedIcon = styled('div', {\n position: 'absolute',\n background: '$secondary500',\n [`.${darkTheme} &`]: {\n $$color: '$colors$secondary400',\n },\n width: '$6',\n height: '$6',\n borderRadius: '$lg',\n right: '$4',\n border: '1px solid $surface100',\n});\n\nexport const SuffixContainer = styled('div', {\n display: 'flex',\n justifyContent: 'flex-end',\n width: '$40',\n});\n\nexport const NotificationsBadgeContainer = styled('div', {\n position: 'absolute',\n backgroundColor: '$secondary500',\n width: '14px',\n height: '14px',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n borderRadius: '7px',\n top: '$0',\n right: '$0',\n});\n", "import type { PropTypes } from './HeaderButtons.types';\n\nimport { i18n } from '@lingui/core';\nimport { Button, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { SuffixContainer } from './HeaderButtons.styles';\n\nfunction CancelButton(props: PropTypes) {\n return (\n <SuffixContainer>\n <Button variant=\"ghost\" onClick={props.onClick} size=\"xsmall\">\n <Typography variant=\"label\" size=\"medium\" color=\"error500\">\n {i18n.t('Cancel')}\n </Typography>\n </Button>\n </SuffixContainer>\n );\n}\n\nexport { CancelButton };\n", "import type { PropTypes } from './HeaderButtons.types';\n\nimport { i18n } from '@lingui/core';\nimport { Tooltip, WalletIcon } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { ConnectedIcon, HeaderButton } from './HeaderButtons.styles';\n\nfunction WalletButton(props: PropTypes) {\n return (\n <Tooltip\n container={props.container}\n side=\"top\"\n content={i18n.t('Connect Wallet')}>\n <HeaderButton variant=\"ghost\" size=\"small\" onClick={props.onClick}>\n {props.isConnected && <ConnectedIcon />}\n <WalletIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n );\n}\n\nexport { WalletButton };\n", "import type { HomeButtonsPropTypes } from './HeaderButtons.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n NotificationsIcon,\n Popover,\n RefreshIcon,\n SettingsIcon,\n Tooltip,\n TransactionIcon,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { getContainer } from '../../utils/common';\nimport { NotificationContent } from '../NotificationContent';\n\nimport { HeaderButton } from './HeaderButtons.styles';\nimport { UnreadNotificationsBadge } from './UnreadNotificationsBadge';\n\nexport function HomeButtons(props: HomeButtonsPropTypes) {\n const {\n layoutRef,\n onClickRefresh,\n onClickHistory,\n onClickSettings,\n onClickNotifications,\n } = props;\n\n return (\n <>\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Refresh')}>\n <HeaderButton\n variant=\"ghost\"\n size=\"small\"\n onClick={onClickRefresh}\n disabled={!onClickRefresh}>\n <RefreshIcon size={16} color={!onClickRefresh ? 'gray' : 'black'} />\n </HeaderButton>\n </Tooltip>\n\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Notifications')}>\n <Popover\n align=\"center\"\n collisionBoundary={layoutRef}\n collisionPadding={{ right: 20, left: 20 }}\n container={getContainer()}\n content={<NotificationContent />}>\n <HeaderButton\n size=\"small\"\n variant=\"ghost\"\n onClick={onClickNotifications}>\n <NotificationsIcon size={18} color=\"black\" />\n <UnreadNotificationsBadge />\n </HeaderButton>\n </Popover>\n </Tooltip>\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Settings')}>\n <HeaderButton size=\"small\" variant=\"ghost\" onClick={onClickSettings}>\n <SettingsIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={i18n.t('Transactions History')}>\n <HeaderButton size=\"small\" variant=\"ghost\" onClick={onClickHistory}>\n <TransactionIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n </>\n );\n}\n", "import type { Notification } from '../../types/notification';\n\nimport { i18n } from '@lingui/core';\nimport {\n ChainToken,\n ChevronRightIcon,\n ListItemButton,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { useMetaStore } from '../../store/meta';\nimport { useNotificationStore } from '../../store/notification';\nimport { useUiStore } from '../../store/ui';\n\nimport { Container, Images, List } from './NotificationContent.styles';\nimport { NotificationNotFound } from './NotificationNotFound';\n\nconst MAX_NOTIFICATIONS_DISPLAYED = 4;\n\nexport function NotificationContent() {\n const navigate = useNavigate();\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n\n const { getUnreadNotifications } = useNotificationStore();\n\n const notifications: Notification[] = getUnreadNotifications();\n const { tokens, blockchains } = useMetaStore.use.meta();\n const sortedNotification = notifications\n .sort((a, b) => b.creationTime - a.creationTime)\n .slice(0, MAX_NOTIFICATIONS_DISPLAYED);\n\n const handleOnClick = (requestId: Notification['requestId']) => {\n setSelectedSwap(requestId);\n navigate(`/swaps/${requestId}`);\n };\n\n return (\n <Container>\n {sortedNotification.length ? (\n <List>\n {sortedNotification.map((notificationItem) => {\n const fromToken = tokens.find(\n (tokenItem) =>\n tokenItem.address ===\n notificationItem.route.from.tokenAddress &&\n tokenItem.blockchain ===\n notificationItem.route.from.blockchain &&\n tokenItem.symbol === notificationItem.route.from.tokenSymbol\n );\n\n const fromBlockchain = blockchains.find(\n (blockchainItem) =>\n blockchainItem.name === notificationItem.route.from.blockchain\n );\n\n const toToken = tokens.find(\n (tokenItem) =>\n tokenItem.address === notificationItem.route.to.tokenAddress &&\n tokenItem.blockchain === notificationItem.route.to.blockchain &&\n tokenItem.symbol === notificationItem.route.to.tokenSymbol\n );\n\n const toBlockchain = blockchains.find(\n (blockchainItem) =>\n blockchainItem.name === notificationItem.route.to.blockchain\n );\n\n return (\n <ListItemButton\n key={notificationItem.requestId}\n onClick={() => handleOnClick(notificationItem.requestId)}\n title={\n <Typography variant=\"body\" size=\"small\" color=\"$neutral700\">\n {i18n.t(notificationItem.event.message)}\n </Typography>\n }\n id={notificationItem.requestId}\n start={\n <Images>\n <div className=\"from-chain-token\">\n <ChainToken\n tokenImage={fromToken ? fromToken.image : ''}\n chainImage={fromBlockchain ? fromBlockchain.logo : ''}\n size=\"small\"\n />\n </div>\n <div className=\"to-chain-token\">\n <ChainToken\n tokenImage={toToken ? toToken.image : ''}\n chainImage={toBlockchain ? toBlockchain.logo : ''}\n size=\"small\"\n />\n </div>\n </Images>\n }\n end={<ChevronRightIcon size={12} color=\"gray\" />}\n />\n );\n })}\n </List>\n ) : (\n <NotificationNotFound />\n )}\n </Container>\n );\n}\n", "import type { Notification } from '../types/notification';\nimport type {\n Route,\n RouteEvent,\n StepEvent,\n} from '@rango-dev/queue-manager-rango-preset';\n\nimport { create } from 'zustand';\nimport { persist, subscribeWithSelector } from 'zustand/middleware';\n\nimport createSelectors from './selectors';\n\nexport interface NotificationState {\n notifications: Notification[];\n setNotification: (event: RouteEvent | StepEvent, route: Route) => void;\n setAsRead: (requestId: Notification['requestId']) => void;\n getUnreadNotifications: () => Notification[];\n}\n\nexport const useNotificationStore = createSelectors(\n create<NotificationState>()(\n persist(\n subscribeWithSelector((set, get) => ({\n notifications: [],\n setNotification: (event, route) => {\n const fromStep = route.steps[0];\n const toStep = route.steps[route.steps.length - 1];\n\n const notification: Notification = {\n event,\n creationTime: Date.now(),\n read: false,\n requestId: route.requestId,\n route: {\n from: {\n blockchain: fromStep.fromBlockchain,\n tokenAddress: fromStep.fromSymbolAddress,\n tokenSymbol: fromStep.fromSymbol,\n },\n to: {\n blockchain: toStep.toBlockchain,\n tokenSymbol: toStep.toSymbol,\n tokenAddress: toStep.toSymbolAddress,\n },\n },\n };\n\n const excludedList = get().notifications.filter(\n (notificationItem) => notificationItem.requestId !== route.requestId\n );\n\n set(() => ({\n notifications: [...excludedList, notification],\n }));\n },\n setAsRead: (requestId) => {\n set((state) => ({\n notifications: state.notifications.map((notificationItem) =>\n notificationItem.requestId === requestId\n ? { ...notificationItem, read: true }\n : notificationItem\n ),\n }));\n },\n getUnreadNotifications: () => {\n return get().notifications.filter(\n (notificationItem) => !notificationItem.read\n );\n },\n })),\n {\n name: 'notification',\n skipHydration: true,\n }\n )\n )\n);\n", "import { create } from 'zustand';\n\nimport createSelectors from './selectors';\n\ninterface UiState {\n connectWalletsButtonDisabled: boolean;\n selectedSwapRequestId: string | null;\n currentPage: string;\n setSelectedSwap: (requestId: string | null) => void;\n setCurrentPage: (path: string) => void;\n}\n\nexport const useUiStore = createSelectors(\n create<UiState>()((set) => ({\n connectWalletsButtonDisabled: false,\n selectedSwapRequestId: null,\n currentPage: '',\n setSelectedSwap: (requestId) => set({ selectedSwapRequestId: requestId }),\n setCurrentPage: (path) => set({ currentPage: path }),\n }))\n);\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n padding: '$10',\n width: '350px',\n minHeight: '150px',\n});\n\nexport const List = styled('ul', {\n padding: 0,\n margin: 0,\n listStyle: 'none',\n\n '.to-chain-token': {\n transform: 'translateX(-3px)',\n },\n});\n\nexport const Images = styled('div', {\n display: 'flex',\n padding: 0,\n alignItems: 'center',\n alignSelf: 'stretch',\n});\n\nexport const NotFoundContainer = styled('div', {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n flexDirection: 'column',\n padding: '$10',\n width: '100%',\n height: '150px',\n});\n", "import { i18n } from '@lingui/core';\nimport { Divider, NoNotificationIcon, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { NotFoundContainer } from './NotificationContent.styles';\n\nexport function NotificationNotFound() {\n return (\n <NotFoundContainer>\n <NoNotificationIcon color=\"secondary\" size={26} />\n <Divider size={12} />\n <Typography variant=\"body\" size=\"medium\" color=\"neutral700\">\n {i18n.t('You have no notification')}\n </Typography>\n </NotFoundContainer>\n );\n}\n", "import { Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { useNotificationStore } from '../../store/notification';\n\nimport { NotificationsBadgeContainer } from './HeaderButtons.styles';\n\nexport function UnreadNotificationsBadge() {\n const { getUnreadNotifications } = useNotificationStore();\n\n const notificationsCount = getUnreadNotifications().length;\n\n return notificationsCount ? (\n <NotificationsBadgeContainer>\n <Typography variant=\"body\" size=\"xsmall\" color=\"$background\">\n {notificationsCount}\n </Typography>\n </NotificationsBadgeContainer>\n ) : null;\n}\n", "import type { PropTypes, Ref } from './Layout.types';\nimport type { PropsWithChildren } from 'react';\n\nimport { BottomLogo, Divider, Header } from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport { useUiStore } from '../../store/ui';\nimport { useWalletsStore } from '../../store/wallets';\nimport { getContainer } from '../../utils/common';\nimport { BackButton, CancelButton, WalletButton } from '../HeaderButtons';\n\nimport { Container, Content, Footer } from './Layout.styles';\n\nfunction LayoutComponent(props: PropsWithChildren<PropTypes>, ref: Ref) {\n const {\n children,\n header,\n footer,\n noPadding,\n hasLogo = true,\n fixedHeight = true,\n } = props;\n const connectedWallets = useWalletsStore.use.connectedWallets();\n\n const connectWalletsButtonDisabled =\n useUiStore.use.connectWalletsButtonDisabled();\n const navigate = useNavigate();\n\n const onConnectWallet = () => {\n if (!connectWalletsButtonDisabled) {\n navigate('/' + navigationRoutes.wallets);\n }\n };\n return (\n <Container ref={ref} fixedHeight={fixedHeight} id=\"swap-box\">\n <Header\n prefix={<>{header.onBack && <BackButton onClick={header.onBack} />}</>}\n title={header.title}\n suffix={\n <>\n {header.suffix}\n {header.hasConnectWallet && (\n <WalletButton\n container={getContainer()}\n onClick={onConnectWallet}\n isConnected={!!connectedWallets?.length}\n />\n )}\n {header.onCancel && <CancelButton onClick={header.onCancel} />}\n </>\n }\n />\n <Content noPadding={noPadding}>{children}</Content>\n {(hasLogo || footer) && (\n <Footer>\n <div className=\"footer__content\">{footer}</div>\n {hasLogo && (\n <div className=\"footer__logo\">\n <Divider size={12} />\n <BottomLogo />\n </div>\n )}\n </Footer>\n )}\n </Container>\n );\n}\n\nconst Layout = React.forwardRef(LayoutComponent);\nLayout.displayName = 'Layout';\n\nexport { Layout };\n", "import { darkTheme, styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n position: 'relative',\n display: 'flex',\n flexDirection: 'column',\n borderRadius: '$primary',\n overflow: 'hidden !important',\n boxShadow: '15px 15px 15px 0px rgba(0, 0, 0, 0.05)',\n width: '95vw',\n maxWidth: '390px',\n maxHeight: '700px',\n $$color: '$colors$neutral100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral300',\n },\n backgroundColor: '$$color',\n variants: {\n fixedHeight: {\n true: {\n height: '95vh',\n },\n false: {\n height: 'auto',\n },\n },\n },\n});\n\nexport const Content = styled('div', {\n borderTopLeftRadius: '20px',\n borderTopRightRadius: '20px',\n display: 'flex',\n flexDirection: 'column',\n flex: 1,\n padding: '$20 $20 $10 $20',\n backgroundColor: '$background',\n position: 'relative',\n overflowY: 'auto',\n overflowX: 'hidden',\n variants: {\n noPadding: {\n true: {\n padding: '0',\n },\n },\n },\n});\n\nexport const Footer = styled('div', {\n backgroundColor: '$background',\n '& .footer__content': {\n padding: '$0 $20',\n },\n '& .footer__logo': {\n padding: '$0 $20 $10 $20',\n },\n});\n", "import type { PropTypes } from './NoRoutes.types';\n\nimport {\n Alert,\n Button,\n Divider,\n NoRouteIcon,\n RefreshIcon,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { errorMessages } from '../../constants/errors';\nimport { useMetaStore } from '../../store/meta';\nimport { useSettingsStore } from '../../store/settings';\n\nimport { makeInfo } from './NoRoutes.helper';\nimport { Container, Footer, PrefixIcon } from './NoRoutes.styles';\n\nexport function NoRoutes(props: PropTypes) {\n const { diagnosisMessage, fetch, error } = props;\n const disabledLiquiditySources =\n useSettingsStore.use.disabledLiquiditySources();\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n const toggleAllLiquiditySources =\n useSettingsStore.use.toggleAllLiquiditySources();\n\n const hasError = error || loadingMetaStatus === 'failed';\n\n const info = makeInfo(\n diagnosisMessage ?? null,\n disabledLiquiditySources,\n hasError,\n toggleAllLiquiditySources,\n fetch\n );\n\n return (\n <Container>\n <NoRouteIcon size={24} color=\"gray\" />\n <Divider size={4} />\n <Typography variant=\"title\" size=\"small\">\n {errorMessages().noRoutesError.title}\n </Typography>\n {!!info.description && (\n <Typography\n variant=\"body\"\n size=\"small\"\n align=\"center\"\n color=\"neutral700\">\n {info.description}\n </Typography>\n )}\n <Divider size={4} />\n {!!info.alert && (\n <Footer>\n <Alert\n type={info.alert.type}\n title={info.alert.text}\n action={\n info.alert.action && (\n <Button\n size=\"xsmall\"\n type={info.alert.type}\n prefix={\n <PrefixIcon>\n <RefreshIcon size={8} />\n </PrefixIcon>\n }\n onClick={info.alert.action.onClick}>\n {info.alert.action.title}\n </Button>\n )\n }\n variant=\"alarm\"\n />\n </Footer>\n )}\n </Container>\n );\n}\n", "import type { ConfirmSwapError } from '../types';\n\nimport { i18n } from '@lingui/core';\n\nimport { ConfirmSwapErrorTypes } from '../types';\n\nexport const errorMessages = () => {\n return {\n genericServerError: i18n.t('Failed Network, Please retry your swap.'),\n liquiditySourcesError: {\n title: i18n.t('Please reset your liquidity sources.'),\n description: i18n.t(\n 'You have limited the liquidity sources and this might result in Rango finding no routes. Please consider resetting your liquidity sources'\n ),\n },\n noRoutesError: {\n title: i18n.t('No Routes Found'),\n description:\n \"Reasons why Rango couldn't find a route: low liquidity on token, very low input amount or no routes available for the selected input/output token combination.\",\n },\n bridgeLimitErrors: {\n increaseAmount: i18n.t('Bridge Limit Error: Please increase your amount'),\n decreaseAmount: i18n.t('Bridge Limit Error: Please decrease your amount'),\n },\n highValueLossError: {\n impactTitle: i18n.t('High Price Impact'),\n title: i18n.t('Price impact is too high!'),\n description: i18n.t(\n 'The price impact is significantly higher than the allowed amount. If you are sure, continue, otherwise, change the swap.'\n ),\n confirmMessage: i18n.t('Confirm High price impact'),\n },\n routeUpdatedWithHighValueLoss: {\n title: i18n.t(\n 'Route updated and price impact is too high, try again later!'\n ),\n },\n unknownPriceError: {\n impactTitle: i18n.t('USD Price Unknown'),\n title: i18n.t('USD Price Unknown, Cannot calculate Price Impact.'),\n description: i18n.t(\n 'USD Price Unknown, Cannot calculate Price Impact. The price impact may be higher than usual. Are you sure to continue the Swap?'\n ),\n confirmMessage: i18n.t('Confirm USD Price Unknown'),\n },\n };\n};\n\nexport function getConfirmSwapErrorMessage(error: ConfirmSwapError) {\n switch (error.type) {\n case ConfirmSwapErrorTypes.NO_ROUTE:\n return error.diagnosisMessage ?? errorMessages().noRoutesError.title;\n case ConfirmSwapErrorTypes.REQUEST_FAILED:\n return errorMessages().genericServerError;\n case ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS:\n return errorMessages().routeUpdatedWithHighValueLoss.title;\n default:\n return '';\n }\n}\n", "/* eslint-disable @typescript-eslint/prefer-enum-initializers */\nimport type { RouteState } from '../store/bestRoute';\nimport type { SettingsState } from '../store/settings';\n\ninterface BestRouteStoreParams {\n fromBlockchain?: RouteState['fromBlockchain'];\n toBlockchain?: RouteState['toBlockchain'];\n fromToken?: RouteState['fromToken'];\n toToken?: RouteState['toToken'];\n inputAmount?: RouteState['inputAmount'];\n}\n\ninterface SettingsStoreParams {\n slippage?: SettingsState['slippage'];\n customSlippage?: SettingsState['customSlippage'];\n disabledLiquiditySources?: SettingsState['disabledLiquiditySources'];\n infiniteApprove?: SettingsState['infiniteApprove'];\n}\n\nexport type BestRouteEqualityParams =\n | {\n store: 'bestRoute';\n prevState: BestRouteStoreParams;\n currentState: BestRouteStoreParams;\n }\n | {\n store: 'settings';\n prevState: SettingsStoreParams;\n currentState: SettingsStoreParams;\n };\n\nexport enum ConfirmSwapErrorTypes {\n NO_ROUTE,\n ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,\n REQUEST_FAILED,\n REQUEST_CANCELED,\n}\n\nexport type ConfirmSwapError =\n | {\n type: ConfirmSwapErrorTypes.NO_ROUTE;\n diagnosisMessage?: string;\n }\n | {\n type: Exclude<ConfirmSwapErrorTypes, ConfirmSwapErrorTypes.NO_ROUTE>;\n };\n\nexport enum RouteWarningType {\n ROUTE_UPDATED,\n ROUTE_SWAPPERS_UPDATED,\n ROUTE_COINS_UPDATED,\n ROUTE_AND_OUTPUT_AMOUNT_UPDATED,\n}\n\nexport type RouteWarning =\n | {\n type: RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED;\n newOutputAmount: string;\n percentageChange: string;\n }\n | {\n type: Exclude<\n RouteWarningType,\n RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED\n >;\n };\n\nexport enum SlippageWarningType {\n INSUFFICIENT_SLIPPAGE,\n HIGH_SLIPPAGE,\n}\n\nexport type ConfirmSwapWarnings = {\n route: RouteWarning | null;\n balance: { messages: string[] } | null;\n slippage: { type: SlippageWarningType; slippage: string | null } | null;\n};\n", "import { type Language } from '@rango-dev/ui';\nimport { create } from 'zustand';\nimport { persist, subscribeWithSelector } from 'zustand/middleware';\n\nimport { BLOCKCHAIN_LIST_SIZE } from '../constants/configs';\nimport { DEFAULT_LANGUAGE } from '../constants/languages';\nimport { DEFAULT_SLIPPAGE } from '../constants/swapSettings';\nimport { removeDuplicateFrom } from '../utils/common';\n\nimport { useMetaStore } from './meta';\nimport createSelectors from './selectors';\n\nexport type ThemeMode = 'auto' | 'dark' | 'light';\n\nexport interface SettingsState {\n /** Keeping a history of blockchains that user has selected (in Swap process) */\n preferredBlockchains: string[];\n slippage: number;\n customSlippage: number | null;\n infiniteApprove: boolean;\n disabledLiquiditySources: string[];\n theme: ThemeMode;\n language: Language;\n affiliateRef: string | null;\n affiliatePercent: number | null;\n affiliateWallets: { [key: string]: string } | null;\n\n setSlippage: (slippage: number) => void;\n setCustomSlippage: (customSlippage: number | null) => void;\n toggleInfiniteApprove: () => void;\n toggleLiquiditySource: (name: string) => void;\n setTheme: (theme: ThemeMode) => void;\n setLanguage: (language: Language) => void;\n toggleAllLiquiditySources: (shouldReset?: boolean) => void;\n setAffiliateRef: (affiliateRef: string | null) => void;\n setAffiliatePercent: (affiliatePercent: number | null) => void;\n setAffiliateWallets: (\n affiliateWallets: { [key: string]: string } | null\n ) => void;\n addPreferredBlockchain: (blockchain: string) => void;\n}\n\nexport const useSettingsStore = createSelectors(\n create<SettingsState>()(\n persist(\n subscribeWithSelector((set, get) => ({\n preferredBlockchains: [],\n slippage: DEFAULT_SLIPPAGE,\n customSlippage: null,\n infiniteApprove: false,\n affiliateRef: null,\n affiliatePercent: null,\n affiliateWallets: null,\n disabledLiquiditySources: [],\n theme: 'auto',\n language: DEFAULT_LANGUAGE,\n addPreferredBlockchain: (blockchain) => {\n const currentPreferredBlockchains = get().preferredBlockchains;\n\n const noNeedToDoAnything = currentPreferredBlockchains.find(\n (preferredBlockchain, index) => {\n const isSameBlockchain = preferredBlockchain === blockchain;\n const isInVisibleList = index <= BLOCKCHAIN_LIST_SIZE - 1;\n\n return isSameBlockchain && isInVisibleList;\n }\n );\n\n if (noNeedToDoAnything) {\n return;\n }\n\n const nextPreferredBlockchains: string[] =\n currentPreferredBlockchains.filter((preferredBlockchain) => {\n const isSameBlockchain = preferredBlockchain === blockchain;\n\n return !isSameBlockchain;\n });\n\n set(() => ({\n preferredBlockchains: [blockchain, ...nextPreferredBlockchains],\n }));\n },\n setSlippage: (slippage) =>\n set(() => ({\n slippage: slippage,\n })),\n setCustomSlippage: (customSlippage) =>\n set(() => ({\n customSlippage: customSlippage,\n })),\n setAffiliateRef: (affiliateRef) =>\n set(() => ({\n affiliateRef,\n })),\n setAffiliatePercent: (affiliatePercent) =>\n set(() => ({\n affiliatePercent,\n })),\n\n setAffiliateWallets: (affiliateWallets) =>\n set(() => ({\n affiliateWallets,\n })),\n toggleAllLiquiditySources: (shouldReset?: boolean) =>\n set((state) => {\n if (shouldReset) {\n return { disabledLiquiditySources: [] };\n }\n const { swappers } = useMetaStore.getState().meta;\n const swappersGroup = removeDuplicateFrom(\n swappers.map((swapper) => swapper.swapperGroup)\n );\n\n if (\n swappersGroup.length === state.disabledLiquiditySources.length\n ) {\n return { disabledLiquiditySources: [] };\n }\n\n return {\n disabledLiquiditySources: swappersGroup,\n };\n }),\n toggleInfiniteApprove: () =>\n set((state) => ({\n infiniteApprove: !state.infiniteApprove,\n })),\n toggleLiquiditySource: (name) =>\n set((state) => {\n if (state.disabledLiquiditySources.includes(name)) {\n return {\n disabledLiquiditySources: state.disabledLiquiditySources.filter(\n (liquiditySource) => liquiditySource != name\n ),\n };\n }\n return {\n disabledLiquiditySources:\n state.disabledLiquiditySources.concat(name),\n };\n }),\n setTheme: (theme) =>\n set(() => ({\n theme,\n })),\n setLanguage: (language) =>\n set(() => ({\n language,\n })),\n })),\n {\n name: 'user-settings',\n skipHydration: true,\n }\n )\n )\n);\n", "import type { FlagPropTypes, Language } from '@rango-dev/ui';\n\nimport { English, French, Japanese, Spanish } from '@rango-dev/ui';\n\nexport type LanguageItem = {\n title: string;\n label: string;\n local: Language;\n SVGFlag: React.ComponentType<FlagPropTypes>;\n};\n\nexport const LANGUAGES: LanguageItem[] = [\n { title: 'English', label: 'English', local: 'en', SVGFlag: English },\n { title: 'Spanish', label: 'Espa\u00F1ol', local: 'es', SVGFlag: Spanish },\n { title: 'French', label: 'Fran\u00E7ais', local: 'fr', SVGFlag: French },\n { title: 'Japanese', label: '\u65E5\u672C\u8A9E', local: 'ja', SVGFlag: Japanese },\n];\n\nexport const DEFAULT_LANGUAGE = 'en';\n", "const LOW = 0.5;\nconst MEDIUM = 1;\nconst HIGH = 3;\n\nexport const SLIPPAGES = [LOW, MEDIUM, HIGH];\n\nexport const DEFAULT_SLIPPAGE = 1;\n\nexport const HIGH_SLIPPAGE = 5;\n\nexport const MAX_SLIPPAGE = 100;\n\nexport const MIN_SLIPPGAE = 0;\n", "import type { Info } from './NoRoutes.types';\n\nimport { i18n } from '@lingui/core';\n\nimport { errorMessages } from '../../constants/errors';\n\nexport function makeInfo(\n diagnosisMessage: string | null,\n disabledLiquiditySources: string[],\n hasError: boolean,\n toggleAllLiquiditySources: (shouldReset: boolean) => void,\n refetchBestRoute: () => void\n): Info {\n if (hasError) {\n return {\n alert: {\n type: 'warning',\n text: errorMessages().genericServerError,\n action: {\n onClick: refetchBestRoute,\n title: i18n.t('Retry'),\n },\n },\n description: '',\n };\n } else if (diagnosisMessage) {\n return {\n alert: {\n type: 'error',\n text: diagnosisMessage,\n action: null,\n },\n description: '',\n };\n } else if (disabledLiquiditySources.length) {\n return {\n alert: {\n type: 'warning',\n text: errorMessages().liquiditySourcesError.title,\n action: {\n onClick: () => toggleAllLiquiditySources(true),\n title: i18n.t('Reset'),\n },\n },\n description: errorMessages().liquiditySourcesError.description,\n };\n }\n return {\n alert: null,\n description: errorMessages().noRoutesError.description,\n };\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n});\n\nexport const Footer = styled('div', {\n width: '100%',\n});\n\nexport const PrefixIcon = styled('div', {\n padding: '$6 $0',\n});\n", "import type { PropTypes } from './RouteErrors.types';\n\nimport { Alert, Divider, InfoIcon } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { errorMessages } from '../../constants/errors';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { hasLimitError, LimitErrorMessage } from '../../utils/swap';\n\nimport { Action, Alerts } from './RouteErrors.styles';\nimport { RouteErrorsModal } from './RouteErrorsModal';\n\nconst WARNING_LEVEL_LIMIT = -10;\n\nexport function RouteErrors(props: PropTypes) {\n const { bestRoute } = useBestRouteStore();\n const {\n highValueLoss,\n percentageChange,\n priceImpactCanNotBeComputed,\n openModal,\n onToggle,\n totalFeeInUsd,\n outputUsdValue,\n inputUsdValue,\n loading,\n extraSpace,\n } = props;\n const error = hasLimitError(bestRoute);\n const { recommendation } = LimitErrorMessage(bestRoute);\n\n const showWarnings = !error && (highValueLoss || priceImpactCanNotBeComputed);\n const showAlerts = showWarnings || error;\n\n return (\n <>\n {(loading || (extraSpace && !showAlerts)) && <Divider size={20} />}\n {showAlerts && (\n <Alerts>\n {showWarnings && (\n <>\n <Alert\n title={\n highValueLoss\n ? errorMessages().highValueLossError.title\n : errorMessages().unknownPriceError.title\n }\n type={\n highValueLoss && !!percentageChange?.lt(WARNING_LEVEL_LIMIT)\n ? 'error'\n : 'warning'\n }\n variant=\"alarm\"\n action={\n <Action onClick={() => onToggle(true)}>\n <InfoIcon size={12} color=\"gray\" />\n </Action>\n }\n />\n </>\n )}\n {error && (\n <Alert type=\"error\" variant=\"alarm\" title={recommendation} />\n )}\n </Alerts>\n )}\n\n <RouteErrorsModal\n highValueLoss={highValueLoss}\n open={openModal}\n onToggle={onToggle}\n percentageChange={percentageChange}\n inputUsdValue={inputUsdValue}\n outputUsdValue={outputUsdValue}\n totalFeeInUsd={totalFeeInUsd}\n />\n </>\n );\n}\n", "import type { TokenWithBalance } from '../components/TokenList';\nimport type { Wallet } from '../types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset/dist/shared';\nimport type { BestRouteResponse, BlockchainMeta, Token } from 'rango-sdk';\n\nimport BigNumber from 'bignumber.js';\nimport { create } from 'zustand';\nimport { subscribeWithSelector } from 'zustand/middleware';\n\nimport { ZERO } from '../constants/numbers';\nimport { isPositiveNumber } from '../utils/numbers';\nimport {\n createRetryRoute,\n getBestRouteToTokenUsdPrice,\n} from '../utils/routing';\nimport { calcOutputUsdValue } from '../utils/swap';\n\nimport { useMetaStore } from './meta';\nimport createSelectors from './selectors';\n\nconst getUsdValue = (token: Token | null, amount: string): BigNumber | null =>\n token?.usdPrice\n ? new BigNumber(amount || ZERO).multipliedBy(token?.usdPrice || 0)\n : null;\n\nexport interface RouteState {\n fromBlockchain: BlockchainMeta | null;\n toBlockchain: BlockchainMeta | null;\n inputAmount: string;\n inputUsdValue: BigNumber | null;\n outputAmount: BigNumber | null;\n outputUsdValue: BigNumber | null;\n fromToken: TokenWithBalance | null;\n toToken: TokenWithBalance | null;\n routeWalletsConfirmed: boolean;\n selectedWallets: Wallet[];\n resetRoute: () => void;\n resetToBlockchain: () => void;\n resetFromBlockchain: () => void;\n setFromBlockchain: (chain: BlockchainMeta | null) => void;\n setToBlockchain: (chian: BlockchainMeta | null) => void;\n\n setFromToken: (token: Token | null) => void;\n setToToken: (token: Token | null) => void;\n setInputAmount: (amount: string) => void;\n bestRoute: BestRouteResponse | null;\n setRoute: (bestRoute: BestRouteResponse | null) => void;\n retry: (pendingSwap: PendingSwap) => void;\n switchFromAndTo: () => void;\n setRouteWalletConfirmed: (flag: boolean) => void;\n setSelectedWallets: (wallets: Wallet[]) => void;\n customDestination: string;\n setCustomDestination: (address: string) => void;\n resetRouteWallets: () => void;\n}\n\nexport const useBestRouteStore = createSelectors(\n create<RouteState>()(\n subscribeWithSelector((set) => ({\n fromBlockchain: null,\n fromToken: null,\n inputAmount: '',\n outputAmount: null,\n inputUsdValue: new BigNumber(0),\n outputUsdValue: new BigNumber(0),\n toBlockchain: null,\n toToken: null,\n bestRoute: null,\n routeWalletsConfirmed: false,\n selectedWallets: [],\n customDestination: '',\n setRoute: (bestRoute) =>\n set((state) => {\n let outputAmount: BigNumber | null = null;\n let outputUsdValue: BigNumber = ZERO;\n if (!isPositiveNumber(state.inputAmount)) {\n return {};\n }\n if (!!bestRoute) {\n outputAmount = !!bestRoute.result?.outputAmount\n ? new BigNumber(bestRoute.result?.outputAmount)\n : null;\n outputUsdValue = calcOutputUsdValue(\n bestRoute.result?.outputAmount,\n getBestRouteToTokenUsdPrice(bestRoute) || state.toToken?.usdPrice\n );\n }\n return {\n bestRoute,\n ...(!!bestRoute && {\n outputAmount,\n outputUsdValue,\n }),\n };\n }),\n resetRoute: () =>\n set(() => ({\n bestRoute: null,\n outputAmount: null,\n outputUsdValue: new BigNumber(0),\n })),\n setFromBlockchain: (chain) => {\n set((state) => {\n if (state.fromBlockchain?.name === chain?.name) {\n return {};\n }\n\n return {\n fromBlockchain: chain,\n ...(state.fromToken && {\n bestRoute: null,\n fromToken: null,\n outputAmount: null,\n outputUsdValue: null,\n }),\n };\n });\n },\n setFromToken: (token) => {\n const { blockchains } = useMetaStore.getState().meta;\n return set((state) => ({\n fromToken: token,\n ...(token && {\n fromBlockchain:\n blockchains.find(\n (blockchain) => blockchain.name === token.blockchain\n ) ?? null,\n }),\n ...(!!state.inputAmount && {\n inputUsdValue: getUsdValue(token, state.inputAmount),\n }),\n }));\n },\n setToBlockchain: (chain) => {\n set((state) => {\n if (state.toBlockchain?.name === chain?.name) {\n return {};\n }\n\n return {\n toBlockchain: chain,\n ...(state.toToken && {\n bestRoute: null,\n toToken: null,\n outputAmount: null,\n outputUsdValue: null,\n }),\n };\n });\n },\n setToToken: (token) => {\n const { blockchains } = useMetaStore.getState().meta;\n return set(() => ({\n toToken: token,\n ...(token && {\n toBlockchain:\n blockchains.find(\n (blockchain) => blockchain.name === token.blockchain\n ) ?? null,\n }),\n }));\n },\n setInputAmount: (amount) => {\n set((state) => ({\n inputAmount: amount,\n ...(!amount && {\n outputAmount: new BigNumber(0),\n outputUsdValue: new BigNumber(0),\n bestRoute: null,\n }),\n ...(!!state.fromToken && {\n inputUsdValue: getUsdValue(state.fromToken, amount),\n }),\n }));\n },\n retry: (pendingSwap) => {\n const { tokens, blockchains } = useMetaStore.getState().meta;\n\n const {\n fromBlockchain,\n fromToken,\n toBlockchain,\n toToken,\n inputAmount,\n } = createRetryRoute(pendingSwap, blockchains, tokens);\n\n set({\n fromBlockchain,\n fromToken,\n inputAmount,\n outputAmount: null,\n inputUsdValue: getUsdValue(fromToken ?? null, inputAmount),\n outputUsdValue: new BigNumber(0),\n toBlockchain,\n toToken,\n bestRoute: null,\n });\n },\n switchFromAndTo: () =>\n set((state) => ({\n fromBlockchain: state.toBlockchain,\n fromToken: state.toToken,\n toBlockchain: state.fromBlockchain,\n toToken: state.fromToken,\n inputAmount: state.outputAmount?.toString() || '',\n inputUsdValue: getUsdValue(\n state.toToken,\n state.outputAmount?.toString() || ''\n ),\n })),\n\n resetFromBlockchain: () =>\n set(() => ({\n fromToken: null,\n fromBlockchain: null,\n outputAmount: null,\n outputUsdValue: null,\n bestRoute: null,\n })),\n resetToBlockchain: () =>\n set(() => ({\n toToken: null,\n toBlockchain: null,\n outputAmount: null,\n outputUsdValue: null,\n bestRoute: null,\n })),\n setRouteWalletConfirmed: (flag) =>\n set({\n routeWalletsConfirmed: flag,\n }),\n setSelectedWallets: (wallets) => set({ selectedWallets: wallets }),\n setCustomDestination: (address) => set({ customDestination: address }),\n resetRouteWallets: () =>\n set({\n routeWalletsConfirmed: false,\n selectedWallets: [],\n customDestination: '',\n }),\n }))\n )\n);\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { BestRouteEqualityParams, Wallet } from '../types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport type { PriceImpactWarningLevel } from '@rango-dev/ui';\nimport type {\n SimulationAssetAndAmount,\n SimulationValidationStatus,\n} from '@rango-dev/ui/dist/widget/ui/src/types/swaps';\nimport type {\n Asset,\n BestRouteResponse,\n BlockchainMeta,\n Token,\n} from 'rango-sdk';\n\nimport { getLastSuccessfulStep } from '@rango-dev/queue-manager-rango-preset';\nimport BigNumber from 'bignumber.js';\n\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n HIGHT_PRICE_IMPACT,\n LOW_PRICE_IMPACT,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n} from '../constants/routing';\n\nimport { areEqual } from './common';\nimport { findBlockchain, findToken } from './meta';\nimport { numberToString } from './numbers';\n\nexport function searchParamsToToken(\n tokens: Token[],\n searchParams: string | null,\n chain: BlockchainMeta | null\n): Token | null {\n if (!chain) {\n return null;\n }\n return (\n tokens.find((token) => {\n const symbolAndAddress = searchParams?.split('--');\n if (symbolAndAddress?.length === 1) {\n return (\n token.symbol === symbolAndAddress[0] &&\n token.address === null &&\n token.blockchain === chain.name\n );\n }\n return (\n token.symbol === symbolAndAddress?.[0] &&\n token.address === symbolAndAddress?.[1] &&\n token.blockchain === chain.name\n );\n }) || null\n );\n}\n\nexport function getBestRouteToTokenUsdPrice(\n bestRoute: BestRouteResponse | null\n): number | null | undefined {\n return bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1].to\n .usdPrice;\n}\n\nexport function isNumberOfSwapsChanged(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n) {\n const route1Swaps = route1.result?.swaps || [];\n const route2Swaps = route2.result?.swaps || [];\n return route1Swaps.length !== route2Swaps.length;\n}\n\nexport function isRouteSwappersUpdated(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n) {\n const route1Swappers =\n route1.result?.swaps.map((swap) => swap.swapperId) || [];\n const route2Swappers =\n route2.result?.swaps.map((swap) => swap.swapperId) || [];\n return !areEqual(route1Swappers, route2Swappers);\n}\n\nexport function isRouteInternalCoinsUpdated(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n) {\n const route1InternalCoins =\n route1.result?.swaps.map((swap) => swap.to.symbol) || [];\n const route2InternalCoins =\n route2.result?.swaps.map((swap) => swap.to.symbol) || [];\n return !areEqual(route1InternalCoins, route2InternalCoins);\n}\n\nexport function isRouteChanged(\n route1: BestRouteResponse,\n route2: BestRouteResponse\n): boolean {\n return (\n isNumberOfSwapsChanged(route1, route2) ||\n isRouteSwappersUpdated(route1, route2) ||\n isRouteInternalCoinsUpdated(route1, route2)\n );\n}\n\nexport function outToRatioHasWarning(\n fromUsdValue: BigNumber | null,\n outToInRatio: BigNumber | 0\n) {\n return (\n (parseInt(outToInRatio?.toFixed(2) || '0') <= -10 &&\n (fromUsdValue === null || fromUsdValue.gte(new BigNumber(200)))) ||\n (parseInt(outToInRatio?.toFixed(2) || '0') <= -5 &&\n (fromUsdValue === null || fromUsdValue.gte(new BigNumber(1000))))\n );\n}\n\nexport function getRequiredBalanceOfWallet(\n selectedWallet: Wallet,\n fee: SimulationValidationStatus[] | null\n): SimulationAssetAndAmount[] | null {\n if (fee === null) {\n return null;\n }\n const relatedFeeStatus = fee\n ?.find((item) => item.blockchain === selectedWallet.chain)\n ?.wallets.find(\n (wallet) =>\n wallet.address?.toLowerCase() === selectedWallet.address.toLowerCase()\n );\n if (!relatedFeeStatus) {\n return null;\n }\n return relatedFeeStatus.requiredAssets;\n}\n\nexport function isRouteParametersChanged(params: BestRouteEqualityParams) {\n if (params.store === 'bestRoute') {\n const { prevState, currentState } = params;\n return (\n !!currentState.fromToken &&\n !!currentState.toToken &&\n (prevState.fromBlockchain?.name !== currentState.fromBlockchain?.name ||\n prevState.toBlockchain?.name !== currentState.toBlockchain?.name ||\n prevState.fromToken?.symbol !== currentState.fromToken?.symbol ||\n prevState.toToken?.symbol !== currentState.toToken?.symbol ||\n prevState.fromToken?.blockchain !== prevState.fromToken?.blockchain ||\n prevState.toToken?.blockchain !== currentState.toToken?.blockchain ||\n prevState.fromToken?.address !== currentState.fromToken?.address ||\n prevState.toToken?.address !== currentState.toToken?.address ||\n prevState.inputAmount !== currentState.inputAmount)\n );\n } else if (params.store === 'settings') {\n const { prevState, currentState } = params;\n return (\n prevState.slippage !== currentState.slippage ||\n prevState.customSlippage !== currentState.customSlippage ||\n prevState.disabledLiquiditySources?.length !==\n currentState.disabledLiquiditySources?.length ||\n prevState.infiniteApprove ||\n currentState.infiniteApprove\n );\n }\n return false;\n}\n\nexport function getFormattedBestRoute(\n bestRoute: BestRouteResponse | null\n): BestRouteResponse | null {\n if (!bestRoute) {\n return null;\n }\n\n const formattedSwaps = (bestRoute.result?.swaps || []).map((swap) => ({\n ...swap,\n fromAmount: numberToString(\n swap.fromAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n toAmount: numberToString(\n swap.toAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n }));\n\n return {\n ...bestRoute,\n ...(bestRoute.result && {\n result: { ...bestRoute.result, swaps: formattedSwaps },\n }),\n };\n}\n\nexport function getFormattedPendingSwap(pendingSwap: PendingSwap): PendingSwap {\n const formattedSteps = pendingSwap.steps.map((step) => ({\n ...step,\n feeInUsd: numberToString(\n step.feeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n ),\n outputAmount: numberToString(\n step.outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n expectedOutputAmountHumanReadable: numberToString(\n step.expectedOutputAmountHumanReadable,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n }));\n\n return {\n ...pendingSwap,\n inputAmount: numberToString(\n pendingSwap.inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n steps: formattedSteps,\n };\n}\n\n//todo: refactor bestRoute store and add loadingStatus\nexport const getBestRouteStatus = (loading: boolean, error: boolean) => {\n if (loading) {\n return 'loading';\n }\n if (error) {\n return 'failed';\n }\n return 'success';\n};\n\nexport function getPriceImpactLevel(\n priceImpact: number\n): PriceImpactWarningLevel {\n let warningLevel: PriceImpactWarningLevel = undefined;\n if (priceImpact <= LOW_PRICE_IMPACT && priceImpact > HIGHT_PRICE_IMPACT) {\n warningLevel = 'low';\n } else if (priceImpact <= HIGHT_PRICE_IMPACT) {\n warningLevel = 'high';\n }\n\n return warningLevel;\n}\n\nexport function findCommonTokens<T extends Asset[], R extends Asset[]>(\n listA: T,\n listB: R\n) {\n const tokenToString = (token: Asset): string =>\n `${token.symbol}-${token.blockchain}-${token.address ?? ''}`;\n\n const set = new Set();\n\n listA.forEach((token) => set.add(tokenToString(token)));\n\n return listB.filter((token) => set.has(tokenToString(token))) as R;\n}\n\nexport function createRetryRoute(\n pendingSwap: PendingSwap,\n blockchains: BlockchainMeta[],\n tokens: Token[]\n): {\n fromBlockchain: BlockchainMeta | null;\n fromToken: Token | null;\n toBlockchain: BlockchainMeta | null;\n toToken: Token | null;\n inputAmount: string;\n} {\n const firstStep = pendingSwap.steps[0];\n const lastStep = pendingSwap.steps[pendingSwap.steps.length - 1];\n const lastSuccessfulStep = getLastSuccessfulStep(pendingSwap.steps);\n\n const toToken = {\n blockchain: lastStep.toBlockchain,\n symbol: lastStep.toSymbol,\n address: lastStep.toSymbolAddress,\n };\n\n const fromBlockchainMeta = findBlockchain(\n lastSuccessfulStep\n ? lastSuccessfulStep.toBlockchain\n : firstStep.fromBlockchain,\n blockchains\n );\n const toBlockchainMeta = findBlockchain(lastStep.toBlockchain, blockchains);\n const fromTokenMeta = findToken(\n lastSuccessfulStep\n ? {\n blockchain: fromBlockchainMeta?.name ?? '',\n symbol: lastSuccessfulStep.toSymbol,\n address: lastSuccessfulStep.toSymbolAddress,\n }\n : {\n blockchain: fromBlockchainMeta?.name ?? '',\n symbol: firstStep.fromSymbol,\n address: firstStep.fromSymbolAddress,\n },\n tokens\n );\n const toTokenMeta = findToken(toToken, tokens);\n const inputAmount = lastSuccessfulStep\n ? lastSuccessfulStep.outputAmount ?? ''\n : pendingSwap.inputAmount;\n\n return {\n fromBlockchain: fromBlockchainMeta,\n fromToken: fromTokenMeta,\n toBlockchain: toBlockchainMeta,\n toToken: toTokenMeta,\n inputAmount,\n };\n}\n", "import type { Asset, BlockchainMeta, Token } from 'rango-sdk';\n\nimport { tokensAreEqual } from './wallets';\n\nexport function getBlockchainDisplayNameFor(\n blockchainName: string,\n blockchains: BlockchainMeta[]\n): string | undefined {\n return blockchains.find((blockchain) => blockchain.name === blockchainName)\n ?.displayName;\n}\nexport function getBlockchainShortNameFor(\n blockchainName: string,\n blockchains: BlockchainMeta[]\n): string | undefined {\n return blockchains.find((blockchain) => blockchain.name === blockchainName)\n ?.shortName;\n}\n\nexport function findToken(t: Asset, tokens: Token[]) {\n return tokens.find((token) => tokensAreEqual(token, t)) ?? null;\n}\n\nexport function findBlockchain(name: string, blockchains: BlockchainMeta[]) {\n return blockchains.find((blockchain) => blockchain.name === name) ?? null;\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { LoadingStatus } from '../store/meta';\nimport type { ConnectedWallet } from '../store/wallets';\nimport type { ConvertedToken, SwapButtonState, Wallet } from '../types';\nimport type {\n PendingSwap,\n PendingSwapStep,\n} from '@rango-dev/queue-manager-rango-preset';\nimport type { WalletType } from '@rango-dev/wallets-shared';\nimport type {\n BestRouteRequest,\n BestRouteResponse,\n BlockchainMeta,\n RecommendedSlippage,\n SwapResult,\n Token,\n} from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\nimport BigNumber from 'bignumber.js';\n\nimport { isValidAddress } from '../components/ConfirmWalletsModal/ConfirmWallets.helpers';\nimport { errorMessages } from '../constants/errors';\nimport { swapButtonTitles } from '../constants/messages';\nimport { ZERO } from '../constants/numbers';\nimport {\n BALANCE_MAX_DECIMALS,\n BALANCE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n} from '../constants/routing';\nimport { useMetaStore } from '../store/meta';\nimport { ButtonState } from '../types';\n\nimport { removeDuplicateFrom } from './common';\nimport { numberToString } from './numbers';\nimport { getRequiredBalanceOfWallet } from './routing';\nimport { getRequiredChains } from './wallets';\n\nexport function getOutputRatio(\n inputUsdValue: BigNumber | null,\n outputUsdValue: BigNumber | null\n) {\n if (\n !inputUsdValue ||\n !outputUsdValue ||\n inputUsdValue.lte(ZERO) ||\n outputUsdValue.lte(ZERO)\n ) {\n return 0;\n }\n return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);\n}\n\nexport function outputRatioHasWarning(\n inputUsdValue: BigNumber | null,\n outputRatio: BigNumber | 0\n): boolean {\n return (\n ((parseInt(outputRatio.toFixed(2) || '0') <= -10 &&\n inputUsdValue?.gte(new BigNumber(400))) ||\n (parseInt(outputRatio.toFixed(2) || '0') <= -5 &&\n inputUsdValue?.gte(new BigNumber(1000)))) ??\n false\n );\n}\n\nexport function hasLimitError(bestRoute: BestRouteResponse | null): boolean {\n return (\n (bestRoute?.result?.swaps || []).filter((swap) => {\n const minimum = !!swap.fromAmountMinValue\n ? new BigNumber(swap.fromAmountMinValue)\n : null;\n const maximum = !!swap.fromAmountMaxValue\n ? new BigNumber(swap.fromAmountMaxValue)\n : null;\n const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';\n if (isExclusive) {\n return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);\n }\n return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);\n }).length > 0\n );\n}\n\nexport function LimitErrorMessage(bestRoute: BestRouteResponse | null): {\n swap: SwapResult | null;\n fromAmountRangeError: string;\n recommendation: string;\n} {\n if (!bestRoute) {\n return { swap: null, fromAmountRangeError: '', recommendation: '' };\n }\n const swap = (bestRoute?.result?.swaps || []).filter((swap) => {\n const minimum = !!swap.fromAmountMinValue\n ? new BigNumber(swap.fromAmountMinValue)\n : null;\n const maximum = !!swap.fromAmountMaxValue\n ? new BigNumber(swap.fromAmountMaxValue)\n : null;\n const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';\n if (isExclusive) {\n return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);\n }\n return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);\n })[0];\n if (!swap) {\n return { swap: null, fromAmountRangeError: '', recommendation: '' };\n }\n const minimum = !!swap.fromAmountMinValue\n ? new BigNumber(swap.fromAmountMinValue)\n : null;\n const maximum = !!swap.fromAmountMaxValue\n ? new BigNumber(swap.fromAmountMaxValue)\n : null;\n const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';\n\n let fromAmountRangeError = '';\n let recommendation = '';\n if (!isExclusive && !!minimum && minimum.gt(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredEqualMin',\n message: 'Required: >= {min} {symbol}',\n values: {\n min: numberToString(\n minimum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.increaseAmount;\n } else if (isExclusive && !!minimum && minimum.gte(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredMin',\n message: 'Required: > {min} {symbol}',\n values: {\n min: numberToString(\n minimum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.increaseAmount;\n }\n\n if (!isExclusive && !!maximum && maximum.lt(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredEqualMax',\n message: 'Required: <= {max} {symbol}',\n values: {\n max: numberToString(\n maximum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.decreaseAmount;\n } else if (isExclusive && !!maximum && maximum.lte(swap.fromAmount)) {\n fromAmountRangeError = i18n.t({\n id: 'requiredMax',\n message: 'Required: < {max} {symbol}',\n values: {\n max: numberToString(\n maximum,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n symbol: swap.from.symbol,\n },\n });\n recommendation = errorMessages().bridgeLimitErrors.decreaseAmount;\n }\n\n return { swap, fromAmountRangeError, recommendation };\n}\n\nexport function getSwapButtonState(\n loadingMetaStatus: LoadingStatus,\n connectedWallets: ConnectedWallet[],\n loading: boolean,\n bestRoute: BestRouteResponse | null,\n hasLimitError: boolean,\n highValueLoss: boolean,\n priceImpactCanNotBeComputed: boolean,\n needsToWarnEthOnPath: boolean,\n inputAmount: string\n): SwapButtonState {\n if (loadingMetaStatus !== 'success') {\n return {\n title: swapButtonTitles().connectWallet,\n state: ButtonState.WAITFORCONNECTING,\n disabled: true,\n };\n }\n if (connectedWallets.length == 0) {\n return {\n title: swapButtonTitles().connectWallet,\n state: ButtonState.WAITFORCONNECTING,\n disabled: false,\n };\n }\n if (\n loading ||\n !bestRoute ||\n !bestRoute.result ||\n hasLimitError ||\n !inputAmount ||\n inputAmount === '0'\n ) {\n return {\n title: swapButtonTitles().swap,\n disabled: true,\n state: ButtonState.SWAP,\n };\n } else if (highValueLoss || priceImpactCanNotBeComputed) {\n return {\n title: swapButtonTitles().swapAnyway,\n disabled: false,\n hasWarning: true,\n state: ButtonState.NEEDTOCONFIRM,\n };\n } else if (needsToWarnEthOnPath) {\n return {\n title: swapButtonTitles().ethRouteWarning,\n disabled: false,\n hasWarning: true,\n state: ButtonState.WARNING,\n };\n }\n return {\n title: swapButtonTitles().swap,\n disabled: false,\n state: ButtonState.SWAP,\n };\n}\n\nexport function canComputePriceImpact(\n bestRoute: BestRouteResponse | null,\n inputAmount: string,\n usdValue: BigNumber | null\n) {\n return !(\n (!usdValue || usdValue.lte(ZERO)) &&\n !!bestRoute?.result &&\n !!inputAmount &&\n inputAmount !== '0' &&\n parseFloat(inputAmount || '0') !== 0 &&\n !!bestRoute.result\n );\n}\n\nexport function requiredWallets(route: BestRouteResponse | null) {\n const wallets: string[] = [];\n\n route?.result?.swaps.forEach((swap) => {\n const currentStepFromBlockchain = swap.from.blockchain;\n const currentStepToBlockchain = swap.to.blockchain;\n let lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepFromBlockchain != lastAddedWallet) {\n wallets.push(currentStepFromBlockchain);\n }\n lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepToBlockchain != lastAddedWallet) {\n wallets.push(currentStepToBlockchain);\n }\n });\n return wallets;\n}\n\nexport const getUsdPrice = (\n blockchain: string,\n symbol: string,\n address: string | null,\n allTokens: Token[]\n): number | null => {\n const token = allTokens?.find(\n (t) =>\n t.blockchain === blockchain &&\n t.symbol?.toUpperCase() === symbol?.toUpperCase() &&\n t.address === address\n );\n return token?.usdPrice || null;\n};\n\nexport function getUsdFeeOfStep(\n step: SwapResult,\n allTokens: Token[]\n): BigNumber {\n let totalFeeInUsd = ZERO;\n for (let i = 0; i < step.fee.length; i++) {\n const fee = step.fee[i];\n if (fee.expenseType === 'DECREASE_FROM_OUTPUT') {\n continue;\n }\n\n const unitPrice = getUsdPrice(\n fee.asset.blockchain,\n fee.asset.symbol,\n fee.asset.address,\n allTokens\n );\n totalFeeInUsd = totalFeeInUsd.plus(\n new BigNumber(fee.amount).multipliedBy(unitPrice || 0)\n );\n }\n\n return totalFeeInUsd;\n}\n\nexport function getTotalFeeInUsd(\n bestRoute: BestRouteResponse | null,\n allTokens: Token[]\n): BigNumber | null {\n return (\n bestRoute?.result?.swaps.reduce(\n (totalFee: BigNumber, step) =>\n totalFee.plus(getUsdFeeOfStep(step, allTokens)),\n ZERO\n ) || null\n );\n}\n\nexport function hasHighFee(totalFeeInUsd: BigNumber | null) {\n if (!totalFeeInUsd) {\n return false;\n }\n return !totalFeeInUsd.lt(new BigNumber(30));\n}\n\nexport function hasSlippageError(\n slippages: (RecommendedSlippage | null)[] | undefined\n) {\n return (slippages?.filter((s) => !!s?.error)?.length || 0) > 0;\n}\n\nexport function getMinRequiredSlippage(\n route: BestRouteResponse\n): string | null {\n const slippages = route.result?.swaps.map(\n (slippage) => slippage.recommendedSlippage\n );\n return (\n slippages\n ?.map((s) => s?.slippage || '0')\n ?.filter((s) => parseFloat(s) > 0)\n ?.sort((a, b) => parseFloat(b) - parseFloat(a))\n ?.find(() => true) || null\n );\n}\n\nexport function hasProperSlippage(\n userSlippage: string,\n minRequiredSlippage: string | null\n) {\n if (!minRequiredSlippage) {\n return true;\n }\n return parseFloat(userSlippage) >= parseFloat(minRequiredSlippage);\n}\n\nexport function hasEnoughBalance(\n route: BestRouteResponse,\n selectedWallets: Wallet[]\n) {\n const fee = route.validationStatus;\n\n if (fee === null || fee.length === 0) {\n return true;\n }\n\n for (const wallet of selectedWallets) {\n const requiredAssets = getRequiredBalanceOfWallet(wallet, fee);\n if (!requiredAssets) {\n continue;\n }\n\n const enoughBalanceInWallet = requiredAssets\n .map((asset) => asset.ok)\n .reduce((previous, current) => previous && current);\n if (!enoughBalanceInWallet) {\n return false;\n }\n }\n\n return true;\n}\n\nexport function hasEnoughBalanceAndProperSlippage(\n route: BestRouteResponse,\n selectedWallets: Wallet[],\n userSlippage: string,\n minRequiredSlippage: string | null\n): boolean {\n return (\n hasEnoughBalance(route, selectedWallets) &&\n hasProperSlippage(userSlippage, minRequiredSlippage)\n );\n}\n\nexport function createBestRouteRequestBody(params: {\n fromToken: Token;\n toToken: Token;\n inputAmount: string;\n wallets?: Wallet[];\n selectedWallets?: Wallet[];\n disabledLiquiditySources: string[];\n slippage: number;\n affiliateRef: string | null;\n affiliatePercent: number | null;\n affiliateWallets: { [key: string]: string } | null;\n initialRoute?: BestRouteResponse;\n destination?: string;\n}): BestRouteRequest {\n const {\n fromToken,\n toToken,\n inputAmount,\n wallets,\n selectedWallets,\n disabledLiquiditySources,\n slippage,\n affiliateRef,\n affiliatePercent,\n affiliateWallets,\n initialRoute,\n destination,\n } = params;\n const selectedWalletsMap = selectedWallets?.reduce(\n (\n selectedWalletsMap: BestRouteRequest['selectedWallets'],\n selectedWallet\n ) => (\n (selectedWalletsMap[selectedWallet.chain] = selectedWallet.address),\n selectedWalletsMap\n ),\n {}\n );\n\n const connectedWallets: BestRouteRequest['connectedWallets'] = [];\n\n wallets?.forEach((wallet) => {\n const chainAndAccounts = connectedWallets.find(\n (connectedWallet) => connectedWallet.blockchain === wallet.chain\n );\n if (!!chainAndAccounts) {\n chainAndAccounts.addresses.push(wallet.address);\n } else {\n connectedWallets.push({\n blockchain: wallet.chain,\n addresses: [wallet.address],\n });\n }\n });\n\n const checkPrerequisites = !!initialRoute;\n\n const filteredBlockchains = removeDuplicateFrom(\n (initialRoute?.result?.swaps || []).reduce(\n (blockchains: string[], swap) => {\n blockchains.push(swap.from.blockchain, swap.to.blockchain);\n // Check if internalSwaps array exists\n if (swap.internalSwaps && Array.isArray(swap.internalSwaps)) {\n swap.internalSwaps.map((internalSwap) => {\n blockchains.push(\n internalSwap.from.blockchain,\n internalSwap.to.blockchain\n );\n });\n }\n return blockchains;\n },\n []\n )\n );\n\n const requestBody: BestRouteRequest = {\n amount: inputAmount.toString(),\n affiliateRef: affiliateRef ?? undefined,\n affiliatePercent: affiliatePercent ?? undefined,\n affiliateWallets: affiliateWallets ?? undefined,\n checkPrerequisites,\n from: {\n address: fromToken.address,\n blockchain: fromToken.blockchain,\n symbol: fromToken.symbol,\n },\n to: {\n address: toToken.address,\n blockchain: toToken.blockchain,\n symbol: toToken.symbol,\n },\n connectedWallets,\n selectedWallets: selectedWalletsMap ?? {},\n slippage: slippage.toString(),\n ...(destination && { destination: destination }),\n ...(disabledLiquiditySources.length > 0 && {\n swapperGroups: disabledLiquiditySources,\n swappersGroupsExclude: true,\n }),\n ...(checkPrerequisites && { blockchains: filteredBlockchains }),\n };\n\n return requestBody;\n}\n\nexport function getWalletsForNewSwap(selectedWallets: Wallet[]) {\n const wallets = selectedWallets.reduce(\n (\n selectedWalletsMap: {\n [p: string]: { address: string; walletType: WalletType };\n },\n selectedWallet\n ) => (\n (selectedWalletsMap[selectedWallet.chain] = {\n address: selectedWallet.address,\n walletType: selectedWallet.walletType,\n }),\n selectedWalletsMap\n ),\n {}\n );\n\n return wallets;\n}\n\nexport function getRouteOutputAmount(route: BestRouteResponse | null) {\n return route?.result?.outputAmount || null;\n}\n\nexport function getPercentageChange(\n inputUsdValue: string | number | null,\n outputUsdValue: string | number | null\n) {\n if (!inputUsdValue || !outputUsdValue) {\n return null;\n }\n return new BigNumber(outputUsdValue)\n .div(new BigNumber(inputUsdValue))\n .minus(1)\n .multipliedBy(100);\n}\n\nexport function isOutputAmountChangedALot(\n oldRoute: BestRouteResponse,\n newRoute: BestRouteResponse\n) {\n const oldOutputAmount = getRouteOutputAmount(oldRoute);\n const newOutputAmount = getRouteOutputAmount(newRoute);\n if (!oldOutputAmount || !newOutputAmount) {\n return false;\n }\n const percentageChange = getPercentageChange(\n oldOutputAmount,\n newOutputAmount\n );\n if (!percentageChange) {\n return true;\n }\n\n return percentageChange.toNumber() <= -1;\n}\n\nexport function getBalanceWarnings(\n route: BestRouteResponse,\n selectedWallets: Wallet[]\n) {\n const fee = route.validationStatus;\n const requiredWallets = getRequiredChains(route);\n const walletsSortedByRequiredWallets = selectedWallets.sort(\n (selectedWallet1, selectedWallet2) =>\n requiredWallets.indexOf(selectedWallet1.chain) -\n requiredWallets.indexOf(selectedWallet2.chain)\n );\n return walletsSortedByRequiredWallets\n .flatMap((wallet) => getRequiredBalanceOfWallet(wallet, fee) || [])\n .filter((asset) => !asset.ok)\n .map((asset) => {\n const symbol = asset.asset.symbol;\n const currentAmount = numberToString(\n new BigNumber(asset.currentAmount.amount).shiftedBy(\n -asset.currentAmount.decimals\n ),\n BALANCE_MIN_DECIMALS,\n BALANCE_MAX_DECIMALS\n );\n const requiredAmount = numberToString(\n new BigNumber(asset.requiredAmount.amount).shiftedBy(\n -asset.requiredAmount.decimals\n ),\n BALANCE_MIN_DECIMALS,\n BALANCE_MAX_DECIMALS\n );\n let reason = '';\n if (asset.reason === 'FEE') {\n reason = i18n.t(' for network fee');\n }\n if (asset.reason === 'INPUT_ASSET') {\n reason = i18n.t(' for swap');\n }\n if (asset.reason === 'FEE_AND_INPUT_ASSET') {\n reason = i18n.t(' for input and network fee');\n }\n const warningMessage = i18n.t({\n id: 'balanceWarningMessage',\n message: `Needs \u2248 {requiredAmount} {symbol}{reason}, but you have {currentAmount} {symbol} in your {blockchain} wallet.`,\n values: {\n requiredAmount,\n symbol,\n reason,\n currentAmount,\n blockchain: asset.asset.blockchain,\n },\n });\n return warningMessage;\n });\n}\n\nexport function calcOutputUsdValue(\n outputAmount?: string,\n tokenPrice?: number | null\n) {\n const amount = !!outputAmount ? new BigNumber(outputAmount) : ZERO;\n\n return amount.multipliedBy(tokenPrice || 0);\n}\n\nexport function isNetworkStatusInWarningState(\n pendingSwapStep: PendingSwapStep | null\n): boolean {\n return (\n !!pendingSwapStep &&\n pendingSwapStep.networkStatus !== null &&\n pendingSwapStep.networkStatus !== PendingSwapNetworkStatus.NetworkChanged\n );\n}\n\nexport function getSwapMessages(\n pendingSwap: PendingSwap,\n currentStep: PendingSwapStep | null\n): {\n shortMessage: string;\n detailedMessage: { content: string; long: boolean };\n} {\n const textForRemove = 'bellow button or';\n let message = pendingSwap.extraMessage;\n let detailedMessage = pendingSwap.extraMessageDetail;\n\n if (pendingSwap.networkStatusExtraMessageDetail?.includes(textForRemove)) {\n pendingSwap.networkStatusExtraMessageDetail =\n pendingSwap.networkStatusExtraMessageDetail.replace(textForRemove, '');\n }\n\n const networkWarningState = isNetworkStatusInWarningState(currentStep);\n\n if (networkWarningState) {\n message = pendingSwap.networkStatusExtraMessage || '';\n detailedMessage = pendingSwap.networkStatusExtraMessageDetail || '';\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check\n switch (currentStep?.networkStatus) {\n case PendingSwapNetworkStatus.WaitingForConnectingWallet:\n message = message || i18n.t('Waiting for connecting wallet');\n break;\n case PendingSwapNetworkStatus.WaitingForQueue:\n message =\n message || i18n.t('Waiting for other running tasks to be finished');\n break;\n case PendingSwapNetworkStatus.WaitingForNetworkChange:\n message = message || i18n.t('Waiting for changing wallet network');\n break;\n default:\n message = message || '';\n break;\n }\n }\n detailedMessage = detailedMessage || '';\n message = message || '';\n const isRpc =\n message?.indexOf('code') !== -1 && message?.indexOf('reason') !== -1;\n\n return {\n shortMessage: message,\n detailedMessage: { content: detailedMessage, long: isRpc },\n };\n}\n\nexport function getLastConvertedTokenInFailedSwap(\n pendingSwap: PendingSwap\n): ConvertedToken {\n let resultToken: ConvertedToken = null;\n if (pendingSwap.status === 'failed') {\n const lastSuccessStep = pendingSwap.steps\n .slice()\n .reverse()\n .filter((step) => step.status === 'success')[0];\n\n if (lastSuccessStep) {\n resultToken = {\n blockchain: lastSuccessStep.toBlockchain,\n symbol: lastSuccessStep.toSymbol,\n outputAmount: lastSuccessStep.outputAmount,\n address: lastSuccessStep.toSymbolAddress,\n };\n }\n }\n return resultToken;\n}\n\nexport function shouldRetrySwap(pendingSwap: PendingSwap) {\n return (\n pendingSwap.status === 'failed' &&\n !!pendingSwap.finishTime &&\n new Date().getTime() - parseInt(pendingSwap.finishTime) < 4 * 3600 * 1000\n );\n}\nexport function isValidCustomDestination(\n blockchain: string,\n address: string\n): boolean {\n const blockchains = useMetaStore.getState().meta.blockchains;\n const regex =\n blockchains.find((chain) => chain.name === blockchain)?.addressPatterns ||\n [];\n return regex.filter((r) => new RegExp(r).test(address)).length > 0;\n}\n\nexport function confirmSwapDisabled(\n fetching: boolean,\n showCustomDestination: boolean,\n customDestination: string,\n bestRoute: BestRouteResponse | null,\n selectedWallets: { walletType: string; chain: string }[],\n lastStepToBlockchain?: BlockchainMeta\n) {\n return (\n fetching ||\n (!showCustomDestination &&\n !requiredWallets(bestRoute).every((chain) =>\n selectedWallets.map((wallet) => wallet.chain).includes(chain)\n )) ||\n (!!showCustomDestination && !customDestination) ||\n (!!showCustomDestination &&\n !!customDestination &&\n lastStepToBlockchain &&\n !isValidAddress(lastStepToBlockchain, customDestination))\n );\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { Step } from '@rango-dev/ui/dist/widget/ui/src/components/BestRoute/BestRoute.types';\nimport type { BestRouteResponse, BlockchainMeta } from 'rango-sdk';\n\nimport {\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { getBlockchainShortNameFor } from '../../utils/meta';\nimport { numberToString } from '../../utils/numbers';\n\nexport function formatBestRoute(\n bestRoute: BestRouteResponse,\n blockchains: BlockchainMeta[]\n): Step[] | undefined {\n return bestRoute.result?.swaps.map((swap) => {\n return {\n swapper: { displayName: swap.swapperId, image: swap.swapperLogo },\n from: {\n token: { displayName: swap.from.symbol, image: swap.from.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.from.blockchain, blockchains) ?? '',\n image: swap.from.blockchainLogo,\n },\n price: {\n value: numberToString(\n swap.fromAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n swap.from.usdPrice?.toString(),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n },\n to: {\n token: { displayName: swap.to.symbol, image: swap.to.logo },\n chain: {\n displayName:\n getBlockchainShortNameFor(swap.to.blockchain, blockchains) ?? '',\n image: swap.to.blockchainLogo,\n },\n price: {\n value: numberToString(\n swap.toAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n swap.to.usdPrice?.toString(),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n },\n };\n });\n}\n\nexport function getRequiredWallets(route: BestRouteResponse | null): string[] {\n const wallets: string[] = [];\n\n route?.result?.swaps.forEach((swap) => {\n const currentStepFromBlockchain = swap.from.blockchain;\n const currentStepToBlockchain = swap.to.blockchain;\n let lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepFromBlockchain != lastAddedWallet) {\n wallets.push(currentStepFromBlockchain);\n }\n lastAddedWallet = wallets[wallets.length - 1];\n if (currentStepToBlockchain != lastAddedWallet) {\n wallets.push(currentStepToBlockchain);\n }\n });\n return wallets;\n}\n\nexport function isValidAddress(\n chain: BlockchainMeta,\n address: string\n): boolean {\n const regex = chain.addressPatterns;\n const valid = regex.filter((r) => new RegExp(r).test(address)).length > 0;\n return valid;\n}\n", "import { i18n } from '@lingui/core';\n\nexport const swapButtonTitles = () => {\n return {\n connectWallet: i18n.t('Connect Wallet'),\n swap: i18n.t('Swap'),\n swapAnyway: i18n.t('Swap anyway'),\n ethRouteWarning: i18n.t('The route goes through Ethereum. Continue?'),\n };\n};\n", "import { styled } from '@rango-dev/ui';\n\nexport const Alerts = styled('div', {\n width: '100%',\n paddingTop: '$10',\n});\n\nexport const Flex = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n gap: 10,\n width: '100%',\n});\n\nexport const Item = styled('div', {\n display: 'flex',\n padding: '$5 0',\n justifyContent: 'space-between',\n alignItems: 'center',\n width: '100%',\n});\n\nexport const Action = styled('div', {\n padding: '$2',\n alignSelf: 'flex-start',\n cursor: 'pointer',\n});\n", "import type { ModalPropTypes } from './RouteErrors.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Divider,\n MessageBox,\n Modal,\n Typography,\n WarningIcon,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { errorMessages } from '../../constants/errors';\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n HIGHT_PRICE_IMPACT,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { numberToString } from '../../utils/numbers';\n\nimport { Flex } from './RouteErrors.styles';\nimport { RouteErrorsModalItem } from './RouteErrorsModalItem';\n\nexport function RouteErrorsModal(props: ModalPropTypes) {\n const {\n highValueLoss,\n open,\n onToggle,\n percentageChange,\n inputUsdValue,\n outputUsdValue,\n totalFeeInUsd,\n } = props;\n const navigate = useNavigate();\n const type =\n highValueLoss && !!percentageChange?.lt(HIGHT_PRICE_IMPACT)\n ? 'error'\n : 'warning';\n const highValueLossData = [\n {\n title: i18n.t('Swapping'),\n value: numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n {\n title: i18n.t('Gas cost'),\n value: numberToString(\n totalFeeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n ),\n },\n {\n title: i18n.t('Receiving'),\n value: numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n },\n {\n title: i18n.t('Price impact'),\n value: numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n ),\n valueColor: `${type}500`,\n },\n ];\n\n return (\n <Modal\n open={open}\n onClose={() => onToggle(false)}\n container={document.getElementById('swap-box') || document.body}>\n {highValueLoss ? (\n <MessageBox\n type={type}\n title={errorMessages().highValueLossError.impactTitle}\n description={errorMessages().highValueLossError.description}\n />\n ) : (\n <MessageBox\n type={type}\n title={errorMessages().unknownPriceError.impactTitle}\n description={errorMessages().unknownPriceError.description}\n />\n )}\n {highValueLoss && (\n <Flex>\n <Divider size={20} />\n <Typography size=\"small\" variant=\"title\">\n {i18n.t('Details')}\n </Typography>\n <Flex>\n {highValueLossData.map((item, index) => {\n const key = index;\n return <RouteErrorsModalItem key={key} {...item} />;\n })}\n </Flex>\n </Flex>\n )}\n <Divider size={32} />\n <Button\n type=\"primary\"\n size=\"large\"\n prefix={<WarningIcon />}\n fullWidth\n onClick={() => {\n navigate(navigationRoutes.confirmSwap);\n }}>\n {highValueLoss\n ? errorMessages().highValueLossError.confirmMessage\n : errorMessages().unknownPriceError.confirmMessage}\n </Button>\n </Modal>\n );\n}\n", "import type { ModalContentData } from './RouteErrors.types';\n\nimport { Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Item } from './RouteErrors.styles';\n\nexport function RouteErrorsModalItem(props: ModalContentData) {\n const { title, value, valueColor } = props;\n\n return (\n <Item>\n <Typography size=\"medium\" variant=\"label\" color=\"neutral600\">\n {title}\n </Typography>\n <Typography\n size=\"large\"\n variant=\"label\"\n color={valueColor || 'foreground'}>\n {`${valueColor ? '%' : '$'}${value}`}\n </Typography>\n </Item>\n );\n}\n", "import { ReverseIcon, styled } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { useBestRouteStore } from '../store/bestRoute';\n\nconst SwitchButtonContainer = styled('div', {\n position: 'absolute',\n bottom: '-12px',\n left: '50%',\n transform: 'translate(-50%, 10%)',\n cursor: 'pointer',\n});\n\nconst StyledButton = styled('div', {\n borderRadius: '$md',\n border: '3px solid $background',\n background: '$neutral100',\n width: '$24',\n height: '$24',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n color: '$foreground',\n '&:hover': {\n color: '$secondary500',\n },\n});\n\nexport function SwitchFromAndToButton() {\n const switchFromAndTo = useBestRouteStore.use.switchFromAndTo();\n\n return (\n <SwitchButtonContainer>\n <StyledButton\n onClick={() => {\n switchFromAndTo();\n }}>\n <ReverseIcon size={12} />\n </StyledButton>\n </SwitchButtonContainer>\n );\n}\n", "import { useEffect, useRef, useState } from 'react';\n\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useSettingsStore } from '../store/settings';\nimport { debounce } from '../utils/common';\nimport { isPositiveNumber } from '../utils/numbers';\nimport { createBestRouteRequestBody } from '../utils/swap';\nimport { tokensAreEqual } from '../utils/wallets';\n\nimport { useFetchBestRoute } from './useFetchBestRoute';\n\nconst DEBOUNCE_DELAY = 600;\n\ntype UseSwapInput = {\n fetch: () => void;\n loading: boolean;\n error: string;\n};\n\n/**\n * a hook for fetching best route based on from and to input values\n * we use this hook in home page\n */\nexport function useSwapInput(): UseSwapInput {\n const { fetch: fetchBestRoute, cancelFetch } = useFetchBestRoute();\n const [loading, setLoading] = useState(false);\n const {\n fromToken,\n toToken,\n inputAmount,\n inputUsdValue,\n resetRoute,\n setRoute,\n } = useBestRouteStore();\n const {\n slippage,\n customSlippage,\n affiliatePercent,\n affiliateRef,\n affiliateWallets,\n disabledLiquiditySources,\n } = useSettingsStore();\n const [error, setError] = useState('');\n const prevDisabledLiquiditySources = useRef(disabledLiquiditySources);\n const userSlippage = customSlippage ?? slippage;\n const hasTokensValue = !fromToken || !toToken;\n const shouldSkipRequest =\n hasTokensValue ||\n tokensAreEqual(fromToken, toToken) ||\n !isPositiveNumber(inputAmount);\n\n const fetch: UseSwapInput['fetch'] = () => {\n if (!loading) {\n setLoading(true);\n }\n if (!shouldSkipRequest) {\n resetRoute();\n const requestBody = createBestRouteRequestBody({\n fromToken,\n toToken,\n inputAmount,\n disabledLiquiditySources,\n slippage: userSlippage,\n affiliateRef,\n affiliatePercent,\n affiliateWallets,\n });\n fetchBestRoute(requestBody)\n .then((res) => {\n setLoading(false);\n setRoute(res);\n })\n .catch((error) => {\n resetRoute();\n if (error?.code !== 'ERR_CANCELED') {\n setError(error.message);\n setLoading(false);\n }\n });\n }\n };\n\n const debouncedFetch = debounce(() => {\n if (!shouldSkipRequest) {\n fetch();\n }\n }, DEBOUNCE_DELAY);\n\n useEffect(() => {\n if (!isPositiveNumber(inputAmount) || inputUsdValue?.eq(0)) {\n setLoading(false);\n cancelFetch();\n return;\n }\n if (shouldSkipRequest) {\n return;\n }\n resetRoute();\n setLoading(true);\n debouncedFetch();\n return cancelFetch;\n }, [inputAmount, shouldSkipRequest]);\n\n useEffect(() => {\n const disabledLiquiditySourceReset =\n !!prevDisabledLiquiditySources.current.length &&\n !disabledLiquiditySources.length;\n if (!shouldSkipRequest && disabledLiquiditySourceReset) {\n fetch();\n }\n prevDisabledLiquiditySources.current = disabledLiquiditySources;\n return cancelFetch;\n }, [disabledLiquiditySources.length]);\n\n return { fetch, loading, error };\n}\n", "import type { BestRouteRequest, BestRouteResponse } from 'rango-sdk';\n\nimport { useRef, useState } from 'react';\n\nimport { httpService } from '../services/httpService';\n\ninterface UseFetchBestRoute {\n fetch: (requestBody: BestRouteRequest) => Promise<BestRouteResponse>;\n cancelFetch: () => void;\n loading: boolean;\n}\n\nexport function useFetchBestRoute(): UseFetchBestRoute {\n const [loading, setLoading] = useState(false);\n const abortController = useRef<AbortController | null>(null);\n const cancel = () => abortController.current?.abort();\n\n const fetch: UseFetchBestRoute['fetch'] = async (requestBody) => {\n cancel();\n abortController.current = new AbortController();\n\n setLoading(true);\n\n try {\n const res = await httpService().getBestRoute(requestBody, {\n signal: abortController.current.signal,\n });\n abortController.current = null;\n return res;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-useless-catch\n } catch (error: any) {\n throw error;\n } finally {\n setLoading(false);\n }\n };\n return { fetch, loading, cancelFetch: cancel };\n}\n", "import type { WidgetConfig } from '../types';\n\nimport { useEffect, useRef } from 'react';\nimport {\n createSearchParams,\n useLocation,\n useSearchParams,\n} from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { SearchParams } from '../constants/searchParams';\nimport { useSyncStoresWithConfig } from '../hooks/useSyncStoresWithConfig';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useUiStore } from '../store/ui';\nimport { searchParamsToToken } from '../utils/routing';\n\ntype Props = { config: WidgetConfig | undefined };\n\nexport function UpdateUrl(props: Props) {\n const firstRender = useRef(true);\n const [searchParams, setSearchParams] = useSearchParams();\n const location = useLocation();\n const firstRenderSearchParams = useRef(location.search);\n const searchParamsRef = useRef<Record<string, string>>({});\n const fromBlockchain = useBestRouteStore.use.fromBlockchain();\n const toBlockchain = useBestRouteStore.use.toBlockchain();\n const fromToken = useBestRouteStore.use.fromToken();\n const toToken = useBestRouteStore.use.toToken();\n const setFromBlockchain = useBestRouteStore.use.setFromBlockchain();\n const setFromToken = useBestRouteStore.use.setFromToken();\n const setToBlockchain = useBestRouteStore.use.setToBlockchain();\n const setToToken = useBestRouteStore.use.setToToken();\n const inputAmount = useBestRouteStore.use.inputAmount();\n const setInputAmount = useBestRouteStore.use.setInputAmount();\n const loadingStatus = useMetaStore.use.loadingStatus();\n const { blockchains, tokens } = useMetaStore.use.meta();\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n useSyncStoresWithConfig(props.config);\n\n useEffect(() => {\n const params: Record<string, string> = {};\n createSearchParams(firstRenderSearchParams.current).forEach(\n (value, key) => {\n params[key] = value;\n }\n );\n searchParamsRef.current = params;\n const requestId =\n location.pathname.split(navigationRoutes.swaps + '/')[1] || null;\n if (requestId) {\n setSelectedSwap(requestId);\n }\n }, []);\n\n useEffect(() => {\n if (!firstRender.current) {\n let fromChainString = '',\n fromTokenString = '',\n toChainString = '',\n toTokenString = '',\n fromAmount = '';\n if (loadingStatus !== 'success') {\n fromChainString = searchParamsRef.current[SearchParams.FROM_CHAIN];\n fromTokenString = searchParamsRef.current[SearchParams.FROM_TOKEN];\n toChainString = searchParamsRef.current[SearchParams.TO_CHAIN];\n toTokenString = searchParamsRef.current[SearchParams.TO_TOKEN];\n fromAmount =\n searchParamsRef.current[SearchParams.FROM_AMOUNT] || inputAmount;\n } else {\n if (location.state === 'redirect') {\n return;\n }\n fromChainString = fromBlockchain?.name || '';\n fromTokenString =\n (fromToken?.symbol || '') +\n (fromToken?.address ? `--${fromToken?.address}` : '');\n toChainString = toBlockchain?.name || '';\n toTokenString =\n (toToken?.symbol || '') +\n (toToken?.address ? `--${toToken?.address}` : '');\n fromAmount = inputAmount;\n }\n setSearchParams(\n {\n ...(fromChainString && {\n [SearchParams.FROM_CHAIN]: fromChainString,\n }),\n ...(fromTokenString && {\n [SearchParams.FROM_TOKEN]: fromTokenString,\n }),\n ...(toChainString && { [SearchParams.TO_CHAIN]: toChainString }),\n ...(toTokenString && { [SearchParams.TO_TOKEN]: toTokenString }),\n ...(fromAmount && {\n [SearchParams.FROM_AMOUNT]: fromAmount.toString(),\n }),\n },\n { replace: true }\n );\n }\n firstRender.current = false;\n }, [\n location.pathname,\n inputAmount,\n fromBlockchain,\n fromToken,\n toBlockchain,\n toToken,\n ]);\n\n useEffect(() => {\n if (loadingStatus === 'success') {\n const fromChainString = searchParams.get(SearchParams.FROM_CHAIN);\n const fromTokenString = searchParams.get(SearchParams.FROM_TOKEN);\n const toChainString = searchParams.get(SearchParams.TO_CHAIN);\n const toTokenString = searchParams.get(SearchParams.TO_TOKEN);\n const fromAmount = searchParams.get(SearchParams.FROM_AMOUNT);\n const fromBlockchain = blockchains.find(\n (blockchain) => blockchain.name === fromChainString\n );\n const fromToken = searchParamsToToken(\n tokens,\n fromTokenString,\n fromBlockchain || null\n );\n const toBlockchain = blockchains.find(\n (blockchain) => blockchain.name === toChainString\n );\n const toToken = searchParamsToToken(\n tokens,\n toTokenString,\n toBlockchain || null\n );\n if (!!fromBlockchain) {\n setFromBlockchain(fromBlockchain);\n if (!!fromToken) {\n setFromToken(fromToken);\n }\n }\n if (!!toBlockchain) {\n setToBlockchain(toBlockchain);\n if (!!toToken) {\n setToToken(toToken);\n }\n }\n if (fromAmount) {\n setInputAmount(fromAmount);\n }\n }\n }, [loadingStatus]);\n\n return null;\n}\n", "import type { WidgetConfig } from '../types';\nimport type { Asset } from 'rango-sdk';\n\nimport { useEffect, useMemo, useRef } from 'react';\n\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { tokensAreEqual } from '../utils/wallets';\n\nexport function useSyncStoresWithConfig(config: WidgetConfig | undefined) {\n const {\n setInputAmount,\n setToToken,\n setToBlockchain,\n setFromBlockchain,\n setFromToken,\n fromToken,\n toToken,\n fromBlockchain,\n toBlockchain,\n } = useBestRouteStore();\n\n const {\n meta: { tokens, blockchains },\n loadingStatus: loadingMetaStatus,\n } = useMetaStore();\n\n const { setAffiliateRef, setAffiliatePercent, setAffiliateWallets } =\n useSettingsStore();\n\n const fromTokensConfig = useMemo(\n () => config?.from?.tokens,\n [config?.from?.tokens]\n );\n const fromBlockchainsConfig = useMemo(\n () => config?.from?.blockchains,\n [config?.from?.blockchains]\n );\n const toTokensConfig = useMemo(\n () => config?.to?.tokens,\n [config?.to?.tokens]\n );\n const toBlockchainsConfig = useMemo(\n () => config?.to?.blockchains,\n [config?.to?.blockchains]\n );\n const prevConfigFromToken = useRef<Asset | undefined>(undefined);\n const prevConfigToToken = useRef<Asset | undefined>(undefined);\n const prevConfigFromBlockchain = useRef<string | undefined>(undefined);\n const prevConfigToBlockchain = useRef<string | undefined>(undefined);\n\n useEffect(() => {\n setInputAmount(config?.amount?.toString() || '');\n }, [config?.amount]);\n\n useEffect(() => {\n if (loadingMetaStatus === 'success') {\n const chain = blockchains.find(\n (chain) => chain.name === config?.from?.blockchain\n );\n const token = tokens.find((t) =>\n tokensAreEqual(t, config?.from?.token || null)\n );\n\n if (chain || (!chain && prevConfigFromBlockchain.current)) {\n setFromBlockchain(chain ?? null);\n }\n\n if (token || (!token && prevConfigFromToken.current)) {\n setFromToken(token ?? null);\n }\n\n prevConfigFromBlockchain.current = config?.from?.blockchain;\n prevConfigFromToken.current = config?.from?.token;\n }\n }, [\n config?.from?.token?.symbol,\n config?.from?.token?.address,\n config?.from?.token?.blockchain,\n config?.from?.blockchain,\n loadingMetaStatus,\n ]);\n\n useEffect(() => {\n if (fromToken && fromTokensConfig) {\n if (!fromTokensConfig.some((token) => tokensAreEqual(token, fromToken))) {\n setFromToken(null);\n }\n }\n\n if (fromBlockchain && fromBlockchainsConfig) {\n if (!fromBlockchainsConfig.includes(fromBlockchain.name)) {\n setFromBlockchain(null);\n }\n }\n }, [fromTokensConfig, fromBlockchainsConfig]);\n\n useEffect(() => {\n if (toToken && toTokensConfig) {\n if (!toTokensConfig.some((token) => tokensAreEqual(token, toToken))) {\n setToToken(null);\n }\n }\n\n if (toBlockchain && toBlockchainsConfig) {\n if (!toBlockchainsConfig.includes(toBlockchain.name)) {\n setToBlockchain(null);\n }\n }\n }, [toTokensConfig, toBlockchainsConfig]);\n\n useEffect(() => {\n if (loadingMetaStatus === 'success') {\n const chain = blockchains.find(\n (chain) => chain.name === config?.to?.blockchain\n );\n const token = tokens.find((t) =>\n tokensAreEqual(t, config?.to?.token || null)\n );\n\n if (chain || (!chain && prevConfigToBlockchain.current)) {\n setToBlockchain(chain ?? null);\n }\n\n if (token || (!token && prevConfigToToken.current)) {\n setToToken(token ?? null);\n }\n\n prevConfigToBlockchain.current = config?.to?.blockchain;\n prevConfigToToken.current = config?.to?.token;\n }\n }, [\n config?.to?.token?.symbol,\n config?.to?.token?.address,\n config?.to?.token?.blockchain,\n config?.to?.blockchain,\n loadingMetaStatus,\n ]);\n\n useEffect(() => {\n setAffiliateRef(config?.affiliate?.ref ?? null);\n setAffiliatePercent(config?.affiliate?.percent ?? null);\n setAffiliateWallets(config?.affiliate?.wallets ?? null);\n }, [\n config?.affiliate?.ref,\n config?.affiliate?.percent,\n config?.affiliate?.wallets,\n ]);\n}\n", "import type { WidgetConfig } from '../types';\n\nimport React from 'react';\nimport { useRoutes } from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { ConfirmSwapPage } from '../pages/ConfirmSwapPage';\nimport { HistoryPage } from '../pages/HistoryPage';\nimport { Home } from '../pages/Home';\nimport { LanguagePage } from '../pages/LanguagePage';\nimport { LiquiditySourcePage } from '../pages/LiquiditySourcePage';\nimport { SelectBlockchainPage } from '../pages/SelectBlockchainPage';\nimport { SelectSwapItemsPage } from '../pages/SelectSwapItemsPage';\nimport { SettingsPage } from '../pages/SettingsPage';\nimport { SwapDetailsPage } from '../pages/SwapDetailsPage';\nimport { ThemePage } from '../pages/ThemePage';\nimport { WalletsPage } from '../pages/WalletsPage';\n\nconst getAbsolutePath = (path: string) => path.replace('/', '');\n\ninterface PropTypes {\n config?: WidgetConfig;\n}\n\nexport function AppRoutes(props: PropTypes) {\n const { config } = props;\n\n return useRoutes([\n {\n path: navigationRoutes.home,\n element: <Home />,\n },\n {\n path: navigationRoutes.fromSwap,\n element: <SelectSwapItemsPage type=\"source\" />,\n },\n {\n path: navigationRoutes.toSwap,\n element: <SelectSwapItemsPage type=\"destination\" />,\n },\n {\n path: navigationRoutes.fromBlockchain,\n element: <SelectBlockchainPage type=\"source\" />,\n },\n {\n path: navigationRoutes.toBlockchain,\n element: <SelectBlockchainPage type=\"destination\" />,\n },\n {\n path: navigationRoutes.settings,\n element: (\n <SettingsPage\n singleTheme={config?.theme?.singleTheme}\n supportedSwappers={config?.liquiditySources}\n />\n ),\n },\n {\n path: navigationRoutes.themes,\n element: <ThemePage />,\n },\n {\n path: navigationRoutes.languages,\n element: <LanguagePage />,\n },\n {\n path: navigationRoutes.exchanges,\n element: (\n <LiquiditySourcePage\n sourceType=\"Exchanges\"\n supportedSwappers={config?.liquiditySources}\n />\n ),\n },\n {\n path: navigationRoutes.bridges,\n element: (\n <LiquiditySourcePage\n sourceType=\"Bridges\"\n supportedSwappers={config?.liquiditySources}\n />\n ),\n },\n { path: navigationRoutes.swaps, element: <HistoryPage /> },\n {\n path: navigationRoutes.swapDetails,\n element: <SwapDetailsPage />,\n },\n {\n path: navigationRoutes.wallets,\n element: (\n <WalletsPage\n supportedWallets={config?.wallets}\n multiWallets={\n typeof config?.multiWallets === 'undefined'\n ? true\n : config.multiWallets\n }\n config={config}\n />\n ),\n },\n {\n path: getAbsolutePath(navigationRoutes.confirmSwap),\n element: <ConfirmSwapPage config={config} />,\n },\n ]);\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type {\n ConfirmSwap,\n ConfirmSwapFetchResult,\n} from '../hooks/useConfirmSwap';\nimport type { WidgetConfig } from '../types';\n\nimport { i18n } from '@lingui/core';\nimport { useManager } from '@rango-dev/queue-manager-react';\nimport {\n Alert,\n BestRoute,\n BestRouteSkeleton,\n Button,\n Divider,\n IconButton,\n MessageBox,\n Modal,\n RefreshIcon,\n SettingsIcon,\n styled,\n Tooltip,\n Typography,\n WalletIcon,\n} from '@rango-dev/ui';\nimport React, { useEffect, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useNavigate } from 'react-router-dom';\n\nimport {\n formatBestRoute,\n getRequiredWallets,\n} from '../components/ConfirmWalletsModal/ConfirmWallets.helpers';\nimport { ConfirmWalletsModal } from '../components/ConfirmWalletsModal/ConfirmWalletsModal';\nimport { HeaderButton } from '../components/HeaderButtons/HeaderButtons.styles';\nimport { Layout } from '../components/Layout';\nimport { NoRoutes } from '../components/NoRoutes';\nimport { getConfirmSwapErrorMessage } from '../constants/errors';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../constants/routing';\nimport { getRouteWarningMessage } from '../constants/warnings';\nimport { useConfirmSwap } from '../hooks/useConfirmSwap';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { useUiStore } from '../store/ui';\nimport { useWalletsStore } from '../store/wallets';\nimport {\n ConfirmSwapErrorTypes,\n RouteWarningType,\n SlippageWarningType,\n} from '../types';\nimport { getContainer } from '../utils/common';\nimport {\n numberToString,\n secondsToString,\n totalArrivalTime,\n} from '../utils/numbers';\nimport { getPriceImpactLevel } from '../utils/routing';\nimport { getPercentageChange, getTotalFeeInUsd } from '../utils/swap';\n\nconst Container = styled('div', {\n position: 'relative',\n width: '100%',\n '& .description': {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n paddingBottom: '$10',\n },\n '& .icon': {\n width: '$24',\n height: '$24',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n },\n});\n\nconst Buttons = styled('div', {\n width: '100%',\n display: 'flex',\n justifyContent: 'space-between',\n '& .confirm-button': {\n flexGrow: 1,\n paddingRight: '$10',\n },\n [`& ${IconButton}`]: {\n width: '$48',\n height: '$48',\n },\n});\n\ntype PropTypes = {\n config?: WidgetConfig;\n};\n\nexport function ConfirmSwapPage(props: PropTypes) {\n //TODO: move component's logics to a custom hook\n const { config } = props;\n const {\n bestRoute,\n inputAmount,\n outputAmount,\n inputUsdValue,\n outputUsdValue,\n setInputAmount,\n selectedWallets,\n routeWalletsConfirmed,\n setRouteWalletConfirmed,\n customDestination,\n } = useBestRouteStore();\n const navigate = useNavigate();\n const [dbErrorMessage, setDbErrorMessage] = useState<string>('');\n const [showSlippageWarning, setShowSlippageWarning] = useState(false);\n\n const { connectedWallets } = useWalletsStore();\n const showWalletsOnInit = !routeWalletsConfirmed;\n const [showWallets, setShowWallets] = useState(false);\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n const {\n meta: { tokens, blockchains },\n loadingStatus: loadingMetaStatus,\n } = useMetaStore();\n const slippage = useSettingsStore.use.slippage();\n const customSlippage = useSettingsStore.use.customSlippage();\n const { manager } = useManager();\n const selectedSlippage = customSlippage || slippage;\n const {\n fetch: confirmSwap,\n loading: fetchingConfirmationRoute,\n cancelFetch,\n } = useConfirmSwap();\n const [confirmSwapResult, setConfirmSwapResult] =\n useState<ConfirmSwapFetchResult>({\n swap: null,\n error: null,\n warnings: null,\n });\n const showSkeleton =\n fetchingConfirmationRoute || loadingMetaStatus === 'loading';\n const showNoRouteFound =\n !fetchingConfirmationRoute &&\n confirmSwapResult.error &&\n [\n ConfirmSwapErrorTypes.NO_ROUTE,\n ConfirmSwapErrorTypes.REQUEST_FAILED,\n ].includes(confirmSwapResult.error.type);\n const showBestRoute =\n !showNoRouteFound &&\n !fetchingConfirmationRoute &&\n bestRoute &&\n bestRoute.result;\n\n const totalFeeInUsd = getTotalFeeInUsd(bestRoute, tokens);\n const percentageChange = numberToString(\n getPercentageChange(\n inputUsdValue?.toNumber() ?? 0,\n outputUsdValue?.toNumber() ?? 0\n ),\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n );\n\n const warningLevel = getPriceImpactLevel(parseFloat(percentageChange));\n\n const onConfirmSwap: ConfirmSwap['fetch'] = async ({\n selectedWallets,\n customDestination,\n }) => {\n const result = await confirmSwap?.({ selectedWallets, customDestination });\n setConfirmSwapResult(result);\n return result;\n };\n\n const addNewSwap = async () => {\n if (confirmSwapResult.swap && routeWalletsConfirmed) {\n try {\n await manager?.create(\n 'swap',\n { swapDetails: confirmSwapResult.swap },\n { id: confirmSwapResult.swap.requestId }\n );\n setSelectedSwap(confirmSwapResult.swap.requestId);\n navigate(\n '/' + navigationRoutes.swaps + `/${confirmSwapResult.swap.requestId}`,\n {\n replace: true,\n }\n );\n setTimeout(() => {\n setInputAmount('');\n }, 0);\n } catch (e) {\n setDbErrorMessage('Error: ' + (e as any)?.message);\n }\n }\n };\n\n const onConfirm = async () => {\n await addNewSwap();\n };\n\n const onStartConfirmSwap = async () => {\n if (confirmSwapResult?.warnings?.slippage) {\n setShowSlippageWarning(true);\n } else {\n await onConfirm();\n }\n };\n\n const onRefresh = async () => {\n setConfirmSwapResult({\n error: null,\n swap: null,\n warnings: null,\n });\n confirmSwap({ selectedWallets })\n .then((res) => {\n setConfirmSwapResult(res);\n })\n .catch((error) => console.error(error));\n };\n\n useEffect(() => {\n if (showWalletsOnInit) {\n cancelFetch();\n }\n }, [showWalletsOnInit]);\n\n useEffect(() => {\n if (showWalletsOnInit) {\n setShowWallets(showWalletsOnInit);\n }\n }, [showWalletsOnInit]);\n\n useEffect(() => {\n if (!showWalletsOnInit) {\n confirmSwap({ selectedWallets, customDestination })\n .then((result) => setConfirmSwapResult(result))\n .catch((error) => console.error(error));\n }\n }, []);\n\n useEffect(() => {\n const routeChanged =\n confirmSwapResult.warnings?.route?.type &&\n Object.values(RouteWarningType).includes(\n confirmSwapResult.warnings?.route?.type\n );\n\n const selectedWalletDisconnected =\n selectedWallets.length < 1 ||\n !selectedWallets.every((selectedWallet) =>\n connectedWallets.find(\n (connectedWallet) =>\n selectedWallet.address === connectedWallet.address &&\n selectedWallet.walletType === connectedWallet.walletType &&\n selectedWallet.chain === connectedWallet.chain\n )\n );\n\n let routeWalletsChanged = false;\n\n if (routeChanged) {\n let requiredWallets = getRequiredWallets(bestRoute);\n\n const lastStepToBlockchain =\n bestRoute?.result?.swaps[bestRoute.result.swaps.length - 1].to\n .blockchain;\n\n const isLastWalletRequired = !!bestRoute?.result?.swaps.find(\n (swap) => swap.from.blockchain === lastStepToBlockchain\n );\n\n if (!isLastWalletRequired) {\n requiredWallets = requiredWallets.slice(\n -requiredWallets.length,\n requiredWallets.length - 1\n );\n }\n\n const allRequiredWalletsSelected = requiredWallets.every(\n (requiredWallet) =>\n selectedWallets.find(\n (selectedWallet) => selectedWallet.chain === requiredWallet\n )\n );\n\n if (!allRequiredWalletsSelected) {\n routeWalletsChanged = true;\n }\n }\n\n if (bestRoute && (selectedWalletDisconnected || routeWalletsChanged)) {\n queueMicrotask(() => flushSync(setShowWallets.bind(null, true)));\n setRouteWalletConfirmed(false);\n }\n }, [\n confirmSwapResult.warnings?.route,\n selectedWallets.length,\n connectedWallets.length,\n ]);\n\n return (\n <Layout\n header={{\n title: i18n.t('Confirm Swap'),\n onBack: navigate.bind(null, -1),\n hasConnectWallet: true,\n suffix: (\n <Tooltip\n container={getContainer()}\n side=\"bottom\"\n content={i18n.t('Settings')}>\n <HeaderButton\n size=\"small\"\n variant=\"ghost\"\n onClick={() => navigate('/' + navigationRoutes.settings)}>\n <SettingsIcon size={18} color=\"black\" />\n </HeaderButton>\n </Tooltip>\n ),\n }}\n footer={\n <Buttons>\n <div className=\"confirm-button\">\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n fullWidth\n loading={fetchingConfirmationRoute}\n disabled={!!confirmSwapResult.error}\n onClick={onStartConfirmSwap}>\n {i18n.t('Start Swap')}\n </Button>\n </div>\n <IconButton\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n loading={fetchingConfirmationRoute}\n onClick={setShowWallets.bind(null, true)}>\n <WalletIcon size={24} />\n </IconButton>\n </Buttons>\n }>\n <Modal\n anchor=\"bottom\"\n open={showSlippageWarning}\n prefix={\n <Button\n size=\"small\"\n variant=\"ghost\"\n onClick={() => navigate('/' + navigationRoutes.settings)}>\n <Typography variant=\"label\" size=\"medium\" color=\"$neutral700\">\n {i18n.t('Change settings')}\n </Typography>\n </Button>\n }\n container={document.querySelector('#swap-box') as HTMLDivElement}\n onClose={setShowSlippageWarning.bind(null, (prevState) => !prevState)}>\n {confirmSwapResult.warnings?.slippage && (\n <MessageBox\n type=\"warning\"\n title={\n confirmSwapResult.warnings.slippage.type ===\n SlippageWarningType.HIGH_SLIPPAGE\n ? i18n.t('High slippage')\n : i18n.t('Low slippage')\n }\n description={\n confirmSwapResult.warnings.slippage.type ===\n SlippageWarningType.HIGH_SLIPPAGE\n ? i18n.t(\n 'highSlippage',\n { selectedSlippage },\n {\n message:\n ' Caution, your slippage is high (={selectedSlippage}). Your trade may be front run.',\n }\n )\n : i18n.t(\n 'increaseSlippage',\n\n {\n minRequiredSlippage:\n confirmSwapResult.warnings.slippage.slippage,\n },\n {\n message:\n 'We recommend you to increase slippage to at least {minRequiredSlippage} for this route.',\n }\n )\n }>\n <Divider size={18} />\n <Divider size={32} />\n <Button\n size=\"large\"\n type=\"primary\"\n variant=\"contained\"\n fullWidth\n onClick={onConfirm}>\n {i18n.t('Confirm anyway')}\n </Button>\n </MessageBox>\n )}\n </Modal>\n {showWallets && (\n <ConfirmWalletsModal\n open={showWallets}\n onClose={() => setShowWallets(false)}\n onCancel={cancelFetch}\n loading={fetchingConfirmationRoute}\n onCheckBalance={onConfirmSwap}\n config={config}\n />\n )}\n\n <Container>\n <div className=\"description\">\n <Typography variant=\"title\" size=\"small\">\n {i18n.t('You get')}\n </Typography>\n <Button\n style={{ padding: '0' }}\n variant=\"ghost\"\n disabled={fetchingConfirmationRoute}\n onClick={onRefresh}>\n <div className=\"icon\">\n <RefreshIcon size={16} />\n </div>\n </Button>\n </div>\n {dbErrorMessage && (\n <>\n <Alert type=\"error\" variant=\"alarm\" title={dbErrorMessage} />\n <Divider size={12} />\n </>\n )}\n {confirmSwapResult.warnings?.route && (\n <>\n <Alert\n variant=\"alarm\"\n type=\"warning\"\n title={getRouteWarningMessage(confirmSwapResult.warnings.route)}\n />\n <Divider size={12} />\n </>\n )}\n {showSkeleton && <BestRouteSkeleton type=\"swap-preview\" expanded />}\n {showBestRoute && (\n <BestRoute\n expanded={true}\n tooltipContainer={getContainer()}\n steps={formatBestRoute(bestRoute, blockchains) ?? []}\n input={{\n value: numberToString(\n inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n inputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n output={{\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: numberToString(\n outputUsdValue,\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n ),\n }}\n totalFee={numberToString(\n totalFeeInUsd,\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n )}\n totalTime={secondsToString(\n totalArrivalTime(bestRoute.result?.swaps)\n )}\n recommended={true}\n type=\"swap-preview\"\n percentageChange={percentageChange}\n warningLevel={warningLevel}\n />\n )}\n {showNoRouteFound && (\n <>\n <Divider size={12} />\n <NoRoutes\n diagnosisMessage={\n confirmSwapResult.error?.type === ConfirmSwapErrorTypes.NO_ROUTE\n ? confirmSwapResult.error.diagnosisMessage\n : undefined\n }\n error={\n confirmSwapResult.error?.type ===\n ConfirmSwapErrorTypes.REQUEST_FAILED\n }\n fetch={onRefresh}\n />\n </>\n )}\n {confirmSwapResult.error?.type ===\n ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS && (\n <>\n <Alert\n variant=\"alarm\"\n type=\"error\"\n title={getConfirmSwapErrorMessage(confirmSwapResult.error)}\n />\n <Divider size={12} />\n </>\n )}\n </Container>\n </Layout>\n );\n}\n", "import type { PropTypes } from './ConfirmWalletsModal.types';\nimport type { ConnectedWallet } from '../../store/wallets';\nimport type { ConfirmSwapWarnings, Wallet } from '../../types';\n\nimport { i18n } from '@lingui/core';\nimport {\n Alert,\n BalanceErrors,\n Button,\n ChevronDownIcon,\n ChevronLeftIcon,\n Divider,\n MessageBox,\n Modal,\n Typography,\n WalletIcon,\n} from '@rango-dev/ui';\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { getConfirmSwapErrorMessage } from '../../constants/errors';\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport { getRouteWarningMessage } from '../../constants/warnings';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { useMetaStore } from '../../store/meta';\nimport { useWalletsStore } from '../../store/wallets';\nimport { confirmSwapDisabled } from '../../utils/swap';\n\nimport { getRequiredWallets, isValidAddress } from './ConfirmWallets.helpers';\nimport {\n CollapsibleContent,\n CollapsibleRoot,\n ConfirmButton,\n CustomDestination,\n CustomDestinationButton,\n EXPANDABLE_TRANSITION_DURATION,\n ExpandedIcon,\n ListContainer,\n NavigateBack,\n ShowMoreHeader,\n StyledTextField,\n Title,\n Trigger,\n Wallets,\n WalletsContainer,\n} from './ConfirmWallets.styles';\nimport { WalletList } from './WalletList';\n\nconst NUMBER_OF_WALLETS_TO_DISPLAY = 2;\n\nexport function ConfirmWalletsModal(props: PropTypes) {\n //TODO: move component's logics to a custom hook\n const { open, onClose, onCancel, onCheckBalance, config, loading } = props;\n const { blockchains } = useMetaStore.use.meta();\n const {\n bestRoute,\n setSelectedWallets: selectRouteWallets,\n routeWalletsConfirmed,\n setRouteWalletConfirmed,\n customDestination,\n setCustomDestination,\n } = useBestRouteStore();\n const { connectedWallets, selectWallets } = useWalletsStore();\n\n const [showMoreWalletFor, setShowMoreWalletFor] = useState('');\n const [balanceWarnings, setBalanceWarnings] = useState<string[]>([]);\n const [error, setError] = useState('');\n const [routeWarning, setRouteWarning] = useState<\n ConfirmSwapWarnings['route'] | null\n >(null);\n const [destination, setDestination] = useState(customDestination);\n const [showCustomDestination, setShowCustomDestination] = useState(\n !!customDestination\n );\n const customDestinationRef = useRef<HTMLDivElement | null>(null);\n\n const requiredWallets = getRequiredWallets(bestRoute);\n const customDestinationEnabled =\n typeof config?.customDestination === 'undefined'\n ? true\n : config.customDestination;\n\n const lastStepToBlockchain = blockchains.find(\n (blockchain) =>\n blockchain.name ===\n bestRoute?.result?.swaps[bestRoute?.result?.swaps.length - 1].to\n .blockchain\n );\n const isWalletRequiredFor = (blockchain: string) =>\n !!bestRoute?.result?.swaps.find(\n (swap) => swap.from.blockchain === blockchain\n );\n\n const [selectableWallets, setSelectableWallets] = useState<ConnectedWallet[]>(\n connectedWallets.filter((connectedWallet) => {\n return (\n connectedWallet.selected &&\n requiredWallets.includes(connectedWallet.chain)\n );\n })\n );\n const lastStepToBlockchainMeta = blockchains.find(\n (chain) => chain.name === lastStepToBlockchain?.name\n );\n\n const isSelected = (walletType: string, chain: string) =>\n !!selectableWallets.find(\n (selectableWallet) =>\n selectableWallet.walletType === walletType &&\n selectableWallet.chain === chain &&\n selectableWallet.selected &&\n (isWalletRequiredFor(chain) ||\n (!isWalletRequiredFor(chain) && !destination))\n );\n\n const isAddressMatched =\n !!destination &&\n showCustomDestination &&\n lastStepToBlockchainMeta &&\n !isValidAddress(lastStepToBlockchainMeta, destination);\n\n const resetCustomDestination = () => {\n setShowCustomDestination(false);\n setDestination('');\n setSelectableWallets((selectableWallets) => {\n let anyWalletSelected = false;\n return selectableWallets.map((selectableWallet) => {\n if (\n !anyWalletSelected &&\n selectableWallet.chain === lastStepToBlockchain?.name\n ) {\n anyWalletSelected = true;\n return {\n ...selectableWallet,\n selected: true,\n };\n }\n return selectableWallet;\n });\n });\n };\n\n const onChange = (wallet: Wallet) => {\n if (showMoreWalletFor) {\n setShowMoreWalletFor('');\n }\n const selected = isSelected(wallet.walletType, wallet.chain);\n if (selected) {\n return;\n }\n const connectedWallet = connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === wallet.walletType &&\n connectedWallet.chain === wallet.chain\n );\n\n if (!connectedWallet) {\n return;\n }\n\n onCancel();\n if (wallet.chain === lastStepToBlockchain?.name && showCustomDestination) {\n setShowCustomDestination(false);\n setDestination('');\n }\n setSelectableWallets((selectableWallets) =>\n selectableWallets\n .filter((selectableWallet) => selectableWallet.chain !== wallet.chain)\n .concat({ ...connectedWallet, selected: true })\n );\n };\n\n const onConfirmBalance = () => {\n const lastSelectedWallets = selectableWallets.filter(\n (wallet) => wallet.selected\n );\n selectWallets(lastSelectedWallets);\n selectRouteWallets(lastSelectedWallets);\n setCustomDestination(destination);\n setRouteWalletConfirmed(true);\n onClose();\n };\n\n const onConfirmWallets = async () => {\n setBalanceWarnings([]);\n setError('');\n setRouteWarning(null);\n const selectedWallets = connectedWallets.filter((connectedWallet) =>\n selectableWallets.find(\n (selectableWallet) =>\n selectableWallet.chain === connectedWallet.chain &&\n selectableWallet.walletType === connectedWallet.walletType\n )\n );\n const result = await onCheckBalance?.({\n selectedWallets,\n customDestination: destination,\n });\n\n const warnings = result.warnings;\n if (warnings?.balance?.messages) {\n setBalanceWarnings(warnings.balance.messages);\n }\n if (warnings?.route) {\n setRouteWarning(warnings.route);\n }\n if (result.error) {\n setError(getConfirmSwapErrorMessage(result.error));\n }\n\n if (!result.error && (!warnings?.balance?.messages.length || 0 > 0)) {\n onConfirmBalance();\n } else {\n setBalanceWarnings(warnings?.balance?.messages ?? []);\n }\n };\n\n useEffect(() => {\n setSelectableWallets((selectableWallets) =>\n selectableWallets.concat(\n connectedWallets.filter((connectedWallet) => {\n const anyWalletSelected = !!selectableWallets.find(\n (selectableWallet) =>\n selectableWallet.chain === connectedWallet.chain\n );\n\n return (\n !anyWalletSelected &&\n connectedWallet.selected &&\n requiredWallets.includes(connectedWallet.chain)\n );\n })\n )\n );\n }, [connectedWallets.length]);\n\n useLayoutEffect(() => {\n if (showCustomDestination && customDestinationRef.current) {\n setTimeout(() => {\n customDestinationRef?.current?.scrollIntoView({ behavior: 'smooth' });\n }, EXPANDABLE_TRANSITION_DURATION);\n }\n }, [showCustomDestination]);\n\n const modalContainer = document.querySelector('#swap-box') as HTMLDivElement;\n\n const navigate = useNavigate();\n return (\n <Modal\n open={open}\n onClose={() => {\n if (!routeWalletsConfirmed) {\n navigate(navigationRoutes.home, { replace: true });\n }\n onClose();\n }}\n dismissible={!showMoreWalletFor}\n container={modalContainer}\n {...(!showMoreWalletFor && {\n footer: (\n <ConfirmButton>\n <Button\n loading={loading}\n disabled={confirmSwapDisabled(\n loading,\n showCustomDestination,\n destination,\n bestRoute,\n selectableWallets,\n lastStepToBlockchain\n )}\n onClick={onConfirmWallets}\n variant=\"contained\"\n type=\"primary\"\n fullWidth\n size=\"large\">\n Confirm\n </Button>\n </ConfirmButton>\n ),\n })}\n {...(showMoreWalletFor && {\n containerStyle: { padding: '$0' },\n header: (\n <ShowMoreHeader>\n <NavigateBack\n variant=\"ghost\"\n onClick={setShowMoreWalletFor.bind(null, '')}>\n <ChevronLeftIcon size={16} />\n </NavigateBack>\n <Typography variant=\"headline\" size=\"small\">\n {i18n.t({\n id: 'yourWallets',\n message: 'Your {blockchainName} wallets',\n values: { blockchainName: showMoreWalletFor },\n })}\n </Typography>\n </ShowMoreHeader>\n ),\n })}\n anchor=\"center\">\n <Modal\n open={balanceWarnings.length > 0}\n onClose={setBalanceWarnings.bind(null, [])}\n container={modalContainer}>\n <MessageBox\n title={i18n.t('Insufficient account balance')}\n type=\"error\"\n description={<BalanceErrors messages={balanceWarnings ?? []} />}>\n <Button\n variant=\"outlined\"\n size=\"large\"\n type=\"primary\"\n fullWidth\n onClick={onConfirmBalance}>\n {i18n.t('Proceed anyway')}\n </Button>\n </MessageBox>\n </Modal>\n {showMoreWalletFor && (\n <WalletsContainer>\n <div className=\"wallets-list\">\n <WalletList\n chain={showMoreWalletFor}\n isSelected={isSelected}\n selectWallet={onChange}\n multiWallets={config?.multiWallets ?? true}\n supportedWallets={config?.wallets ?? []}\n config={config}\n onShowMore={setShowMoreWalletFor.bind(null, showMoreWalletFor)}\n />\n </div>\n </WalletsContainer>\n )}\n {!showMoreWalletFor && (\n <>\n {error && (\n <>\n <Alert variant=\"alarm\" type=\"error\" title={i18n.t(error)} />\n <Divider size={12} />\n </>\n )}\n {routeWarning && (\n <>\n <Alert\n variant=\"alarm\"\n type=\"warning\"\n title={getRouteWarningMessage(routeWarning)}\n />\n <Divider size={12} />\n </>\n )}\n <Wallets>\n {requiredWallets.map((requiredWallet, index) => {\n const blockchain = blockchains.find(\n (blockchain) => blockchain.name === requiredWallet\n );\n\n const key = `wallet-${index}`;\n const isLastWallet = index === requiredWallets.length - 1;\n\n return (\n <div key={key}>\n <Title>\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t({\n id: 'yourWallets',\n message: 'Your {blockchainName} wallets',\n values: { blockchainName: blockchain?.displayName },\n })}\n </Typography>\n <Typography\n variant=\"label\"\n color=\"$neutral700\"\n size=\"medium\">\n {i18n.t({\n id: 'needConnect',\n message:\n 'You need to connect a {blockchainName} wallet.',\n values: { blockchainName: blockchain?.displayName },\n })}\n </Typography>\n </Title>\n <Divider size={24} />\n <ListContainer>\n <WalletList\n chain={requiredWallet}\n isSelected={isSelected}\n selectWallet={onChange}\n multiWallets={config?.multiWallets ?? true}\n supportedWallets={config?.wallets ?? []}\n config={config}\n limit={NUMBER_OF_WALLETS_TO_DISPLAY}\n onShowMore={() =>\n setShowMoreWalletFor(blockchain?.name ?? '')\n }\n />\n </ListContainer>\n {!isLastWallet && <Divider size={32} />}\n {isLastWallet && customDestinationEnabled && (\n <CustomDestination>\n <CollapsibleRoot\n ref={customDestinationRef}\n selected={showCustomDestination}\n open={showCustomDestination}\n onOpenChange={(checked) => {\n if (!checked) {\n resetCustomDestination();\n } else {\n if (\n !isWalletRequiredFor(\n lastStepToBlockchain?.name ?? ''\n )\n ) {\n setSelectableWallets((selectableWallets) =>\n selectableWallets.map((selectableWallet) => {\n if (\n selectableWallet.chain ===\n lastStepToBlockchain?.name\n ) {\n return {\n ...selectableWallet,\n selected: false,\n };\n }\n return selectableWallet;\n })\n );\n }\n }\n }}>\n <Trigger\n onClick={() =>\n setShowCustomDestination((prevState) => !prevState)\n }>\n <CustomDestinationButton\n fullWidth\n variant=\"default\"\n suffix={\n <ExpandedIcon\n orientation={\n showCustomDestination ? 'up' : 'down'\n }>\n <ChevronDownIcon size={10} color=\"gray\" />\n </ExpandedIcon>\n }>\n <div className=\"button__content\">\n <WalletIcon size={18} color=\"info\" />\n <Divider size={4} direction=\"horizontal\" />\n <Typography variant=\"label\" size=\"medium\">\n {i18n.t('Send to a different address')}\n </Typography>\n </div>\n </CustomDestinationButton>\n </Trigger>\n <CollapsibleContent open={showCustomDestination}>\n <>\n <Divider size={4} />\n <StyledTextField\n autoFocus\n placeholder={i18n.t('Your destination address')}\n value={destination}\n onChange={(e) => {\n setDestination(e.target.value);\n }}\n />\n </>\n </CollapsibleContent>\n </CollapsibleRoot>\n {isAddressMatched && (\n <div className=\"alarms\">\n <Alert\n variant=\"alarm\"\n type=\"error\"\n title={i18n.t({\n id: 'addressMatch',\n values: { destination },\n message:\n \"Address {destination} doesn't match the blockchain address pattern.\",\n })}\n />\n </div>\n )}\n </CustomDestination>\n )}\n </div>\n );\n })}\n </Wallets>\n </>\n )}\n </Modal>\n );\n}\n", "import type { RouteWarning } from '../types';\n\nimport { i18n } from '@lingui/core';\n\nimport { RouteWarningType } from '../types';\n\nexport function getRouteWarningMessage(warning: RouteWarning) {\n switch (warning.type) {\n case RouteWarningType.ROUTE_UPDATED:\n return i18n.t('Route has been updated.');\n case RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED:\n return i18n.t(\n 'Output amount changed to {newOutputAmount} ({percentageChange}% change).',\n {\n newOutputAmount: warning.newOutputAmount,\n percentageChange: warning.percentageChange,\n }\n );\n case RouteWarningType.ROUTE_SWAPPERS_UPDATED:\n return i18n.t('Route swappers has been updated.');\n case RouteWarningType.ROUTE_COINS_UPDATED:\n return i18n.t('Route internal coins has been updated.');\n default:\n return '';\n }\n}\n", "import * as Collapsible from '@radix-ui/react-collapsible';\nimport {\n Button,\n darkTheme,\n IconButton,\n keyframes,\n styled,\n TextField,\n} from '@rango-dev/ui';\n\nexport const EXPANDABLE_TRANSITION_DURATION = 300;\n\nconst slideDown = keyframes({\n from: {\n height: 0,\n },\n to: {\n height: 'var(--radix-collapsible-content-height)',\n },\n});\n\nconst slideUp = keyframes({\n from: {\n height: 'var(--radix-collapsible-content-height)',\n },\n to: {\n height: 0,\n },\n});\n\nexport const Title = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n alignItems: 'center',\n});\n\nexport const ListContainer = styled('div', {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: ' repeat(3, minmax(0, 1fr))',\n alignContent: 'baseline',\n});\n\nexport const WalletButton = styled('button', {\n borderRadius: '$xm',\n padding: '$10',\n border: '0',\n display: 'flex',\n justifyContent: 'center',\n $$color: '$colors$neutral100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral300',\n },\n backgroundColor: '$$color',\n alignItems: 'center',\n cursor: 'pointer',\n width: 110,\n position: 'relative',\n\n '&:hover': {\n $$color: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral100',\n },\n backgroundColor: '$$color',\n },\n\n '&:focus-visible': {\n $$color: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$info700',\n },\n backgroundColor: '$$color',\n outline: 0,\n },\n variants: {\n selected: {\n true: {\n outlineWidth: 1,\n outlineColor: '$secondary',\n outlineStyle: 'solid',\n },\n },\n },\n});\nexport const Trigger = styled(Collapsible.Trigger, {\n padding: '$0',\n border: 'none',\n outline: 'none',\n width: '100%',\n backgroundColor: 'transparent',\n fontFamily: 'inherit',\n});\n\nexport const ShowMoreHeader = styled('div', {\n padding: '$20',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n backgroundColor: '$neutral200',\n position: 'relative',\n width: '100%',\n});\n\nexport const NavigateBack = styled(IconButton, {\n position: 'absolute',\n left: '$20',\n});\n\nexport const WalletsContainer = styled('div', {\n paddingTop: '$20',\n '& .wallets-list': {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: ' repeat(3, minmax(0, 1fr))',\n alignContent: 'baseline',\n },\n});\n\nexport const CollapsibleRoot = styled(Collapsible.Root, {\n backgroundColor: '$neutral200',\n borderRadius: '$sm',\n variants: {\n selected: {\n true: {\n outlineWidth: 1,\n outlineColor: '$secondary500',\n outlineStyle: 'solid',\n },\n },\n },\n});\n\nexport const CustomDestinationButton = styled(Button, {\n width: '100%',\n borderRadius: '$sm !important',\n padding: '$15 !important',\n justifyContent: 'space-between',\n alignItems: 'center',\n $$color: '$colors$neutral100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral300',\n },\n backgroundColor: '$$color',\n\n '&:hover': {\n $$color: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral100',\n },\n backgroundColor: '$$color',\n },\n '&:focus-visible': {\n $$background: '$colors$info100',\n [`.${darkTheme} &`]: {\n $$background: '$colors$info700',\n },\n backgroundColor: '$$background',\n outline: 0,\n },\n});\n\nexport const CustomDestination = styled('div', {\n padding: '$10 $0',\n '& .button__content': {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n },\n '& .alarms': { paddingTop: '5px' },\n});\n\nexport const ExpandedIcon = styled('div', {\n transition: `all ${EXPANDABLE_TRANSITION_DURATION}ms ease`,\n variants: {\n orientation: {\n down: {\n transform: 'rotate(0)',\n },\n up: {\n transform: 'rotate(180deg)',\n },\n },\n },\n});\n\nexport const ConfirmButton = styled('div', {\n display: 'flex',\n});\n\nexport const StyledTextField = styled(TextField, {\n padding: '$0 $15 $15 $15',\n});\n\nexport const CollapsibleContent = styled(Collapsible.Content, {\n overflow: 'hidden',\n variants: {\n open: {\n true: {\n animation: `${slideDown} ${EXPANDABLE_TRANSITION_DURATION}ms ease-out`,\n },\n false: {\n animation: `${slideUp} ${EXPANDABLE_TRANSITION_DURATION}ms ease-out`,\n },\n },\n },\n});\n\nexport const Wallets = styled('div', { overflow: 'visible', width: '100%' });\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { PropTypes } from './WalletList.type';\nimport type { Wallet } from '../../types';\nimport type { WalletInfo } from '@rango-dev/ui';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Divider,\n Image,\n MessageBox,\n Modal,\n SelectableWallet,\n Typography,\n WalletState,\n} from '@rango-dev/ui';\nimport React, { useEffect, useState } from 'react';\n\nimport { useWallets } from '../..';\nimport { useWalletList } from '../../hooks/useWalletList';\nimport {\n TIME_TO_CLOSE_MODAL,\n TIME_TO_IGNORE_MODAL,\n} from '../../pages/WalletsPage';\nimport { useMetaStore } from '../../store/meta';\nimport { useWalletsStore } from '../../store/wallets';\nimport { getBlockchainDisplayNameFor } from '../../utils/meta';\nimport {\n getAddress,\n getConciseAddress,\n isExperimentalChain,\n} from '../../utils/wallets';\nimport { WalletModal } from '../WalletModal';\n\nimport { WalletButton } from './ConfirmWallets.styles';\nimport {\n LogoContainer,\n Spinner,\n WalletImageContainer,\n} from './WalletList.styles';\n\nexport function WalletList(props: PropTypes) {\n const { config, chain, isSelected, selectWallet, limit, onShowMore } = props;\n\n const connectedWallets = useWalletsStore.use.connectedWallets();\n const { blockchains } = useMetaStore.use.meta();\n const [openWalletStateModal, setOpenWalletStateModal] =\n useState<WalletType>('');\n const [experimentalChainWallet, setExperimentalChainWallet] =\n useState<Wallet | null>(null);\n const [showExperimentalChainModal, setShowExperimentalChainModal] =\n useState(false);\n const [addingExperimentalChainStatus, setAddingExperimentalChainStatus] =\n useState<'in-progress' | 'completed' | null>(null);\n const { connect } = useWallets();\n let modalTimerId: ReturnType<typeof setTimeout> | null = null;\n const { list, error, handleClick } = useWalletList({\n config,\n chain,\n onBeforeConnect: (type) => {\n modalTimerId = setTimeout(() => {\n setOpenWalletStateModal(type);\n }, TIME_TO_IGNORE_MODAL);\n },\n onConnect: () => {\n if (modalTimerId) {\n clearTimeout(modalTimerId);\n }\n setTimeout(() => {\n setOpenWalletStateModal('');\n }, TIME_TO_CLOSE_MODAL);\n },\n });\n const [sortedList, setSortedList] = useState<WalletInfo[]>(list);\n const numberOfSupportedWallets = list.length;\n const shouldShowMoreWallets = limit && numberOfSupportedWallets - limit > 0;\n\n const addExperimentalChain = async (wallet: Wallet) => {\n setShowExperimentalChainModal(false);\n setAddingExperimentalChainStatus('in-progress');\n await connect(wallet.walletType, wallet.chain);\n setAddingExperimentalChainStatus('completed');\n };\n\n useEffect(() => {\n setSortedList((sortedList) => {\n const selectedWalletIndex = list.findIndex((wallet) =>\n isSelected(wallet.type, chain)\n );\n\n if (shouldShowMoreWallets && selectedWalletIndex > 1) {\n return [list[selectedWalletIndex]].concat(\n list.filter((_, index) => index !== selectedWalletIndex)\n );\n }\n return sortedList.map(\n (sortedItem) =>\n list.find((listItem) => listItem.type === sortedItem.type) ??\n sortedItem\n );\n });\n }, [JSON.stringify(list)]);\n\n const modalContainer = document.querySelector('#swap-box') as HTMLDivElement;\n\n useEffect(() => {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n if (addingExperimentalChainStatus === 'completed') {\n timeout = setTimeout(\n () => setAddingExperimentalChainStatus(null),\n TIME_TO_CLOSE_MODAL\n );\n }\n\n return () => {\n if (timeout) {\n clearTimeout(timeout);\n }\n };\n }, [addingExperimentalChainStatus]);\n\n return (\n <>\n {sortedList.slice(0, limit).map((wallet) => {\n const address = getAddress({\n connectedWallets,\n walletType: wallet.type,\n chain,\n });\n const conciseAddress = address ? getConciseAddress(address) : '';\n\n const experimentalChain = isExperimentalChain(blockchains, chain);\n\n const experimentalChainNotAdded = !connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === wallet.type &&\n connectedWallet.chain === chain\n );\n\n const couldAddExperimentalChain =\n experimentalChain &&\n experimentalChainNotAdded &&\n wallet.state === WalletState.CONNECTED;\n\n const connectedWalletDescription = couldAddExperimentalChain\n ? i18n.t({\n id: 'addChain',\n message: 'Add {chain} chain',\n values: { chain },\n })\n : conciseAddress;\n\n const onClick = () => {\n if (wallet.state === WalletState.DISCONNECTED) {\n void handleClick(wallet.type);\n } else if (couldAddExperimentalChain) {\n setExperimentalChainWallet({\n walletType: wallet.type,\n chain,\n address: address ?? '',\n });\n setShowExperimentalChainModal(true);\n } else {\n selectWallet({\n walletType: wallet.type,\n chain,\n address: address ?? '',\n });\n }\n };\n\n const blockchainDisplayName: string | undefined =\n experimentalChainWallet?.chain\n ? getBlockchainDisplayNameFor(\n experimentalChainWallet.chain,\n blockchains\n )\n : undefined;\n return (\n <>\n <WalletModal\n open={openWalletStateModal === wallet.type}\n onClose={() => setOpenWalletStateModal('')}\n image={wallet.image}\n state={wallet.state}\n error={error}\n />\n {!!experimentalChainWallet && (\n <Modal\n open={!!experimentalChainWallet && showExperimentalChainModal}\n container={modalContainer}\n onClose={() => {\n setExperimentalChainWallet(null);\n }}>\n <MessageBox\n title={i18n.t({\n id: 'addBlockchain',\n message: 'Add {blockchainDisplayName} Chain',\n values: { blockchainDisplayName },\n })}\n type=\"warning\"\n description={i18n.t({\n id: 'addBlockchainDescription',\n message:\n 'You should connect a {blockchainDisplayName} supported wallet or choose a different {blockchainDisplayName} address',\n values: { blockchainDisplayName },\n })}>\n <Divider size={18} />\n <Divider size={32} />\n <Button\n onClick={addExperimentalChain.bind(\n null,\n experimentalChainWallet\n )}\n variant=\"outlined\"\n type=\"primary\"\n fullWidth\n size=\"large\">\n {i18n.t('Confirm')}\n </Button>\n </MessageBox>\n </Modal>\n )}\n {addingExperimentalChainStatus && (\n <Modal\n open={!!addingExperimentalChainStatus}\n onClose={setAddingExperimentalChainStatus.bind(null, null)}\n container={modalContainer}>\n {addingExperimentalChainStatus === 'in-progress' ? (\n <MessageBox\n type=\"loading\"\n title={i18n.t({\n id: 'addBlockchain',\n message: 'Add {blockchainDisplayName} Chain',\n values: { blockchainDisplayName },\n })}\n description={i18n.t({\n id: 'addBlockchainDescription',\n message:\n 'You should connect a {blockchainDisplayName} supported wallet or choose a different {blockchainDisplayName} address',\n values: { blockchainDisplayName },\n })}\n icon={\n <LogoContainer>\n <WalletImageContainer>\n <Image src={wallet.image} size={45} />\n </WalletImageContainer>\n <Spinner />\n </LogoContainer>\n }\n />\n ) : (\n <MessageBox\n type=\"success\"\n title={i18n.t({\n id: 'blockchainAdded',\n message: '{blockchainDisplayName} Chain Added',\n values: { blockchainDisplayName },\n })}\n description={i18n.t({\n id: 'blockchainAddedDescription',\n message:\n '{blockchainDisplayName} is added to your wallet, you can use it to swap.',\n values: { blockchainDisplayName },\n })}\n />\n )}\n <Divider direction=\"vertical\" size={32} />\n </Modal>\n )}\n <SelectableWallet\n key={wallet.type}\n description={connectedWalletDescription}\n onClick={onClick}\n selected={isSelected(wallet.type, chain)}\n {...wallet}\n />\n </>\n );\n })}\n {shouldShowMoreWallets && (\n <WalletButton selected={false} onClick={onShowMore.bind(null)}>\n <Typography variant=\"label\" size=\"medium\">\n {i18n.t('Show more wallets')}\n <Typography variant=\"label\" size=\"medium\" color=\"$primary\">\n +{numberOfSupportedWallets - (limit ?? 0)}\n </Typography>\n </Typography>\n </WalletButton>\n )}\n </>\n );\n}\n", "import type { WidgetConfig } from '../types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { WalletState } from '@rango-dev/ui';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport {\n KEPLR_COMPATIBLE_WALLETS,\n type WalletType,\n WalletTypes,\n} from '@rango-dev/wallets-shared';\nimport { useEffect, useState } from 'react';\n\nimport { useMetaStore } from '../store/meta';\nimport { useWalletsStore } from '../store/wallets';\nimport { configWalletsToWalletName } from '../utils/providers';\nimport {\n isExperimentalChain,\n mapWalletTypesToWalletInfo,\n sortWalletsBasedOnConnectionState,\n} from '../utils/wallets';\n\nconst ALL_SUPPORTED_WALLETS = Object.values(WalletTypes);\n\ninterface Params {\n config?: WidgetConfig;\n chain?: string;\n onBeforeConnect?: (walletType: string) => void;\n onConnect?: (walletType: string) => void;\n}\n\n/**\n * gets list of wallets with their information and an action for handling click callback fo UI\n * we need to share the logic of rendering list of wallets and handle clicking on them in different places\n * you can use this list whenever you need to show the list of wallets and needed callbacks\n */\nexport function useWalletList(params: Params) {\n const { config, chain, onBeforeConnect, onConnect } = params;\n const { state, disconnect, getWalletInfo, connect } = useWallets();\n const { connectedWallets } = useWalletsStore();\n const { blockchains } = useMetaStore().meta;\n const multiWallets =\n typeof config?.multiWallets === 'undefined' ? true : config.multiWallets;\n\n /** It can be what has been set by widget config or as a fallback we use all the supported wallets by our library */\n const listAvailableWalletTypes =\n configWalletsToWalletName(config?.wallets, {\n walletConnectProjectId: config?.walletConnectProjectId,\n }) || ALL_SUPPORTED_WALLETS;\n\n const wallets = mapWalletTypesToWalletInfo(\n state,\n getWalletInfo,\n listAvailableWalletTypes,\n chain\n );\n\n const sortedWallets = sortWalletsBasedOnConnectionState(wallets);\n const [error, setError] = useState('');\n\n const isExperimentalChainNotAdded = (walletType: string) =>\n !connectedWallets.find(\n (connectedWallet) =>\n connectedWallet.walletType === walletType &&\n connectedWallet.chain === chain\n );\n\n const handleClick = async (type: WalletType) => {\n const wallet = state(type);\n try {\n if (error) {\n setError('');\n }\n if (wallet.connected) {\n await disconnect(type);\n } else {\n const atLeastOneWalletIsConnected = !!wallets.find(\n (w) => w.state === WalletState.CONNECTED\n );\n if (!multiWallets && atLeastOneWalletIsConnected) {\n return;\n }\n onBeforeConnect?.(type);\n await connect(type);\n onConnect?.(type);\n }\n } catch (e) {\n setError('Error: ' + (e as any)?.message);\n }\n };\n\n const disconnectConnectingWallets = () => {\n const connectingWallets =\n wallets?.filter((wallet) => wallet.state === WalletState.CONNECTING) ||\n [];\n for (const wallet of connectingWallets) {\n void disconnect(wallet.type);\n }\n };\n\n useEffect(() => {\n return () => {\n disconnectConnectingWallets();\n };\n }, []);\n\n const shouldExcludeWallet = (\n walletType: string,\n chain: string,\n blockchains: BlockchainMeta[]\n ) => {\n return (\n isExperimentalChain(blockchains, chain) &&\n isExperimentalChainNotAdded(walletType) &&\n !KEPLR_COMPATIBLE_WALLETS.includes(walletType)\n );\n };\n\n return {\n list: sortedWallets.filter(\n (wallet) => !shouldExcludeWallet(wallet.type, chain ?? '', blockchains)\n ),\n error,\n handleClick,\n };\n}\n", "import type { WidgetConfig } from '../types';\nimport type { WalletType } from '@rango-dev/wallets-shared';\n\nimport { i18n } from '@lingui/core';\nimport { styled, Typography, Wallet, WalletState } from '@rango-dev/ui';\nimport React, { Fragment, useState } from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { WalletModal } from '../components/WalletModal';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useWalletList } from '../hooks/useWalletList';\nimport { useMetaStore } from '../store/meta';\nimport { getContainer } from '../utils/common';\n\ninterface PropTypes {\n supportedWallets: WidgetConfig['wallets'];\n multiWallets: boolean;\n config?: WidgetConfig;\n}\n\nconst ListContainer = styled('div', {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: ' repeat(3, minmax(0, 1fr))',\n alignContent: 'baseline',\n paddingTop: '$15',\n height: '100%',\n});\n\nconst Container = styled('div', {\n textAlign: 'center',\n});\n\nexport const TIME_TO_CLOSE_MODAL = 3_000;\nexport const TIME_TO_IGNORE_MODAL = 300;\n\nexport function WalletsPage({ config }: PropTypes) {\n const { navigateBackFrom } = useNavigateBack();\n const [openModal, setOpenModal] = useState(false);\n const [selectedWalletType, setSelectedWalletType] = useState<WalletType>('');\n let modalTimerId: ReturnType<typeof setTimeout> | null = null;\n\n const { list, handleClick, error } = useWalletList({\n config,\n onBeforeConnect: (type) => {\n modalTimerId = setTimeout(() => {\n setOpenModal(true);\n setSelectedWalletType(type);\n }, TIME_TO_IGNORE_MODAL);\n },\n onConnect: () => {\n if (modalTimerId) {\n clearTimeout(modalTimerId);\n }\n setTimeout(() => {\n setOpenModal(false);\n }, TIME_TO_CLOSE_MODAL);\n },\n });\n\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n const selectedWallet = list.find(\n (wallet) => wallet.type === selectedWalletType\n );\n const selectedWalletImage = selectedWallet?.image || '';\n const selectedWalletState =\n selectedWallet?.state || WalletState.NOT_INSTALLED;\n\n return (\n <Layout\n header={{\n title: i18n.t('Connect Wallets'),\n onBack: navigateBackFrom.bind(null, navigationRoutes.wallets),\n }}>\n <Container>\n <Typography variant=\"title\" size=\"xmedium\" align=\"center\">\n {i18n.t('Choose a wallet to connect.')}\n </Typography>\n <ListContainer>\n {list.map((wallet, index) => {\n const key = `wallet-${index}-${wallet.type}`;\n return (\n <Fragment key={key}>\n <Wallet\n {...wallet}\n container={getContainer()}\n onClick={(type) => {\n void handleClick(type);\n }}\n isLoading={loadingMetaStatus === 'loading'}\n />\n </Fragment>\n );\n })}\n <WalletModal\n open={!!openModal}\n onClose={() => setOpenModal(false)}\n image={selectedWalletImage}\n state={selectedWalletState}\n error={error}\n />\n </ListContainer>\n </Container>\n </Layout>\n );\n}\n", "import type { PropTypes } from './WalletModal.types';\n\nimport { Divider, Modal } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { ModalContent } from './WalletModalContent';\n\nexport function WalletModal(props: PropTypes) {\n const { open, onClose, ...otherProps } = props;\n\n return (\n <Modal\n open={open}\n onClose={onClose}\n container={document.getElementById('swap-box') || document.body}>\n <ModalContent {...otherProps} />\n <Divider direction=\"vertical\" size={32} />\n </Modal>\n );\n}\n", "import type { ModalContentProps } from './WalletModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { Image, MessageBox, WalletState } from '@rango-dev/ui';\nimport React from 'react';\n\nimport {\n LogoContainer,\n Spinner,\n WalletImageContainer,\n} from './WalletModalContent.styles';\n\nexport function ModalContent(props: ModalContentProps) {\n const { state, image, error } = props;\n if (state === WalletState.CONNECTED) {\n return (\n <MessageBox\n type=\"success\"\n title={i18n.t('Wallet Connected')}\n description={i18n.t(\n 'Your wallet is connected, you can use it to swap.'\n )}\n />\n );\n }\n\n if (error) {\n return (\n <MessageBox\n type=\"error\"\n title={i18n.t('Failed to Connect')}\n description={\n error || i18n.t('Your wallet is not connected. Please try again.')\n }\n />\n );\n }\n\n return (\n <MessageBox\n type=\"loading\"\n title={i18n.t('Connecting to your wallet')}\n description={i18n.t('Click connect in your wallet popup.')}\n icon={\n <LogoContainer>\n <WalletImageContainer>\n <Image src={image} size={45} />\n </WalletImageContainer>\n <Spinner />\n </LogoContainer>\n }\n />\n );\n}\n", "import { keyframes, styled } from '@rango-dev/ui';\n\nexport const IconContainer = styled('div', {\n borderRadius: '$lg',\n width: '$45',\n height: '$45',\n backgroundColor: '$success300',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n});\n\nexport const LogoContainer = styled('div', {\n position: 'relative',\n});\n\nconst spin = keyframes({\n '0%': {\n transform: 'rotate(0deg)',\n },\n '100%': {\n transform: 'rotate(360deg)',\n },\n});\n\nexport const Spinner = styled('div', {\n position: 'absolute',\n border: '2px solid rgba(0, 0, 0, 0.1)',\n borderTop: '2px solid $info500',\n borderRadius: '$lg',\n width: '$45',\n height: '$45',\n animation: `${spin} 1s linear infinite`,\n top: 0,\n bottom: 0,\n right: 0,\n left: 0,\n});\n\nexport const WalletImageContainer = styled('div', {\n '& img': {\n borderRadius: '50%',\n },\n});\n", "import { useInRouterContext, useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useBestRouteStore } from '../store/bestRoute';\n\nexport function useNavigateBack() {\n const isRouterInContext = useInRouterContext();\n const navigate = useNavigate();\n const routeWalletsConfirmed = useBestRouteStore.use.routeWalletsConfirmed();\n\n navigationRoutes;\n\n const navigateBackFrom = (currentRoute: string) => {\n if (currentRoute === navigationRoutes.swapDetails) {\n return navigate('/' + navigationRoutes.swaps, { replace: true });\n }\n\n if (\n !isRouterInContext ||\n (window.history.state && window.history.state.idx > 0)\n ) {\n // eslint-disable-next-line @typescript-eslint/no-magic-numbers\n navigate(-1);\n } else {\n if (\n [navigationRoutes.settings, navigationRoutes.wallets].includes(\n currentRoute\n ) &&\n routeWalletsConfirmed\n ) {\n return navigate('/' + navigationRoutes.confirmSwap, { replace: true });\n }\n if (\n [\n navigationRoutes.fromSwap,\n navigationRoutes.toSwap,\n navigationRoutes.settings,\n navigationRoutes.wallets,\n navigationRoutes.swaps,\n navigationRoutes.confirmSwap,\n ].includes(currentRoute)\n ) {\n navigate(navigationRoutes.home, { replace: true });\n } else if (currentRoute === navigationRoutes.fromBlockchain) {\n navigate('/' + navigationRoutes.fromSwap, { replace: true });\n } else if (currentRoute === navigationRoutes.toBlockchain) {\n navigate('/' + navigationRoutes.fromSwap, { replace: true });\n } else if (currentRoute === navigationRoutes.liquiditySources) {\n navigate('/' + navigationRoutes.settings, { replace: true });\n }\n }\n };\n\n return { navigateBackFrom };\n}\n", "import { keyframes, styled } from '@rango-dev/ui';\n\nexport const LogoContainer = styled('div', {\n position: 'relative',\n});\n\nconst SpinAnimation = keyframes({\n '0%': {\n transform: 'rotate(0deg)',\n },\n '100%': {\n transform: 'rotate(360deg)',\n },\n});\n\nexport const Spinner = styled('div', {\n position: 'absolute',\n border: '2px solid rgba(0, 0, 0, 0.1)',\n borderTop: '2px solid $info500',\n borderRadius: '$lg',\n width: '$45',\n height: '$45',\n animation: `${SpinAnimation} 1s linear infinite`,\n top: 0,\n bottom: 0,\n right: 0,\n left: 0,\n});\n\nexport const WalletImageContainer = styled('div', {\n '& img': {\n borderRadius: '50%',\n },\n});\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type {\n ConfirmSwapError,\n ConfirmSwapWarnings,\n PendingSwapSettings,\n Wallet,\n} from '../types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport type { BestRouteResponse } from 'rango-sdk';\n\nimport { calculatePendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport BigNumber from 'bignumber.js';\nimport { useEffect } from 'react';\n\nimport { errorMessages } from '../constants/errors';\nimport { HIGH_SLIPPAGE } from '../constants/swapSettings';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { useWalletsStore } from '../store/wallets';\nimport {\n ConfirmSwapErrorTypes,\n RouteWarningType,\n SlippageWarningType,\n} from '../types';\nimport { numberToString } from '../utils/numbers';\nimport {\n isNumberOfSwapsChanged,\n isRouteChanged,\n isRouteInternalCoinsUpdated,\n isRouteSwappersUpdated,\n} from '../utils/routing';\nimport {\n createBestRouteRequestBody,\n getBalanceWarnings,\n getMinRequiredSlippage,\n getOutputRatio,\n getPercentageChange,\n getRouteOutputAmount,\n getWalletsForNewSwap,\n hasProperSlippage,\n isOutputAmountChangedALot,\n outputRatioHasWarning,\n} from '../utils/swap';\n\nimport { useFetchBestRoute } from './useFetchBestRoute';\n\nexport type ConfirmSwapFetchResult = {\n swap: PendingSwap | null;\n error: ConfirmSwapError | null;\n warnings: ConfirmSwapWarnings | null;\n};\n\nexport type ConfirmSwap = {\n loading: boolean;\n fetch: (params: Params) => Promise<ConfirmSwapFetchResult>;\n cancelFetch: () => void;\n};\n\ntype Params = {\n selectedWallets: Wallet[];\n customDestination?: string;\n};\n\n/**\n * A request can be successful but in body of the response, it can be some case which is considered as failed.\n */\nfunction throwErrorIfResponseIsNotValid(\n response: BestRouteResponse,\n params: { inputUsdValue: BigNumber | null; outputUsdValue: number | null }\n) {\n if (!response.result) {\n throw new Error(errorMessages().noRoutesError.title, {\n cause: {\n type: ConfirmSwapErrorTypes.NO_ROUTE,\n diagnosisMessage: response.diagnosisMessages?.[0],\n },\n });\n }\n\n const newRouteOutputUsdValue = new BigNumber(\n response.result?.outputAmount || '0'\n ).multipliedBy(params.outputUsdValue || 0);\n\n const outputRatio = getOutputRatio(\n params.inputUsdValue,\n newRouteOutputUsdValue\n );\n const highValueLoss = outputRatioHasWarning(\n params.inputUsdValue,\n outputRatio\n );\n\n if (highValueLoss) {\n throw new Error('High value loss for route', {\n cause: {\n type: ConfirmSwapErrorTypes.ROUTE_UPDATED_WITH_HIGH_VALUE_LOSS,\n },\n });\n }\n\n return response;\n}\n\nfunction generateWarnings(\n previousRoute: BestRouteResponse,\n currentRoute: BestRouteResponse,\n params: {\n selectedWallets: Wallet[];\n userSlippage: number;\n }\n): ConfirmSwapWarnings {\n const routeChanged = isRouteChanged(previousRoute, currentRoute);\n const output: ConfirmSwapWarnings = {\n balance: null,\n route: null,\n slippage: null,\n };\n\n if (routeChanged) {\n if (isOutputAmountChangedALot(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_AND_OUTPUT_AMOUNT_UPDATED,\n newOutputAmount: numberToString(getRouteOutputAmount(currentRoute)),\n percentageChange: numberToString(\n getPercentageChange(\n getRouteOutputAmount(previousRoute),\n getRouteOutputAmount(currentRoute)\n ),\n null,\n 2\n ),\n };\n } else if (isNumberOfSwapsChanged(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_UPDATED,\n };\n } else if (isRouteSwappersUpdated(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_SWAPPERS_UPDATED,\n };\n } else if (isRouteInternalCoinsUpdated(previousRoute, currentRoute)) {\n output.route = {\n type: RouteWarningType.ROUTE_COINS_UPDATED,\n };\n }\n }\n\n const balanceWarnings = getBalanceWarnings(\n currentRoute,\n params.selectedWallets\n );\n const enoughBalance = balanceWarnings.length === 0;\n\n if (!enoughBalance) {\n output.balance = {\n messages: balanceWarnings,\n };\n }\n\n const minRequiredSlippage = getMinRequiredSlippage(previousRoute);\n const highSlippage = params.userSlippage > HIGH_SLIPPAGE;\n\n if (!hasProperSlippage(params.userSlippage.toString(), minRequiredSlippage)) {\n output.slippage = {\n type: SlippageWarningType.INSUFFICIENT_SLIPPAGE,\n slippage: minRequiredSlippage,\n };\n } else if (highSlippage) {\n output.slippage = {\n type: SlippageWarningType.HIGH_SLIPPAGE,\n slippage: params.userSlippage.toString(),\n };\n }\n\n return output;\n}\n\nexport function useConfirmSwap(): ConfirmSwap {\n const {\n fromToken,\n toToken,\n inputAmount,\n inputUsdValue,\n setRoute,\n bestRoute: initialRoute,\n customDestination: customDestinationFromStore,\n } = useBestRouteStore();\n\n const {\n slippage,\n customSlippage,\n affiliatePercent,\n affiliateRef,\n affiliateWallets,\n disabledLiquiditySources,\n } = useSettingsStore();\n const { connectedWallets } = useWalletsStore();\n\n const { meta } = useMetaStore();\n\n const userSlippage = customSlippage || slippage;\n\n const { fetch: fetchBestRoute, cancelFetch, loading } = useFetchBestRoute();\n\n useEffect(() => cancelFetch, []);\n\n const fetch: ConfirmSwap['fetch'] = async (params: Params) => {\n const selectedWallets = params.selectedWallets;\n const customDestination =\n params?.customDestination ?? customDestinationFromStore;\n\n if (!fromToken || !toToken || !inputAmount || !initialRoute) {\n return {\n route: null,\n swap: null,\n error: null,\n warnings: null,\n };\n }\n\n const requestBody = createBestRouteRequestBody({\n fromToken,\n toToken,\n inputAmount,\n wallets: connectedWallets,\n selectedWallets,\n disabledLiquiditySources,\n slippage: userSlippage,\n affiliateRef,\n affiliatePercent,\n affiliateWallets,\n initialRoute,\n destination: customDestination,\n });\n\n let currentRoute: BestRouteResponse;\n try {\n currentRoute = await fetchBestRoute(requestBody).then((response) =>\n throwErrorIfResponseIsNotValid(response, {\n outputUsdValue: toToken.usdPrice,\n inputUsdValue,\n })\n );\n setRoute(currentRoute);\n } catch (error: any) {\n if (error?.code === 'ERR_CANCELED') {\n return {\n swap: null,\n error: {\n type: ConfirmSwapErrorTypes.REQUEST_CANCELED,\n },\n warnings: null,\n };\n }\n\n if (error.cause) {\n return {\n swap: null,\n error: error.cause,\n warnings: null,\n };\n }\n\n return {\n swap: null,\n error: {\n type: ConfirmSwapErrorTypes.REQUEST_FAILED,\n },\n warnings: null,\n };\n }\n\n const swapSettings: PendingSwapSettings = {\n slippage: userSlippage.toString(),\n disabledSwappersGroups: disabledLiquiditySources,\n };\n const swap = calculatePendingSwap(\n inputAmount.toString(),\n currentRoute,\n getWalletsForNewSwap(selectedWallets),\n swapSettings,\n false,\n meta\n );\n\n return {\n route: currentRoute,\n swap,\n error: null,\n warnings: generateWarnings(initialRoute, currentRoute, {\n selectedWallets,\n userSlippage,\n }),\n };\n };\n\n return {\n loading,\n fetch,\n cancelFetch,\n };\n}\n", "import type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\nimport type { PendingSwapStep } from 'rango-types';\n\nimport { i18n } from '@lingui/core';\nimport { useManager } from '@rango-dev/queue-manager-react';\nimport { Divider, NotFound, styled } from '@rango-dev/ui';\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { Layout } from '../components/Layout';\nimport { SearchInput } from '../components/SearchInput';\nimport { SwapsGroup } from '../components/SwapsGroup';\nimport { NotFoundContainer } from '../components/SwapsGroup/SwapsGroup.styles';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useUiStore } from '../store/ui';\nimport { groupSwapsByDate } from '../utils/date';\nimport { containsText } from '../utils/numbers';\nimport { getPendingSwaps } from '../utils/queue';\n\nconst Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'flex-start',\n height: '100%',\n gap: 15,\n});\n\nconst SwapsGroupContainer = styled('div', {\n overflowY: 'visible',\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n gap: 15,\n height: '100%',\n});\n\nconst isStepContainsText = (steps: PendingSwapStep[], value: string) => {\n if (!steps?.length) {\n return false;\n }\n return steps.filter(\n (step) =>\n containsText(step.fromBlockchain, value) ||\n containsText(step.toBlockchain, value) ||\n containsText(step.toSymbol, value) ||\n containsText(step.fromSymbol, value)\n ).length;\n};\n\nexport function HistoryPage() {\n const setSelectedSwap = useUiStore.use.setSelectedSwap();\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n const { manager, state } = useManager();\n const list: PendingSwap[] = getPendingSwaps(manager).map(({ swap }) => swap);\n const [searchedFor, setSearchedFor] = useState<string>('');\n const loading = !state.loadedFromPersistor;\n\n const searchHandler = (event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n setSearchedFor(value);\n };\n\n let filteredList = list;\n if (searchedFor) {\n filteredList = list.filter(\n (swap) =>\n containsText(swap.inputAmount, searchedFor) ||\n containsText(swap.status, searchedFor) ||\n isStepContainsText(swap.steps, searchedFor) ||\n containsText(swap.requestId, searchedFor)\n );\n }\n\n const isEmpty = !filteredList?.length && !loading;\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.swaps),\n title: i18n.t('History'),\n }}>\n <Container>\n <SearchInput\n setValue={setSearchedFor}\n fullWidth\n variant=\"contained\"\n placeholder={i18n.t('Search Transaction')}\n autoFocus\n onChange={searchHandler}\n value={searchedFor}\n />\n <SwapsGroupContainer>\n {isEmpty && (\n <NotFoundContainer>\n <Divider size={32} />\n <NotFound\n title={i18n.t('No results found')}\n description={\n searchedFor ? i18n.t('Try using different keywords') : ''\n }\n />\n </NotFoundContainer>\n )}\n {!isEmpty && (\n <SwapsGroup\n list={filteredList}\n onSwapClick={(requestId) => {\n setSelectedSwap(requestId);\n navigate(`${requestId}`, { replace: true });\n }}\n groupBy={groupSwapsByDate}\n isLoading={loading}\n />\n )}\n </SwapsGroupContainer>\n </Container>\n </Layout>\n );\n}\n", "import type { PropTypes } from './SearchInput.types';\n\nimport { CloseIcon, IconButton, SearchIcon, TextField } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { IconWrapper } from './SearchInput.styles';\n\nexport function SearchInput(props: PropTypes) {\n const {\n variant,\n fullWidth,\n color,\n size,\n onChange,\n value,\n setValue,\n ...inputAttributes\n } = props;\n\n return (\n <TextField\n prefix={\n <IconWrapper>\n <SearchIcon color=\"black\" />\n </IconWrapper>\n }\n suffix={\n !!value.length && (\n <IconButton\n variant=\"ghost\"\n onClick={() => setValue?.('')}\n size=\"small\">\n <CloseIcon color=\"gray\" size={10} />\n </IconButton>\n )\n }\n fullWidth={fullWidth}\n color={color}\n variant={variant}\n style={{\n padding: 10,\n borderRadius: 25,\n alignItems: 'center',\n }}\n size={size}\n value={value}\n onChange={onChange}\n {...inputAttributes}\n />\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const IconWrapper = styled('div', {\n width: '$24',\n height: '$24',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n});\n", "import type { PropTypes } from './SwapsGroup.types';\n\nimport { i18n } from '@lingui/core';\nimport { Divider, SwapListItem, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { limitDecimalPlaces } from '../../utils/numbers';\n\nimport { Group, SwapList, Time } from './SwapsGroup.styles';\n\nexport function SwapsGroup(props: PropTypes) {\n const { list, onSwapClick, groupBy, isLoading } = props;\n const groups = groupBy ? groupBy(list) : [{ title: 'History', swaps: list }];\n\n if (isLoading) {\n const swaps = [{}, {}];\n\n const loadingGroups = [\n {\n title: 'Today',\n swaps,\n },\n {\n title: 'Last month',\n swaps,\n },\n ];\n return (\n <>\n {loadingGroups.map((group) => (\n <React.Fragment key={group.title}>\n <Group>\n <Time>\n <Typography\n variant=\"label\"\n size=\"medium\"\n color=\"neutral600\"\n className=\"group-title\">\n {i18n.t(group.title)}\n </Typography>\n </Time>\n <Divider size={4} />\n <SwapList>\n {group.swaps.map((_, index) => {\n const key = index + group.title;\n return (\n <React.Fragment key={key}>\n <SwapListItem isLoading={true} />\n </React.Fragment>\n );\n })}\n </SwapList>\n </Group>\n </React.Fragment>\n ))}\n </>\n );\n }\n\n return (\n <>\n {groups\n .filter((group) => group.swaps.length > 0)\n .map((group) => (\n <React.Fragment key={group.title}>\n <Group>\n <Time>\n <Typography\n variant=\"label\"\n size=\"medium\"\n color=\"neutral600\"\n className=\"group-title\">\n {i18n.t(group.title)}\n </Typography>\n </Time>\n <Divider size={4} />\n <SwapList>\n {group.swaps.map((swap) => {\n const firstStep = swap.steps[0];\n const lastStep = swap.steps[swap.steps.length - 1];\n return (\n <React.Fragment key={swap.requestId}>\n <SwapListItem\n requestId={swap.requestId}\n creationTime={swap.creationTime}\n status={swap.status}\n onClick={onSwapClick}\n onlyShowTime={group.title === 'Today'}\n swapTokenData={{\n from: {\n token: {\n image: firstStep.fromLogo,\n displayName: firstStep.fromSymbol,\n },\n blockchain: {\n image: firstStep.fromBlockchainLogo || '',\n },\n amount: limitDecimalPlaces(swap.inputAmount),\n },\n to: {\n token: {\n image: lastStep.toLogo,\n displayName: lastStep.toSymbol,\n },\n blockchain: {\n image: lastStep.toBlockchainLogo || '',\n },\n amount: limitDecimalPlaces(\n lastStep.outputAmount || ''\n ),\n estimatedAmount: limitDecimalPlaces(\n lastStep.expectedOutputAmountHumanReadable || ''\n ),\n },\n }}\n />\n </React.Fragment>\n );\n })}\n </SwapList>\n </Group>\n </React.Fragment>\n ))}\n </>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Group = styled('div', {\n width: '100%',\n display: 'flex',\n flexDirection: 'column',\n});\n\nexport const Time = styled('div', {\n display: 'flex',\n justifyContent: 'flex-start',\n padding: '$2',\n});\n\nexport const SwapList = styled('div', {\n gap: '$10',\n display: 'flex',\n flexDirection: 'column',\n});\n\nexport const NotFoundContainer = styled('div', {\n height: '100%',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n});\n", "import type { GroupBy } from '../components/SwapsGroup/SwapsGroup.types';\nimport type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\n\nimport dayjs from 'dayjs';\n\nexport const groupSwapsByDate: GroupBy = (swaps) => {\n const output: Map<\n string,\n {\n title: string;\n swaps: PendingSwap[];\n }\n > = new Map([\n [\n 'today',\n {\n title: 'Today',\n swaps: [],\n },\n ],\n [\n 'month',\n {\n title: 'Last month',\n swaps: [],\n },\n ],\n [\n 'year',\n {\n title: 'Last year',\n swaps: [],\n },\n ],\n [\n 'history',\n {\n title: 'History',\n swaps: [],\n },\n ],\n ]);\n\n const now = dayjs();\n swaps.forEach((swap) => {\n const swapDate = dayjs(Number(swap.creationTime));\n if (now.isSame(swapDate, 'day')) {\n output.get('today')?.swaps.push(swap);\n } else if (now.isSame(swapDate, 'month')) {\n output.get('month')?.swaps.push(swap);\n } else if (now.isSame(swapDate, 'year')) {\n output.get('year')?.swaps.push(swap);\n } else {\n output.get('history')?.swaps.push(swap);\n }\n });\n\n return Array.from(output.values());\n};\n", "import { Manager } from '@rango-dev/queue-manager-core';\nimport {\n PendingSwapWithQueueID,\n SwapStorage,\n} from '@rango-dev/queue-manager-rango-preset';\n\nexport const getPendingSwaps = (manager: Manager | undefined) => {\n const result: PendingSwapWithQueueID[] = [];\n\n manager?.getAll().forEach((q, id) => {\n const storage = q.list.getStorage() as SwapStorage;\n\n if (storage?.swapDetails) {\n result.push({\n id,\n swap: storage?.swapDetails,\n });\n }\n });\n\n return result.sort(\n (a, b) => Number(b.swap.creationTime) - Number(a.swap.creationTime)\n );\n};\n", "import { i18n } from '@lingui/core';\nimport {\n List,\n ListItemButton,\n Radio,\n RadioRoot,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { SettingsContainer } from '../components/SettingsContainer';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useLanguage } from '../hooks/useLanguage';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\n\nexport function LanguagePage() {\n const { navigateBackFrom } = useNavigateBack();\n\n const { activeLanguage, changeLanguage, languages } = useLanguage();\n\n const languageList = languages.map((languageItem) => {\n const { local, label, SVGFlag } = languageItem;\n return {\n id: local,\n value: local,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {label}\n </Typography>\n ),\n onClick: () => changeLanguage(languageItem.local),\n end: <Radio value={local} />,\n start: <SVGFlag />,\n };\n });\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t('Language'),\n }}>\n <SettingsContainer>\n <RadioRoot value={activeLanguage}>\n <List\n type={\n <ListItemButton\n title={i18n.t('language')}\n id=\"_\"\n onClick={() => console.log()}\n />\n }\n items={languageList}\n />\n </RadioRoot>\n </SettingsContainer>\n </Layout>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const SettingsContainer = styled('div', {\n height: '100%',\n overflow: 'hidden',\n});\n\nexport const LiquiditySourceList = styled('ul', {\n padding: '$15 $5 0',\n margin: 0,\n listStyle: 'none',\n height: '100%',\n overflowY: 'auto',\n});\n\nexport const LiquiditySourceSuffix = styled('div', {\n width: 80,\n display: 'flex',\n justifyContent: 'flex-end',\n});\n\nexport const NotFoundContainer = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n height: '100%',\n});\n", "import type { LanguageItem } from '../constants/languages';\n\nimport { type Language } from '@rango-dev/ui';\n\nimport { DEFAULT_LANGUAGE, LANGUAGES } from '../constants/languages';\nimport { useSettingsStore } from '../store/settings';\n\ninterface UseLanguage {\n languages: LanguageItem[];\n defaultLanguage: Language;\n activeLanguage: Language;\n changeLanguage: (language: Language) => void;\n}\n\nexport function useLanguage(): UseLanguage {\n const language = useSettingsStore.use.language();\n const setLanguage = useSettingsStore.use.setLanguage();\n const languages = LANGUAGES;\n const defaultLanguage = DEFAULT_LANGUAGE;\n\n return {\n activeLanguage: language,\n languages,\n defaultLanguage,\n changeLanguage: setLanguage,\n };\n}\n", "import type {\n LiquiditySourceType,\n UniqueSwappersGroupType,\n} from '../utils/settings';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Checkbox,\n Image,\n ListItemButton,\n NotFound,\n Typography,\n} from '@rango-dev/ui';\nimport React, { useState } from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { LoadingLiquiditySourceList } from '../components/LoadingLiquiditySourceList';\nimport { SearchInput } from '../components/SearchInput';\nimport {\n LiquiditySourceList,\n LiquiditySourceSuffix,\n NotFoundContainer,\n SettingsContainer,\n} from '../components/SettingsContainer';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { containsText } from '../utils/numbers';\nimport {\n getUniqueSwappersGroups,\n sortLiquiditySourcesByGroupTitle,\n} from '../utils/settings';\n\ninterface PropTypes {\n supportedSwappers?: string[];\n sourceType: 'Exchanges' | 'Bridges';\n}\n\nexport function LiquiditySourcePage({\n supportedSwappers,\n sourceType,\n}: PropTypes) {\n const [searchedFor, setSearchedFor] = useState<string>('');\n const toggleLiquiditySource = useSettingsStore.use.toggleLiquiditySource();\n const { navigateBackFrom } = useNavigateBack();\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n\n const supportedUniqueSwappersGroups: Array<UniqueSwappersGroupType> =\n getUniqueSwappersGroups(supportedSwappers);\n\n const validTypes: Array<LiquiditySourceType> = [];\n if (sourceType === 'Exchanges') {\n validTypes.push('DEX');\n }\n if (sourceType === 'Bridges') {\n validTypes.push('BRIDGE');\n validTypes.push('AGGREGATOR');\n }\n\n const liquiditySources = supportedUniqueSwappersGroups.filter((uniqueItem) =>\n validTypes.includes(uniqueItem.type)\n );\n\n const hasSelectAll =\n liquiditySources.length ===\n liquiditySources.filter((sourceItem) => sourceItem.selected).length;\n\n const toggleAllSources = () => {\n liquiditySources.forEach((sourceItem) => {\n if (hasSelectAll) {\n toggleLiquiditySource(sourceItem.groupTitle);\n } else {\n if (!sourceItem.selected) {\n toggleLiquiditySource(sourceItem.groupTitle);\n }\n }\n });\n };\n\n const list = liquiditySources\n .sort(sortLiquiditySourcesByGroupTitle)\n .map((sourceItem) => {\n const { selected, groupTitle, logo } = sourceItem;\n return {\n start: <Image src={logo} size={22} type=\"circular\" />,\n onClick: () => toggleLiquiditySource(groupTitle),\n end: <Checkbox checked={selected} />,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t(groupTitle)}\n </Typography>\n ),\n ...sourceItem,\n };\n });\n\n const searchHandler = (event: React.ChangeEvent<HTMLInputElement>) => {\n const value = event.target.value;\n setSearchedFor(value);\n };\n\n let filteredList = list;\n if (searchedFor) {\n filteredList = list.filter((sourceItem) =>\n containsText(sourceItem.groupTitle, searchedFor)\n );\n }\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t(sourceType),\n suffix: (\n <LiquiditySourceSuffix>\n <Button variant=\"ghost\" size=\"xsmall\" onClick={toggleAllSources}>\n {i18n.t(hasSelectAll ? 'Deselect all' : 'Select all')}\n </Button>\n </LiquiditySourceSuffix>\n ),\n }}>\n <SettingsContainer>\n <SearchInput\n value={searchedFor}\n setValue={setSearchedFor}\n fullWidth\n color=\"light\"\n variant=\"contained\"\n placeholder={i18n.t('Search {sourceType}', { sourceType })}\n onChange={searchHandler}\n />\n {loadingMetaStatus === 'loading' && <LoadingLiquiditySourceList />}\n\n {!filteredList.length && !!searchedFor ? (\n <NotFoundContainer>\n <NotFound\n title={i18n.t('No results found')}\n description={i18n.t('Try using different keywords')}\n />\n </NotFoundContainer>\n ) : (\n loadingMetaStatus === 'success' && (\n <LiquiditySourceList>\n {filteredList.map((sourceItem) => {\n return (\n <React.Fragment key={sourceItem.id}>\n <ListItemButton\n style={{ height: '61px' }}\n {...sourceItem}\n selected={false}\n hasDivider\n />\n </React.Fragment>\n );\n })}\n </LiquiditySourceList>\n )\n )}\n </SettingsContainer>\n </Layout>\n );\n}\n", "import { Checkbox, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { LiquiditySourceList } from '../SettingsContainer';\n\nimport { CustomeListItem } from './LoadingLiquiditySourceList.styles';\n\nconst ITEM_SKELETON_COUNT = 30;\nexport function LoadingLiquiditySourceList() {\n return (\n <LiquiditySourceList>\n {Array.from(Array(ITEM_SKELETON_COUNT), (e) => (\n <CustomeListItem\n hasDivider\n key={e}\n start={<Skeleton variant=\"circular\" width={35} height={35} />}\n title={<Skeleton variant=\"text\" size=\"large\" width={90} />}\n end={<Checkbox checked={false} />}\n />\n ))}\n </LiquiditySourceList>\n );\n}\n", "import { ListItem, styled } from '@rango-dev/ui';\n\nexport const CustomeListItem = styled(ListItem, {\n height: 61,\n});\n", "import { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\n\nimport { removeDuplicateFrom } from './common';\n\nexport type LiquiditySourceType = 'BRIDGE' | 'AGGREGATOR' | 'DEX';\n\nexport type UniqueSwappersGroupType = {\n id: string;\n groupTitle: string;\n logo: string;\n type: LiquiditySourceType;\n selected: boolean;\n};\n\nexport function getUniqueSwappersGroups(\n supportedSwappers?: string[]\n): UniqueSwappersGroupType[] {\n const swappers = useMetaStore.use.meta().swappers;\n const disabledLiquiditySources =\n useSettingsStore.use.disabledLiquiditySources();\n\n const uniqueSupportedSwappersGroups: Array<UniqueSwappersGroupType> = [];\n\n const uniqueGroup = removeDuplicateFrom(swappers.map((s) => s.swapperGroup));\n\n uniqueGroup.map((uniqueGroupItem) => {\n const swapperItem = swappers.find(\n (swapper) => swapper.swapperGroup === uniqueGroupItem\n );\n\n if (swapperItem) {\n let isSupportedSwapper = true;\n if (supportedSwappers) {\n isSupportedSwapper = supportedSwappers.some(\n (supportedItem) => supportedItem === swapperItem.swapperGroup\n );\n }\n\n if (isSupportedSwapper) {\n swapperItem.types.map((swapperTypeItem) => {\n uniqueSupportedSwappersGroups.push({\n id: swapperItem.swapperGroup,\n groupTitle: swapperItem.swapperGroup,\n logo: swapperItem.logo,\n type: swapperTypeItem,\n selected: !disabledLiquiditySources.includes(\n swapperItem.swapperGroup\n ),\n });\n });\n }\n }\n });\n\n return uniqueSupportedSwappersGroups;\n}\n\nexport function sortLiquiditySourcesByGroupTitle(\n a: UniqueSwappersGroupType,\n b: UniqueSwappersGroupType\n) {\n if (a.groupTitle < b.groupTitle) {\n return -1;\n }\n\n if (a.groupTitle > b.groupTitle) {\n return 1;\n }\n\n return 0;\n}\n", "import { i18n } from '@lingui/core';\nimport { Divider, SelectableCategoryList } from '@rango-dev/ui';\nimport React, { useState } from 'react';\n\nimport { BlockchainList } from '../components/BlockchainList';\nimport { Layout } from '../components/Layout';\nimport { SearchInput } from '../components/SearchInput';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useAppStore } from '../store/app';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useMetaStore } from '../store/meta';\n\ninterface PropTypes {\n type: 'source' | 'destination';\n}\n\nexport function SelectBlockchainPage(props: PropTypes) {\n const { type } = props;\n const { navigateBackFrom } = useNavigateBack();\n const [searchedFor, setSearchedFor] = useState<string>('');\n const [blockchainCategory, setBlockchainCategory] = useState<string>('ALL');\n const setToBlockchain = useBestRouteStore.use.setToBlockchain();\n const setFromBlockchain = useBestRouteStore.use.setFromBlockchain();\n const { loadingStatus } = useMetaStore();\n\n const blockchains = useAppStore().blockchains({\n type: type,\n });\n const routeKey = type === 'source' ? 'fromBlockchain' : 'toBlockchain';\n\n return (\n <Layout\n header={{\n onBack: () => {\n navigateBackFrom(navigationRoutes[routeKey]);\n },\n title: i18n.t(`Select Blockchain`),\n }}>\n <Divider size={12} />\n <SelectableCategoryList\n setCategory={setBlockchainCategory}\n category={blockchainCategory}\n blockchains={blockchains}\n isLoading={loadingStatus === 'loading'}\n />\n <Divider size={24} />\n <SearchInput\n value={searchedFor}\n autoFocus\n placeholder={i18n.t('Search Blockchain')}\n color=\"light\"\n variant=\"contained\"\n size=\"large\"\n setValue={() => setSearchedFor('')}\n onChange={(event) => setSearchedFor(event.target.value)}\n />\n <Divider size={16} />\n\n <BlockchainList\n list={blockchains}\n searchedFor={searchedFor}\n blockchainCategory={blockchainCategory}\n onChange={(blockchain) => {\n if (type === 'source') {\n setFromBlockchain(blockchain);\n } else {\n setToBlockchain(blockchain);\n }\n\n navigateBackFrom(navigationRoutes[routeKey]);\n }}\n />\n </Layout>\n );\n}\n", "import type { PropTypes } from './BlockchainList.types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport {\n Divider,\n Image,\n ListItemButton,\n NotFound,\n Typography,\n} from '@rango-dev/ui';\nimport React, { useEffect, useState } from 'react';\n\nimport { useMetaStore } from '../../store/meta';\n\nimport { filterBlockchains } from './BlockchainList.helpers';\nimport { Container, List } from './BlockchainList.styles';\nimport { LoadingBlockchainList } from './LoadingBlockchainList';\n\nexport function BlockchainList(props: PropTypes) {\n const { list, searchedFor, onChange, blockchainCategory } = props;\n const [blockchains, setBlockchains] = useState<BlockchainMeta[]>(list);\n const loadingStatus = useMetaStore.use.loadingStatus();\n\n useEffect(() => {\n setBlockchains([\n ...filterBlockchains(list, searchedFor, blockchainCategory),\n ]);\n }, [list, searchedFor, blockchainCategory]);\n\n const renderList = () => {\n if (!blockchains.length && !!searchedFor) {\n return (\n <>\n <Divider size={32} />\n <NotFound\n title={i18n.t('No results found')}\n description={i18n.t('Try using different keywords')}\n />\n </>\n );\n }\n return (\n <List key={`${blockchainCategory}-${searchedFor}`}>\n {blockchains.map((item) => (\n <ListItemButton\n key={`${item.name}-${item.chainId}`}\n hasDivider\n onClick={() => onChange(item)}\n start={<Image src={item.logo} size={30} />}\n title={\n <Typography variant=\"title\" size=\"medium\">\n {item.displayName}\n </Typography>\n }\n id={item.chainId as string}\n />\n ))}\n </List>\n );\n };\n\n return (\n <Container>\n <Typography variant=\"label\" size=\"large\">\n {i18n.t('Select Blockchain')}\n </Typography>\n <Divider size={4} />\n {loadingStatus === 'loading' && <LoadingBlockchainList />}\n {loadingStatus === 'success' && renderList()}\n </Container>\n );\n}\n", "import { BlockchainCategories } from '@rango-dev/ui';\nimport { type BlockchainMeta, TransactionType } from 'rango-sdk';\n\nimport { containsText } from '../../utils/common';\n\nexport const filterByType = (\n blockchain: BlockchainMeta,\n type: string\n): boolean => {\n switch (type) {\n case BlockchainCategories.ALL:\n return true;\n case BlockchainCategories.UTXO:\n return blockchain.type === TransactionType.TRANSFER;\n case BlockchainCategories.OTHER:\n return (\n blockchain.type !== TransactionType.TRANSFER &&\n blockchain.type !== TransactionType.COSMOS &&\n blockchain.type !== TransactionType.EVM\n );\n default:\n return blockchain.type === type;\n }\n};\n\nexport const filterBlockchains = (\n list: BlockchainMeta[],\n searchedFor: string,\n blockchainType: string\n) =>\n list\n .filter((blockchain) => filterByType(blockchain, blockchainType))\n .filter(\n (blockchain) =>\n containsText(blockchain.name, searchedFor) ||\n containsText(blockchain.displayName, searchedFor)\n );\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n overflow: 'hidden',\n});\n\nexport const List = styled('ul', {\n padding: 0,\n margin: 0,\n listStyle: 'none',\n overflowY: 'auto',\n paddingRight: '$5',\n '.image-container': {\n borderRadius: '$xm',\n overflow: 'hidden',\n },\n});\n", "import { ListItem, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { List } from './BlockchainList.styles';\n\nconst ITEM_SKELETON_COUNT = 20;\nexport function LoadingBlockchainList() {\n return (\n <List>\n {Array.from(Array(ITEM_SKELETON_COUNT), (e) => (\n <ListItem\n key={e}\n hasDivider\n start={<Skeleton variant=\"circular\" width={35} height={35} />}\n title={<Skeleton variant=\"text\" size=\"large\" width={90} />}\n />\n ))}\n </List>\n );\n}\n", "import type { BlockchainMeta, Token } from 'rango-sdk';\n\nimport { i18n } from '@lingui/core';\nimport { Divider } from '@rango-dev/ui';\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { BlockchainsSection } from '../components/BlockchainsSection';\nimport { Layout } from '../components/Layout';\nimport { SearchInput } from '../components/SearchInput';\nimport { TokenList } from '../components/TokenList/TokenList';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useAppStore } from '../store/app';\nimport { useBestRouteStore } from '../store/bestRoute';\nimport { useWalletsStore } from '../store/wallets';\nimport { getTokensBalanceFromWalletAndSort } from '../utils/wallets';\n\ninterface PropTypes {\n type: 'source' | 'destination';\n}\n\nexport function SelectSwapItemsPage(props: PropTypes) {\n const { type } = props;\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n const {\n fromBlockchain,\n toBlockchain,\n setFromToken,\n setToToken,\n setFromBlockchain,\n setToBlockchain,\n } = useBestRouteStore();\n const { connectedWallets } = useWalletsStore();\n const [searchedFor, setSearchedFor] = useState<string>('');\n\n const selectedBlockchain = type === 'source' ? fromBlockchain : toBlockchain;\n const selectedBlockchainName = selectedBlockchain?.name ?? '';\n\n // Tokens & Blockchains list\n const blockchains = useAppStore().blockchains({\n type: type,\n });\n const tokens = useAppStore().tokens({\n type,\n blockchain: selectedBlockchainName,\n searchFor: searchedFor,\n });\n const tokensList = getTokensBalanceFromWalletAndSort(\n tokens,\n connectedWallets\n );\n\n // Actions\n const updateBlockchain = (blockchain: BlockchainMeta) => {\n if (type === 'source') {\n setFromBlockchain(blockchain);\n } else {\n setToBlockchain(blockchain);\n }\n };\n\n const updateToken = (token: Token) => {\n if (type === 'source') {\n setFromToken(token);\n } else {\n setToToken(token);\n }\n };\n\n return (\n <Layout\n header={{\n onBack: () =>\n navigateBackFrom(\n type === 'source'\n ? navigationRoutes.fromSwap\n : navigationRoutes.toSwap\n ),\n title: i18n.t('Swap {type}', {\n type: type === 'source' ? 'from' : 'to',\n }),\n }}>\n <BlockchainsSection\n blockchains={blockchains}\n type={type == 'source' ? 'from' : 'to'}\n blockchain={type === 'source' ? fromBlockchain : toBlockchain}\n onMoreClick={() =>\n navigate(\n type === 'source'\n ? navigationRoutes.fromBlockchain\n : navigationRoutes.toBlockchain\n )\n }\n onChange={(blockchain) => {\n updateBlockchain(blockchain);\n }}\n />\n <Divider size={24} />\n <SearchInput\n value={searchedFor}\n autoFocus\n placeholder={i18n.t('Search Token')}\n color=\"light\"\n variant=\"contained\"\n size=\"large\"\n setValue={() => setSearchedFor('')}\n onChange={(event) => setSearchedFor(event.target.value)}\n />\n <Divider size={16} />\n <TokenList\n list={tokensList}\n selectedBlockchain={selectedBlockchainName}\n searchedFor={searchedFor}\n onChange={(token) => {\n updateToken(token);\n\n const tokenBlockchain = blockchains.find(\n (chain) => token.blockchain === chain.name\n );\n if (tokenBlockchain) {\n updateBlockchain(tokenBlockchain);\n }\n\n navigateBackFrom(navigationRoutes.fromSwap);\n }}\n />\n </Layout>\n );\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { PropTypes } from './BlockchainsSection.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n BlockchainsChip,\n Divider,\n Image,\n Skeleton,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { BLOCKCHAIN_LIST_SIZE } from '../../constants/configs';\nimport { usePrepareBlockchainList } from '../../hooks/usePrepareBlockchainList';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { useMetaStore } from '../../store/meta';\n\nimport { Container } from './BlockchainsSection.styles';\n\nconst NUMBER_OF_LOADING = 12;\n\nexport function BlockchainsSection(props: PropTypes) {\n const { blockchains, type, blockchain, onChange, onMoreClick } = props;\n const blockchainsList = usePrepareBlockchainList(blockchains, {\n limit: BLOCKCHAIN_LIST_SIZE,\n selected: blockchain?.name,\n });\n\n const loadingStatus = useMetaStore.use.loadingStatus();\n const resetToBlockchain = useBestRouteStore.use.resetToBlockchain();\n const resetFromBlockchain = useBestRouteStore.use.resetFromBlockchain();\n const hasMoreItemsInList = blockchainsList.more.length > 0;\n /**\n * When only one item is left on list, we will not show the `More` button and will show the item itself instead.\n */\n const onlyOneItemInList = blockchainsList.more.length === 1;\n const showMoreButton = !onlyOneItemInList && hasMoreItemsInList;\n\n return (\n <div>\n <Divider size={12} />\n <Typography variant=\"label\" size=\"large\">\n {i18n.t('Select Blockchain')}\n </Typography>\n <Divider size={12} />\n <Container>\n {loadingStatus === 'loading' &&\n Array.from(Array(NUMBER_OF_LOADING), (e) => (\n <Skeleton key={e} variant=\"rounded\" height={50} />\n ))}\n {loadingStatus === 'success' && (\n <>\n <BlockchainsChip\n selected={!blockchain}\n onClick={() => {\n if (type === 'from') {\n resetFromBlockchain();\n } else {\n resetToBlockchain();\n }\n }}>\n <Typography variant=\"body\" size=\"xsmall\" color=\"secondary500\">\n {i18n.t('All')}\n </Typography>\n </BlockchainsChip>\n {blockchainsList.list.map((item) => (\n <BlockchainsChip\n key={item.name}\n selected={!!blockchain && blockchain.name === item.name}\n onClick={() => onChange(item)}>\n <Image src={item.logo} size={30} />\n </BlockchainsChip>\n ))}\n\n {onlyOneItemInList ? (\n <BlockchainsChip\n key={blockchainsList.more[0].name}\n selected={\n !!blockchain &&\n blockchain.name === blockchainsList.more[0].name\n }\n onClick={() => onChange(blockchainsList.more[0])}>\n <Image src={blockchainsList.more[0].logo} size={30} />\n </BlockchainsChip>\n ) : null}\n\n {showMoreButton ? (\n <BlockchainsChip onClick={onMoreClick} key=\"more-blockchains\">\n <Typography variant=\"body\" size=\"xsmall\" color=\"secondary500\">\n {i18n._('More +{count}', {\n count: blockchainsList.more.length,\n })}\n </Typography>\n </BlockchainsChip>\n ) : null}\n </>\n )}\n </Container>\n </div>\n );\n}\n", "import type {\n PrepareListOptions,\n PrepareListOutput,\n} from './usePrepareBlockchainList.types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { useEffect } from 'react';\n\nimport { useSettingsStore } from '../../store/settings';\n\nimport { prepare } from './usePrepareBlockchainList.helpers';\n\n/**\n *\n * UI needs some specific logics like limiting the list and sorting,\n * this function is getting the raw blockchains list and return a list for showing in UI.\n *\n */\nexport function usePrepareBlockchainList(\n blockchains: BlockchainMeta[],\n options?: PrepareListOptions\n): PrepareListOutput {\n const { preferredBlockchains, addPreferredBlockchain } = useSettingsStore();\n\n useEffect(() => {\n if (options?.selected) {\n addPreferredBlockchain(options?.selected);\n }\n }, [options?.selected]);\n\n const output = prepare(blockchains, preferredBlockchains, options);\n\n return {\n list: output.list,\n more: output.more,\n history: [],\n };\n}\n", "export const MOST_USED_BLOCKChAINS = ['ETH', 'COSMOS', 'OSMOSIS'];\n", "import type { PrepareListOptions } from './usePrepareBlockchainList.types';\nimport type { BlockchainMeta } from 'rango-sdk';\n\nimport { MOST_USED_BLOCKChAINS } from './usePrepareBlockchainList.constants';\n\nexport function prepare(\n blockchains: BlockchainMeta[],\n preferredBlockchains: string[],\n options?: PrepareListOptions\n) {\n /*\n * TODO:\n * We copying the `blockchains` which can causes performance penalties but we should because we are mutating the original object.\n * A better way to solve the problem maybe is using new JS features like Use toSpliced() but\n * we can not use it right now because we need to upgrade our toolings first.\n */\n const list: BlockchainMeta[] = JSON.parse(JSON.stringify(blockchains));\n let more: BlockchainMeta[] = [];\n\n list.sort(sortByMostUsedBlockchains);\n\n // Checking `limit` has set and it should be more than of the list items.\n if (!!options?.limit && blockchains.length > options.limit) {\n const start = options.limit;\n let preferredBlockchainsWithoutMainList = preferredBlockchains;\n\n if (preferredBlockchains.length <= options.limit) {\n /*\n * For first X (limit) numbers, we need to remove them from preferred if exists.\n */\n for (let i = 0; i < options.limit; i++) {\n const blockchain = list[i];\n preferredBlockchainsWithoutMainList =\n preferredBlockchainsWithoutMainList.filter((preferredBlockchain) => {\n return blockchain.name !== preferredBlockchain;\n });\n }\n }\n list.sort(\n generateSortByPreferredBlockchainsFor(preferredBlockchainsWithoutMainList)\n );\n\n /*\n * Splice will modify the original list and returns the deleted items\n * We use the deleted items as `more`\n */\n more = list.splice(start);\n }\n return {\n list,\n more,\n };\n}\n\n/** There is a hardcoded list of blockchains that we want to show them first in the list. */\nexport function sortByMostUsedBlockchains(\n a: BlockchainMeta,\n b: BlockchainMeta\n) {\n const mostUsed = MOST_USED_BLOCKChAINS;\n const aIndexInMostUsed = mostUsed.findIndex((token) => token === a.name);\n const bIndexInMostUsed = mostUsed.findIndex((token) => token === b.name);\n const aIsMostUsed = aIndexInMostUsed > -1;\n const bIsMostUsed = bIndexInMostUsed > -1;\n\n if (aIsMostUsed && bIsMostUsed) {\n return aIndexInMostUsed > bIndexInMostUsed ? 1 : -1;\n }\n\n if (aIsMostUsed) {\n return -1;\n }\n\n if (bIsMostUsed) {\n return 1;\n }\n\n return 0;\n}\n\nexport function generateSortByPreferredBlockchainsFor(\n preferredBlockchains: string[]\n) {\n return function sortByPreferred(a: BlockchainMeta, b: BlockchainMeta) {\n const aIndexInPreferred = preferredBlockchains.findIndex(\n (blockchain) => blockchain === a.name\n );\n const bIndexInPreferred = preferredBlockchains.findIndex(\n (blockchain) => blockchain === b.name\n );\n\n const aIsPreferred = aIndexInPreferred > -1;\n const bIsPreferred = bIndexInPreferred > -1;\n\n if (aIsPreferred && bIsPreferred) {\n return aIndexInPreferred > bIndexInPreferred ? 1 : -1;\n }\n\n if (preferredBlockchains.includes(a.name)) {\n return -1;\n }\n if (preferredBlockchains.includes(b.name)) {\n return 1;\n }\n\n return 0;\n };\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'grid',\n gap: '$10',\n gridTemplateColumns: 'repeat(6, minmax(0, 1fr))',\n});\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type {\n PropTypes,\n RenderDescProps,\n TokenWithBalance,\n} from './TokenList.types';\nimport type { CommonProps } from 'react-window';\n\nimport { i18n } from '@lingui/core';\nimport {\n darkTheme,\n Divider,\n ExternalLinkIcon,\n Image,\n ListItemButton,\n NotFound,\n PinIcon,\n Skeleton,\n Typography,\n VirtualizedList,\n} from '@rango-dev/ui';\nimport React, { forwardRef, useEffect, useState } from 'react';\n\nimport { useAppStore } from '../../store/app';\nimport { useMetaStore } from '../../store/meta';\nimport { useWalletsStore } from '../../store/wallets';\nimport { generateRangeColors } from '../../utils/colors';\n\nimport { LoadingTokenList } from './LoadingTokenList';\nimport {\n BalanceContainer,\n Container,\n End,\n ImageSection,\n List,\n Pin,\n Tag,\n TagTitle,\n Title,\n} from './TokenList.styles';\n\nconst PAGE_SIZE = 20;\n\nconst renderDesc = (props: RenderDescProps) => {\n const { address, name, url, token, customCssForTag, customCssForTagTitle } =\n props;\n const length = address.length;\n\n return (\n <div className=\"description\">\n {name ? (\n <div className=\"token-name\">{name}</div>\n ) : (\n <Title className=\"token-title\">\n <Typography variant=\"title\" size=\"xmedium\">\n {token.symbol}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tag css={customCssForTag}>\n <TagTitle variant=\"body\" size=\"xsmall\" css={customCssForTagTitle}>\n {token.blockchain}\n </TagTitle>\n </Tag>\n </Title>\n )}\n\n {!!address && (\n <div\n className={`token-address ${!name && 'token-address-without-name'}`}>\n <a\n href={url}\n target=\"_blank\"\n rel=\"nofollow noreferrer\"\n onClick={(e) => e.stopPropagation()}>\n {length > 10\n ? `${address.slice(0, 5)}...${address.slice(length - 6, length)}`\n : address}{' '}\n <ExternalLinkIcon color=\"gray\" size={12} />\n </a>\n </div>\n )}\n </div>\n );\n};\n\nexport function TokenList(props: PropTypes) {\n const { list, searchedFor = '', onChange, selectedBlockchain } = props;\n\n const [tokens, setTokens] = useState<TokenWithBalance[]>(list);\n const loadingStatus = useMetaStore.use.loadingStatus();\n const [hasNextPage, setHasNextPage] = useState<boolean>(true);\n const loadingWallet = useWalletsStore.use.loading();\n const { blockchains } = useMetaStore.use.meta();\n const { isTokenPinned } = useAppStore();\n\n // eslint-disable-next-line react/display-name\n const innerElementType: React.FC<CommonProps> = forwardRef((render, ref) => {\n return (\n <div\n {...render}\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref={ref as any}\n style={{\n ...render.style,\n height: `${parseFloat(render.style?.height as string) + 8 * 2}px`,\n }}\n />\n );\n });\n const loadNextPage = () => {\n setTokens(list.slice(0, tokens.length + PAGE_SIZE));\n };\n\n useEffect(() => {\n setHasNextPage(list.length > tokens.length);\n }, [tokens.length]);\n\n useEffect(() => {\n setTokens(list.slice(0, PAGE_SIZE));\n }, [list]);\n\n const renderList = () => {\n if (!tokens.length && !!searchedFor) {\n return (\n <>\n <Divider size={32} />\n <NotFound\n title={i18n.t('No results found')}\n description={i18n.t('Try using different keywords')}\n />\n </>\n );\n }\n return (\n <VirtualizedList\n Item={({ index, style }) => {\n const token = tokens[index];\n\n const address = token.address || '';\n const blockchain = blockchains.find(\n (blockchain) => blockchain.name === token.blockchain\n );\n const color = generateRangeColors(\n token.symbol,\n blockchain?.color || ''\n );\n\n const customCssForTag = {\n $$color: color[`${token.symbol}100`],\n [`.${darkTheme} &`]: {\n $$color: color[`${token.symbol}900`],\n },\n backgroundColor: '$$color',\n };\n\n const customCssForTagTitle = {\n $$color: color[`${token.symbol}700`],\n [`.${darkTheme} &`]: {\n $$color: color[`${token.symbol}100`],\n },\n color: '$$color',\n };\n\n return (\n <div\n style={{\n ...style,\n paddingRight: 5,\n }}>\n <ListItemButton\n style={{\n height: style?.height,\n }}\n tab-index={index}\n key={`${token.symbol}${token.address}`}\n id={`${token.symbol}${token.address}`}\n hasDivider\n onClick={() => onChange(tokens[index])}\n start={\n <ImageSection>\n <Image src={token.image} size={30} />\n {isTokenPinned(token) && (\n <Pin>\n <PinIcon size={12} color=\"gray\" />\n </Pin>\n )}\n </ImageSection>\n }\n title={\n blockchain?.type === 'COSMOS' ||\n !!token.name ||\n (!token.name && !address) ? (\n <Title>\n <Typography variant=\"title\" size=\"xmedium\">\n {token.symbol}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tag css={customCssForTag}>\n <TagTitle\n variant=\"body\"\n size=\"xsmall\"\n css={customCssForTagTitle}>\n {token.blockchain}\n </TagTitle>\n </Tag>\n </Title>\n ) : undefined\n }\n description={\n !!blockchain?.info &&\n !!address &&\n blockchain.type !== 'COSMOS'\n ? renderDesc({\n address,\n token: tokens[index],\n customCssForTag,\n customCssForTagTitle,\n name: token.name,\n url: blockchain.info.addressUrl\n .split('{wallet}')\n .join(address),\n })\n : token.name || undefined\n }\n end={\n loadingWallet ? (\n <End>\n <Skeleton variant=\"text\" size=\"large\" width={70} />\n <Divider size={4} />\n <Skeleton variant=\"text\" size=\"medium\" width={50} />\n </End>\n ) : (\n tokens[index]?.balance && (\n <BalanceContainer>\n <Typography variant=\"title\" size=\"small\">\n {token.balance?.amount}\n </Typography>\n <div />\n {token.balance?.usdValue && (\n <Typography\n variant=\"body\"\n color=\"neutral600\"\n size=\"xsmall\">\n {`$${token.balance?.usdValue}`}\n </Typography>\n )}\n </BalanceContainer>\n )\n )\n }\n />\n </div>\n );\n }}\n hasNextPage={hasNextPage}\n itemCount={tokens.length}\n loadNextPage={loadNextPage}\n innerElementType={innerElementType}\n size={60}\n key={`${selectedBlockchain}-${searchedFor}`}\n />\n );\n };\n\n return (\n <Container>\n <Typography variant=\"label\" size=\"large\">\n {i18n.t('Select Token')}\n </Typography>\n <Divider size={4} />\n {loadingStatus === 'loading' && <LoadingTokenList size={PAGE_SIZE} />}\n {loadingStatus === 'success' && <List>{renderList()}</List>}\n </Container>\n );\n}\n", "import type { WidgetColors, WidgetColorsKeys } from '../types';\n\nexport const colorShade = (col: string, amt: number) => {\n const RANGE = 255;\n const COL = 3;\n const RADIX = 16;\n\n col = col.replace(/^#/, '');\n if (col.length === COL) {\n col = col[0] + col[0] + col[1] + col[1] + col[2] + col[2];\n }\n let [r, g, b]: any = col.match(/.{2}/g);\n [r, g, b] = [\n parseInt(r, RADIX) + amt,\n parseInt(g, RADIX) + amt,\n parseInt(b, RADIX) + amt,\n ];\n\n r = Math.max(Math.min(RANGE, r), 0).toString(RADIX);\n g = Math.max(Math.min(RANGE, g), 0).toString(RADIX);\n b = Math.max(Math.min(RANGE, b), 0).toString(RADIX);\n\n const rr = (r.length < 2 ? '0' : '') + r;\n const gg = (g.length < 2 ? '0' : '') + g;\n const bb = (b.length < 2 ? '0' : '') + b;\n\n return `#${rr}${gg}${bb}`;\n};\n\nexport const generateRangeColors = (name: string, color: string) => {\n const NUMBER_OF_COLORS = 10;\n const HALF_NUMBER_OF_COLORS = 5;\n const COLOR_SUFFIX = 100;\n const AMT = 32;\n\n let colors = { [name]: color };\n for (let i = 1; i < NUMBER_OF_COLORS; i++) {\n if (i < HALF_NUMBER_OF_COLORS) {\n colors = {\n ...colors,\n [name + i * COLOR_SUFFIX]: colorShade(\n color,\n (HALF_NUMBER_OF_COLORS - i) * AMT\n ),\n };\n }\n if (i === HALF_NUMBER_OF_COLORS) {\n colors = {\n ...colors,\n [name + i * COLOR_SUFFIX]: color,\n };\n }\n if (i > HALF_NUMBER_OF_COLORS) {\n colors = {\n ...colors,\n [name + i * COLOR_SUFFIX]: colorShade(\n color,\n -((i - HALF_NUMBER_OF_COLORS) * AMT)\n ),\n };\n }\n }\n return colors;\n};\nexport const generateColors = (\n mainColors: { [x: string]: string },\n reverseNeutralRange: boolean,\n colors?: WidgetColors\n) => {\n if (!colors || !Object.entries(colors).length) {\n return {};\n }\n let changeColors = false;\n let listOfColors = { ...mainColors };\n for (const colorKey in colors) {\n const color = colors[colorKey as WidgetColorsKeys];\n\n if (!!color && color !== mainColors[colorKey]) {\n changeColors = true;\n if (colorKey === 'background' || colorKey === 'foreground') {\n listOfColors = {\n ...listOfColors,\n [colorKey]: color,\n };\n } else if (colorKey === 'neutral' && reverseNeutralRange) {\n const range = generateRangeColors(colorKey, color);\n listOfColors = {\n ...listOfColors,\n // Reverse the neutral shade\n [`${colorKey}100`]: range[`${colorKey}900`],\n [`${colorKey}200`]: range[`${colorKey}800`],\n [`${colorKey}300`]: range[`${colorKey}700`],\n [`${colorKey}400`]: range[`${colorKey}600`],\n [`${colorKey}500`]: range[`${colorKey}500`],\n [`${colorKey}600`]: range[`${colorKey}400`],\n [`${colorKey}700`]: range[`${colorKey}300`],\n [`${colorKey}800`]: range[`${colorKey}200`],\n [`${colorKey}900`]: range[`${colorKey}100`],\n };\n } else {\n listOfColors = {\n ...listOfColors,\n ...generateRangeColors(colorKey, color),\n };\n }\n }\n }\n return changeColors ? listOfColors : {};\n};\n", "import type { LoadingTokenListProps } from './TokenList.types';\n\nimport { Divider, ListItem, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { End, List } from './TokenList.styles';\n\nexport function LoadingTokenList(props: LoadingTokenListProps) {\n return (\n <List>\n {Array.from(Array(props.size), (e) => (\n <ListItem\n key={e}\n hasDivider\n start={<Skeleton variant=\"circular\" width={35} height={35} />}\n end={\n <End>\n <Skeleton variant=\"text\" size=\"large\" width={70} />\n <Divider size={4} />\n <Skeleton variant=\"text\" size=\"medium\" width={50} />\n </End>\n }\n title={\n <div>\n <Skeleton variant=\"text\" size=\"large\" width={90} />\n <Divider size={4} />\n <Skeleton variant=\"text\" size=\"medium\" width={90} />\n </div>\n }\n />\n ))}\n </List>\n );\n}\n", "import { styled, Typography } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n flexGrow: 1,\n});\n\nexport const Title = styled('div', {\n display: 'flex',\n alignItems: 'center',\n '._typography': {\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: 100,\n overflow: 'hidden',\n },\n});\nexport const List = styled('ul', {\n flexGrow: 1,\n padding: 0,\n margin: 0,\n listStyle: 'none',\n '& li': {\n alignItems: 'none',\n '.description': {\n position: 'relative',\n height: 12,\n width: 150,\n '.token-title': {\n position: 'absolute',\n transform: 'none',\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms',\n bottom: '-8px',\n },\n\n '.token-address': {\n transform: 'translateY(12px)',\n visibility: 'hidden',\n '& a': {\n fontSize: '$12',\n lineHeight: '$16',\n color: '$neutral600',\n textDecoration: 'none',\n },\n },\n '.token-name': {\n position: 'absolute',\n transform: 'none',\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: 100,\n overflow: 'hidden',\n },\n },\n '&:hover': {\n '.description': {\n '.token-address': {\n position: 'absolute',\n transform: 'none',\n transition: 'transform 225ms cubic-bezier(0, 0, 0.2, 1) 0ms',\n visibility: 'visible',\n },\n '.token-address-without-name': {\n bottom: '-15px',\n },\n '.token-name': {\n position: 'absolute',\n transform: 'translateY(-12px)',\n visibility: 'hidden',\n },\n '.token-title': {\n position: 'absolute',\n transform: 'translateY(-12px)',\n bottom: '-10px',\n },\n },\n },\n },\n});\n\nexport const Tag = styled('div', {\n paddingLeft: '$5',\n paddingRight: '$5',\n borderRadius: '$md',\n display: 'flex',\n alignItems: 'center',\n});\n\nexport const TagTitle = styled(Typography, {});\n\nexport const BalanceContainer = styled('div', {\n textAlign: 'right',\n});\n\nexport const End = styled('ul', {\n display: 'flex',\n alignItems: 'end',\n flexDirection: 'column',\n});\n\nexport const Description = styled('div', {\n display: 'flex',\n alignItems: 'center',\n});\nexport const ImageSection = styled('div', {\n position: 'relative',\n '.image-container': {\n borderRadius: '$xm',\n overflow: 'hidden',\n },\n});\nexport const Pin = styled('div', {\n position: 'absolute',\n backgroundColor: '$neutral100',\n padding: '$4',\n borderRadius: '50%',\n bottom: -6,\n right: -6,\n});\n", "import { i18n } from '@lingui/core';\nimport {\n ChevronRightIcon,\n Divider,\n InfoIcon,\n List,\n ListItemButton,\n Skeleton,\n Switch,\n Tooltip,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { Layout } from '../components/Layout';\nimport { SettingsContainer } from '../components/SettingsContainer';\nimport { Slippage } from '../components/Slippage';\nimport { SlippageTooltipContainer as TooltipContainer } from '../components/Slippage/Slippage.styles';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useMetaStore } from '../store/meta';\nimport { useSettingsStore } from '../store/settings';\nimport { getContainer } from '../utils/common';\nimport { getUniqueSwappersGroups } from '../utils/settings';\n\ninterface PropTypes {\n supportedSwappers?: string[];\n singleTheme?: boolean;\n}\n\nexport function SettingsPage({ supportedSwappers, singleTheme }: PropTypes) {\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n\n const infiniteApprove = useSettingsStore.use.infiniteApprove();\n const toggleInfiniteApprove = useSettingsStore.use.toggleInfiniteApprove();\n const loadingMetaStatus = useMetaStore.use.loadingStatus();\n\n const supportedUniqueSwappersGroups =\n getUniqueSwappersGroups(supportedSwappers);\n\n const bridgeSources = supportedUniqueSwappersGroups.filter(\n (uniqueItem) =>\n uniqueItem.type === 'BRIDGE' || uniqueItem.type === 'AGGREGATOR'\n );\n const totalBridgeSources = bridgeSources.length;\n const totalSelectedBridgeSources = bridgeSources.filter(\n (uniqueItem) => uniqueItem.selected\n ).length;\n\n const exchangeSources = supportedUniqueSwappersGroups.filter(\n (uniqueItem) => uniqueItem.type === 'DEX'\n );\n const totalExchangeSources = exchangeSources.length;\n const totalSelectedExchangeSources = exchangeSources.filter(\n (uniqueItem) => uniqueItem.selected\n ).length;\n\n const handleEndItem = (totalSelected: number, total: number) => {\n switch (loadingMetaStatus) {\n case 'loading':\n return <Skeleton variant=\"text\" size=\"medium\" width={50} />;\n case 'failed':\n return (\n <Typography variant=\"body\" size=\"medium\" color=\"$error500\">\n {i18n.t('Loading failed')}\n </Typography>\n );\n default:\n return (\n <Typography variant=\"body\" size=\"medium\">\n {`${totalSelected} / ${total}`}\n </Typography>\n );\n }\n };\n\n const bridgeItem = {\n id: 'bridge-item',\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Enabled bridges')}\n </Typography>\n ),\n end: (\n <>\n {handleEndItem(totalSelectedBridgeSources, totalBridgeSources)}\n <Divider direction=\"horizontal\" size={8} />\n <ChevronRightIcon color=\"black\" />\n </>\n ),\n onClick: () => navigate(navigationRoutes.bridges),\n };\n\n const exchangeItem = {\n id: 'exchange-item',\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Enabled exchanges')}\n </Typography>\n ),\n end: (\n <>\n {handleEndItem(totalSelectedExchangeSources, totalExchangeSources)}\n <Divider direction=\"horizontal\" size={8} />\n <ChevronRightIcon color=\"gray\" />\n </>\n ),\n onClick: () => navigate(navigationRoutes.exchanges),\n };\n\n /*\n * const languageItem = {\n * id: 'language-item',\n * title: (\n * <Typography variant=\"title\" size=\"xmedium\">\n * {i18n.t('Language')}\n * </Typography>\n * ),\n * end: <ChevronRightIcon color=\"gray\" />,\n * onClick: () => navigate(navigationRoutes.languages),\n * };\n */\n\n const themeItem = {\n id: 'theme-item',\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Theme')}\n </Typography>\n ),\n end: <ChevronRightIcon color=\"gray\" />,\n onClick: () => navigate(navigationRoutes.themes),\n };\n\n const infiniteApprovalItem = {\n id: 'infinite-approval-item',\n title: (\n <>\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Infinite Approval')}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tooltip\n side=\"top\"\n container={getContainer()}\n content={\n <TooltipContainer>\n <Typography variant=\"label\" size=\"medium\" color=\"neutral700\">\n {i18n.t(\n \"Enabling the 'Infinite Approval' mode grants unrestricted access to smart contracts of DEXes/Bridges, allowing them to utilize the approved token amount without limitations.\"\n )}\n </Typography>\n </TooltipContainer>\n }>\n <InfoIcon color=\"gray\" />\n </Tooltip>\n </>\n ),\n end: <Switch checked={infiniteApprove} />,\n onClick: toggleInfiniteApprove,\n };\n\n const settingItems = [\n bridgeItem,\n exchangeItem,\n // languageItem\n ];\n if (!singleTheme) {\n settingItems.push(themeItem);\n }\n settingItems.push(infiniteApprovalItem);\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t('Setting'),\n }}>\n <SettingsContainer>\n <Slippage />\n <List\n type={\n <ListItemButton title=\"_\" id=\"_\" onClick={() => console.log()} />\n }\n items={settingItems}\n />\n </SettingsContainer>\n </Layout>\n );\n}\n", "import { i18n } from '@lingui/core';\nimport {\n Chip,\n Divider,\n InfoIcon,\n TextField,\n Tooltip,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport {\n MAX_SLIPPAGE,\n MIN_SLIPPGAE,\n SLIPPAGES,\n} from '../../constants/swapSettings';\nimport { useSettingsStore } from '../../store/settings';\nimport { getContainer } from '../../utils/common';\n\nimport { BaseContainer, Head, SlippageChipsContainer } from './Slippage.styles';\nimport { SlippageTooltipContent } from './SlippageTooltipContent';\n\nexport function Slippage() {\n const slippage = useSettingsStore.use.slippage();\n const setSlippage = useSettingsStore.use.setSlippage();\n const customSlippage = useSettingsStore.use.customSlippage();\n const setCustomSlippage = useSettingsStore.use.setCustomSlippage();\n\n return (\n <BaseContainer>\n <Head>\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Slippage tolerance per swap')}\n </Typography>\n <Divider direction=\"horizontal\" size={4} />\n <Tooltip\n container={getContainer()}\n side=\"top\"\n content={<SlippageTooltipContent />}>\n <InfoIcon color=\"gray\" />\n </Tooltip>\n </Head>\n <SlippageChipsContainer>\n {SLIPPAGES.map((slippageItem, index) => {\n const key = `slippage-${index}`;\n return (\n <>\n <Chip\n style={{ width: '64px', flexShrink: 0 }}\n key={key}\n onClick={() => {\n if (customSlippage) {\n setCustomSlippage(null);\n }\n setSlippage(slippageItem);\n }}\n selected={!customSlippage && slippageItem === slippage}\n label={`${slippageItem.toString()}%`}\n />\n <Divider direction=\"horizontal\" size={8} />\n </>\n );\n })}\n <TextField\n type=\"number\"\n min=\"0.01\"\n max=\"30\"\n step=\"0.01\"\n fullWidth\n variant=\"contained\"\n value={customSlippage || ''}\n color=\"dark\"\n onChange={(event) => {\n const parsedValue = parseFloat(event.target.value);\n if (\n !parsedValue ||\n (parsedValue >= MIN_SLIPPGAE && parsedValue <= MAX_SLIPPAGE)\n ) {\n setCustomSlippage(parsedValue);\n }\n }}\n suffix={\n customSlippage && (\n <Typography variant=\"body\" size=\"small\">\n %\n </Typography>\n )\n }\n placeholder={i18n.t('Custom')}\n />\n </SlippageChipsContainer>\n </BaseContainer>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const BaseContainer = styled('div', {\n paddingTop: '$5',\n paddingBottom: '30px',\n});\n\nexport const SlippageChipsContainer = styled('div', {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'start',\n});\n\nexport const Head = styled('div', {\n display: 'flex',\n justifyContent: 'start',\n alignItems: 'center',\n paddingBottom: '$10',\n});\n\nexport const SlippageTooltipContainer = styled('div', {\n maxWidth: '300px',\n padding: '$10',\n});\n", "import { i18n } from '@lingui/core';\nimport { Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { SlippageTooltipContainer } from './Slippage.styles';\n\nexport function SlippageTooltipContent() {\n return (\n <SlippageTooltipContainer>\n <Typography variant=\"label\" size=\"medium\" color=\"neutral700\">\n {i18n.t(\n 'Your transaction will be reverted if the price changes unfavorably by more than this percentage'\n )}\n <br />\n <br />\n <b>{i18n.t('Warning')}</b>:\n {i18n.t(\n 'This setting is applied per step, e.g. 1Inch, Thorchain, etc. and only that step will be reverted, not the whole transaction'\n )}\n </Typography>\n </SlippageTooltipContainer>\n );\n}\n", "import { cancelSwap } from '@rango-dev/queue-manager-rango-preset';\nimport { useManager } from '@rango-dev/queue-manager-react';\nimport React from 'react';\n\nimport { SwapDetails } from '../components/SwapDetails';\nimport { SwapDetailsPlaceholder } from '../components/SwapDetails/SwapDetails.Placeholder';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useMetaStore } from '../store/meta';\nimport { useUiStore } from '../store/ui';\nimport { getPendingSwaps } from '../utils/queue';\n\nexport function SwapDetailsPage() {\n const { manager, state } = useManager();\n const loading = !state.loadedFromPersistor;\n const pendingSwaps = getPendingSwaps(manager);\n const requestId = useUiStore.use.selectedSwapRequestId();\n const { navigateBackFrom } = useNavigateBack();\n const { loadingStatus } = useMetaStore();\n\n const showSkeleton = loading || loadingStatus === 'loading';\n\n const selectedSwap = pendingSwaps.find(\n ({ swap }) => swap.requestId === requestId\n );\n\n const onCancel = () => {\n if (selectedSwap?.id) {\n const swap = manager?.get(selectedSwap.id);\n if (swap) {\n cancelSwap(swap);\n }\n }\n };\n\n const onDelete = async () => {\n if (selectedSwap?.id) {\n try {\n await manager?.deleteQueue(selectedSwap.id);\n navigateBackFrom(navigationRoutes.swapDetails);\n } catch (e) {\n console.log(e);\n }\n }\n };\n const swap = selectedSwap?.swap;\n\n if (!swap || showSkeleton) {\n return (\n <SwapDetailsPlaceholder\n requestId={requestId || ''}\n showSkeleton={showSkeleton}\n />\n );\n }\n\n return (\n <SwapDetails\n swap={swap}\n requestId={requestId || ''}\n onCancel={onCancel}\n onDelete={onDelete}\n />\n );\n}\n", "import type { SwapDetailsProps } from './SwapDetails.types';\nimport type { ModalState } from '../SwapDetailsModal';\n\nimport { i18n } from '@lingui/core';\nimport {\n getCurrentBlockchainOfOrNull,\n getCurrentStep,\n getRelatedWalletOrNull,\n PendingSwapNetworkStatus,\n} from '@rango-dev/queue-manager-rango-preset';\nimport {\n Button,\n CopyIcon,\n Divider,\n IconButton,\n RouteCost,\n RouteSummary,\n StepDetails,\n Typography,\n useCopyToClipboard,\n} from '@rango-dev/ui';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport {\n GAS_FEE_MAX_DECIMALS,\n GAS_FEE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS,\n USD_VALUE_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { useNavigateBack } from '../../hooks/useNavigateBack';\nimport { useBestRouteStore } from '../../store/bestRoute';\nimport { useMetaStore } from '../../store/meta';\nimport { useNotificationStore } from '../../store/notification';\nimport {\n numberToString,\n secondsToString,\n totalArrivalTime,\n} from '../../utils/numbers';\nimport { getPriceImpactLevel } from '../../utils/routing';\nimport {\n getLastConvertedTokenInFailedSwap,\n getPercentageChange,\n getSwapMessages,\n shouldRetrySwap,\n} from '../../utils/swap';\nimport { getSwapDate } from '../../utils/time';\nimport { getConciseAddress, getUsdPrice } from '../../utils/wallets';\nimport { SuffixContainer } from '../HeaderButtons/HeaderButtons.styles';\nimport { Layout } from '../Layout';\nimport {\n SwapDetailsCompleteModal,\n SwapDetailsModal,\n} from '../SwapDetailsModal';\n\nimport { getSteps, getStepState, RESET_INTERVAL } from './SwapDetails.helpers';\nimport { Container, HeaderDetails, StepsList } from './SwapDetails.styles';\n\nexport function SwapDetails(props: SwapDetailsProps) {\n const { swap, requestId, onDelete, onCancel: onCancelProps } = props;\n const { canSwitchNetworkTo, connect, getWalletInfo } = useWallets();\n const retry = useBestRouteStore.use.retry();\n const navigate = useNavigate();\n const { navigateBackFrom } = useNavigateBack();\n const [_, handleCopy] = useCopyToClipboard(RESET_INTERVAL);\n const listRef = useRef<HTMLDivElement | null>(null);\n const [modalState, setModalState] = useState<ModalState>(null);\n const [showCompletedModal, setShowCompletedModal] = useState<\n 'success' | 'failed' | null\n >(null);\n const {\n meta: { tokens, blockchains },\n } = useMetaStore();\n\n const onCancel = () => {\n onCancelProps();\n setModalState(null);\n };\n\n const getUnreadNotifications =\n useNotificationStore.use.getUnreadNotifications();\n const setAsRead = useNotificationStore.use.setAsRead();\n const unreadNotifications = getUnreadNotifications();\n const currentStep = getCurrentStep(swap);\n const currentStepNetworkStatus = currentStep?.networkStatus;\n\n useEffect(() => {\n const existNotification = unreadNotifications.find(\n (n) => n.requestId === swap.requestId\n );\n if (existNotification) {\n if (swap.status === 'success' || swap.status === 'failed') {\n setShowCompletedModal(swap.status);\n setAsRead(swap.requestId);\n }\n }\n }, [swap.status]);\n\n useEffect(() => {\n if (showSwitchNetwork) {\n setModalState(PendingSwapNetworkStatus.WaitingForNetworkChange);\n } else if (\n currentStepNetworkStatus ===\n PendingSwapNetworkStatus.WaitingForConnectingWallet ||\n currentStepNetworkStatus === PendingSwapNetworkStatus.NetworkChanged\n ) {\n setModalState(currentStepNetworkStatus);\n } else {\n setModalState(null);\n }\n }, [currentStepNetworkStatus]);\n\n const lastConvertedTokenInFailedSwap =\n getLastConvertedTokenInFailedSwap(swap);\n\n const currentStepBlockchain = currentStep\n ? getCurrentBlockchainOfOrNull(swap, currentStep)\n : null;\n const currentStepWallet = currentStep\n ? getRelatedWalletOrNull(swap, currentStep)\n : null;\n\n const swapDate = getSwapDate(swap);\n const shouldRetry = shouldRetrySwap(swap);\n\n const isMobileWallet = (walletType: string): boolean =>\n !!getWalletInfo(walletType)?.mobileWallet;\n\n const showSwitchNetwork =\n currentStepNetworkStatus ===\n PendingSwapNetworkStatus.WaitingForNetworkChange &&\n !!currentStepBlockchain &&\n !!currentStepWallet?.walletType &&\n (isMobileWallet(currentStepWallet.walletType) ||\n canSwitchNetworkTo(currentStepWallet.walletType, currentStepBlockchain));\n\n const switchNetwork = showSwitchNetwork\n ? connect.bind(null, currentStepWallet.walletType, currentStepBlockchain)\n : undefined;\n\n const stepMessage = getSwapMessages(swap, currentStep);\n const steps = getSteps({\n swap,\n switchNetwork,\n showNetworkModal: currentStepNetworkStatus,\n setNetworkModal: setModalState,\n message: stepMessage,\n blockchains,\n });\n const numberOfSteps = steps.length;\n const [firstStep, lastStep] = [swap.steps[0], swap.steps[numberOfSteps - 1]];\n const outputAmount =\n lastStep.outputAmount || lastStep.expectedOutputAmountHumanReadable;\n\n const totalFee = swap.steps.reduce(\n (totalFee, steps) => totalFee + parseFloat(steps.feeInUsd || ''),\n 0\n );\n\n const diagnosisUrl = swap.steps.find(\n (step) => step.diagnosisUrl\n )?.diagnosisUrl;\n\n const outputUsdValue = numberToString(\n String(\n parseFloat(\n numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n )\n ) *\n (getUsdPrice(\n lastStep.toBlockchain,\n lastStep.toSymbol,\n lastStep.toSymbolAddress,\n tokens\n ) || 0)\n ),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n );\n\n const inputUsdValue = numberToString(\n String(\n parseFloat(swap.inputAmount) *\n (getUsdPrice(\n firstStep.fromBlockchain,\n firstStep.fromSymbol,\n firstStep.fromSymbolAddress,\n tokens\n ) || 0)\n ),\n USD_VALUE_MIN_DECIMALS,\n USD_VALUE_MAX_DECIMALS\n );\n\n const percentageChange = getPercentageChange(inputUsdValue, outputUsdValue);\n\n const completeModalDesc =\n swap.status === 'success'\n ? i18n.t({\n id: 'receivedMessage',\n message:\n 'You have received {amount} {token} in {conciseAddress} wallet on {chain} chain.',\n values: {\n amount: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n token: steps[numberOfSteps - 1].to.token.displayName,\n conciseAddress: getConciseAddress(\n swap.wallets[steps[numberOfSteps - 1].to.chain.displayName]\n ?.address || ''\n ),\n chain: steps[numberOfSteps - 1].to.chain.displayName,\n },\n })\n : `${i18n.t('Transaction was not sent.')} ${\n lastConvertedTokenInFailedSwap\n ? i18n.t({\n id: 'remainSymbol',\n message:\n '{amount} {symbol} on {blockchain} remain in your wallet',\n values: {\n amount: lastConvertedTokenInFailedSwap.outputAmount,\n symbol: lastConvertedTokenInFailedSwap.symbol,\n blockchain: lastConvertedTokenInFailedSwap.blockchain,\n },\n })\n : ''\n }`;\n\n return (\n <Layout\n noPadding\n header={{\n title: i18n.t('Swap and Bridge'),\n onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),\n onCancel:\n swap.status === 'running' ? () => setModalState('cancel') : undefined,\n suffix: swap.status !== 'running' && (\n <SuffixContainer>\n <Button\n variant=\"ghost\"\n type=\"error\"\n size=\"xsmall\"\n onClick={() => setModalState('delete')}>\n <Typography size=\"medium\" variant=\"label\" color=\"error\">\n {i18n.t('Delete')}\n </Typography>\n </Button>\n </SuffixContainer>\n ),\n }}\n footer={\n shouldRetry &&\n !showCompletedModal && (\n <Button\n fullWidth\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={() => {\n retry(swap);\n setTimeout(() => {\n navigate(navigationRoutes.home);\n }, 0);\n }}>\n {i18n.t('Try again')}\n </Button>\n )\n }>\n <Container>\n <HeaderDetails>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Request ID')}:`}\n </Typography>\n <div className=\"request-id\">\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n {requestId}\n </Typography>\n <IconButton\n variant=\"ghost\"\n onClick={handleCopy.bind(null, requestId || '')}>\n <CopyIcon size={16} color=\"gray\" />\n </IconButton>\n </div>\n </div>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Created at')}:`}\n </Typography>\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n {swapDate}\n </Typography>\n </div>\n </HeaderDetails>\n\n <div className=\"output\">\n <RouteCost\n fee={numberToString(\n String(totalFee),\n GAS_FEE_MIN_DECIMALS,\n GAS_FEE_MAX_DECIMALS\n )}\n time={secondsToString(totalArrivalTime(swap.steps))}\n steps={numberOfSteps}\n />\n <RouteSummary\n from={{\n price: {\n value: numberToString(\n swap.inputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: inputUsdValue,\n },\n token: {\n displayName: steps[0].from.token.displayName,\n image: steps[0].from.token.image,\n },\n chain: {\n image: steps[0].from.chain.image,\n displayName: steps[0].from.chain.displayName,\n },\n }}\n to={{\n price: {\n value: numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n usdValue: outputUsdValue,\n },\n token: {\n displayName: steps[numberOfSteps - 1].to.token.displayName,\n image: steps[numberOfSteps - 1].to.token.image,\n },\n chain: {\n image: steps[numberOfSteps - 1].to.chain.image,\n displayName: steps[numberOfSteps - 1].to.chain.displayName,\n },\n }}\n percentageChange={numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )}\n warningLevel={getPriceImpactLevel(\n percentageChange?.toNumber() ?? 0\n )}\n />\n </div>\n <div className=\"title-steps\">\n <Typography variant=\"title\" size=\"small\">\n {i18n.t('Swaps steps')}\n </Typography>\n </div>\n <Divider size={8} />\n <StepsList ref={listRef}>\n {steps.map((step, index) => {\n const key = index;\n const state = getStepState(swap.steps[index]);\n const isFocused =\n state === 'error' ||\n state === 'in-progress' ||\n state === 'warning' ||\n (state === 'completed' && index === steps.length - 1);\n return (\n <StepDetails\n key={key}\n step={step}\n type=\"route-progress\"\n ref={listRef}\n state={state}\n hasSeparator={index !== 0}\n tabIndex={key}\n isFocused={isFocused}\n />\n );\n })}\n </StepsList>\n </Container>\n\n <SwapDetailsModal\n state={modalState}\n onClose={() => setModalState(null)}\n onCancel={onCancel}\n onDelete={onDelete}\n message={stepMessage.detailedMessage.content}\n currentStepWallet={currentStepWallet}\n />\n <SwapDetailsCompleteModal\n open={!!showCompletedModal}\n diagnosisUrl={diagnosisUrl}\n onClose={() => setShowCompletedModal(null)}\n status={swap.status === 'success' ? 'success' : 'failed'}\n priceValue={numberToString(\n outputAmount,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n )}\n usdValue={outputUsdValue}\n percentageChange={numberToString(\n percentageChange,\n PERCENTAGE_CHANGE_MIN_DECIMALS,\n PERCENTAGE_CHANGE_MAX_DECIMALS\n )}\n token={{\n displayName: steps[numberOfSteps - 1].to.token.displayName,\n image: steps[numberOfSteps - 1].to.token.image,\n }}\n chain={{ image: steps[numberOfSteps - 1].to.chain.image }}\n description={completeModalDesc}\n />\n </Layout>\n );\n}\n", "import type { PendingSwap } from '@rango-dev/queue-manager-rango-preset';\n\nimport { i18n } from '@lingui/core';\n\nconst MILLISECOND_PER_SECOND = 1000;\nconst SECONDS_PER_YEAR = 31536000;\nconst SECONDS_PER_MONTH = 2592000;\nconst SECONDS_PER_DAY = 86400;\nconst SECONDS_PER_HOUR = 3600;\nconst SECONDS_PER_MINUTE = 60;\n\nexport function timeSince(millisecond: number): string {\n const seconds = Math.floor(\n (Date.now() - millisecond) / MILLISECOND_PER_SECOND\n );\n\n const intervals = [\n {\n turningPoint: SECONDS_PER_YEAR,\n label: i18n.t('year'),\n pluralLabel: i18n.t('years'),\n },\n {\n turningPoint: SECONDS_PER_MONTH,\n label: i18n.t('month'),\n pluralLabel: i18n.t('months'),\n },\n {\n turningPoint: SECONDS_PER_DAY,\n label: i18n.t('day'),\n pluralLabel: i18n.t('days'),\n },\n {\n turningPoint: SECONDS_PER_HOUR,\n label: i18n.t('hour'),\n pluralLabel: i18n.t('hours'),\n },\n {\n turningPoint: SECONDS_PER_MINUTE,\n label: i18n.t('minute'),\n pluralLabel: i18n.t('minutes'),\n },\n ];\n\n const sortedIntervals = intervals.sort(\n (a, b) => b.turningPoint - a.turningPoint\n );\n\n for (const interval of sortedIntervals) {\n const { turningPoint, label, pluralLabel } = interval;\n const intervalCount = Math.floor(seconds / turningPoint);\n if (intervalCount > 1) {\n return `${intervalCount} ${pluralLabel}`;\n }\n if (intervalCount === 1) {\n return `${intervalCount} ${label}`;\n }\n }\n\n if (seconds > 1) {\n return `${seconds} ${i18n.t('seconds')}`;\n }\n\n return `${seconds} ${i18n.t('second')}`;\n}\n\nexport function getSwapDate(pendingSwap: PendingSwap) {\n return pendingSwap.finishTime\n ? i18n.t({\n id: 'timeAgo',\n message: '{time} ago',\n values: { time: timeSince(parseInt(pendingSwap.finishTime)) },\n })\n : i18n.t({\n id: 'timeAgo',\n message: '{time} ago',\n values: { time: timeSince(parseInt(pendingSwap.creationTime)) },\n });\n}\n", "import type { ModalPropTypes } from './SwapDetailsModal.types';\n\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\nimport { Modal } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { CancelContent } from './SwapDetailsModal.Cancel';\nimport { DeleteContent } from './SwapDetailsModal.Delete';\nimport { modalNetworkValues } from './SwapDetailsModal.helpers';\nimport { WalletStateContent } from './SwapDetailsModal.WalletState';\n\nexport function SwapDetailsModal(props: ModalPropTypes) {\n const { state, onClose, onDelete, onCancel, currentStepWallet, message } =\n props;\n\n const showWalletStateContent =\n state === PendingSwapNetworkStatus.WaitingForNetworkChange ||\n state === PendingSwapNetworkStatus.WaitingForConnectingWallet ||\n state === PendingSwapNetworkStatus.NetworkChanged;\n\n return (\n <Modal\n open={!!state}\n onClose={onClose}\n container={document.getElementById('swap-box') || document.body}>\n {showWalletStateContent && (\n <WalletStateContent\n type={modalNetworkValues[state].type}\n title={modalNetworkValues[state].title}\n currentStepWallet={currentStepWallet}\n message={message}\n showWalletButton={\n state !== PendingSwapNetworkStatus.WaitingForNetworkChange\n }\n />\n )}\n {state === 'delete' && (\n <DeleteContent onClose={onClose} onDelete={onDelete} />\n )}\n {state === 'cancel' && (\n <CancelContent onClose={onClose} onCancel={onCancel} />\n )}\n </Modal>\n );\n}\n", "import type { CancelContentProps } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { Button, Divider, MessageBox, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nexport const CancelContent = ({ onCancel, onClose }: CancelContentProps) => {\n return (\n <>\n <Divider size={20} />\n <MessageBox\n type=\"error\"\n title={i18n.t('Transaction Cancel')}\n description={i18n.t('Are you sure you want to Cancel this swap?')}\n />\n <Divider size={32} />\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={onCancel}>\n <Typography variant=\"title\" size=\"medium\" color=\"neutral100\">\n {i18n.t('Yes, Cancel it')}\n </Typography>\n </Button>\n <Divider size={12} />\n <Button variant=\"outlined\" type=\"primary\" size=\"large\" onClick={onClose}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('No, Continue')}\n </Typography>\n </Button>\n </>\n );\n};\n", "import type { DeleteContentProps } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { Button, Divider, MessageBox, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nexport const DeleteContent = ({ onDelete, onClose }: DeleteContentProps) => {\n return (\n <>\n <Divider size={20} />\n <MessageBox\n type=\"error\"\n title={i18n.t('Delete Transaction')}\n description={i18n.t('Are you sure you want to delete this swap?')}\n />\n <Divider size={32} />\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={onDelete}>\n <Typography variant=\"title\" size=\"medium\" color=\"neutral100\">\n {i18n.t('Yes, Delete it')}\n </Typography>\n </Button>\n <Divider size={12} />\n <Button variant=\"outlined\" type=\"primary\" size=\"large\" onClick={onClose}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('No, Cancel')}\n </Typography>\n </Button>\n </>\n );\n};\n", "import type { ModalNetworkValueTypes } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\n\nexport const modalNetworkValues: Record<\n Exclude<PendingSwapNetworkStatus, PendingSwapNetworkStatus.WaitingForQueue>,\n ModalNetworkValueTypes\n> = {\n [PendingSwapNetworkStatus.WaitingForNetworkChange]: {\n type: 'loading',\n title: i18n.t('Change Network'),\n },\n [PendingSwapNetworkStatus.WaitingForConnectingWallet]: {\n type: 'warning',\n title: i18n.t('Connect Wallet'),\n },\n [PendingSwapNetworkStatus.NetworkChanged]: {\n type: 'success',\n title: i18n.t('Network Changed'),\n },\n};\n", "import type { WalletStateContentProps } from './SwapDetailsModal.types';\n\nimport { MessageBox, Wallet, WalletState } from '@rango-dev/ui';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport React from 'react';\n\nimport { getContainer } from '../../utils/common';\n\nimport { WalletContainer } from './SwapDetailsModal.styles';\n\nexport const WalletStateContent = (props: WalletStateContentProps) => {\n const { type, title, currentStepWallet, message, showWalletButton } = props;\n const { connect, getWalletInfo, state: walletState } = useWallets();\n const walletType = currentStepWallet?.walletType;\n const isConnected = walletType && walletState(walletType).connected;\n const state = isConnected ? WalletState.CONNECTED : WalletState.DISCONNECTED;\n return (\n <>\n <MessageBox type={type} title={title} description={message} />\n {showWalletButton && walletType && (\n <WalletContainer>\n <Wallet\n container={getContainer()}\n title={getWalletInfo(walletType).name}\n image={getWalletInfo(walletType).img}\n type={walletType}\n state={state}\n onClick={async () => connect(walletType)}\n />\n </WalletContainer>\n )}\n </>\n );\n};\n", "import { styled } from '@rango-dev/ui';\n\nexport const WalletContainer = styled('div', {\n display: 'flex',\n justifyContent: 'center',\n});\n", "import type { CompleteModalPropTypes } from './SwapDetailsModal.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n Button,\n Divider,\n MessageBox,\n Modal,\n TokenAmount,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\nimport { useNavigate } from 'react-router-dom';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\n\nexport function SwapDetailsCompleteModal(props: CompleteModalPropTypes) {\n const {\n open,\n onClose,\n status,\n priceValue,\n usdValue,\n token,\n chain,\n percentageChange,\n description,\n diagnosisUrl,\n } = props;\n const navigate = useNavigate();\n\n return (\n <Modal\n open={open}\n onClose={onClose}\n container={document.getElementById('swap-box') || document.body}>\n {status === 'success' ? (\n <MessageBox type=\"success\" title={i18n.t('Swap Successful')}>\n <TokenAmount\n direction=\"vertical\"\n type=\"output\"\n centerAlign={true}\n price={{\n value: priceValue,\n usdValue,\n }}\n token={token}\n chain={chain}\n percentageChange={percentageChange}\n />\n <Divider size={12} />\n <Typography\n variant=\"body\"\n size=\"medium\"\n color=\"neutral700\"\n align=\"center\">\n {description}\n </Typography>\n </MessageBox>\n ) : (\n <MessageBox\n type=\"error\"\n title={i18n.t('Transaction Failed')}\n description={description}\n />\n )}\n <Divider size={32} />\n {status === 'success' && (\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={() => navigate(navigationRoutes.home)}>\n <Typography variant=\"title\" size=\"medium\" color=\"neutral100\">\n {i18n.t('Done')}\n </Typography>\n </Button>\n )}\n <Divider size={12} />\n {diagnosisUrl && (\n <>\n <Button\n variant=\"contained\"\n type=\"primary\"\n size=\"large\"\n onClick={() => window.open(diagnosisUrl, '_blank')}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('Diagnosis')}\n </Typography>\n </Button>\n <Divider size={12} />\n </>\n )}\n <Button variant=\"outlined\" type=\"primary\" size=\"large\" onClick={onClose}>\n <Typography variant=\"title\" size=\"medium\" color=\"primary\">\n {i18n.t('See Details')}\n </Typography>\n </Button>\n </Modal>\n );\n}\n", "import type { GetStep } from '../SwapDetailsAlerts';\nimport type { PendingSwapStep } from '@rango-dev/queue-manager-rango-preset';\nimport type { Step, StepDetailsProps } from '@rango-dev/ui';\n\nimport React from 'react';\n\nimport {\n TOKEN_AMOUNT_MAX_DECIMALS,\n TOKEN_AMOUNT_MIN_DECIMALS,\n} from '../../constants/routing';\nimport { getBlockchainShortNameFor } from '../../utils/meta';\nimport { numberToString } from '../../utils/numbers';\nimport { isNetworkStatusInWarningState } from '../../utils/swap';\nimport { SwapDetailsAlerts } from '../SwapDetailsAlerts';\n\nexport const RESET_INTERVAL = 2_000;\nexport const SECONDS = 60;\n\nexport const getSteps = ({ swap, blockchains, ...args }: GetStep): Step[] => {\n const hasAlreadyProceededToSign = swap.hasAlreadyProceededToSign !== false;\n return swap.steps.map((step, index) => {\n const amountToConvert =\n index === 0 ? swap.inputAmount : swap.steps[index - 1].outputAmount;\n return {\n from: {\n token: { displayName: step.fromSymbol, image: step.fromLogo ?? '' },\n chain: {\n displayName:\n getBlockchainShortNameFor(step.fromBlockchain, blockchains) ?? '',\n image: step.fromBlockchainLogo ?? '',\n },\n price: {\n value: numberToString(\n amountToConvert,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n },\n },\n to: {\n token: { displayName: step.toSymbol, image: step.toLogo },\n chain: {\n displayName:\n getBlockchainShortNameFor(step.toBlockchain, blockchains) ?? '',\n image: step.toBlockchainLogo ?? '',\n },\n price: {\n value: numberToString(\n step.outputAmount || step.expectedOutputAmountHumanReadable,\n TOKEN_AMOUNT_MIN_DECIMALS,\n TOKEN_AMOUNT_MAX_DECIMALS\n ),\n },\n },\n swapper: { displayName: step.swapperId, image: step.swapperLogo ?? '' },\n alerts: (\n <SwapDetailsAlerts\n step={step}\n hasAlreadyProceededToSign={hasAlreadyProceededToSign}\n {...args}\n />\n ),\n };\n });\n};\n\nexport function getStepState(step: PendingSwapStep): StepDetailsProps['state'] {\n if (\n isNetworkStatusInWarningState(step) &&\n step.status !== 'failed' &&\n step.status !== 'success'\n ) {\n return 'warning';\n }\n\n switch (step.status) {\n case 'created':\n return 'default';\n case 'approved':\n case 'waitingForApproval':\n case 'running':\n return 'in-progress';\n case 'failed':\n return 'error';\n case 'success':\n return 'completed';\n }\n}\n", "import type { SwapAlertsProps } from './SwapDetailsAlerts.types';\n\nimport { i18n } from '@lingui/core';\nimport { Alert, IconButton, LinkIcon } from '@rango-dev/ui';\nimport React, { Fragment } from 'react';\n\nimport { isNetworkStatusInWarningState } from '../../utils/swap';\n\nimport { FailedAlert } from './SwapDetailsAlerts.Failed';\nimport { Alerts } from './SwapDetailsAlerts.styles';\nimport { WarningAlert } from './SwapDetailsAlerts.Warning';\n\nexport function SwapDetailsAlerts(props: SwapAlertsProps) {\n const {\n switchNetwork,\n showNetworkModal,\n setNetworkModal,\n message,\n step,\n hasAlreadyProceededToSign,\n } = props;\n\n const hasWarning = isNetworkStatusInWarningState(step);\n const waitingForApproval =\n step.status === 'waitingForApproval' && !hasWarning;\n const inProgress = step.status === 'running' && !hasWarning;\n return (\n <Alerts>\n {step.explorerUrl?.map((explorerUrl, index, urls) => {\n const key = index + explorerUrl.url;\n const lastUrl = index === urls.length - 1;\n const loading = (lastUrl && inProgress) || waitingForApproval;\n const error = lastUrl && step.status === 'failed';\n\n return (\n <Fragment key={key}>\n <Alert\n type={(loading && 'loading') || (error && 'error') || 'success'}\n title={\n !explorerUrl.description\n ? i18n.t('View transaction')\n : `${explorerUrl.description} Tx`\n }\n action={\n explorerUrl.url && (\n <IconButton\n variant=\"ghost\"\n size=\"xsmall\"\n onClick={() => window.open(explorerUrl.url, '_blank')}>\n <LinkIcon size={16} />\n </IconButton>\n )\n }\n />\n </Fragment>\n );\n })}\n {((inProgress && !hasAlreadyProceededToSign) ||\n (waitingForApproval && !step.explorerUrl?.length)) && (\n <Alert type=\"loading\" title={message.shortMessage} />\n )}\n {step.status !== 'failed' && hasWarning && (\n <WarningAlert\n switchNetwork={switchNetwork}\n showNetworkModal={showNetworkModal}\n setNetworkModal={setNetworkModal}\n message={message}\n />\n )}\n\n {step.status === 'failed' && <FailedAlert message={message} />}\n </Alerts>\n );\n}\n", "import type { FailedAlertsProps } from './SwapDetailsAlerts.types';\n\nimport {\n Alert,\n ChevronDownIcon,\n ChevronUpIcon,\n IconButton,\n} from '@rango-dev/ui';\nimport React, { useState } from 'react';\n\nexport function FailedAlert(props: FailedAlertsProps) {\n const { message } = props;\n const [showContentError, setShowContentError] = useState(false);\n\n return (\n <Alert\n type=\"error\"\n title={message.shortMessage}\n action={\n message.detailedMessage.content && (\n <IconButton\n onClick={() => setShowContentError((prev) => !prev)}\n variant=\"ghost\"\n size=\"xsmall\">\n {showContentError ? (\n <ChevronUpIcon size={12} color=\"gray\" />\n ) : (\n <ChevronDownIcon size={12} color=\"gray\" />\n )}\n </IconButton>\n )\n }\n footer={showContentError ? message.detailedMessage.content : undefined}\n />\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Alerts = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n gap: '$10',\n});\n", "import type { WaningAlertsProps } from './SwapDetailsAlerts.types';\n\nimport { i18n } from '@lingui/core';\nimport { PendingSwapNetworkStatus } from '@rango-dev/queue-manager-rango-preset';\nimport { Alert, Button } from '@rango-dev/ui';\nimport React from 'react';\n\nexport function WarningAlert(props: WaningAlertsProps) {\n const { switchNetwork, setNetworkModal, message, showNetworkModal } = props;\n if (!!switchNetwork) {\n return (\n <Alert\n type=\"warning\"\n title={message.shortMessage}\n action={\n <Button\n size=\"xxsmall\"\n type=\"warning\"\n onClick={() => {\n setNetworkModal(PendingSwapNetworkStatus.WaitingForNetworkChange);\n switchNetwork().catch((e) => {\n console.log(e);\n });\n }}>\n {i18n.t('Change')}\n </Button>\n }\n />\n );\n }\n if (\n showNetworkModal === PendingSwapNetworkStatus.WaitingForConnectingWallet\n ) {\n return (\n <Alert\n type=\"warning\"\n title={message.shortMessage}\n action={\n <Button\n size=\"xxsmall\"\n type=\"warning\"\n onClick={() => {\n setNetworkModal(\n PendingSwapNetworkStatus.WaitingForConnectingWallet\n );\n }}>\n {i18n.t('Connect')}\n </Button>\n }\n />\n );\n }\n\n return <Alert type=\"warning\" title={message.shortMessage} />;\n}\n", "import { darkTheme, styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n display: 'flex',\n width: '100%',\n flexDirection: 'column',\n alignItems: 'center',\n height: '0',\n flexGrow: 1,\n '& .row': {\n display: 'flex',\n width: '100%',\n justifyContent: 'space-between',\n alignItems: 'center',\n padding: '$10 $20',\n borderBottom: '1px solid',\n $$color: '$colors$neutral300',\n [`.${darkTheme} &`]: {\n $$color: '$colors$neutral400',\n },\n borderColor: '$$color',\n color: '$neutral500',\n },\n '& .request-id': {\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '$24',\n },\n '& .output': {\n display: 'flex',\n width: '100%',\n padding: '$15 $20 $20',\n flexDirection: 'column',\n alignItems: 'start',\n },\n '& .title-steps': {\n textAlign: 'left',\n width: '100%',\n padding: '0 $20 $10',\n },\n});\n\nexport const HeaderDetails = styled('div', {\n width: '100%',\n});\n\nexport const StepsList = styled('div', {\n padding: '$0 $20 $20 $20',\n width: '100%',\n overflow: 'auto',\n});\nexport const Alerts = styled('div', {\n display: 'flex',\n flexDirection: 'column',\n gap: '$10',\n});\n\nexport const PlaceholderContainer = styled('div', {\n height: '450px',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n});\n\nexport const LoaderContainer = styled('div', {\n display: 'flex',\n justifyContent: 'center',\n width: '100%',\n paddingTop: '33%',\n flex: 1,\n});\n", "import type { SwapDetailsPlaceholderPropTypes } from './SwapDetails.types';\n\nimport { i18n } from '@lingui/core';\nimport {\n CopyIcon,\n IconButton,\n NotFound,\n Skeleton,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { navigationRoutes } from '../../constants/navigationRoutes';\nimport { useNavigateBack } from '../../hooks/useNavigateBack';\nimport { SuffixContainer } from '../HeaderButtons/HeaderButtons.styles';\nimport { Layout } from '../Layout';\nimport { LoadingSwapDetails } from '../LoadingSwapDetails';\n\nimport {\n Container,\n HeaderDetails,\n PlaceholderContainer,\n} from './SwapDetails.styles';\n\nexport function SwapDetailsPlaceholder(props: SwapDetailsPlaceholderPropTypes) {\n const { requestId, showSkeleton } = props;\n const { navigateBackFrom } = useNavigateBack();\n\n return (\n <Layout\n noPadding\n header={{\n title: i18n.t('Swap and Bridge'),\n onBack: navigateBackFrom.bind(null, navigationRoutes.swapDetails),\n suffix: <SuffixContainer />,\n }}>\n {showSkeleton && (\n <Container>\n <HeaderDetails>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Request ID')}:`}\n </Typography>\n <div className=\"request-id\">\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n <Skeleton width={60} height={10} variant=\"rounded\" />\n </Typography>\n <IconButton variant=\"ghost\">\n <CopyIcon size={16} color=\"gray\" />\n </IconButton>\n </div>\n </div>\n <div className=\"row\">\n <Typography variant=\"label\" size=\"large\" color=\"neutral700\">\n {`${i18n.t('Created at')}:`}\n </Typography>\n <Typography variant=\"label\" size=\"small\" color=\"neutral700\">\n <Skeleton width={60} height={10} variant=\"rounded\" />\n </Typography>\n </div>\n </HeaderDetails>\n <LoadingSwapDetails />\n </Container>\n )}\n {!showSkeleton && (\n <PlaceholderContainer>\n <NotFound\n title={i18n.t('Not found')}\n description={i18n.t({\n id: 'swapNotFound',\n values: { requestId },\n message: 'Swap with request ID = {requestId} not found.',\n })}\n />\n </PlaceholderContainer>\n )}\n </Layout>\n );\n}\n", "import { i18n } from '@lingui/core';\nimport { ChainToken, Divider, Skeleton, Typography } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Container, StepSeparator } from './LoadingSwapDetails.styles';\nimport { LoadingSwapDetailStep } from './LoadingSwapDetailStep';\n\nexport function LoadingSwapDetails() {\n const routeSummary = (\n <div className=\"route-summary-item\">\n <div className=\"token-amount\">\n <ChainToken loading size=\"medium\" chainImage=\"\" tokenImage=\"\" />\n <Divider size={8} direction=\"horizontal\" />\n <Skeleton height={15} width={148} variant=\"rounded\" />\n </div>\n <Skeleton height={12} width={64} variant=\"rounded\" />\n </div>\n );\n\n return (\n <Container>\n <div className=\"cost\">\n <Skeleton width={60} height={10} variant=\"rounded\" />\n <Divider size={4} direction=\"horizontal\" />\n <Skeleton width={60} height={10} variant=\"rounded\" />\n <Divider size={4} direction=\"horizontal\" />\n <Skeleton width={60} height={10} variant=\"rounded\" />\n </div>\n\n <div className=\"route-summary\">\n {routeSummary}\n <div className=\"route-summary-separator\"></div>\n {routeSummary}\n </div>\n\n <div className=\"swaps-steps\">\n <Typography variant=\"title\" size=\"small\">\n {i18n.t('Swaps steps')}\n </Typography>\n </div>\n\n <div className=\"step-container\">\n <LoadingSwapDetailStep extraInfo />\n <StepSeparator />\n <LoadingSwapDetailStep />\n <StepSeparator />\n <LoadingSwapDetailStep />\n <StepSeparator />\n <LoadingSwapDetailStep />\n </div>\n </Container>\n );\n}\n", "import { styled } from '@rango-dev/ui';\n\nexport const Container = styled('div', {\n width: '100%',\n height: '100%',\n padding: '$0 $20',\n\n '.cost': {\n paddingTop: '$15',\n display: 'flex',\n },\n\n '.route-summary': {\n padding: '$15 $0',\n },\n\n '.route-summary-item': {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n\n '.token-amount': {\n display: 'flex',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n\n '.route-summary-separator': {\n width: '0px',\n height: '$16',\n borderLeft: '1px solid $neutral400',\n marginLeft: '13px',\n },\n\n '.swaps-steps': {\n paddingBottom: '$10',\n },\n});\n\nexport const StepContainer = styled('div', {\n backgroundColor: '$neutral100',\n borderRadius: '$xm',\n padding: '$10 $15',\n\n '.step-title': {\n display: 'flex',\n justifyContent: 'start',\n alignItems: 'center',\n },\n '.step-tokens': {\n paddingTop: '$5',\n display: 'flex',\n alignItems: 'center',\n },\n '.step-token-info': {\n display: 'flex',\n alignItems: 'center',\n },\n '.step-icon-container': {\n padding: '$4 $6',\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n },\n\n '.extra-info': {\n display: 'flex',\n paddingTop: '$10',\n paddingBottom: '$5',\n },\n});\nexport const StepSeparator = styled('div', {\n width: '0px',\n height: '$20',\n borderLeft: '1px dashed $neutral700',\n marginLeft: '25px',\n});\n", "import type { StepSkeletonPropsTypes } from './LoadingSwapDetails.types';\n\nimport { ChainToken, Divider, NextIcon, Skeleton } from '@rango-dev/ui';\nimport React from 'react';\n\nimport { StepContainer } from './LoadingSwapDetails.styles';\n\nexport function LoadingSwapDetailStep(props: StepSkeletonPropsTypes) {\n const { extraInfo } = props;\n return (\n <StepContainer>\n <div className=\"step-title\">\n <Skeleton height={28} width={28} variant=\"circular\" />\n <Divider direction=\"horizontal\" size={8} />\n <Skeleton height={15} width={148} variant=\"rounded\" />\n </div>\n <div className=\"step-tokens\">\n <Divider direction=\"horizontal\" size={20} />\n <div className=\"step-token-info\">\n <ChainToken size=\"small\" loading chainImage=\"\" tokenImage=\"\" />\n <Divider direction=\"horizontal\" size={8} />\n <Skeleton height={12} width={76} variant=\"rounded\" />\n </div>\n <div className=\"step-icon-container\">\n <NextIcon color=\"gray\" size={16} />\n </div>\n <div className=\"step-token-info\">\n <ChainToken size=\"small\" loading chainImage=\"\" tokenImage=\"\" />\n <Divider direction=\"horizontal\" size={8} />\n <Skeleton height={12} width={76} variant=\"rounded\" />\n </div>\n </div>\n {extraInfo && (\n <div className=\"extra-info\">\n <Divider direction=\"horizontal\" size={20} />\n <Skeleton height={22} width={297} variant=\"rectangular\" />\n </div>\n )}\n </StepContainer>\n );\n}\n", "import { i18n } from '@lingui/core';\nimport {\n AutoThemeIcon,\n DarkModeIcon,\n LightModeIcon,\n List,\n ListItemButton,\n Radio,\n RadioRoot,\n Typography,\n} from '@rango-dev/ui';\nimport React from 'react';\n\nimport { Layout } from '../components/Layout';\nimport { SettingsContainer } from '../components/SettingsContainer';\nimport { navigationRoutes } from '../constants/navigationRoutes';\nimport { useNavigateBack } from '../hooks/useNavigateBack';\nimport { useSettingsStore } from '../store/settings';\n\ntype Theme = 'dark' | 'light' | 'auto';\n\nenum Mode {\n DARK = 'dark',\n LIGHT = 'light',\n AUTO = 'auto',\n}\n\nexport function ThemePage() {\n const { navigateBackFrom } = useNavigateBack();\n const theme = useSettingsStore.use.theme();\n const setTheme = useSettingsStore.use.setTheme();\n\n const themesList = [\n {\n id: Mode.LIGHT,\n value: Mode.LIGHT,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Light')}\n </Typography>\n ),\n onClick: () => setTheme(Mode.LIGHT as Theme),\n start: <LightModeIcon color=\"gray\" />,\n end: <Radio value={Mode.LIGHT} />,\n },\n {\n id: Mode.DARK,\n value: Mode.DARK,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Dark')}\n </Typography>\n ),\n onClick: () => setTheme(Mode.DARK as Theme),\n start: <DarkModeIcon color=\"gray\" />,\n end: <Radio value={Mode.DARK} />,\n },\n {\n id: Mode.AUTO,\n value: Mode.AUTO,\n title: (\n <Typography variant=\"title\" size=\"xmedium\">\n {i18n.t('Auto')}\n </Typography>\n ),\n onClick: () => setTheme(Mode.AUTO as Theme),\n start: <AutoThemeIcon color=\"gray\" />,\n end: <Radio value={Mode.AUTO} />,\n },\n ];\n\n return (\n <Layout\n header={{\n onBack: navigateBackFrom.bind(null, navigationRoutes.settings),\n title: i18n.t('Theme'),\n }}>\n <SettingsContainer>\n <RadioRoot\n onValueChange={(value) => setTheme(value as Theme)}\n value={theme}>\n <List\n type={\n <ListItemButton\n title={i18n.t('Theme')}\n id=\"_\"\n onClick={() => console.log()}\n />\n }\n items={themesList}\n />\n </RadioRoot>\n </SettingsContainer>\n </Layout>\n );\n}\n", "import {\n isApprovalTX,\n MainEvents,\n RouteEventType,\n StepEventType,\n StepExecutionEventStatus,\n useEvents,\n} from '@rango-dev/queue-manager-rango-preset';\nimport { useEffect } from 'react';\n\nimport { useNotificationStore } from '../store/notification';\nimport { useWalletsStore } from '../store/wallets';\nimport { validBlockedStatuses } from '../types/notification';\n\nexport function WidgetEvents() {\n const connectedWallets = useWalletsStore.use.connectedWallets();\n const getWalletsDetails = useWalletsStore.use.getWalletsDetails();\n const setNotification = useNotificationStore.use.setNotification();\n const setAsRead = useNotificationStore.use.setAsRead();\n const widgetEvents = useEvents();\n\n useEffect(() => {\n widgetEvents.on(MainEvents.StepEvent, (widgetEvent) => {\n const { event, step, route } = widgetEvent;\n const shouldRefetchBalance =\n (event.type === StepEventType.TX_EXECUTION &&\n event.status === StepExecutionEventStatus.TX_SENT &&\n !isApprovalTX(step)) ||\n event.type === StepEventType.SUCCEEDED;\n\n if (shouldRefetchBalance) {\n const fromAccount = connectedWallets.find(\n (account) => account.chain === step?.fromBlockchain\n );\n const toAccount =\n step?.fromBlockchain !== step?.toBlockchain &&\n connectedWallets.find(\n (wallet) => wallet.chain === step?.toBlockchain\n );\n\n fromAccount && getWalletsDetails([fromAccount]);\n toAccount && getWalletsDetails([toAccount]);\n }\n if (\n (event.type === StepEventType.TX_EXECUTION_BLOCKED &&\n validBlockedStatuses.includes(event.status)) ||\n event.type === StepEventType.FAILED\n ) {\n setNotification(event, route);\n } else if (\n event.type === StepEventType.TX_EXECUTION ||\n event.type === StepEventType.CHECK_STATUS\n ) {\n setAsRead(route.requestId);\n }\n });\n\n return () => widgetEvents.all.clear();\n }, [widgetEvents, connectedWallets.length]);\n\n useEffect(() => {\n widgetEvents.on(MainEvents.RouteEvent, (widgetEvent) => {\n const { event, route } = widgetEvent;\n\n if (\n event.type === RouteEventType.FAILED ||\n event.type === RouteEventType.SUCCEEDED\n ) {\n setNotification(event, route);\n }\n });\n\n return () => widgetEvents.all.clear();\n }, [widgetEvents, connectedWallets.length]);\n\n return null;\n}\n", "import {\n type Route,\n type RouteEvent,\n type Step,\n type StepEvent,\n StepExecutionBlockedEventStatus,\n} from '@rango-dev/queue-manager-rango-preset';\n\ntype NotificationRoute = {\n from: {\n blockchain: Step['fromBlockchain'];\n tokenSymbol: Step['fromSymbol'];\n tokenAddress: Step['fromSymbolAddress'];\n };\n to: {\n blockchain: Step['toBlockchain'];\n tokenSymbol: Step['toSymbol'];\n tokenAddress: Step['toSymbolAddress'];\n };\n};\n\nexport type Notification = Pick<Route, 'requestId'> & {\n event: RouteEvent | StepEvent;\n creationTime: number;\n read: boolean;\n route: NotificationRoute;\n};\n\nexport const validBlockedStatuses: StepExecutionBlockedEventStatus[] = [\n StepExecutionBlockedEventStatus.WAITING_FOR_CHANGE_WALLET_ACCOUNT,\n StepExecutionBlockedEventStatus.WAITING_FOR_NETWORK_CHANGE,\n StepExecutionBlockedEventStatus.WAITING_FOR_WALLET_CONNECT,\n];\n", "import { globalCss } from '@rango-dev/ui';\n\nexport const globalFont = () =>\n globalCss({\n '@import': [\n \"url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap')\",\n \"url('https://fonts.cdnfonts.com/css/times-new-roman')\",\n ],\n })();\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { WidgetTheme } from '../types';\n\nimport {\n createTheme,\n darkTheme as defaultDarkTheme,\n lightTheme as defaultLightTheme,\n} from '@rango-dev/ui';\nimport { useEffect, useState } from 'react';\n\nimport { useSettingsStore } from '../store/settings';\nimport {\n DEFAULT_FONT_FAMILY,\n DEFAULT_PRIMARY_RADIUS,\n DEFAULT_SECONDARY_RADIUS,\n} from '../utils/configs';\nimport { customizedThemeTokens } from '../utils/ui';\n\nexport function useTheme(props: WidgetTheme) {\n const {\n colors,\n fontFamily = DEFAULT_FONT_FAMILY,\n borderRadius = DEFAULT_PRIMARY_RADIUS,\n secondaryBorderRadius = DEFAULT_SECONDARY_RADIUS,\n mode = 'auto',\n } = props;\n\n const [OSTheme, setOSTheme] = useState('light');\n const theme = useSettingsStore.use.theme();\n const setTheme = useSettingsStore.use.setTheme();\n\n const { dark, light } = customizedThemeTokens(colors);\n\n const baseTheme = createTheme({\n radii: {\n primary: `${borderRadius}px`,\n secondary: `${secondaryBorderRadius}px`,\n },\n fonts: {\n widget: fontFamily,\n },\n });\n const lightThemeClasses = [baseTheme.className, defaultLightTheme.className];\n const darkThemeClasses = [baseTheme.className, defaultDarkTheme.className];\n\n /*\n * If theme has been customized, we will push the customized theme to override the default themes.\n * To be overridden, it should be last thing that has been pushed.\n */\n if (light) {\n const customizedLightTheme = createTheme(light.id, light.tokens);\n lightThemeClasses.push(customizedLightTheme.className);\n }\n if (dark) {\n const customizedDarkTheme = createTheme(dark.id, dark.tokens);\n darkThemeClasses.push(customizedDarkTheme.className);\n }\n\n useEffect(() => {\n const switchThemeListener = (event: MediaQueryListEvent) => {\n if (event.matches) {\n setOSTheme('dark');\n } else {\n setOSTheme('light');\n }\n };\n\n if (\n window.matchMedia &&\n window.matchMedia('(prefers-color-scheme: dark)').matches\n ) {\n setOSTheme('dark');\n }\n\n window\n .matchMedia('(prefers-color-scheme: dark)')\n .addEventListener('change', switchThemeListener);\n return () => {\n window\n .matchMedia('(prefers-color-scheme: dark)')\n .removeEventListener('change', switchThemeListener);\n };\n }, []);\n\n useEffect(() => {\n if (mode !== 'auto') {\n setTheme(mode);\n }\n }, [mode]);\n\n const getActiveTheme = () => {\n const lightClassNames = lightThemeClasses.join(' ');\n const darkClassNames = darkThemeClasses.join(' ');\n if (theme === 'auto') {\n return OSTheme === 'dark' ? darkClassNames : lightClassNames;\n }\n return theme === 'dark' ? darkClassNames : lightClassNames;\n };\n\n return { activeTheme: getActiveTheme };\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\nimport type { WidgetTheme } from '../types';\nimport type { createTheme } from '@rango-dev/ui';\n\nimport {\n theme as baseThemeTokens,\n darkColors as defaultDarkColors,\n} from '@rango-dev/ui';\n\nimport { generateColors } from '../utils/colors';\nimport { toHash } from '../utils/hash';\n\nimport { THEME_CLASS_NAME_PREFIX } from './configs';\n\ninterface CustomizedThemeValues {\n id: string;\n tokens: Parameters<typeof createTheme>[0];\n}\n\ninterface CustomizedTheme {\n light: undefined | CustomizedThemeValues;\n dark: undefined | CustomizedThemeValues;\n}\n\nexport function customizedThemeTokens(\n colors: WidgetTheme['colors']\n): CustomizedTheme {\n const baseColors = baseThemeTokens.colors;\n\n const darkColorsWithDefaults = generateColors(\n {\n ...baseColors,\n ...defaultDarkColors,\n },\n true,\n colors?.dark\n );\n const lightColorsWithDefaults = generateColors(\n baseColors,\n false,\n colors?.light\n );\n const hasDefaultDarkColors = Object.keys(darkColorsWithDefaults).length > 0;\n const hasDefaultLightColors = Object.keys(lightColorsWithDefaults).length > 0;\n\n let light: CustomizedTheme['light'] = undefined;\n let dark: CustomizedTheme['dark'] = undefined;\n\n if (hasDefaultLightColors) {\n const tokens = { colors: lightColorsWithDefaults };\n const id = `${THEME_CLASS_NAME_PREFIX}-light-${toHash(tokens)}`;\n light = {\n id,\n tokens,\n };\n }\n if (hasDefaultDarkColors) {\n const tokens = {\n colors: darkColorsWithDefaults,\n };\n const id = `${THEME_CLASS_NAME_PREFIX}-dark-${toHash(tokens)}`;\n dark = {\n id,\n tokens,\n };\n }\n\n return {\n light,\n dark,\n };\n}\n", "/* eslint-disable @typescript-eslint/no-magic-numbers */\n// Original Code: https://github.com/stitchesjs/stitches/blob/canary/packages/core/src/convert/toHash.js\n\nconst toAlphabeticChar = (code: number) =>\n String.fromCharCode(code + (code > 25 ? 39 : 97));\n\nconst toAlphabeticName = (code: number) => {\n let name = '';\n let x;\n\n for (x = Math.abs(code); x > 52; x = (x / 52) | 0) {\n name = toAlphabeticChar(x % 52) + name;\n }\n\n return toAlphabeticChar(x % 52) + name;\n};\n\nconst toPhash = (h: number, x: string) => {\n let i = x.length;\n while (i) {\n h = (h * 33) ^ x.charCodeAt(--i);\n }\n return h;\n};\n\nexport const toHash = (value: object) =>\n toAlphabeticName(toPhash(5381, JSON.stringify(value)) >>> 0);\n", "import React, { PropsWithChildren, useMemo } from 'react';\nimport { Provider as ManagerProvider } from '@rango-dev/queue-manager-react';\nimport {\n makeQueueDefinition,\n SwapQueueContext,\n checkWaitingForNetworkChange,\n} from '@rango-dev/queue-manager-rango-preset';\nimport { useWallets } from '@rango-dev/wallets-react';\nimport {\n convertEvmBlockchainMetaToEvmChainInfo,\n Network,\n WalletType,\n} from '@rango-dev/wallets-shared';\nimport { useMetaStore } from './store/meta';\nimport { useWalletsStore } from './store/wallets';\nimport { walletAndSupportedChainsNames } from './utils/wallets';\nimport { getConfig } from './utils/configs';\nimport { isEvmBlockchain } from 'rango-types';\n\nfunction QueueManager(props: PropsWithChildren) {\n const {\n providers,\n getSigners,\n state,\n connect,\n canSwitchNetworkTo,\n getWalletInfo,\n } = useWallets();\n\n const swapQueueDef = useMemo(() => {\n return makeQueueDefinition({\n API_KEY: getConfig('API_KEY'),\n });\n }, []);\n\n const { blockchains } = useMetaStore.use.meta();\n const connectedWallets = useWalletsStore.use.connectedWallets();\n\n const wallets = {\n blockchains: connectedWallets.map((wallet) => ({\n accounts: [wallet],\n name: wallet.chain,\n })),\n };\n\n const switchNetwork = (wallet: WalletType, network: Network) => {\n if (!canSwitchNetworkTo(wallet, network)) {\n return undefined;\n }\n return connect(wallet, network);\n };\n\n const isMobileWallet = (walletType: WalletType): boolean =>\n !!getWalletInfo(walletType).mobileWallet;\n\n // TODO: this code copy & pasted from rango, should be refactored.\n const allBlockchains = blockchains\n .filter((blockchain) => blockchain.enabled)\n .reduce(\n (blockchainsObj: any, blockchain) => (\n (blockchainsObj[blockchain.name] = blockchain), blockchainsObj\n ),\n {}\n );\n const evmBasedChains = blockchains.filter(isEvmBlockchain);\n const getSupportedChainNames = (type: WalletType) => {\n const { supportedChains } = getWalletInfo(type);\n return walletAndSupportedChainsNames(supportedChains);\n };\n const allProviders = providers();\n\n const context: SwapQueueContext = {\n meta: {\n blockchains: allBlockchains,\n evmBasedChains: evmBasedChains,\n evmNetworkChainInfo:\n convertEvmBlockchainMetaToEvmChainInfo(evmBasedChains),\n getSupportedChainNames,\n },\n getSigners,\n //todo: remove Network type\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n //@ts-ignore\n wallets,\n providers: allProviders,\n switchNetwork,\n canSwitchNetworkTo,\n connect,\n state,\n isMobileWallet,\n };\n\n return (\n <ManagerProvider\n queuesDefs={[swapQueueDef]}\n context={context}\n onPersistedDataLoaded={(manager) => {\n checkWaitingForNetworkChange(manager);\n }}\n isPaused={false}>\n {props.children}\n </ManagerProvider>\n );\n}\n\nexport default QueueManager;\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["MainEvents", "RouteEventType", "StepEventType", "StepExecutionBlockedEventStatus", "StepExecutionEventStatus", "useWidgetEvents", "useWallets", "Events", "Provider", "isEvmBlockchain", "React", "createContext", "useRef", "useEffect", "create", "subscribeWithSelector", "RangoClient", "RANGO_PUBLIC_API_KEY", "configs", "RANGO_PUBLIC_API_KEY", "getConfig", "name", "__name", "initConfig", "nextConfigs", "clonedConfigs", "configs", "__name", "DEFAULT_PRIMARY_RADIUS", "DEFAULT_SECONDARY_RADIUS", "DEFAULT_FONT_FAMILY", "THEME_CLASS_NAME_PREFIX", "rango", "httpService", "__name", "RangoClient", "getConfig", "WalletStatus", "readAccountAddress", "detectInstallLink", "getCosmosExperimentalChainInfo", "isEvmAddress", "KEPLR_COMPATIBLE_WALLETS", "Networks", "BigNumber", "isCosmosBlockchain", "BigNumber", "ZERO", "WalletTypes", "EXCLUDED_WALLETS", "BigNumber", "secondsToString", "__name", "s", "seconds", "numberToString", "number", "minDecimals", "maxDecimals", "BigNumber", "roundingMode", "maxI", "i", "totalArrivalTime", "__name", "data", "a", "b", "containsText", "__name", "text", "searchText", "isPositiveNumber", "limitDecimalPlaces", "numberString", "maxDecimalPlaces", "number", "multiplier", "mapStatusToWalletState", "state", "WalletStatus", "__name", "mapWalletTypesToWalletInfo", "getState", "getWalletInfo", "list", "chain", "wallet", "EXCLUDED_WALLETS", "supportedChains", "hideWhenNotInstalled", "supportedChain", "type", "name", "image", "installLink", "detectInstallLink", "walletAndSupportedChainsNames", "supportedBlockchains", "blockchainMeta", "prepareAccountsForWalletStore", "accounts", "evmBasedChains", "supportedChainNames", "result", "addAccount", "network", "address", "account", "newAccount", "readAccountAddress", "hasLimitation", "isSupported", "isUnknown", "Networks", "isUnknownAndEvmBased", "isEvmAddress", "getRequiredChains", "route", "wallets", "swap", "currentStepFromBlockchain", "currentStepToBlockchain", "internalSwap", "internalStepFromBlockchain", "internalStepToBlockchain", "getBalanceFromWallet", "connectedWallets", "symbol", "selectedChainWallets", "balance", "a", "b", "isAccountAndWalletMatched", "connectedWallet", "makeBalanceFor", "retrievedBalance", "tokens", "balances", "tokenBalance", "BigNumber", "getUsdPrice", "resetConnectedWalletState", "getUsdPrice", "__name", "blockchain", "symbol", "address", "allTokens", "t", "isExperimentalChain", "blockchains", "wallet", "cosmosExperimentalChainInfo", "getCosmosExperimentalChainInfo", "blockchainMeta", "isCosmosBlockchain", "getTokensWithBalance", "tokens", "connectedWallets", "balance", "otherProps", "tokenAmount", "numberToString", "BigNumber", "getBalanceFromWallet", "ZERO", "tokenUsdValue", "__name", "getTokensBalanceFromWalletAndSort", "list", "tokenA", "tokenB", "tokensAreEqual", "tokenA", "tokenB", "__name", "sortWalletsBasedOnConnectionState", "wallets", "a", "b", "WalletStatus", "getConciseAddress", "address", "maxChars", "ellipsisLength", "start", "end", "getAddress", "chain", "connectedWallets", "walletType", "connectedWallet", "create", "create", "createSelectors", "__name", "_store", "store", "k", "s", "selectors_default", "initConfig", "createConfigSlice", "__name", "set", "get", "nextConfig", "currentConfig", "removeDuplicateFrom", "array", "__name", "areEqual", "array1", "array2", "v", "i", "debounce", "fn", "time", "timeoutId", "wrapper", "args", "containsText", "text", "searchText", "getContainer", "createDataSlice", "__name", "set", "get", "options", "blockchainsFromState", "config", "supportedBlockchainsFromConfig", "blockchain", "tokensFromState", "supportedTokensFromConfig", "blockchains", "token", "asset", "tokensAreEqual", "containsText", "a", "b", "pinnedToken", "response", "httpService", "tokens", "popularTokens", "swappers", "blockchainsWithAtLeastOneToken", "store", "create", "a", "createDataSlice", "createConfigSlice", "useAppStore", "selectors_default", "useMetaStore", "selectors_default", "create", "set", "useAppStore", "state", "response", "useWalletsStore", "selectors_default", "create", "subscribeWithSelector", "set", "get", "accounts", "getWalletsDetails", "state", "wallet", "account", "shouldMarkWalletAsSelected", "connectedWallet", "walletType", "selectedWallets", "selectedWallet", "wallets", "walletSelected", "walletNotSelected", "shouldRetry", "tokens", "useMetaStore", "isAccountAndWalletMatched", "data", "address", "chain", "retrievedBalance", "httpService", "matchedAccount", "retrievedBalanceAccount", "balance", "makeBalanceFor", "resetConnectedWalletState", "allProviders", "matchAndGenerateProviders", "providers", "options", "all", "allProviders", "selectedProviders", "requestedProvider", "result", "provider", "__name", "configWalletsToWalletName", "config", "useWalletProviders", "providers", "options", "clearConnectedWallet", "useWalletsStore", "generateProviders", "matchAndGenerateProviders", "useEffect", "__name", "WidgetContext", "createContext", "WidgetWallets", "props", "blockchains", "useMetaStore", "providers", "useWalletProviders", "disconnectWallet", "useWalletsStore", "connectWallet", "onConnectWalletHandler", "useRef", "evmBasedChainNames", "isEvmBlockchain", "chain", "onUpdateState", "__name", "type", "event", "value", "state", "supportedBlockchains", "Events", "supportedChainNames", "walletAndSupportedChainsNames", "data", "prepareAccountsForWalletStore", "key", "React", "handler", "Provider", "I18nManager", "styled", "React", "useContext", "useEffect", "useMemo", "useState", "useQueueManager", "useWallets", "isEvmBlockchain", "React", "useEffect", "useRef", "MemoryRouter", "useInRouterContext", "useLocation", "useNavigate", "navigationRoutes", "i18n", "Alert", "BestRoute", "BestRouteSkeleton", "Button", "Divider", "styled", "SwapInput", "Typography", "WarningIcon", "React", "useEffect", "useRef", "useState", "useNavigate", "ChevronLeftIcon", "React", "darkTheme", "IconButton", "styled", "HeaderButton", "ConnectedIcon", "SuffixContainer", "NotificationsBadgeContainer", "BackButton", "props", "React", "HeaderButton", "ChevronLeftIcon", "__name", "i18n", "Button", "Typography", "React", "CancelButton", "props", "React", "SuffixContainer", "Button", "Typography", "i18n", "__name", "i18n", "Tooltip", "WalletIcon", "React", "WalletButton", "props", "React", "Tooltip", "i18n", "HeaderButton", "ConnectedIcon", "WalletIcon", "__name", "i18n", "NotificationsIcon", "Popover", "RefreshIcon", "SettingsIcon", "Tooltip", "TransactionIcon", "React", "i18n", "ChainToken", "ChevronRightIcon", "ListItemButton", "Typography", "React", "useNavigate", "create", "persist", "subscribeWithSelector", "useNotificationStore", "selectors_default", "create", "persist", "subscribeWithSelector", "set", "get", "event", "route", "fromStep", "toStep", "notification", "excludedList", "notificationItem", "requestId", "state", "create", "useUiStore", "selectors_default", "create", "set", "requestId", "path", "styled", "Container", "List", "Images", "NotFoundContainer", "i18n", "Divider", "NoNotificationIcon", "Typography", "React", "NotificationNotFound", "React", "NotFoundContainer", "NoNotificationIcon", "Divider", "Typography", "i18n", "__name", "MAX_NOTIFICATIONS_DISPLAYED", "NotificationContent", "navigate", "useNavigate", "setSelectedSwap", "useUiStore", "getUnreadNotifications", "useNotificationStore", "notifications", "tokens", "blockchains", "useMetaStore", "sortedNotification", "a", "b", "handleOnClick", "__name", "requestId", "React", "Container", "List", "notificationItem", "fromToken", "tokenItem", "fromBlockchain", "blockchainItem", "toToken", "toBlockchain", "ListItemButton", "Typography", "i18n", "Images", "ChainToken", "ChevronRightIcon", "NotificationNotFound", "Typography", "React", "UnreadNotificationsBadge", "getUnreadNotifications", "useNotificationStore", "notificationsCount", "React", "NotificationsBadgeContainer", "Typography", "__name", "HomeButtons", "props", "layoutRef", "onClickRefresh", "onClickHistory", "onClickSettings", "onClickNotifications", "React", "Tooltip", "getContainer", "i18n", "HeaderButton", "RefreshIcon", "Popover", "NotificationContent", "NotificationsIcon", "UnreadNotificationsBadge", "SettingsIcon", "TransactionIcon", "__name", "BottomLogo", "Divider", "Header", "React", "useNavigate", "darkTheme", "styled", "Container", "Content", "Footer", "LayoutComponent", "props", "ref", "children", "header", "footer", "noPadding", "hasLogo", "fixedHeight", "connectedWallets", "useWalletsStore", "connectWalletsButtonDisabled", "useUiStore", "navigate", "useNavigate", "onConnectWallet", "__name", "navigationRoutes", "React", "Container", "Header", "BackButton", "WalletButton", "getContainer", "CancelButton", "Content", "Footer", "Divider", "BottomLogo", "Layout", "Alert", "Button", "Divider", "NoRouteIcon", "RefreshIcon", "Typography", "React", "i18n", "RouteWarningType", "errorMessages", "__name", "i18n", "getConfirmSwapErrorMessage", "error", "create", "persist", "subscribeWithSelector", "English", "French", "Japanese", "Spanish", "LANGUAGES", "DEFAULT_LANGUAGE", "SLIPPAGES", "DEFAULT_SLIPPAGE", "HIGH_SLIPPAGE", "MAX_SLIPPAGE", "MIN_SLIPPGAE", "useSettingsStore", "selectors_default", "create", "persist", "subscribeWithSelector", "set", "get", "DEFAULT_SLIPPAGE", "DEFAULT_LANGUAGE", "blockchain", "currentPreferredBlockchains", "preferredBlockchain", "index", "isSameBlockchain", "isInVisibleList", "nextPreferredBlockchains", "slippage", "customSlippage", "affiliateRef", "affiliatePercent", "affiliateWallets", "shouldReset", "state", "swappers", "useMetaStore", "swappersGroup", "removeDuplicateFrom", "swapper", "name", "liquiditySource", "theme", "language", "i18n", "makeInfo", "diagnosisMessage", "disabledLiquiditySources", "hasError", "toggleAllLiquiditySources", "refetchBestRoute", "errorMessages", "i18n", "__name", "styled", "Container", "Footer", "PrefixIcon", "NoRoutes", "props", "diagnosisMessage", "fetch", "error", "disabledLiquiditySources", "useSettingsStore", "loadingMetaStatus", "useMetaStore", "toggleAllLiquiditySources", "info", "makeInfo", "React", "Container", "NoRouteIcon", "Divider", "Typography", "errorMessages", "Footer", "Alert", "Button", "PrefixIcon", "RefreshIcon", "__name", "Alert", "Divider", "InfoIcon", "React", "BigNumber", "create", "subscribeWithSelector", "getLastSuccessfulStep", "BigNumber", "getBlockchainDisplayNameFor", "blockchainName", "blockchains", "blockchain", "__name", "getBlockchainShortNameFor", "findToken", "tokens", "token", "tokensAreEqual", "findBlockchain", "name", "searchParamsToToken", "tokens", "searchParams", "chain", "token", "symbolAndAddress", "__name", "getBestRouteToTokenUsdPrice", "bestRoute", "isNumberOfSwapsChanged", "route1", "route2", "route1Swaps", "route2Swaps", "isRouteSwappersUpdated", "route1Swappers", "swap", "route2Swappers", "areEqual", "isRouteInternalCoinsUpdated", "route1InternalCoins", "route2InternalCoins", "isRouteChanged", "getRequiredBalanceOfWallet", "selectedWallet", "fee", "relatedFeeStatus", "item", "wallet", "__name", "getFormattedBestRoute", "bestRoute", "formattedSwaps", "swap", "numberToString", "__name", "getPriceImpactLevel", "priceImpact", "warningLevel", "__name", "createRetryRoute", "pendingSwap", "blockchains", "tokens", "firstStep", "lastStep", "lastSuccessfulStep", "getLastSuccessfulStep", "toToken", "fromBlockchainMeta", "findBlockchain", "toBlockchainMeta", "fromTokenMeta", "findToken", "toTokenMeta", "inputAmount", "__name", "i18n", "PendingSwapNetworkStatus", "BigNumber", "formatBestRoute", "bestRoute", "blockchains", "swap", "getBlockchainShortNameFor", "numberToString", "__name", "getRequiredWallets", "route", "wallets", "currentStepFromBlockchain", "currentStepToBlockchain", "lastAddedWallet", "isValidAddress", "chain", "address", "i18n", "swapButtonTitles", "__name", "i18n", "getOutputRatio", "inputUsdValue", "outputUsdValue", "ZERO", "__name", "outputRatioHasWarning", "outputRatio", "BigNumber", "hasLimitError", "bestRoute", "swap", "minimum", "maximum", "LimitErrorMessage", "isExclusive", "fromAmountRangeError", "recommendation", "i18n", "numberToString", "errorMessages", "getSwapButtonState", "loadingMetaStatus", "connectedWallets", "loading", "highValueLoss", "priceImpactCanNotBeComputed", "needsToWarnEthOnPath", "inputAmount", "swapButtonTitles", "canComputePriceImpact", "usdValue", "requiredWallets", "route", "wallets", "currentStepFromBlockchain", "currentStepToBlockchain", "lastAddedWallet", "getUsdPrice", "blockchain", "symbol", "address", "allTokens", "t", "getUsdFeeOfStep", "step", "totalFeeInUsd", "i", "fee", "unitPrice", "getTotalFeeInUsd", "totalFee", "getMinRequiredSlippage", "route", "slippage", "s", "a", "b", "__name", "hasProperSlippage", "userSlippage", "minRequiredSlippage", "createBestRouteRequestBody", "params", "fromToken", "toToken", "inputAmount", "wallets", "selectedWallets", "disabledLiquiditySources", "slippage", "affiliateRef", "affiliatePercent", "affiliateWallets", "initialRoute", "destination", "selectedWalletsMap", "selectedWallet", "connectedWallets", "wallet", "chainAndAccounts", "connectedWallet", "checkPrerequisites", "filteredBlockchains", "removeDuplicateFrom", "blockchains", "swap", "internalSwap", "__name", "getWalletsForNewSwap", "getRouteOutputAmount", "route", "getPercentageChange", "inputUsdValue", "outputUsdValue", "BigNumber", "isOutputAmountChangedALot", "oldRoute", "newRoute", "oldOutputAmount", "newOutputAmount", "percentageChange", "getBalanceWarnings", "fee", "requiredWallets", "getRequiredChains", "selectedWallet1", "selectedWallet2", "getRequiredBalanceOfWallet", "asset", "symbol", "currentAmount", "numberToString", "requiredAmount", "reason", "i18n", "calcOutputUsdValue", "outputAmount", "tokenPrice", "ZERO", "isNetworkStatusInWarningState", "pendingSwapStep", "PendingSwapNetworkStatus", "getSwapMessages", "pendingSwap", "currentStep", "textForRemove", "message", "detailedMessage", "isRpc", "getLastConvertedTokenInFailedSwap", "resultToken", "lastSuccessStep", "step", "shouldRetrySwap", "confirmSwapDisabled", "fetching", "showCustomDestination", "customDestination", "bestRoute", "selectedWallets", "lastStepToBlockchain", "requiredWallets", "chain", "wallet", "isValidAddress", "__name", "getUsdValue", "__name", "token", "amount", "BigNumber", "ZERO", "useBestRouteStore", "selectors_default", "create", "subscribeWithSelector", "set", "bestRoute", "state", "outputAmount", "outputUsdValue", "isPositiveNumber", "calcOutputUsdValue", "getBestRouteToTokenUsdPrice", "chain", "blockchains", "useMetaStore", "blockchain", "pendingSwap", "tokens", "fromBlockchain", "fromToken", "toBlockchain", "toToken", "inputAmount", "createRetryRoute", "flag", "wallets", "address", "styled", "Alerts", "Flex", "Item", "Action", "i18n", "Button", "Divider", "MessageBox", "Modal", "Typography", "WarningIcon", "React", "useNavigate", "Typography", "React", "RouteErrorsModalItem", "props", "title", "value", "valueColor", "React", "Item", "Typography", "__name", "RouteErrorsModal", "props", "highValueLoss", "open", "onToggle", "percentageChange", "inputUsdValue", "outputUsdValue", "totalFeeInUsd", "navigate", "useNavigate", "type", "highValueLossData", "i18n", "numberToString", "React", "Modal", "MessageBox", "errorMessages", "Flex", "Divider", "Typography", "item", "index", "RouteErrorsModalItem", "Button", "WarningIcon", "navigationRoutes", "__name", "WARNING_LEVEL_LIMIT", "RouteErrors", "props", "bestRoute", "useBestRouteStore", "highValueLoss", "percentageChange", "priceImpactCanNotBeComputed", "openModal", "onToggle", "totalFeeInUsd", "outputUsdValue", "inputUsdValue", "loading", "extraSpace", "error", "hasLimitError", "recommendation", "LimitErrorMessage", "showWarnings", "showAlerts", "React", "Divider", "Alerts", "Alert", "errorMessages", "Action", "InfoIcon", "RouteErrorsModal", "__name", "ReverseIcon", "styled", "React", "SwitchButtonContainer", "styled", "StyledButton", "SwitchFromAndToButton", "switchFromAndTo", "useBestRouteStore", "React", "ReverseIcon", "__name", "useEffect", "useRef", "useState", "useRef", "useState", "useFetchBestRoute", "loading", "setLoading", "useState", "abortController", "useRef", "cancel", "__name", "requestBody", "res", "httpService", "error", "DEBOUNCE_DELAY", "useSwapInput", "fetchBestRoute", "cancelFetch", "useFetchBestRoute", "loading", "setLoading", "useState", "fromToken", "toToken", "inputAmount", "inputUsdValue", "resetRoute", "setRoute", "useBestRouteStore", "slippage", "customSlippage", "affiliatePercent", "affiliateRef", "affiliateWallets", "disabledLiquiditySources", "useSettingsStore", "error", "setError", "prevDisabledLiquiditySources", "useRef", "userSlippage", "shouldSkipRequest", "tokensAreEqual", "isPositiveNumber", "fetch", "__name", "requestBody", "createBestRouteRequestBody", "res", "debouncedFetch", "debounce", "useEffect", "disabledLiquiditySourceReset", "Container", "styled", "FromContainer", "InputsContainer", "BestRouteContainer", "FooterStepAlarm", "FooterAlert", "Home", "navigate", "useNavigate", "refetchBestRoute", "fetchingBestRoute", "bestRouteError", "useSwapInput", "fromToken", "fromBlockchain", "toToken", "toBlockchain", "setInputAmount", "inputAmount", "inputUsdValue", "outputAmount", "outputUsdValue", "bestRoute", "resetRouteWallets", "useBestRouteStore", "tokens", "blockchains", "loadingMetaStatus", "useMetaStore", "connectedWallets", "useWalletsStore", "setCurrentPage", "useUiStore", "openWarningModal", "setOpenWarningModal", "useState", "fromAmountRangeError", "swapHasError", "recommendation", "LimitErrorMessage", "layoutRef", "useRef", "showBestRoute", "needsToWarnEthOnPath", "outToInRatio", "getOutputRatio", "highValueLoss", "outputRatioHasWarning", "priceImpactInputCanNotBeComputed", "canComputePriceImpact", "priceImpactOutputCanNotBeComputed", "swapButtonState", "getSwapButtonState", "hasLimitError", "tokenBalance", "numberToString", "getBalanceFromWallet", "tokenBalanceReal", "useEffect", "navigationRoutes", "percentageChange", "getPercentageChange", "getBestRouteSteps", "__name", "swaps", "swap", "index", "getBlockchainShortNameFor", "React", "Alert", "Typography", "Divider", "i18n", "totalFeeInUsd", "getTotalFeeInUsd", "bestRouteData", "getFormattedBestRoute", "Layout", "Button", "WarningIcon", "HomeButtons", "SwapInput", "errorMessages", "SwitchFromAndToButton", "getPriceImpactLevel", "BestRouteSkeleton", "BestRoute", "getContainer", "secondsToString", "totalArrivalTime", "NoRoutes", "RouteErrors", "useEffect", "useRef", "createSearchParams", "useLocation", "useSearchParams", "useEffect", "useMemo", "useRef", "useSyncStoresWithConfig", "config", "setInputAmount", "setToToken", "setToBlockchain", "setFromBlockchain", "setFromToken", "fromToken", "toToken", "fromBlockchain", "toBlockchain", "useBestRouteStore", "tokens", "blockchains", "loadingMetaStatus", "useMetaStore", "setAffiliateRef", "setAffiliatePercent", "setAffiliateWallets", "useSettingsStore", "fromTokensConfig", "useMemo", "fromBlockchainsConfig", "toTokensConfig", "toBlockchainsConfig", "prevConfigFromToken", "useRef", "prevConfigToToken", "prevConfigFromBlockchain", "prevConfigToBlockchain", "useEffect", "chain", "token", "t", "tokensAreEqual", "__name", "UpdateUrl", "props", "firstRender", "useRef", "searchParams", "setSearchParams", "useSearchParams", "location", "useLocation", "firstRenderSearchParams", "searchParamsRef", "fromBlockchain", "useBestRouteStore", "toBlockchain", "fromToken", "toToken", "setFromBlockchain", "setFromToken", "setToBlockchain", "setToToken", "inputAmount", "setInputAmount", "loadingStatus", "useMetaStore", "blockchains", "tokens", "setSelectedSwap", "useUiStore", "useSyncStoresWithConfig", "useEffect", "params", "createSearchParams", "value", "key", "requestId", "navigationRoutes", "fromChainString", "fromTokenString", "toChainString", "toTokenString", "fromAmount", "blockchain", "searchParamsToToken", "__name", "Route", "props", "location", "useLocation", "navigate", "useNavigate", "firstRender", "useRef", "paths", "shouldRedirectToMainPage", "navigationRoutes", "useEffect", "React", "Home", "__name", "AppRouter", "children", "isRouterInContext", "useInRouterContext", "Router", "MemoryRouter", "blockchains", "useMetaStore", "canSwitchNetworkTo", "useWallets", "evmChains", "isEvmBlockchain", "useQueueManager", "UpdateUrl", "React", "useRoutes", "i18n", "useManager", "Alert", "BestRoute", "BestRouteSkeleton", "Button", "Divider", "IconButton", "MessageBox", "Modal", "RefreshIcon", "SettingsIcon", "styled", "Tooltip", "Typography", "WalletIcon", "React", "useEffect", "useState", "flushSync", "useNavigate", "i18n", "Alert", "BalanceErrors", "Button", "ChevronDownIcon", "ChevronLeftIcon", "Divider", "MessageBox", "Modal", "Typography", "WalletIcon", "React", "useEffect", "useLayoutEffect", "useRef", "useState", "useNavigate", "i18n", "getRouteWarningMessage", "warning", "i18n", "__name", "Collapsible", "Button", "darkTheme", "IconButton", "keyframes", "styled", "TextField", "EXPANDABLE_TRANSITION_DURATION", "slideDown", "slideUp", "Title", "ListContainer", "WalletButton", "Trigger", "ShowMoreHeader", "NavigateBack", "WalletsContainer", "CollapsibleRoot", "CustomDestinationButton", "CustomDestination", "ExpandedIcon", "ConfirmButton", "StyledTextField", "CollapsibleContent", "Wallets", "i18n", "Button", "Divider", "Image", "MessageBox", "Modal", "SelectableWallet", "Typography", "WalletState", "React", "useEffect", "useState", "WalletState", "useWallets", "KEPLR_COMPATIBLE_WALLETS", "WalletTypes", "useEffect", "useState", "ALL_SUPPORTED_WALLETS", "WalletTypes", "useWalletList", "params", "config", "chain", "onBeforeConnect", "onConnect", "state", "disconnect", "getWalletInfo", "connect", "useWallets", "connectedWallets", "useWalletsStore", "blockchains", "useMetaStore", "multiWallets", "listAvailableWalletTypes", "configWalletsToWalletName", "wallets", "mapWalletTypesToWalletInfo", "sortedWallets", "sortWalletsBasedOnConnectionState", "error", "setError", "useState", "isExperimentalChainNotAdded", "__name", "walletType", "connectedWallet", "handleClick", "type", "wallet", "atLeastOneWalletIsConnected", "w", "WalletState", "e", "disconnectConnectingWallets", "connectingWallets", "useEffect", "shouldExcludeWallet", "isExperimentalChain", "KEPLR_COMPATIBLE_WALLETS", "i18n", "styled", "Typography", "Wallet", "WalletState", "React", "Fragment", "useState", "Divider", "Modal", "React", "i18n", "Image", "MessageBox", "WalletState", "React", "keyframes", "styled", "IconContainer", "LogoContainer", "spin", "Spinner", "WalletImageContainer", "ModalContent", "props", "state", "image", "error", "WalletState", "React", "MessageBox", "i18n", "LogoContainer", "WalletImageContainer", "Image", "Spinner", "__name", "WalletModal", "props", "open", "onClose", "otherProps", "React", "Modal", "ModalContent", "Divider", "__name", "useInRouterContext", "useNavigate", "useNavigateBack", "isRouterInContext", "useInRouterContext", "navigate", "useNavigate", "routeWalletsConfirmed", "useBestRouteStore", "navigationRoutes", "__name", "currentRoute", "ListContainer", "styled", "Container", "TIME_TO_CLOSE_MODAL", "TIME_TO_IGNORE_MODAL", "WalletsPage", "config", "navigateBackFrom", "useNavigateBack", "openModal", "setOpenModal", "useState", "selectedWalletType", "setSelectedWalletType", "modalTimerId", "list", "handleClick", "error", "useWalletList", "type", "loadingMetaStatus", "useMetaStore", "selectedWallet", "wallet", "selectedWalletImage", "selectedWalletState", "WalletState", "React", "Layout", "i18n", "navigationRoutes", "Typography", "index", "key", "Fragment", "Wallet", "getContainer", "WalletModal", "__name", "keyframes", "styled", "LogoContainer", "SpinAnimation", "Spinner", "WalletImageContainer", "WalletList", "props", "config", "chain", "isSelected", "selectWallet", "limit", "onShowMore", "connectedWallets", "useWalletsStore", "blockchains", "useMetaStore", "openWalletStateModal", "setOpenWalletStateModal", "useState", "experimentalChainWallet", "setExperimentalChainWallet", "showExperimentalChainModal", "setShowExperimentalChainModal", "addingExperimentalChainStatus", "setAddingExperimentalChainStatus", "connect", "useWallets", "modalTimerId", "list", "error", "handleClick", "useWalletList", "type", "TIME_TO_IGNORE_MODAL", "TIME_TO_CLOSE_MODAL", "sortedList", "setSortedList", "numberOfSupportedWallets", "shouldShowMoreWallets", "addExperimentalChain", "__name", "wallet", "useEffect", "selectedWalletIndex", "_", "index", "sortedItem", "listItem", "modalContainer", "timeout", "React", "address", "getAddress", "conciseAddress", "getConciseAddress", "experimentalChain", "isExperimentalChain", "experimentalChainNotAdded", "connectedWallet", "couldAddExperimentalChain", "WalletState", "connectedWalletDescription", "i18n", "onClick", "blockchainDisplayName", "getBlockchainDisplayNameFor", "WalletModal", "Modal", "MessageBox", "Divider", "Button", "LogoContainer", "WalletImageContainer", "Image", "Spinner", "SelectableWallet", "WalletButton", "Typography", "NUMBER_OF_WALLETS_TO_DISPLAY", "ConfirmWalletsModal", "props", "open", "onClose", "onCancel", "onCheckBalance", "config", "loading", "blockchains", "useMetaStore", "bestRoute", "selectRouteWallets", "routeWalletsConfirmed", "setRouteWalletConfirmed", "customDestination", "setCustomDestination", "useBestRouteStore", "connectedWallets", "selectWallets", "useWalletsStore", "showMoreWalletFor", "setShowMoreWalletFor", "useState", "balanceWarnings", "setBalanceWarnings", "error", "setError", "routeWarning", "setRouteWarning", "destination", "setDestination", "showCustomDestination", "setShowCustomDestination", "customDestinationRef", "useRef", "requiredWallets", "getRequiredWallets", "customDestinationEnabled", "lastStepToBlockchain", "blockchain", "isWalletRequiredFor", "__name", "swap", "selectableWallets", "setSelectableWallets", "connectedWallet", "lastStepToBlockchainMeta", "chain", "isSelected", "walletType", "selectableWallet", "isAddressMatched", "isValidAddress", "resetCustomDestination", "anyWalletSelected", "onChange", "wallet", "onConfirmBalance", "lastSelectedWallets", "onConfirmWallets", "selectedWallets", "result", "warnings", "getConfirmSwapErrorMessage", "useEffect", "useLayoutEffect", "EXPANDABLE_TRANSITION_DURATION", "modalContainer", "navigate", "useNavigate", "React", "Modal", "navigationRoutes", "ConfirmButton", "Button", "confirmSwapDisabled", "ShowMoreHeader", "NavigateBack", "ChevronLeftIcon", "Typography", "i18n", "MessageBox", "BalanceErrors", "WalletsContainer", "WalletList", "Alert", "Divider", "getRouteWarningMessage", "Wallets", "requiredWallet", "index", "key", "isLastWallet", "Title", "ListContainer", "CustomDestination", "CollapsibleRoot", "checked", "Trigger", "prevState", "CustomDestinationButton", "ExpandedIcon", "ChevronDownIcon", "WalletIcon", "CollapsibleContent", "StyledTextField", "e", "calculatePendingSwap", "BigNumber", "useEffect", "throwErrorIfResponseIsNotValid", "response", "params", "errorMessages", "newRouteOutputUsdValue", "BigNumber", "outputRatio", "getOutputRatio", "outputRatioHasWarning", "__name", "generateWarnings", "previousRoute", "currentRoute", "routeChanged", "isRouteChanged", "output", "isOutputAmountChangedALot", "numberToString", "getRouteOutputAmount", "getPercentageChange", "isNumberOfSwapsChanged", "isRouteSwappersUpdated", "isRouteInternalCoinsUpdated", "balanceWarnings", "getBalanceWarnings", "minRequiredSlippage", "getMinRequiredSlippage", "highSlippage", "HIGH_SLIPPAGE", "hasProperSlippage", "useConfirmSwap", "fromToken", "toToken", "inputAmount", "inputUsdValue", "setRoute", "initialRoute", "customDestinationFromStore", "useBestRouteStore", "slippage", "customSlippage", "affiliatePercent", "affiliateRef", "affiliateWallets", "disabledLiquiditySources", "useSettingsStore", "connectedWallets", "useWalletsStore", "meta", "useMetaStore", "userSlippage", "fetchBestRoute", "cancelFetch", "loading", "useFetchBestRoute", "useEffect", "selectedWallets", "customDestination", "requestBody", "createBestRouteRequestBody", "error", "swapSettings", "swap", "calculatePendingSwap", "getWalletsForNewSwap", "Container", "styled", "Buttons", "IconButton", "ConfirmSwapPage", "props", "config", "bestRoute", "inputAmount", "outputAmount", "inputUsdValue", "outputUsdValue", "setInputAmount", "selectedWallets", "routeWalletsConfirmed", "setRouteWalletConfirmed", "customDestination", "useBestRouteStore", "navigate", "useNavigate", "dbErrorMessage", "setDbErrorMessage", "useState", "showSlippageWarning", "setShowSlippageWarning", "connectedWallets", "useWalletsStore", "showWalletsOnInit", "showWallets", "setShowWallets", "setSelectedSwap", "useUiStore", "tokens", "blockchains", "loadingMetaStatus", "useMetaStore", "slippage", "useSettingsStore", "customSlippage", "manager", "useManager", "selectedSlippage", "confirmSwap", "fetchingConfirmationRoute", "cancelFetch", "useConfirmSwap", "confirmSwapResult", "setConfirmSwapResult", "showSkeleton", "showNoRouteFound", "showBestRoute", "totalFeeInUsd", "getTotalFeeInUsd", "percentageChange", "numberToString", "getPercentageChange", "warningLevel", "getPriceImpactLevel", "onConfirmSwap", "__name", "result", "addNewSwap", "navigationRoutes", "e", "onConfirm", "onStartConfirmSwap", "onRefresh", "res", "error", "useEffect", "routeChanged", "RouteWarningType", "selectedWalletDisconnected", "selectedWallet", "connectedWallet", "routeWalletsChanged", "requiredWallets", "getRequiredWallets", "lastStepToBlockchain", "swap", "requiredWallet", "flushSync", "React", "Layout", "i18n", "Tooltip", "getContainer", "HeaderButton", "SettingsIcon", "Button", "WalletIcon", "Modal", "Typography", "prevState", "MessageBox", "Divider", "ConfirmWalletsModal", "RefreshIcon", "Alert", "getRouteWarningMessage", "BestRouteSkeleton", "BestRoute", "formatBestRoute", "secondsToString", "totalArrivalTime", "NoRoutes", "getConfirmSwapErrorMessage", "i18n", "useManager", "Divider", "NotFound", "styled", "React", "useState", "useNavigate", "CloseIcon", "IconButton", "SearchIcon", "TextField", "React", "styled", "IconWrapper", "SearchInput", "props", "variant", "fullWidth", "color", "size", "onChange", "value", "setValue", "inputAttributes", "React", "TextField", "IconWrapper", "SearchIcon", "IconButton", "CloseIcon", "__name", "i18n", "Divider", "SwapListItem", "Typography", "React", "styled", "Group", "Time", "SwapList", "NotFoundContainer", "SwapsGroup", "props", "list", "onSwapClick", "groupBy", "isLoading", "groups", "swaps", "React", "group", "Group", "Time", "Typography", "i18n", "Divider", "SwapList", "_", "index", "key", "SwapListItem", "swap", "firstStep", "lastStep", "limitDecimalPlaces", "__name", "dayjs", "groupSwapsByDate", "__name", "swaps", "output", "now", "dayjs", "swap", "swapDate", "getPendingSwaps", "__name", "manager", "result", "q", "id", "storage", "a", "b", "Container", "styled", "SwapsGroupContainer", "isStepContainsText", "__name", "steps", "value", "step", "containsText", "HistoryPage", "setSelectedSwap", "useUiStore", "navigate", "useNavigate", "navigateBackFrom", "useNavigateBack", "manager", "state", "useManager", "list", "getPendingSwaps", "swap", "searchedFor", "setSearchedFor", "useState", "loading", "searchHandler", "event", "filteredList", "isEmpty", "React", "Layout", "navigationRoutes", "i18n", "SearchInput", "NotFoundContainer", "Divider", "NotFound", "SwapsGroup", "requestId", "groupSwapsByDate", "i18n", "List", "ListItemButton", "Radio", "RadioRoot", "Typography", "React", "styled", "SettingsContainer", "LiquiditySourceList", "LiquiditySourceSuffix", "NotFoundContainer", "useLanguage", "language", "useSettingsStore", "setLanguage", "LANGUAGES", "DEFAULT_LANGUAGE", "__name", "LanguagePage", "navigateBackFrom", "useNavigateBack", "activeLanguage", "changeLanguage", "languages", "useLanguage", "languageList", "languageItem", "local", "label", "SVGFlag", "React", "Typography", "Radio", "Layout", "navigationRoutes", "i18n", "SettingsContainer", "RadioRoot", "List", "ListItemButton", "__name", "i18n", "Button", "Checkbox", "Image", "ListItemButton", "NotFound", "Typography", "React", "useState", "Checkbox", "Skeleton", "React", "ListItem", "styled", "CustomeListItem", "ITEM_SKELETON_COUNT", "LoadingLiquiditySourceList", "React", "LiquiditySourceList", "e", "CustomeListItem", "Skeleton", "Checkbox", "__name", "getUniqueSwappersGroups", "supportedSwappers", "swappers", "useMetaStore", "disabledLiquiditySources", "useSettingsStore", "uniqueSupportedSwappersGroups", "removeDuplicateFrom", "s", "uniqueGroupItem", "swapperItem", "swapper", "isSupportedSwapper", "supportedItem", "swapperTypeItem", "__name", "sortLiquiditySourcesByGroupTitle", "a", "b", "LiquiditySourcePage", "supportedSwappers", "sourceType", "searchedFor", "setSearchedFor", "useState", "toggleLiquiditySource", "useSettingsStore", "navigateBackFrom", "useNavigateBack", "loadingMetaStatus", "useMetaStore", "supportedUniqueSwappersGroups", "getUniqueSwappersGroups", "validTypes", "liquiditySources", "uniqueItem", "hasSelectAll", "sourceItem", "toggleAllSources", "__name", "list", "sortLiquiditySourcesByGroupTitle", "selected", "groupTitle", "logo", "React", "Image", "Checkbox", "Typography", "i18n", "searchHandler", "event", "value", "filteredList", "containsText", "Layout", "navigationRoutes", "LiquiditySourceSuffix", "Button", "SettingsContainer", "SearchInput", "LoadingLiquiditySourceList", "NotFoundContainer", "NotFound", "LiquiditySourceList", "ListItemButton", "i18n", "Divider", "SelectableCategoryList", "React", "useState", "i18n", "Divider", "Image", "ListItemButton", "NotFound", "Typography", "React", "useEffect", "useState", "BlockchainCategories", "TransactionType", "filterByType", "__name", "blockchain", "type", "BlockchainCategories", "TransactionType", "filterBlockchains", "list", "searchedFor", "blockchainType", "containsText", "styled", "Container", "List", "ListItem", "Skeleton", "React", "ITEM_SKELETON_COUNT", "LoadingBlockchainList", "React", "List", "e", "ListItem", "Skeleton", "__name", "BlockchainList", "props", "list", "searchedFor", "onChange", "blockchainCategory", "blockchains", "setBlockchains", "useState", "loadingStatus", "useMetaStore", "useEffect", "filterBlockchains", "renderList", "__name", "React", "Divider", "NotFound", "i18n", "List", "item", "ListItemButton", "Image", "Typography", "Container", "LoadingBlockchainList", "SelectBlockchainPage", "props", "type", "navigateBackFrom", "useNavigateBack", "searchedFor", "setSearchedFor", "useState", "blockchainCategory", "setBlockchainCategory", "setToBlockchain", "useBestRouteStore", "setFromBlockchain", "loadingStatus", "useMetaStore", "blockchains", "useAppStore", "routeKey", "React", "Layout", "navigationRoutes", "i18n", "Divider", "SelectableCategoryList", "SearchInput", "event", "BlockchainList", "blockchain", "__name", "i18n", "Divider", "React", "useState", "useNavigate", "i18n", "BlockchainsChip", "Divider", "Image", "Skeleton", "Typography", "React", "useEffect", "MOST_USED_BLOCKChAINS", "prepare", "blockchains", "preferredBlockchains", "options", "list", "more", "sortByMostUsedBlockchains", "start", "preferredBlockchainsWithoutMainList", "i", "blockchain", "preferredBlockchain", "generateSortByPreferredBlockchainsFor", "__name", "a", "b", "mostUsed", "MOST_USED_BLOCKChAINS", "aIndexInMostUsed", "token", "bIndexInMostUsed", "aIsMostUsed", "bIsMostUsed", "aIndexInPreferred", "bIndexInPreferred", "aIsPreferred", "bIsPreferred", "usePrepareBlockchainList", "blockchains", "options", "preferredBlockchains", "addPreferredBlockchain", "useSettingsStore", "useEffect", "output", "prepare", "__name", "styled", "Container", "NUMBER_OF_LOADING", "BlockchainsSection", "props", "blockchains", "type", "blockchain", "onChange", "onMoreClick", "blockchainsList", "usePrepareBlockchainList", "loadingStatus", "useMetaStore", "resetToBlockchain", "useBestRouteStore", "resetFromBlockchain", "hasMoreItemsInList", "onlyOneItemInList", "showMoreButton", "React", "Divider", "Typography", "i18n", "Container", "e", "Skeleton", "BlockchainsChip", "item", "Image", "__name", "i18n", "darkTheme", "Divider", "ExternalLinkIcon", "Image", "ListItemButton", "NotFound", "PinIcon", "Skeleton", "Typography", "VirtualizedList", "React", "forwardRef", "useEffect", "useState", "colorShade", "__name", "col", "amt", "r", "g", "b", "rr", "gg", "bb", "generateRangeColors", "name", "color", "colors", "i", "generateColors", "mainColors", "reverseNeutralRange", "changeColors", "listOfColors", "colorKey", "range", "Divider", "ListItem", "Skeleton", "React", "styled", "Typography", "Container", "Title", "List", "Tag", "TagTitle", "BalanceContainer", "End", "Description", "ImageSection", "Pin", "LoadingTokenList", "props", "React", "List", "ListItem", "Skeleton", "End", "Divider", "__name", "PAGE_SIZE", "renderDesc", "__name", "props", "address", "name", "url", "token", "customCssForTag", "customCssForTagTitle", "length", "React", "Title", "Typography", "Divider", "Tag", "TagTitle", "e", "ExternalLinkIcon", "TokenList", "list", "searchedFor", "onChange", "selectedBlockchain", "tokens", "setTokens", "useState", "loadingStatus", "useMetaStore", "hasNextPage", "setHasNextPage", "loadingWallet", "useWalletsStore", "blockchains", "isTokenPinned", "useAppStore", "innerElementType", "forwardRef", "render", "ref", "loadNextPage", "useEffect", "renderList", "NotFound", "i18n", "VirtualizedList", "index", "style", "blockchain", "color", "generateRangeColors", "darkTheme", "ListItemButton", "ImageSection", "Image", "Pin", "PinIcon", "End", "Skeleton", "BalanceContainer", "Container", "LoadingTokenList", "List", "SelectSwapItemsPage", "props", "type", "navigate", "useNavigate", "navigateBackFrom", "useNavigateBack", "fromBlockchain", "toBlockchain", "setFromToken", "setToToken", "setFromBlockchain", "setToBlockchain", "useBestRouteStore", "connectedWallets", "useWalletsStore", "searchedFor", "setSearchedFor", "useState", "selectedBlockchainName", "blockchains", "useAppStore", "tokens", "tokensList", "getTokensBalanceFromWalletAndSort", "updateBlockchain", "__name", "blockchain", "updateToken", "token", "React", "Layout", "navigationRoutes", "i18n", "BlockchainsSection", "Divider", "SearchInput", "event", "TokenList", "tokenBlockchain", "chain", "i18n", "ChevronRightIcon", "Divider", "InfoIcon", "List", "ListItemButton", "Skeleton", "Switch", "Tooltip", "Typography", "React", "useNavigate", "i18n", "Chip", "Divider", "InfoIcon", "TextField", "Tooltip", "Typography", "React", "styled", "BaseContainer", "SlippageChipsContainer", "Head", "SlippageTooltipContainer", "i18n", "Typography", "React", "SlippageTooltipContent", "React", "SlippageTooltipContainer", "Typography", "i18n", "__name", "Slippage", "slippage", "useSettingsStore", "setSlippage", "customSlippage", "setCustomSlippage", "React", "BaseContainer", "Head", "Typography", "i18n", "Divider", "Tooltip", "getContainer", "SlippageTooltipContent", "InfoIcon", "SlippageChipsContainer", "SLIPPAGES", "slippageItem", "index", "key", "Chip", "TextField", "event", "parsedValue", "MIN_SLIPPGAE", "MAX_SLIPPAGE", "__name", "SettingsPage", "supportedSwappers", "singleTheme", "navigate", "useNavigate", "navigateBackFrom", "useNavigateBack", "infiniteApprove", "useSettingsStore", "toggleInfiniteApprove", "loadingMetaStatus", "useMetaStore", "supportedUniqueSwappersGroups", "getUniqueSwappersGroups", "bridgeSources", "uniqueItem", "totalBridgeSources", "totalSelectedBridgeSources", "exchangeSources", "totalExchangeSources", "totalSelectedExchangeSources", "handleEndItem", "__name", "totalSelected", "total", "React", "Skeleton", "Typography", "i18n", "bridgeItem", "Divider", "ChevronRightIcon", "navigationRoutes", "exchangeItem", "themeItem", "infiniteApprovalItem", "Tooltip", "getContainer", "SlippageTooltipContainer", "InfoIcon", "Switch", "settingItems", "Layout", "SettingsContainer", "Slippage", "List", "ListItemButton", "cancelSwap", "useManager", "React", "i18n", "getCurrentBlockchainOfOrNull", "getCurrentStep", "getRelatedWalletOrNull", "PendingSwapNetworkStatus", "Button", "CopyIcon", "Divider", "IconButton", "RouteCost", "RouteSummary", "StepDetails", "Typography", "useCopyToClipboard", "useWallets", "React", "useEffect", "useRef", "useState", "useNavigate", "i18n", "MILLISECOND_PER_SECOND", "SECONDS_PER_YEAR", "SECONDS_PER_MONTH", "SECONDS_PER_DAY", "SECONDS_PER_HOUR", "SECONDS_PER_MINUTE", "timeSince", "millisecond", "seconds", "sortedIntervals", "i18n", "a", "b", "interval", "turningPoint", "label", "pluralLabel", "intervalCount", "__name", "getSwapDate", "pendingSwap", "PendingSwapNetworkStatus", "Modal", "React", "i18n", "Button", "Divider", "MessageBox", "Typography", "React", "CancelContent", "__name", "onCancel", "onClose", "React", "Divider", "MessageBox", "i18n", "Button", "Typography", "i18n", "Button", "Divider", "MessageBox", "Typography", "React", "DeleteContent", "__name", "onDelete", "onClose", "React", "Divider", "MessageBox", "i18n", "Button", "Typography", "i18n", "PendingSwapNetworkStatus", "modalNetworkValues", "MessageBox", "Wallet", "WalletState", "useWallets", "React", "styled", "WalletContainer", "WalletStateContent", "__name", "props", "type", "title", "currentStepWallet", "message", "showWalletButton", "connect", "getWalletInfo", "walletState", "useWallets", "walletType", "state", "WalletState", "React", "MessageBox", "WalletContainer", "Wallet", "getContainer", "SwapDetailsModal", "props", "state", "onClose", "onDelete", "onCancel", "currentStepWallet", "message", "showWalletStateContent", "PendingSwapNetworkStatus", "React", "Modal", "WalletStateContent", "modalNetworkValues", "DeleteContent", "CancelContent", "__name", "i18n", "Button", "Divider", "MessageBox", "Modal", "TokenAmount", "Typography", "React", "useNavigate", "SwapDetailsCompleteModal", "props", "open", "onClose", "status", "priceValue", "usdValue", "token", "chain", "percentageChange", "description", "diagnosisUrl", "navigate", "useNavigate", "React", "Modal", "MessageBox", "i18n", "TokenAmount", "Divider", "Typography", "Button", "navigationRoutes", "__name", "React", "i18n", "Alert", "IconButton", "LinkIcon", "React", "Fragment", "Alert", "ChevronDownIcon", "ChevronUpIcon", "IconButton", "React", "useState", "FailedAlert", "props", "message", "showContentError", "setShowContentError", "useState", "React", "Alert", "IconButton", "prev", "ChevronUpIcon", "ChevronDownIcon", "__name", "styled", "Alerts", "i18n", "PendingSwapNetworkStatus", "Alert", "Button", "React", "WarningAlert", "props", "switchNetwork", "setNetworkModal", "message", "showNetworkModal", "React", "Alert", "Button", "PendingSwapNetworkStatus", "e", "i18n", "__name", "SwapDetailsAlerts", "props", "switchNetwork", "showNetworkModal", "setNetworkModal", "message", "step", "hasAlreadyProceededToSign", "hasWarning", "isNetworkStatusInWarningState", "waitingForApproval", "inProgress", "React", "Alerts", "explorerUrl", "index", "urls", "key", "lastUrl", "loading", "error", "Fragment", "Alert", "i18n", "IconButton", "LinkIcon", "WarningAlert", "FailedAlert", "__name", "RESET_INTERVAL", "getSteps", "__name", "swap", "blockchains", "args", "hasAlreadyProceededToSign", "step", "index", "amountToConvert", "getBlockchainShortNameFor", "numberToString", "React", "SwapDetailsAlerts", "getStepState", "isNetworkStatusInWarningState", "darkTheme", "styled", "Container", "HeaderDetails", "StepsList", "Alerts", "PlaceholderContainer", "LoaderContainer", "SwapDetails", "props", "swap", "requestId", "onDelete", "onCancelProps", "canSwitchNetworkTo", "connect", "getWalletInfo", "useWallets", "retry", "useBestRouteStore", "navigate", "useNavigate", "navigateBackFrom", "useNavigateBack", "_", "handleCopy", "useCopyToClipboard", "RESET_INTERVAL", "listRef", "useRef", "modalState", "setModalState", "useState", "showCompletedModal", "setShowCompletedModal", "tokens", "blockchains", "useMetaStore", "onCancel", "__name", "getUnreadNotifications", "useNotificationStore", "setAsRead", "unreadNotifications", "currentStep", "getCurrentStep", "currentStepNetworkStatus", "useEffect", "n", "showSwitchNetwork", "PendingSwapNetworkStatus", "lastConvertedTokenInFailedSwap", "getLastConvertedTokenInFailedSwap", "currentStepBlockchain", "getCurrentBlockchainOfOrNull", "currentStepWallet", "getRelatedWalletOrNull", "swapDate", "getSwapDate", "shouldRetry", "shouldRetrySwap", "isMobileWallet", "walletType", "switchNetwork", "stepMessage", "getSwapMessages", "steps", "getSteps", "numberOfSteps", "firstStep", "lastStep", "outputAmount", "totalFee", "diagnosisUrl", "step", "outputUsdValue", "numberToString", "getUsdPrice", "inputUsdValue", "percentageChange", "getPercentageChange", "completeModalDesc", "i18n", "getConciseAddress", "React", "Layout", "navigationRoutes", "SuffixContainer", "Button", "Typography", "Container", "HeaderDetails", "IconButton", "CopyIcon", "RouteCost", "secondsToString", "totalArrivalTime", "RouteSummary", "getPriceImpactLevel", "Divider", "StepsList", "index", "key", "state", "getStepState", "isFocused", "StepDetails", "SwapDetailsModal", "SwapDetailsCompleteModal", "i18n", "CopyIcon", "IconButton", "NotFound", "Skeleton", "Typography", "React", "i18n", "ChainToken", "Divider", "Skeleton", "Typography", "React", "styled", "Container", "StepContainer", "StepSeparator", "ChainToken", "Divider", "NextIcon", "Skeleton", "React", "LoadingSwapDetailStep", "props", "extraInfo", "React", "StepContainer", "Skeleton", "Divider", "ChainToken", "NextIcon", "__name", "LoadingSwapDetails", "routeSummary", "React", "ChainToken", "Divider", "Skeleton", "Container", "Typography", "i18n", "LoadingSwapDetailStep", "StepSeparator", "__name", "SwapDetailsPlaceholder", "props", "requestId", "showSkeleton", "navigateBackFrom", "useNavigateBack", "React", "Layout", "i18n", "navigationRoutes", "SuffixContainer", "Container", "HeaderDetails", "Typography", "Skeleton", "IconButton", "CopyIcon", "LoadingSwapDetails", "PlaceholderContainer", "NotFound", "__name", "SwapDetailsPage", "manager", "state", "useManager", "loading", "pendingSwaps", "getPendingSwaps", "requestId", "useUiStore", "navigateBackFrom", "useNavigateBack", "loadingStatus", "useMetaStore", "showSkeleton", "selectedSwap", "swap", "onCancel", "__name", "cancelSwap", "onDelete", "navigationRoutes", "e", "React", "SwapDetailsPlaceholder", "SwapDetails", "i18n", "AutoThemeIcon", "DarkModeIcon", "LightModeIcon", "List", "ListItemButton", "Radio", "RadioRoot", "Typography", "React", "ThemePage", "navigateBackFrom", "useNavigateBack", "theme", "useSettingsStore", "setTheme", "themesList", "React", "Typography", "i18n", "LightModeIcon", "Radio", "DarkModeIcon", "AutoThemeIcon", "Layout", "navigationRoutes", "SettingsContainer", "RadioRoot", "value", "List", "ListItemButton", "__name", "getAbsolutePath", "__name", "path", "AppRoutes", "props", "config", "useRoutes", "navigationRoutes", "React", "Home", "SelectSwapItemsPage", "SelectBlockchainPage", "SettingsPage", "ThemePage", "LanguagePage", "LiquiditySourcePage", "HistoryPage", "SwapDetailsPage", "WalletsPage", "ConfirmSwapPage", "isApprovalTX", "MainEvents", "RouteEventType", "StepEventType", "StepExecutionEventStatus", "useEvents", "useEffect", "StepExecutionBlockedEventStatus", "validBlockedStatuses", "WidgetEvents", "connectedWallets", "useWalletsStore", "getWalletsDetails", "setNotification", "useNotificationStore", "setAsRead", "widgetEvents", "useEvents", "useEffect", "MainEvents", "widgetEvent", "event", "step", "route", "StepEventType", "StepExecutionEventStatus", "isApprovalTX", "fromAccount", "account", "toAccount", "wallet", "validBlockedStatuses", "RouteEventType", "__name", "globalCss", "globalFont", "__name", "globalCss", "createTheme", "defaultDarkTheme", "defaultLightTheme", "useEffect", "useState", "baseThemeTokens", "defaultDarkColors", "toAlphabeticChar", "__name", "code", "toAlphabeticName", "name", "x", "toPhash", "h", "i", "toHash", "value", "customizedThemeTokens", "colors", "baseColors", "baseThemeTokens", "darkColorsWithDefaults", "generateColors", "defaultDarkColors", "lightColorsWithDefaults", "hasDefaultDarkColors", "hasDefaultLightColors", "light", "dark", "tokens", "THEME_CLASS_NAME_PREFIX", "toHash", "__name", "useTheme", "props", "colors", "fontFamily", "DEFAULT_FONT_FAMILY", "borderRadius", "DEFAULT_PRIMARY_RADIUS", "secondaryBorderRadius", "DEFAULT_SECONDARY_RADIUS", "mode", "OSTheme", "setOSTheme", "useState", "theme", "useSettingsStore", "setTheme", "dark", "light", "customizedThemeTokens", "baseTheme", "createTheme", "lightThemeClasses", "defaultLightTheme", "darkThemeClasses", "defaultDarkTheme", "customizedLightTheme", "customizedDarkTheme", "useEffect", "switchThemeListener", "__name", "event", "lightClassNames", "darkClassNames", "React", "useMemo", "ManagerProvider", "makeQueueDefinition", "checkWaitingForNetworkChange", "useWallets", "convertEvmBlockchainMetaToEvmChainInfo", "isEvmBlockchain", "QueueManager", "props", "providers", "getSigners", "state", "connect", "canSwitchNetworkTo", "getWalletInfo", "useWallets", "swapQueueDef", "useMemo", "makeQueueDefinition", "getConfig", "blockchains", "useMetaStore", "wallets", "useWalletsStore", "wallet", "switchNetwork", "__name", "network", "isMobileWallet", "walletType", "allBlockchains", "blockchain", "blockchainsObj", "evmBasedChains", "isEvmBlockchain", "getSupportedChainNames", "type", "supportedChains", "walletAndSupportedChainsNames", "allProviders", "context", "convertEvmBlockchainMetaToEvmChainInfo", "React", "ManagerProvider", "manager", "checkWaitingForNetworkChange", "QueueManager_default", "MainContainer", "styled", "Main", "props", "config", "globalFont", "activeTheme", "useTheme", "activeLanguage", "changeLanguage", "useLanguage", "lastConnectedWalletWithNetwork", "setLastConnectedWalletWithNetwork", "useState", "disconnectedWallet", "setDisconnectedWallet", "widgetContext", "useContext", "WidgetContext", "fetchMeta", "useMetaStore", "useMemo", "initConfig", "useEffect", "useSettingsStore", "useNotificationStore", "React", "I18nManager", "QueueManager_default", "WidgetEvents", "AppRouter", "AppRoutes", "__name", "Widget", "updateConfig", "useAppStore", "WidgetWallets"]
|
|
7
7
|
}
|