@lifi/widget 4.7.1 → 4.9.0
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/esm/components/AmountInput/AmountInput.style.d.ts.map +1 -1
- package/dist/esm/components/AmountInputCard/AmountInputCardPair.js +5 -2
- package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -1
- package/dist/esm/components/Card/Card.d.ts.map +1 -1
- package/dist/esm/components/Card/CardIconButton.d.ts.map +1 -1
- package/dist/esm/components/ContractComponent/ItemPrice.d.ts.map +1 -1
- package/dist/esm/components/ListItem/ListItemButton.d.ts.map +1 -1
- package/dist/esm/components/ListItemButton.d.ts.map +1 -1
- package/dist/esm/components/SelectChainAndToken.js +5 -2
- package/dist/esm/components/SelectChainAndToken.js.map +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletButton.js +5 -4
- package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
- package/dist/esm/components/Token/Token.d.ts.map +1 -1
- package/dist/esm/components/TokenList/types.d.ts.map +1 -1
- package/dist/esm/components/TokenList/useTokenSelect.d.ts.map +1 -1
- package/dist/esm/components/TokenList/useTokenSelect.js +10 -0
- package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
- package/dist/esm/config/constants.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/config/version.js.map +1 -1
- package/dist/esm/hooks/useAccountsBalancesData.js +5 -2
- package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
- package/dist/esm/hooks/useAddressValidation.d.ts +3 -2
- package/dist/esm/hooks/useAddressValidation.d.ts.map +1 -1
- package/dist/esm/hooks/useAddressValidation.js +48 -21
- package/dist/esm/hooks/useAddressValidation.js.map +1 -1
- package/dist/esm/hooks/useAvailableChains.d.ts.map +1 -1
- package/dist/esm/hooks/useAvailableChains.js +21 -38
- package/dist/esm/hooks/useAvailableChains.js.map +1 -1
- package/dist/esm/hooks/useFromTokenSufficiency.js +3 -3
- package/dist/esm/hooks/useFromTokenSufficiency.js.map +1 -1
- package/dist/esm/hooks/useGasRecommendation.js +3 -3
- package/dist/esm/hooks/useGasRecommendation.js.map +1 -1
- package/dist/esm/hooks/useGasRefuel.js +4 -1
- package/dist/esm/hooks/useGasRefuel.js.map +1 -1
- package/dist/esm/hooks/useGasSufficiency.js +3 -3
- package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
- package/dist/esm/hooks/useIsBatchingSupported.js +2 -2
- package/dist/esm/hooks/useIsBatchingSupported.js.map +1 -1
- package/dist/esm/hooks/useRouteExecution.js +6 -6
- package/dist/esm/hooks/useRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
- package/dist/esm/hooks/useRoutes.js +18 -13
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useToAddressAutoPopulate.js +6 -8
- package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
- package/dist/esm/hooks/useToAddressRequirements.d.ts +3 -2
- package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
- package/dist/esm/hooks/useToAddressRequirements.js +8 -7
- package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
- package/dist/esm/hooks/useToAddressReset.js +6 -3
- package/dist/esm/hooks/useToAddressReset.js.map +1 -1
- package/dist/esm/hooks/useTokenBalance.js +6 -5
- package/dist/esm/hooks/useTokenBalance.js.map +1 -1
- package/dist/esm/hooks/useTokenBalancesQueries.js +3 -3
- package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
- package/dist/esm/hooks/useTokenSearch.js +3 -3
- package/dist/esm/hooks/useTokenSearch.js.map +1 -1
- package/dist/esm/hooks/useTokens.js +15 -15
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/hooks/useTools.d.ts.map +1 -1
- package/dist/esm/hooks/useTools.js +26 -27
- package/dist/esm/hooks/useTools.js.map +1 -1
- package/dist/esm/hooks/useTransactionDetails.js +2 -2
- package/dist/esm/hooks/useTransactionDetails.js.map +1 -1
- package/dist/esm/hooks/useTransactionHistory.js +3 -3
- package/dist/esm/hooks/useTransactionHistory.js.map +1 -1
- package/dist/esm/i18n/bn.json +2 -1
- package/dist/esm/i18n/de.json +2 -1
- package/dist/esm/i18n/en.json +2 -1
- package/dist/esm/i18n/es.json +2 -1
- package/dist/esm/i18n/fr.json +2 -1
- package/dist/esm/i18n/hi.json +2 -1
- package/dist/esm/i18n/id.json +2 -1
- package/dist/esm/i18n/it.json +2 -1
- package/dist/esm/i18n/ja.json +2 -1
- package/dist/esm/i18n/ko.json +2 -1
- package/dist/esm/i18n/pl.json +2 -1
- package/dist/esm/i18n/pt.json +2 -1
- package/dist/esm/i18n/th.json +2 -1
- package/dist/esm/i18n/tr.json +2 -1
- package/dist/esm/i18n/uk.json +2 -1
- package/dist/esm/i18n/vi.json +2 -1
- package/dist/esm/i18n/zh.json +2 -1
- package/dist/esm/index.d.ts +5 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/pages/RoutesPage/RoutesPage.style.d.ts.map +1 -1
- package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js +7 -4
- package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
- package/dist/esm/pages/SendToWallet/BookmarksPage.js +35 -31
- package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js +4 -3
- package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/RecentWalletsPage.js +43 -39
- package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js +32 -26
- package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToWalletPage.js +5 -10
- package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
- package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
- package/dist/esm/providers/WalletProvider/WalletProvider.d.ts.map +1 -1
- package/dist/esm/providers/WalletProvider/WalletProvider.js +14 -2
- package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
- package/dist/esm/providers/WidgetProvider/WidgetProvider.d.ts.map +1 -1
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js +15 -11
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
- package/dist/esm/providers/WidgetProvider/types.d.ts +2 -0
- package/dist/esm/providers/WidgetProvider/types.d.ts.map +1 -1
- package/dist/esm/queries/getChains.d.ts +38 -0
- package/dist/esm/queries/getChains.d.ts.map +1 -0
- package/dist/esm/queries/getChains.js +51 -0
- package/dist/esm/queries/getChains.js.map +1 -0
- package/dist/esm/queries/getTools.d.ts +26 -0
- package/dist/esm/queries/getTools.d.ts.map +1 -0
- package/dist/esm/queries/getTools.js +30 -0
- package/dist/esm/queries/getTools.js.map +1 -0
- package/dist/esm/queries/index.d.ts +4 -0
- package/dist/esm/queries/index.js +3 -0
- package/dist/esm/queries/types.d.ts +25 -0
- package/dist/esm/queries/types.d.ts.map +1 -0
- package/dist/esm/shared.d.ts +2 -1
- package/dist/esm/shared.js +2 -1
- package/dist/esm/stores/StoreProvider.d.ts.map +1 -1
- package/dist/esm/stores/StoreProvider.js +16 -17
- package/dist/esm/stores/StoreProvider.js.map +1 -1
- package/dist/esm/stores/bookmarks/types.d.ts +3 -0
- package/dist/esm/stores/bookmarks/types.d.ts.map +1 -1
- package/dist/esm/stores/chains/ChainOrderStore.d.ts.map +1 -1
- package/dist/esm/stores/chains/ChainOrderStore.js +4 -1
- package/dist/esm/stores/chains/ChainOrderStore.js.map +1 -1
- package/dist/esm/stores/form/FormStore.js +3 -2
- package/dist/esm/stores/form/FormStore.js.map +1 -1
- package/dist/esm/stores/form/URLSearchParamsBuilder.js +7 -3
- package/dist/esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
- package/dist/esm/stores/form/getDefaultValuesFromQueryString.js +4 -1
- package/dist/esm/stores/form/getDefaultValuesFromQueryString.js.map +1 -1
- package/dist/esm/stores/header/useHeaderStore.d.ts +1 -1
- package/dist/esm/stores/header/useHeaderStore.d.ts.map +1 -1
- package/dist/esm/stores/header/useHeaderStore.js.map +1 -1
- package/dist/esm/themes/createTheme.d.ts.map +1 -1
- package/dist/esm/types/events.d.ts.map +1 -1
- package/dist/esm/types/token.d.ts.map +1 -1
- package/dist/esm/types/widget.d.ts +30 -0
- package/dist/esm/types/widget.d.ts.map +1 -1
- package/dist/esm/types/widget.js.map +1 -1
- package/dist/esm/utils/chainType.js +32 -1
- package/dist/esm/utils/chainType.js.map +1 -1
- package/dist/esm/utils/customReceiver.js +6 -1
- package/dist/esm/utils/customReceiver.js.map +1 -1
- package/dist/esm/utils/queries.js.map +1 -1
- package/dist/esm/utils/scopeKeys.d.ts +6 -0
- package/dist/esm/utils/scopeKeys.d.ts.map +1 -0
- package/dist/esm/utils/scopeKeys.js +8 -0
- package/dist/esm/utils/scopeKeys.js.map +1 -0
- package/package.json +15 -7
- package/src/components/AmountInputCard/AmountInputCardPair.tsx +6 -2
- package/src/components/SelectChainAndToken.tsx +5 -1
- package/src/components/SendToWallet/SendToWalletButton.tsx +13 -8
- package/src/components/TokenList/useTokenSelect.ts +15 -0
- package/src/config/constants.ts +3 -0
- package/src/config/version.ts +1 -1
- package/src/hooks/useAccountsBalancesData.ts +6 -2
- package/src/hooks/useAddressValidation.ts +87 -32
- package/src/hooks/useAvailableChains.test.tsx +170 -0
- package/src/hooks/useAvailableChains.ts +29 -47
- package/src/hooks/useFromTokenSufficiency.ts +2 -2
- package/src/hooks/useGasRecommendation.ts +2 -2
- package/src/hooks/useGasRefuel.ts +11 -1
- package/src/hooks/useGasSufficiency.ts +2 -2
- package/src/hooks/useIsBatchingSupported.ts +2 -2
- package/src/hooks/useRouteExecution.ts +5 -5
- package/src/hooks/useRoutes.ts +28 -23
- package/src/hooks/useToAddressAutoPopulate.ts +13 -17
- package/src/hooks/useToAddressRequirements.ts +19 -4
- package/src/hooks/useToAddressReset.ts +13 -4
- package/src/hooks/useTokenBalance.ts +10 -5
- package/src/hooks/useTokenBalancesQueries.ts +3 -3
- package/src/hooks/useTokenSearch.ts +7 -3
- package/src/hooks/useTokens.ts +13 -14
- package/src/hooks/useTools.sharedEntry.test.tsx +155 -0
- package/src/hooks/useTools.ts +42 -37
- package/src/hooks/useTransactionDetails.ts +3 -3
- package/src/hooks/useTransactionHistory.ts +2 -2
- package/src/index.ts +2 -1
- package/src/pages/SendToWallet/BookmarkAddressSheet.tsx +5 -1
- package/src/pages/SendToWallet/BookmarksPage.tsx +42 -52
- package/src/pages/SendToWallet/ConnectedWalletsPage.tsx +4 -14
- package/src/pages/SendToWallet/RecentWalletsPage.tsx +59 -66
- package/src/pages/SendToWallet/SendToConfiguredWalletPage.tsx +45 -50
- package/src/pages/SendToWallet/SendToWalletPage.tsx +4 -16
- package/src/providers/WalletProvider/WalletProvider.tsx +28 -3
- package/src/providers/WidgetProvider/WidgetProvider.test.tsx +73 -0
- package/src/providers/WidgetProvider/WidgetProvider.tsx +28 -14
- package/src/providers/WidgetProvider/types.ts +2 -0
- package/src/queries/getChains.ts +93 -0
- package/src/queries/getTools.ts +62 -0
- package/src/queries/index.ts +30 -0
- package/src/queries/sharedCache.test.tsx +223 -0
- package/src/queries/types.ts +38 -0
- package/src/shared.ts +1 -0
- package/src/stores/StoreProvider.test.tsx +107 -0
- package/src/stores/StoreProvider.tsx +8 -6
- package/src/stores/bookmarks/types.ts +3 -0
- package/src/stores/chains/ChainOrderStore.tsx +4 -1
- package/src/stores/form/FormStore.tsx +2 -0
- package/src/stores/form/URLSearchParamsBuilder.tsx +4 -2
- package/src/stores/form/getDefaultValuesFromQueryString.ts +19 -0
- package/src/stores/header/useHeaderStore.tsx +3 -4
- package/src/types/widget.ts +30 -0
- package/src/utils/chainType.ts +73 -1
- package/src/utils/customReceiver.ts +36 -0
- package/src/utils/queries.ts +1 -0
- package/src/utils/scopeKeys.ts +18 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChainOrderStore.js","names":[],"sources":["../../../../src/stores/chains/ChainOrderStore.tsx"],"sourcesContent":["import { createContext, type JSX, use, useEffect, useRef } from 'react'\nimport type { StoreApi, UseBoundStore } from 'zustand'\nimport { useShallow } from 'zustand/shallow'\nimport { useChains } from '../../hooks/useChains.js'\nimport { useSwapOnly } from '../../hooks/useSwapOnly.js'\nimport { useExternalWalletProvider } from '../../providers/WalletProvider/useExternalWalletProvider.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../../utils/item.js'\nimport { getDefaultValuesFromQueryString } from '../form/getDefaultValuesFromQueryString.js'\nimport type { FormType } from '../form/types.js'\nimport { useFieldActions } from '../form/useFieldActions.js'\nimport type { PersistStoreProviderProps } from '../types.js'\nimport { createChainOrderStore } from './createChainOrderStore.js'\nimport type { ChainOrderState } from './types.js'\n\ntype ChainOrderStore = UseBoundStore<StoreApi<ChainOrderState>>\n\nconst ChainOrderStoreContext = createContext<ChainOrderStore | null>(null)\n\nexport function ChainOrderStoreProvider({\n children,\n ...props\n}: PersistStoreProviderProps): JSX.Element {\n const {\n chains: chainsConfig,\n hiddenUI,\n fromChain: fromChainConfig,\n toChain: toChainConfig,\n buildUrl,\n } = useWidgetConfig()\n const storeRef = useRef<ChainOrderStore>(null)\n const { chains } = useChains()\n const { setFieldValue, getFieldValues, isTouched } = useFieldActions()\n const swapOnly = useSwapOnly()\n const { variant } = useWidgetConfig()\n const { externalChainTypes, useExternalWalletProvidersOnly } =\n useExternalWalletProvider()\n\n if (!storeRef.current) {\n storeRef.current = createChainOrderStore({\n ...props,\n })\n }\n\n useEffect(() => {\n if (chains) {\n ;(['from', 'to'] as FormType[]).forEach((key) => {\n const configChainIds = chainsConfig?.[key]\n const isFromKey = key === 'from'\n\n // Convert configChainIds to Sets for O(1) lookup\n const configChainIdsSet = getConfigItemSets(\n configChainIds,\n (chainIds) => new Set(chainIds)\n )\n const filteredChains = chains.filter((chain) => {\n const passesChainsConfigFilter = configChainIdsSet\n ? isItemAllowedForSets(chain.id, configChainIdsSet)\n : true\n // If the integrator uses external wallet management and has not opted in for partial wallet management,\n // restrict the displayed chains to those compatible with external wallet management.\n // This ensures users only see chains for which they can sign transactions.\n const passesWalletConfigFilter = isFromKey\n ? !useExternalWalletProvidersOnly ||\n externalChainTypes.includes(chain.chainType)\n : true\n return passesChainsConfigFilter && passesWalletConfigFilter\n })\n\n const chainOrder = storeRef.current?.getState().initializeChains(\n filteredChains.map((chain) => chain.id),\n key\n )\n\n const isSwapTo = swapOnly && key === 'to'\n\n // Show \"All networks\" button if there are multiple networks\n const showAllNetworks =\n filteredChains.length > 1 && !hiddenUI?.allNetworks && !isSwapTo\n\n // Initialize the isAllNetworks with true if the tab is shown,\n // there is no config chain value and no url chain value\n const urlValues = getDefaultValuesFromQueryString({
|
|
1
|
+
{"version":3,"file":"ChainOrderStore.js","names":[],"sources":["../../../../src/stores/chains/ChainOrderStore.tsx"],"sourcesContent":["import { createContext, type JSX, use, useEffect, useRef } from 'react'\nimport type { StoreApi, UseBoundStore } from 'zustand'\nimport { useShallow } from 'zustand/shallow'\nimport { useChains } from '../../hooks/useChains.js'\nimport { useSwapOnly } from '../../hooks/useSwapOnly.js'\nimport { useExternalWalletProvider } from '../../providers/WalletProvider/useExternalWalletProvider.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { getConfigItemSets, isItemAllowedForSets } from '../../utils/item.js'\nimport { getDefaultValuesFromQueryString } from '../form/getDefaultValuesFromQueryString.js'\nimport type { FormType } from '../form/types.js'\nimport { useFieldActions } from '../form/useFieldActions.js'\nimport type { PersistStoreProviderProps } from '../types.js'\nimport { createChainOrderStore } from './createChainOrderStore.js'\nimport type { ChainOrderState } from './types.js'\n\ntype ChainOrderStore = UseBoundStore<StoreApi<ChainOrderState>>\n\nconst ChainOrderStoreContext = createContext<ChainOrderStore | null>(null)\n\nexport function ChainOrderStoreProvider({\n children,\n ...props\n}: PersistStoreProviderProps): JSX.Element {\n const {\n chains: chainsConfig,\n hiddenUI,\n fromChain: fromChainConfig,\n toChain: toChainConfig,\n buildUrl,\n } = useWidgetConfig()\n const storeRef = useRef<ChainOrderStore>(null)\n const { chains } = useChains()\n const { setFieldValue, getFieldValues, isTouched } = useFieldActions()\n const swapOnly = useSwapOnly()\n const { variant } = useWidgetConfig()\n const { externalChainTypes, useExternalWalletProvidersOnly } =\n useExternalWalletProvider()\n\n if (!storeRef.current) {\n storeRef.current = createChainOrderStore({\n ...props,\n })\n }\n\n useEffect(() => {\n if (chains) {\n ;(['from', 'to'] as FormType[]).forEach((key) => {\n const configChainIds = chainsConfig?.[key]\n const isFromKey = key === 'from'\n\n // Convert configChainIds to Sets for O(1) lookup\n const configChainIdsSet = getConfigItemSets(\n configChainIds,\n (chainIds) => new Set(chainIds)\n )\n const filteredChains = chains.filter((chain) => {\n const passesChainsConfigFilter = configChainIdsSet\n ? isItemAllowedForSets(chain.id, configChainIdsSet)\n : true\n // If the integrator uses external wallet management and has not opted in for partial wallet management,\n // restrict the displayed chains to those compatible with external wallet management.\n // This ensures users only see chains for which they can sign transactions.\n const passesWalletConfigFilter = isFromKey\n ? !useExternalWalletProvidersOnly ||\n externalChainTypes.includes(chain.chainType)\n : true\n return passesChainsConfigFilter && passesWalletConfigFilter\n })\n\n const chainOrder = storeRef.current?.getState().initializeChains(\n filteredChains.map((chain) => chain.id),\n key\n )\n\n const isSwapTo = swapOnly && key === 'to'\n\n // Show \"All networks\" button if there are multiple networks\n const showAllNetworks =\n filteredChains.length > 1 && !hiddenUI?.allNetworks && !isSwapTo\n\n // Initialize the isAllNetworks with true if the tab is shown,\n // there is no config chain value and no url chain value\n const urlValues = getDefaultValuesFromQueryString({\n buildUrl,\n chains: chainsConfig,\n })\n const urlChainValue =\n key === 'from' ? urlValues.fromChain : urlValues.toChain\n const configChainValue =\n key === 'from' ? fromChainConfig : toChainConfig\n\n // A touched, empty chain field was cleared deliberately — \"All\n // networks\". It has to outrank the two values above, because both\n // still name the chain the page was opened on at that moment: the\n // query string is rewritten a commit later, and an integrator that\n // seeds its config from the URL never rewrites it.\n const [chainValue] = getFieldValues(`${key}Chain`)\n const clearedForAllNetworks = !chainValue && isTouched(`${key}Chain`)\n\n const initialIsAllNetworks =\n showAllNetworks &&\n (clearedForAllNetworks || (!configChainValue && !urlChainValue))\n storeRef.current?.getState().setIsAllNetworks(initialIsAllNetworks, key)\n storeRef.current?.getState().setShowAllNetworks(showAllNetworks, key)\n\n // Copying an empty source would alternate with the fallback below.\n if (isSwapTo) {\n const [fromChainValue] = getFieldValues('fromChain')\n if (fromChainValue) {\n if (fromChainValue !== chainValue) {\n setFieldValue('toChain', fromChainValue)\n }\n return\n }\n }\n\n // When \"All Networks\" is active, don't auto-select a chain from the\n // persisted chain order. This prevents stale cross-ecosystem selections\n // (e.g. EVM from + Solana to) from triggering the \"destination wallet\n // address required\" message after a page refresh.\n if (initialIsAllNetworks) {\n return\n }\n\n // With no source to follow, drop a destination the list no longer offers.\n const keepsChain =\n chainValue &&\n (!isSwapTo || filteredChains.some((chain) => chain.id === chainValue))\n if (keepsChain) {\n return\n }\n\n const firstAllowedPinnedChain = storeRef.current\n ?.getState()\n .pinnedChains?.find((chainId) =>\n filteredChains.some((chain) => chain.id === chainId)\n )\n if (\n variant === 'wide' &&\n !hiddenUI?.chainSidebar &&\n firstAllowedPinnedChain\n ) {\n setFieldValue(`${key}Chain`, firstAllowedPinnedChain)\n } else if (chainOrder?.length) {\n setFieldValue(`${key}Chain`, chainOrder[0])\n }\n })\n }\n }, [\n chains,\n chainsConfig,\n externalChainTypes,\n getFieldValues,\n isTouched,\n setFieldValue,\n useExternalWalletProvidersOnly,\n variant,\n hiddenUI,\n swapOnly,\n fromChainConfig,\n toChainConfig,\n buildUrl,\n ])\n\n return (\n <ChainOrderStoreContext value={storeRef.current}>\n {children}\n </ChainOrderStoreContext>\n )\n}\n\nfunction useChainOrderStoreContext() {\n const useStore = use(ChainOrderStoreContext)\n if (!useStore) {\n throw new Error(\n `You forgot to wrap your component in <${ChainOrderStoreProvider.name}>.`\n )\n }\n return useStore\n}\n\nexport function useChainOrderStore<T>(\n selector: (state: ChainOrderState) => T\n): T {\n const useStore = useChainOrderStoreContext()\n return useStore(useShallow(selector))\n}\n"],"mappings":";;;;;;;;;;;;AAiBA,MAAM,yBAAyB,cAAsC,IAAI;AAEzE,SAAgB,wBAAwB,EACtC,UACA,GAAG,SACsC;CACzC,MAAM,EACJ,QAAQ,cACR,UACA,WAAW,iBACX,SAAS,eACT,aACE,gBAAgB;CACpB,MAAM,WAAW,OAAwB,IAAI;CAC7C,MAAM,EAAE,WAAW,UAAU;CAC7B,MAAM,EAAE,eAAe,gBAAgB,cAAc,gBAAgB;CACrE,MAAM,WAAW,YAAY;CAC7B,MAAM,EAAE,YAAY,gBAAgB;CACpC,MAAM,EAAE,oBAAoB,mCAC1B,0BAA0B;CAE5B,IAAI,CAAC,SAAS,SACZ,SAAS,UAAU,sBAAsB,EACvC,GAAG,MACL,CAAC;CAGH,gBAAgB;EACd,IAAI,QACD,CAAE,QAAQ,IAAI,CAAC,CAAgB,SAAS,QAAQ;GAC/C,MAAM,iBAAiB,eAAe;GACtC,MAAM,YAAY,QAAQ;GAG1B,MAAM,oBAAoB,kBACxB,iBACC,aAAa,IAAI,IAAI,QAAQ,CAChC;GACA,MAAM,iBAAiB,OAAO,QAAQ,UAAU;IAC9C,MAAM,2BAA2B,oBAC7B,qBAAqB,MAAM,IAAI,iBAAiB,IAChD;IAIJ,MAAM,2BAA2B,YAC7B,CAAC,kCACD,mBAAmB,SAAS,MAAM,SAAS,IAC3C;IACJ,OAAO,4BAA4B;GACrC,CAAC;GAED,MAAM,aAAa,SAAS,SAAS,SAAS,CAAC,CAAC,iBAC9C,eAAe,KAAK,UAAU,MAAM,EAAE,GACtC,GACF;GAEA,MAAM,WAAW,YAAY,QAAQ;GAGrC,MAAM,kBACJ,eAAe,SAAS,KAAK,CAAC,UAAU,eAAe,CAAC;GAI1D,MAAM,YAAY,gCAAgC;IAChD;IACA,QAAQ;GACV,CAAC;GACD,MAAM,gBACJ,QAAQ,SAAS,UAAU,YAAY,UAAU;GACnD,MAAM,mBACJ,QAAQ,SAAS,kBAAkB;GAOrC,MAAM,CAAC,cAAc,eAAe,GAAG,IAAI,MAAM;GACjD,MAAM,wBAAwB,CAAC,cAAc,UAAU,GAAG,IAAI,MAAM;GAEpE,MAAM,uBACJ,oBACC,yBAA0B,CAAC,oBAAoB,CAAC;GACnD,SAAS,SAAS,SAAS,CAAC,CAAC,iBAAiB,sBAAsB,GAAG;GACvE,SAAS,SAAS,SAAS,CAAC,CAAC,mBAAmB,iBAAiB,GAAG;GAGpE,IAAI,UAAU;IACZ,MAAM,CAAC,kBAAkB,eAAe,WAAW;IACnD,IAAI,gBAAgB;KAClB,IAAI,mBAAmB,YACrB,cAAc,WAAW,cAAc;KAEzC;IACF;GACF;GAMA,IAAI,sBACF;GAOF,IAFE,eACC,CAAC,YAAY,eAAe,MAAM,UAAU,MAAM,OAAO,UAAU,IAEpE;GAGF,MAAM,0BAA0B,SAAS,SACrC,SAAS,CAAC,CACX,cAAc,MAAM,YACnB,eAAe,MAAM,UAAU,MAAM,OAAO,OAAO,CACrD;GACF,IACE,YAAY,UACZ,CAAC,UAAU,gBACX,yBAEA,cAAc,GAAG,IAAI,QAAQ,uBAAuB;QAC/C,IAAI,YAAY,QACrB,cAAc,GAAG,IAAI,QAAQ,WAAW,EAAE;EAE9C,CAAC;CAEL,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,OACE,oBAAC,wBAAD;EAAwB,OAAO,SAAS;EACrC;CACqB,CAAA;AAE5B;AAEA,SAAS,4BAA4B;CACnC,MAAM,WAAW,IAAI,sBAAsB;CAC3C,IAAI,CAAC,UACH,MAAM,IAAI,MACR,yCAAyC,wBAAwB,KAAK,GACxE;CAEF,OAAO;AACT;AAEA,SAAgB,mBACd,UACG;CAEH,OADiB,0BACH,CAAC,CAAC,WAAW,QAAQ,CAAC;AACtC"}
|
|
@@ -16,7 +16,7 @@ const initialiseDefaultValues = (defaultValues) => ({
|
|
|
16
16
|
});
|
|
17
17
|
const FormStoreProvider = ({ children, formRef }) => {
|
|
18
18
|
const widgetConfig = useWidgetConfig();
|
|
19
|
-
const { fromChain, fromToken, toChain, toToken, fromAmount, toAmount, toAddress, formUpdateKey, buildUrl } = widgetConfig;
|
|
19
|
+
const { fromChain, fromToken, toChain, toToken, fromAmount, toAmount, toAddress, formUpdateKey, buildUrl, chains } = widgetConfig;
|
|
20
20
|
const storeRef = useRef(null);
|
|
21
21
|
const configHasFromChain = Object.hasOwn(widgetConfig, "fromChain");
|
|
22
22
|
const configHasFromToken = Object.hasOwn(widgetConfig, "fromToken");
|
|
@@ -53,7 +53,8 @@ const FormStoreProvider = ({ children, formRef }) => {
|
|
|
53
53
|
if (!storeRef.current) {
|
|
54
54
|
const queryDefaults = getDefaultValuesFromQueryString({
|
|
55
55
|
buildUrl,
|
|
56
|
-
includeToAddress: false
|
|
56
|
+
includeToAddress: false,
|
|
57
|
+
chains
|
|
57
58
|
});
|
|
58
59
|
storeRef.current = createFormStore(initialiseDefaultValues({
|
|
59
60
|
...reactiveFormValues,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormStore.js","names":[],"sources":["../../../../src/stores/form/FormStore.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react'\nimport { useMemo, useRef } from 'react'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormRef } from '../../types/widget.js'\nimport { createFormStore, formDefaultValues } from './createFormStore.js'\nimport { FormStoreContext } from './FormStoreContext.js'\nimport { FormUpdater } from './FormUpdater.js'\nimport { getDefaultValuesFromQueryString } from './getDefaultValuesFromQueryString.js'\nimport type { DefaultValues, FormStoreStore } from './types.js'\nimport { useFormRef } from './useFormRef.js'\n\n// decorates and initialise the form date for use in the form store\nconst initialiseDefaultValues = (defaultValues: Partial<DefaultValues>) => ({\n ...formDefaultValues,\n ...defaultValues,\n fromAmount:\n (typeof defaultValues.fromAmount === 'number'\n ? (defaultValues.fromAmount as number)?.toPrecision?.()\n : defaultValues.fromAmount) || formDefaultValues.fromAmount,\n toAmount:\n (typeof defaultValues.toAmount === 'number'\n ? (defaultValues.toAmount as number)?.toPrecision?.()\n : defaultValues.toAmount) || formDefaultValues.toAmount,\n // Prevent setting address when the field is hidden\n toAddress: defaultValues.toAddress || formDefaultValues.toAddress,\n})\n\ninterface FormStoreProviderProps extends PropsWithChildren {\n formRef?: FormRef\n}\n\nexport const FormStoreProvider: React.FC<FormStoreProviderProps> = ({\n children,\n formRef,\n}) => {\n const widgetConfig = useWidgetConfig()\n\n const {\n fromChain,\n fromToken,\n toChain,\n toToken,\n fromAmount,\n toAmount,\n toAddress,\n formUpdateKey,\n buildUrl,\n } = widgetConfig\n\n const storeRef = useRef<FormStoreStore>(null)\n\n const configHasFromChain = Object.hasOwn(widgetConfig, 'fromChain')\n const configHasFromToken = Object.hasOwn(widgetConfig, 'fromToken')\n const configHasFromAmount = Object.hasOwn(widgetConfig, 'fromAmount')\n const configHasToAmount = Object.hasOwn(widgetConfig, 'toAmount')\n const configHasToAddress = Object.hasOwn(widgetConfig, 'toAddress')\n const configHasToChain = Object.hasOwn(widgetConfig, 'toChain')\n const configHasToToken = Object.hasOwn(widgetConfig, 'toToken')\n\n // We use the presence/absence of a property to decide if the form values in state need to be updated\n // We only build and set a property on the memoized form values here if they are included in the\n // config - undefined is considered a valid value that will reset that form field\n // biome-ignore lint/correctness/useExhaustiveDependencies: formUpdateKey is needed here.\n const reactiveFormValues = useMemo(\n () => ({\n ...(configHasFromChain ? { fromChain } : undefined),\n ...(configHasFromToken ? { fromToken } : undefined),\n ...(configHasFromAmount\n ? {\n fromAmount:\n (typeof fromAmount === 'number'\n ? fromAmount?.toPrecision()\n : fromAmount) || formDefaultValues.fromAmount,\n }\n : undefined),\n ...(configHasToAmount\n ? {\n toAmount:\n (typeof toAmount === 'number'\n ? toAmount?.toPrecision()\n : toAmount) || formDefaultValues.toAmount,\n }\n : undefined),\n ...(configHasToChain ? { toChain } : undefined),\n ...(configHasToToken ? { toToken } : undefined),\n ...(configHasToAddress\n ? {\n toAddress: toAddress?.address || formDefaultValues.toAddress,\n }\n : undefined),\n }),\n [\n fromAmount,\n toAmount,\n fromChain,\n fromToken,\n toAddress,\n toChain,\n toToken,\n // formUpdateKey should be a randomly assigned unique key. It can be used to force updates for the form field values\n formUpdateKey,\n configHasFromChain,\n configHasFromToken,\n configHasFromAmount,\n configHasToAmount,\n configHasToAddress,\n configHasToChain,\n configHasToToken,\n ]\n )\n\n if (!storeRef.current) {\n const queryDefaults = getDefaultValuesFromQueryString({\n buildUrl,\n includeToAddress: false,\n })\n storeRef.current = createFormStore(\n initialiseDefaultValues({\n ...reactiveFormValues,\n ...queryDefaults,\n })\n )\n }\n\n useFormRef(storeRef.current, formRef)\n\n return (\n <FormStoreContext value={storeRef.current}>\n {children}\n <FormUpdater reactiveFormValues={reactiveFormValues} />\n </FormStoreContext>\n )\n}\n"],"mappings":";;;;;;;;;AAYA,MAAM,2BAA2B,mBAA2C;CAC1E,GAAG;CACH,GAAG;CACH,aACG,OAAO,cAAc,eAAe,WAChC,cAAc,YAAuB,cAAc,IACpD,cAAc,eAAe,kBAAkB;CACrD,WACG,OAAO,cAAc,aAAa,WAC9B,cAAc,UAAqB,cAAc,IAClD,cAAc,aAAa,kBAAkB;CAEnD,WAAW,cAAc,aAAa,kBAAkB;AAC1D;AAMA,MAAa,qBAAuD,EAClE,UACA,cACI;CACJ,MAAM,eAAe,gBAAgB;CAErC,MAAM,EACJ,WACA,WACA,SACA,SACA,YACA,UACA,WACA,eACA,
|
|
1
|
+
{"version":3,"file":"FormStore.js","names":[],"sources":["../../../../src/stores/form/FormStore.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react'\nimport { useMemo, useRef } from 'react'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport type { FormRef } from '../../types/widget.js'\nimport { createFormStore, formDefaultValues } from './createFormStore.js'\nimport { FormStoreContext } from './FormStoreContext.js'\nimport { FormUpdater } from './FormUpdater.js'\nimport { getDefaultValuesFromQueryString } from './getDefaultValuesFromQueryString.js'\nimport type { DefaultValues, FormStoreStore } from './types.js'\nimport { useFormRef } from './useFormRef.js'\n\n// decorates and initialise the form date for use in the form store\nconst initialiseDefaultValues = (defaultValues: Partial<DefaultValues>) => ({\n ...formDefaultValues,\n ...defaultValues,\n fromAmount:\n (typeof defaultValues.fromAmount === 'number'\n ? (defaultValues.fromAmount as number)?.toPrecision?.()\n : defaultValues.fromAmount) || formDefaultValues.fromAmount,\n toAmount:\n (typeof defaultValues.toAmount === 'number'\n ? (defaultValues.toAmount as number)?.toPrecision?.()\n : defaultValues.toAmount) || formDefaultValues.toAmount,\n // Prevent setting address when the field is hidden\n toAddress: defaultValues.toAddress || formDefaultValues.toAddress,\n})\n\ninterface FormStoreProviderProps extends PropsWithChildren {\n formRef?: FormRef\n}\n\nexport const FormStoreProvider: React.FC<FormStoreProviderProps> = ({\n children,\n formRef,\n}) => {\n const widgetConfig = useWidgetConfig()\n\n const {\n fromChain,\n fromToken,\n toChain,\n toToken,\n fromAmount,\n toAmount,\n toAddress,\n formUpdateKey,\n buildUrl,\n chains,\n } = widgetConfig\n\n const storeRef = useRef<FormStoreStore>(null)\n\n const configHasFromChain = Object.hasOwn(widgetConfig, 'fromChain')\n const configHasFromToken = Object.hasOwn(widgetConfig, 'fromToken')\n const configHasFromAmount = Object.hasOwn(widgetConfig, 'fromAmount')\n const configHasToAmount = Object.hasOwn(widgetConfig, 'toAmount')\n const configHasToAddress = Object.hasOwn(widgetConfig, 'toAddress')\n const configHasToChain = Object.hasOwn(widgetConfig, 'toChain')\n const configHasToToken = Object.hasOwn(widgetConfig, 'toToken')\n\n // We use the presence/absence of a property to decide if the form values in state need to be updated\n // We only build and set a property on the memoized form values here if they are included in the\n // config - undefined is considered a valid value that will reset that form field\n // biome-ignore lint/correctness/useExhaustiveDependencies: formUpdateKey is needed here.\n const reactiveFormValues = useMemo(\n () => ({\n ...(configHasFromChain ? { fromChain } : undefined),\n ...(configHasFromToken ? { fromToken } : undefined),\n ...(configHasFromAmount\n ? {\n fromAmount:\n (typeof fromAmount === 'number'\n ? fromAmount?.toPrecision()\n : fromAmount) || formDefaultValues.fromAmount,\n }\n : undefined),\n ...(configHasToAmount\n ? {\n toAmount:\n (typeof toAmount === 'number'\n ? toAmount?.toPrecision()\n : toAmount) || formDefaultValues.toAmount,\n }\n : undefined),\n ...(configHasToChain ? { toChain } : undefined),\n ...(configHasToToken ? { toToken } : undefined),\n ...(configHasToAddress\n ? {\n toAddress: toAddress?.address || formDefaultValues.toAddress,\n }\n : undefined),\n }),\n [\n fromAmount,\n toAmount,\n fromChain,\n fromToken,\n toAddress,\n toChain,\n toToken,\n // formUpdateKey should be a randomly assigned unique key. It can be used to force updates for the form field values\n formUpdateKey,\n configHasFromChain,\n configHasFromToken,\n configHasFromAmount,\n configHasToAmount,\n configHasToAddress,\n configHasToChain,\n configHasToToken,\n ]\n )\n\n if (!storeRef.current) {\n const queryDefaults = getDefaultValuesFromQueryString({\n buildUrl,\n includeToAddress: false,\n chains,\n })\n storeRef.current = createFormStore(\n initialiseDefaultValues({\n ...reactiveFormValues,\n ...queryDefaults,\n })\n )\n }\n\n useFormRef(storeRef.current, formRef)\n\n return (\n <FormStoreContext value={storeRef.current}>\n {children}\n <FormUpdater reactiveFormValues={reactiveFormValues} />\n </FormStoreContext>\n )\n}\n"],"mappings":";;;;;;;;;AAYA,MAAM,2BAA2B,mBAA2C;CAC1E,GAAG;CACH,GAAG;CACH,aACG,OAAO,cAAc,eAAe,WAChC,cAAc,YAAuB,cAAc,IACpD,cAAc,eAAe,kBAAkB;CACrD,WACG,OAAO,cAAc,aAAa,WAC9B,cAAc,UAAqB,cAAc,IAClD,cAAc,aAAa,kBAAkB;CAEnD,WAAW,cAAc,aAAa,kBAAkB;AAC1D;AAMA,MAAa,qBAAuD,EAClE,UACA,cACI;CACJ,MAAM,eAAe,gBAAgB;CAErC,MAAM,EACJ,WACA,WACA,SACA,SACA,YACA,UACA,WACA,eACA,UACA,WACE;CAEJ,MAAM,WAAW,OAAuB,IAAI;CAE5C,MAAM,qBAAqB,OAAO,OAAO,cAAc,WAAW;CAClE,MAAM,qBAAqB,OAAO,OAAO,cAAc,WAAW;CAClE,MAAM,sBAAsB,OAAO,OAAO,cAAc,YAAY;CACpE,MAAM,oBAAoB,OAAO,OAAO,cAAc,UAAU;CAChE,MAAM,qBAAqB,OAAO,OAAO,cAAc,WAAW;CAClE,MAAM,mBAAmB,OAAO,OAAO,cAAc,SAAS;CAC9D,MAAM,mBAAmB,OAAO,OAAO,cAAc,SAAS;CAM9D,MAAM,qBAAqB,eAClB;EACL,GAAI,qBAAqB,EAAE,UAAU,IAAI,KAAA;EACzC,GAAI,qBAAqB,EAAE,UAAU,IAAI,KAAA;EACzC,GAAI,sBACA,EACE,aACG,OAAO,eAAe,WACnB,YAAY,YAAY,IACxB,eAAe,kBAAkB,WACzC,IACA,KAAA;EACJ,GAAI,oBACA,EACE,WACG,OAAO,aAAa,WACjB,UAAU,YAAY,IACtB,aAAa,kBAAkB,SACvC,IACA,KAAA;EACJ,GAAI,mBAAmB,EAAE,QAAQ,IAAI,KAAA;EACrC,GAAI,mBAAmB,EAAE,QAAQ,IAAI,KAAA;EACrC,GAAI,qBACA,EACE,WAAW,WAAW,WAAW,kBAAkB,UACrD,IACA,KAAA;CACN,IACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;CAEA,IAAI,CAAC,SAAS,SAAS;EACrB,MAAM,gBAAgB,gCAAgC;GACpD;GACA,kBAAkB;GAClB;EACF,CAAC;EACD,SAAS,UAAU,gBACjB,wBAAwB;GACtB,GAAG;GACH,GAAG;EACL,CAAC,CACH;CACF;CAEA,WAAW,SAAS,SAAS,OAAO;CAEpC,OACE,qBAAC,kBAAD;EAAkB,OAAO,SAAS;EAAlC,UAAA,CACG,UACD,oBAAC,aAAD,EAAiC,mBAAqB,CAAA,CACtC;;AAEtB"}
|
|
@@ -27,10 +27,13 @@ const URLSearchParamsBuilder = () => {
|
|
|
27
27
|
const values = useFieldValues(...formValueKeys, ...limitFormValueKeys);
|
|
28
28
|
const { setSelectedBookmark, addRecentWallet } = useBookmarkActions();
|
|
29
29
|
const { validateAddress } = useAddressValidation();
|
|
30
|
-
const { buildUrl, mode } = useWidgetConfig();
|
|
30
|
+
const { buildUrl, mode, chains } = useWidgetConfig();
|
|
31
31
|
const { getFieldValues, isTouched, setUserAndDefaultValues } = useFieldActions();
|
|
32
32
|
useEffect(() => {
|
|
33
|
-
const { toAddress, ...initialFormValues } = getDefaultValuesFromQueryString({
|
|
33
|
+
const { toAddress, ...initialFormValues } = getDefaultValuesFromQueryString({
|
|
34
|
+
buildUrl,
|
|
35
|
+
chains
|
|
36
|
+
});
|
|
34
37
|
/**
|
|
35
38
|
* When URL builder is enabled and user opens a page with toAddress parameter,
|
|
36
39
|
* validate the address and set it up as a bookmark. This allows direct linking
|
|
@@ -43,7 +46,8 @@ const URLSearchParamsBuilder = () => {
|
|
|
43
46
|
if (validationResult.isValid && toAddress) {
|
|
44
47
|
const bookmark = {
|
|
45
48
|
address: validationResult.address,
|
|
46
|
-
chainType: validationResult.chainType
|
|
49
|
+
chainType: validationResult.chainType,
|
|
50
|
+
chainId: validationResult.chainId
|
|
47
51
|
};
|
|
48
52
|
setUserAndDefaultValues({ toAddress });
|
|
49
53
|
setSelectedBookmark(bookmark);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"URLSearchParamsBuilder.js","names":[],"sources":["../../../../src/stores/form/URLSearchParamsBuilder.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router'\nimport { useEffect } from 'react'\nimport { useAddressValidation } from '../../hooks/useAddressValidation.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useBookmarkActions } from '../bookmarks/useBookmarkActions.js'\nimport type { FormFieldNames } from '../form/types.js'\nimport { useFieldActions } from '../form/useFieldActions.js'\nimport { useFieldValues } from '../form/useFieldValues.js'\nimport { useTouchedFields } from '../form/useTouchedFields.js'\nimport { getDefaultValuesFromQueryString } from './getDefaultValuesFromQueryString.js'\n\nconst formValueKeys: FormFieldNames[] = [\n 'fromAmount',\n 'fromChain',\n 'fromToken',\n 'toAddress',\n 'toChain',\n 'toToken',\n]\n\n// Limit-order params are only mirrored to the URL while the limit tab is\n// active, and stripped when the user leaves it. Unlike the base keys these are\n// presence-gated (not touched-gated) so the URL fully reproduces the limit\n// order — including the boolean/number fields, which are never \"falsy-empty\".\nconst limitFormValueKeys: FormFieldNames[] = [\n 'toAmount',\n 'validUntil',\n 'partiallyFillable',\n]\n\nexport const URLSearchParamsBuilder = () => {\n const { pathname } = useLocation()\n const touchedFields = useTouchedFields()\n const values = useFieldValues(...formValueKeys, ...limitFormValueKeys)\n const { setSelectedBookmark, addRecentWallet } = useBookmarkActions()\n const { validateAddress } = useAddressValidation()\n const { buildUrl, mode } = useWidgetConfig()\n // Using these methods as trying to use the touchedFields and values above\n // often has a lag that can effect the widgets initialisation sequence\n // and accidentally cause values to be wiped from the query string\n const { getFieldValues, isTouched, setUserAndDefaultValues } =\n useFieldActions()\n\n useEffect(() => {\n // get the initial values from the querystring\n const formValues = getDefaultValuesFromQueryString({ buildUrl })\n const { toAddress, ...initialFormValues } = formValues\n\n /**\n * When URL builder is enabled and user opens a page with toAddress parameter,\n * validate the address and set it up as a bookmark. This allows direct linking\n * to the widget with a pre-filled destination address that will be treated the\n * same way as a manually entered and validated address.\n */\n const initializeFromAddress = async () => {\n if (toAddress) {\n try {\n const validationResult = await validateAddress({\n value: toAddress,\n })\n if (validationResult.isValid && toAddress) {\n const bookmark = {\n address: validationResult.address,\n chainType: validationResult.chainType,\n }\n setUserAndDefaultValues({ toAddress })\n setSelectedBookmark(bookmark)\n addRecentWallet(bookmark)\n }\n } catch (_) {\n // Address validation failed\n }\n }\n }\n\n setUserAndDefaultValues(initialFormValues)\n initializeFromAddress()\n }, [\n setUserAndDefaultValues,\n validateAddress,\n setSelectedBookmark,\n addRecentWallet,\n buildUrl,\n ])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when pathname changes\n useEffect(() => {\n // set the values on the querysting\n const url = new URL(window.location as any)\n formValueKeys.forEach((key, _index) => {\n const value = getFieldValues(key)[0]\n if (isTouched(key) && value) {\n url.searchParams.set(key, value.toString())\n } else if (url.searchParams.has(key) && !value) {\n url.searchParams.delete(key)\n }\n })\n // Limit params live in the URL only while the limit tab is active.\n limitFormValueKeys.forEach((key) => {\n const value = getFieldValues(key)[0]\n // Booleans are always \"set\" (false is meaningful); strings/numbers use\n // truthiness so an empty toAmount is treated as absent.\n const hasValue = typeof value === 'boolean' ? true : Boolean(value)\n if (mode === 'limit' && hasValue) {\n url.searchParams.set(key, String(value))\n } else {\n url.searchParams.delete(key)\n }\n })\n url.searchParams.sort()\n window.history.replaceState(window.history.state, '', url)\n }, [pathname, touchedFields, values, isTouched, getFieldValues, mode])\n\n return null\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,gBAAkC;CACtC;CACA;CACA;CACA;CACA;CACA;AACF;AAMA,MAAM,qBAAuC;CAC3C;CACA;CACA;AACF;AAEA,MAAa,+BAA+B;CAC1C,MAAM,EAAE,aAAa,YAAY;CACjC,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,SAAS,eAAe,GAAG,eAAe,GAAG,kBAAkB;CACrE,MAAM,EAAE,qBAAqB,oBAAoB,mBAAmB;CACpE,MAAM,EAAE,oBAAoB,qBAAqB;CACjD,MAAM,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"URLSearchParamsBuilder.js","names":[],"sources":["../../../../src/stores/form/URLSearchParamsBuilder.tsx"],"sourcesContent":["import { useLocation } from '@tanstack/react-router'\nimport { useEffect } from 'react'\nimport { useAddressValidation } from '../../hooks/useAddressValidation.js'\nimport { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'\nimport { useBookmarkActions } from '../bookmarks/useBookmarkActions.js'\nimport type { FormFieldNames } from '../form/types.js'\nimport { useFieldActions } from '../form/useFieldActions.js'\nimport { useFieldValues } from '../form/useFieldValues.js'\nimport { useTouchedFields } from '../form/useTouchedFields.js'\nimport { getDefaultValuesFromQueryString } from './getDefaultValuesFromQueryString.js'\n\nconst formValueKeys: FormFieldNames[] = [\n 'fromAmount',\n 'fromChain',\n 'fromToken',\n 'toAddress',\n 'toChain',\n 'toToken',\n]\n\n// Limit-order params are only mirrored to the URL while the limit tab is\n// active, and stripped when the user leaves it. Unlike the base keys these are\n// presence-gated (not touched-gated) so the URL fully reproduces the limit\n// order — including the boolean/number fields, which are never \"falsy-empty\".\nconst limitFormValueKeys: FormFieldNames[] = [\n 'toAmount',\n 'validUntil',\n 'partiallyFillable',\n]\n\nexport const URLSearchParamsBuilder = () => {\n const { pathname } = useLocation()\n const touchedFields = useTouchedFields()\n const values = useFieldValues(...formValueKeys, ...limitFormValueKeys)\n const { setSelectedBookmark, addRecentWallet } = useBookmarkActions()\n const { validateAddress } = useAddressValidation()\n const { buildUrl, mode, chains } = useWidgetConfig()\n // Using these methods as trying to use the touchedFields and values above\n // often has a lag that can effect the widgets initialisation sequence\n // and accidentally cause values to be wiped from the query string\n const { getFieldValues, isTouched, setUserAndDefaultValues } =\n useFieldActions()\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: the URL is read once, not again on each config render\n useEffect(() => {\n // get the initial values from the querystring\n const formValues = getDefaultValuesFromQueryString({ buildUrl, chains })\n const { toAddress, ...initialFormValues } = formValues\n\n /**\n * When URL builder is enabled and user opens a page with toAddress parameter,\n * validate the address and set it up as a bookmark. This allows direct linking\n * to the widget with a pre-filled destination address that will be treated the\n * same way as a manually entered and validated address.\n */\n const initializeFromAddress = async () => {\n if (toAddress) {\n try {\n const validationResult = await validateAddress({\n value: toAddress,\n })\n if (validationResult.isValid && toAddress) {\n const bookmark = {\n address: validationResult.address,\n chainType: validationResult.chainType,\n chainId: validationResult.chainId,\n }\n setUserAndDefaultValues({ toAddress })\n setSelectedBookmark(bookmark)\n addRecentWallet(bookmark)\n }\n } catch (_) {\n // Address validation failed\n }\n }\n }\n\n setUserAndDefaultValues(initialFormValues)\n initializeFromAddress()\n }, [\n setUserAndDefaultValues,\n validateAddress,\n setSelectedBookmark,\n addRecentWallet,\n buildUrl,\n ])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: run only when pathname changes\n useEffect(() => {\n // set the values on the querysting\n const url = new URL(window.location as any)\n formValueKeys.forEach((key, _index) => {\n const value = getFieldValues(key)[0]\n if (isTouched(key) && value) {\n url.searchParams.set(key, value.toString())\n } else if (url.searchParams.has(key) && !value) {\n url.searchParams.delete(key)\n }\n })\n // Limit params live in the URL only while the limit tab is active.\n limitFormValueKeys.forEach((key) => {\n const value = getFieldValues(key)[0]\n // Booleans are always \"set\" (false is meaningful); strings/numbers use\n // truthiness so an empty toAmount is treated as absent.\n const hasValue = typeof value === 'boolean' ? true : Boolean(value)\n if (mode === 'limit' && hasValue) {\n url.searchParams.set(key, String(value))\n } else {\n url.searchParams.delete(key)\n }\n })\n url.searchParams.sort()\n window.history.replaceState(window.history.state, '', url)\n }, [pathname, touchedFields, values, isTouched, getFieldValues, mode])\n\n return null\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,gBAAkC;CACtC;CACA;CACA;CACA;CACA;CACA;AACF;AAMA,MAAM,qBAAuC;CAC3C;CACA;CACA;AACF;AAEA,MAAa,+BAA+B;CAC1C,MAAM,EAAE,aAAa,YAAY;CACjC,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,SAAS,eAAe,GAAG,eAAe,GAAG,kBAAkB;CACrE,MAAM,EAAE,qBAAqB,oBAAoB,mBAAmB;CACpE,MAAM,EAAE,oBAAoB,qBAAqB;CACjD,MAAM,EAAE,UAAU,MAAM,WAAW,gBAAgB;CAInD,MAAM,EAAE,gBAAgB,WAAW,4BACjC,gBAAgB;CAGlB,gBAAgB;EAGd,MAAM,EAAE,WAAW,GAAG,sBADH,gCAAgC;GAAE;GAAU;EAAO,CACjB;;;;;;;EAQrD,MAAM,wBAAwB,YAAY;GACxC,IAAI,WACF,IAAI;IACF,MAAM,mBAAmB,MAAM,gBAAgB,EAC7C,OAAO,UACT,CAAC;IACD,IAAI,iBAAiB,WAAW,WAAW;KACzC,MAAM,WAAW;MACf,SAAS,iBAAiB;MAC1B,WAAW,iBAAiB;MAC5B,SAAS,iBAAiB;KAC5B;KACA,wBAAwB,EAAE,UAAU,CAAC;KACrC,oBAAoB,QAAQ;KAC5B,gBAAgB,QAAQ;IAC1B;GACF,SAAS,GAAG,CAEZ;EAEJ;EAEA,wBAAwB,iBAAiB;EACzC,sBAAsB;CACxB,GAAG;EACD;EACA;EACA;EACA;EACA;CACF,CAAC;CAGD,gBAAgB;EAEd,MAAM,MAAM,IAAI,IAAI,OAAO,QAAe;EAC1C,cAAc,SAAS,KAAK,WAAW;GACrC,MAAM,QAAQ,eAAe,GAAG,CAAC,CAAC;GAClC,IAAI,UAAU,GAAG,KAAK,OACpB,IAAI,aAAa,IAAI,KAAK,MAAM,SAAS,CAAC;QACrC,IAAI,IAAI,aAAa,IAAI,GAAG,KAAK,CAAC,OACvC,IAAI,aAAa,OAAO,GAAG;EAE/B,CAAC;EAED,mBAAmB,SAAS,QAAQ;GAClC,MAAM,QAAQ,eAAe,GAAG,CAAC,CAAC;GAIlC,IAAI,SAAS,YADI,OAAO,UAAU,YAAY,OAAO,QAAQ,KAAK,IAEhE,IAAI,aAAa,IAAI,KAAK,OAAO,KAAK,CAAC;QAEvC,IAAI,aAAa,OAAO,GAAG;EAE/B,CAAC;EACD,IAAI,aAAa,KAAK;EACtB,OAAO,QAAQ,aAAa,OAAO,QAAQ,OAAO,IAAI,GAAG;CAC3D,GAAG;EAAC;EAAU;EAAe;EAAQ;EAAW;EAAgB;CAAI,CAAC;CAErE,OAAO;AACT"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import { isDestinationOnlyChain, isUnservedDestinationChain } from "../../utils/chainType.js";
|
|
1
2
|
import { formatInputAmount } from "../../utils/format.js";
|
|
2
3
|
//#region src/stores/form/getDefaultValuesFromQueryString.ts
|
|
3
|
-
const getDefaultValuesFromQueryString = ({ buildUrl = false, includeToAddress = true }) => {
|
|
4
|
+
const getDefaultValuesFromQueryString = ({ buildUrl = false, includeToAddress = true, chains }) => {
|
|
4
5
|
if (typeof window === "undefined") return {};
|
|
5
6
|
if (!buildUrl) return {};
|
|
6
7
|
const searchParams = Object.fromEntries(new URLSearchParams(window.location.search));
|
|
8
|
+
if (isDestinationOnlyChain(Number.parseInt(searchParams.fromChain, 10))) delete searchParams.fromChain;
|
|
9
|
+
if (isUnservedDestinationChain(Number.parseInt(searchParams.toChain, 10), chains)) delete searchParams.toChain;
|
|
7
10
|
["from", "to"].forEach((key) => {
|
|
8
11
|
if (searchParams[`${key}Token`] && !searchParams[`${key}Chain`]) delete searchParams[`${key}Token`];
|
|
9
12
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getDefaultValuesFromQueryString.js","names":[],"sources":["../../../../src/stores/form/getDefaultValuesFromQueryString.ts"],"sourcesContent":["import { formatInputAmount } from '../../utils/format.js'\nimport type { DefaultValues } from './types.js'\n\ninterface GetDefaultValuesFromQueryStringOptions {\n includeToAddress?: boolean\n buildUrl?: boolean\n}\n\nexport const getDefaultValuesFromQueryString = ({\n buildUrl = false,\n includeToAddress = true,\n}: GetDefaultValuesFromQueryStringOptions): Partial<DefaultValues> => {\n if (typeof window === 'undefined') {\n return {}\n }\n\n if (!buildUrl) {\n return {}\n }\n\n const searchParams = Object.fromEntries(\n new URLSearchParams(window.location.search)\n )\n\n // Prevent using fromToken/toToken params if chain is not selected.\n ;(['from', 'to'] as const).forEach((key) => {\n if (searchParams[`${key}Token`] && !searchParams[`${key}Chain`]) {\n delete searchParams[`${key}Token`]\n }\n })\n\n return {\n ...(Number.isFinite(Number.parseInt(searchParams.fromChain, 10))\n ? { fromChain: Number.parseInt(searchParams.fromChain, 10) }\n : {}),\n ...(Number.isFinite(Number.parseInt(searchParams.toChain, 10))\n ? { toChain: Number.parseInt(searchParams.toChain, 10) }\n : {}),\n ...(searchParams.fromToken ? { fromToken: searchParams.fromToken } : {}),\n ...(searchParams.toToken ? { toToken: searchParams.toToken } : {}),\n ...(Number.isFinite(Number.parseFloat(searchParams.fromAmount))\n ? { fromAmount: formatInputAmount(searchParams.fromAmount) }\n : {}),\n ...(Number.isFinite(Number.parseFloat(searchParams.toAmount))\n ? { toAmount: formatInputAmount(searchParams.toAmount) }\n : {}),\n // Limit-order params (written only while on the limit tab).\n ...(Number.isFinite(Number.parseInt(searchParams.validUntil, 10))\n ? { validUntil: Number.parseInt(searchParams.validUntil, 10) }\n : {}),\n ...(searchParams.partiallyFillable === 'true' ||\n searchParams.partiallyFillable === 'false'\n ? { partiallyFillable: searchParams.partiallyFillable === 'true' }\n : {}),\n ...(includeToAddress && searchParams.toAddress\n ? { toAddress: searchParams.toAddress }\n : {}),\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"getDefaultValuesFromQueryString.js","names":[],"sources":["../../../../src/stores/form/getDefaultValuesFromQueryString.ts"],"sourcesContent":["import type { WidgetChains } from '../../types/widget.js'\nimport {\n isDestinationOnlyChain,\n isUnservedDestinationChain,\n} from '../../utils/chainType.js'\nimport { formatInputAmount } from '../../utils/format.js'\nimport type { DefaultValues } from './types.js'\n\ninterface GetDefaultValuesFromQueryStringOptions {\n includeToAddress?: boolean\n buildUrl?: boolean\n chains?: WidgetChains\n}\n\nexport const getDefaultValuesFromQueryString = ({\n buildUrl = false,\n includeToAddress = true,\n chains,\n}: GetDefaultValuesFromQueryStringOptions): Partial<DefaultValues> => {\n if (typeof window === 'undefined') {\n return {}\n }\n\n if (!buildUrl) {\n return {}\n }\n\n const searchParams = Object.fromEntries(\n new URLSearchParams(window.location.search)\n )\n\n // The loop below then drops their tokens too.\n if (isDestinationOnlyChain(Number.parseInt(searchParams.fromChain, 10))) {\n delete searchParams.fromChain\n }\n if (\n isUnservedDestinationChain(\n Number.parseInt(searchParams.toChain, 10),\n chains\n )\n ) {\n delete searchParams.toChain\n }\n // Prevent using fromToken/toToken params if chain is not selected.\n ;(['from', 'to'] as const).forEach((key) => {\n if (searchParams[`${key}Token`] && !searchParams[`${key}Chain`]) {\n delete searchParams[`${key}Token`]\n }\n })\n\n return {\n ...(Number.isFinite(Number.parseInt(searchParams.fromChain, 10))\n ? { fromChain: Number.parseInt(searchParams.fromChain, 10) }\n : {}),\n ...(Number.isFinite(Number.parseInt(searchParams.toChain, 10))\n ? { toChain: Number.parseInt(searchParams.toChain, 10) }\n : {}),\n ...(searchParams.fromToken ? { fromToken: searchParams.fromToken } : {}),\n ...(searchParams.toToken ? { toToken: searchParams.toToken } : {}),\n ...(Number.isFinite(Number.parseFloat(searchParams.fromAmount))\n ? { fromAmount: formatInputAmount(searchParams.fromAmount) }\n : {}),\n ...(Number.isFinite(Number.parseFloat(searchParams.toAmount))\n ? { toAmount: formatInputAmount(searchParams.toAmount) }\n : {}),\n // Limit-order params (written only while on the limit tab).\n ...(Number.isFinite(Number.parseInt(searchParams.validUntil, 10))\n ? { validUntil: Number.parseInt(searchParams.validUntil, 10) }\n : {}),\n ...(searchParams.partiallyFillable === 'true' ||\n searchParams.partiallyFillable === 'false'\n ? { partiallyFillable: searchParams.partiallyFillable === 'true' }\n : {}),\n ...(includeToAddress && searchParams.toAddress\n ? { toAddress: searchParams.toAddress }\n : {}),\n }\n}\n"],"mappings":";;;AAcA,MAAa,mCAAmC,EAC9C,WAAW,OACX,mBAAmB,MACnB,aACoE;CACpE,IAAI,OAAO,WAAW,aACpB,OAAO,CAAC;CAGV,IAAI,CAAC,UACH,OAAO,CAAC;CAGV,MAAM,eAAe,OAAO,YAC1B,IAAI,gBAAgB,OAAO,SAAS,MAAM,CAC5C;CAGA,IAAI,uBAAuB,OAAO,SAAS,aAAa,WAAW,EAAE,CAAC,GACpE,OAAO,aAAa;CAEtB,IACE,2BACE,OAAO,SAAS,aAAa,SAAS,EAAE,GACxC,MACF,GAEA,OAAO,aAAa;CAGrB,CAAE,QAAQ,IAAI,CAAC,CAAW,SAAS,QAAQ;EAC1C,IAAI,aAAa,GAAG,IAAI,WAAW,CAAC,aAAa,GAAG,IAAI,SACtD,OAAO,aAAa,GAAG,IAAI;CAE/B,CAAC;CAED,OAAO;EACL,GAAI,OAAO,SAAS,OAAO,SAAS,aAAa,WAAW,EAAE,CAAC,IAC3D,EAAE,WAAW,OAAO,SAAS,aAAa,WAAW,EAAE,EAAE,IACzD,CAAC;EACL,GAAI,OAAO,SAAS,OAAO,SAAS,aAAa,SAAS,EAAE,CAAC,IACzD,EAAE,SAAS,OAAO,SAAS,aAAa,SAAS,EAAE,EAAE,IACrD,CAAC;EACL,GAAI,aAAa,YAAY,EAAE,WAAW,aAAa,UAAU,IAAI,CAAC;EACtE,GAAI,aAAa,UAAU,EAAE,SAAS,aAAa,QAAQ,IAAI,CAAC;EAChE,GAAI,OAAO,SAAS,OAAO,WAAW,aAAa,UAAU,CAAC,IAC1D,EAAE,YAAY,kBAAkB,aAAa,UAAU,EAAE,IACzD,CAAC;EACL,GAAI,OAAO,SAAS,OAAO,WAAW,aAAa,QAAQ,CAAC,IACxD,EAAE,UAAU,kBAAkB,aAAa,QAAQ,EAAE,IACrD,CAAC;EAEL,GAAI,OAAO,SAAS,OAAO,SAAS,aAAa,YAAY,EAAE,CAAC,IAC5D,EAAE,YAAY,OAAO,SAAS,aAAa,YAAY,EAAE,EAAE,IAC3D,CAAC;EACL,GAAI,aAAa,sBAAsB,UACvC,aAAa,sBAAsB,UAC/B,EAAE,mBAAmB,aAAa,sBAAsB,OAAO,IAC/D,CAAC;EACL,GAAI,oBAAoB,aAAa,YACjC,EAAE,WAAW,aAAa,UAAU,IACpC,CAAC;CACP;AACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import "../types.js";
|
|
2
1
|
import { HeaderState } from "./types.js";
|
|
2
|
+
import { PropsWithChildren } from "react";
|
|
3
3
|
//#region src/stores/header/useHeaderStore.d.ts
|
|
4
4
|
export declare function useHeaderStore<T>(selector: (state: HeaderState) => T): T;
|
|
5
5
|
export declare function useSetHeaderHeight(): any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHeaderStore.d.ts","names":[],"sources":["../../../../src/stores/header/useHeaderStore.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"useHeaderStore.d.ts","names":[],"sources":["../../../../src/stores/header/useHeaderStore.tsx"],"mappings":";;;wBA6BgB,eAAe,GAAG,WAAW,OAAO,gBAAgB,IAAI;wBAkBxD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useHeaderStore.js","names":[],"sources":["../../../../src/stores/header/useHeaderStore.tsx"],"sourcesContent":["import { createContext, use, useRef } from 'react'\nimport { create } from 'zustand'\nimport { useShallow } from 'zustand/shallow'\nimport type {
|
|
1
|
+
{"version":3,"file":"useHeaderStore.js","names":[],"sources":["../../../../src/stores/header/useHeaderStore.tsx"],"sourcesContent":["import type { PropsWithChildren } from 'react'\nimport { createContext, use, useRef } from 'react'\nimport { create } from 'zustand'\nimport { useShallow } from 'zustand/shallow'\nimport type { HeaderState, HeaderStore } from './types.js'\n\nconst HeaderStoreContext = createContext<HeaderStore | null>(null)\n\n// Not persisted, so it takes no storage scope.\nexport function HeaderStoreProvider({ children }: PropsWithChildren): any {\n const storeRef = useRef<HeaderStore>(null)\n if (!storeRef.current) {\n storeRef.current = createHeaderStore()\n }\n return (\n <HeaderStoreContext value={storeRef.current}>{children}</HeaderStoreContext>\n )\n}\n\nfunction useHeaderStoreContext() {\n const useStore = use(HeaderStoreContext)\n if (!useStore) {\n throw new Error(\n `You forgot to wrap your component in <${HeaderStoreProvider.name}>.`\n )\n }\n return useStore\n}\n\nexport function useHeaderStore<T>(selector: (state: HeaderState) => T): T {\n const useStore = useHeaderStoreContext()\n return useStore(useShallow(selector))\n}\n\n// We use fixed position on the header when Widget is in Full Height layout.\n// We do this to get it to work like the sticky header does in the other layout modes.\n// As the header is position fixed its not in the document flow anymore.\n// To prevent the remaining page content from appearing behind the header we need to\n// pass the headers height so that the position of the page content can be adjusted\nexport function useHeaderHeight(): any {\n const headerHeight = useHeaderStore((state) => state.headerHeight)\n\n return {\n headerHeight,\n }\n}\n\nexport function useSetHeaderHeight(): any {\n const setHeaderHeight = useHeaderStore((state) => state.setHeaderHeight)\n\n return {\n setHeaderHeight,\n }\n}\n\nconst createHeaderStore = () =>\n create<HeaderState>((set, get) => ({\n headerHeight: 108, // default header height\n setAction: (element) => {\n set(() => ({\n element,\n }))\n return get().removeAction\n },\n setTitle: (title) => {\n set(() => ({\n title,\n }))\n return get().removeTitle\n },\n removeAction: () => {\n set(() => ({\n element: null,\n }))\n },\n removeTitle: () => {\n set(() => ({\n title: undefined,\n }))\n },\n setHeaderHeight: (headerHeight) => {\n set(() => ({\n headerHeight,\n }))\n },\n setBackAction: (action) => {\n set(() => ({\n backAction: action,\n }))\n },\n executeBackAction: () => {\n const { backAction } = get()\n if (backAction) {\n backAction()\n set(() => ({\n backAction: undefined,\n }))\n }\n },\n }))\n"],"mappings":";;;;;AAMA,MAAM,qBAAqB,cAAkC,IAAI;AAGjE,SAAgB,oBAAoB,EAAE,YAAoC;CACxE,MAAM,WAAW,OAAoB,IAAI;CACzC,IAAI,CAAC,SAAS,SACZ,SAAS,UAAU,kBAAkB;CAEvC,OACE,oBAAC,oBAAD;EAAoB,OAAO,SAAS;EAAU;CAA6B,CAAA;AAE/E;AAEA,SAAS,wBAAwB;CAC/B,MAAM,WAAW,IAAI,kBAAkB;CACvC,IAAI,CAAC,UACH,MAAM,IAAI,MACR,yCAAyC,oBAAoB,KAAK,GACpE;CAEF,OAAO;AACT;AAEA,SAAgB,eAAkB,UAAwC;CAExE,OADiB,sBACH,CAAC,CAAC,WAAW,QAAQ,CAAC;AACtC;AAOA,SAAgB,kBAAuB;CAGrC,OAAO,EACL,cAHmB,gBAAgB,UAAU,MAAM,YAGxC,EACb;AACF;AAEA,SAAgB,qBAA0B;CAGxC,OAAO,EACL,iBAHsB,gBAAgB,UAAU,MAAM,eAGxC,EAChB;AACF;AAEA,MAAM,0BACJ,QAAqB,KAAK,SAAS;CACjC,cAAc;CACd,YAAY,YAAY;EACtB,WAAW,EACT,QACF,EAAE;EACF,OAAO,IAAI,CAAC,CAAC;CACf;CACA,WAAW,UAAU;EACnB,WAAW,EACT,MACF,EAAE;EACF,OAAO,IAAI,CAAC,CAAC;CACf;CACA,oBAAoB;EAClB,WAAW,EACT,SAAS,KACX,EAAE;CACJ;CACA,mBAAmB;EACjB,WAAW,EACT,OAAO,KAAA,EACT,EAAE;CACJ;CACA,kBAAkB,iBAAiB;EACjC,WAAW,EACT,aACF,EAAE;CACJ;CACA,gBAAgB,WAAW;EACzB,WAAW,EACT,YAAY,OACd,EAAE;CACJ;CACA,yBAAyB;EACvB,MAAM,EAAE,eAAe,IAAI;EAC3B,IAAI,YAAY;GACd,WAAW;GACX,WAAW,EACT,YAAY,KAAA,EACd,EAAE;EACJ;CACF;AACF,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createTheme.d.ts","names":[],"sources":["../../../src/themes/createTheme.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"createTheme.d.ts","names":["createTheme"],"sources":["../../../src/themes/createTheme.ts"],"mappings":";;;cAuCaA,gBAAe,cAAa,gBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","names":[],"sources":["../../../src/types/events.ts"],"mappings":";;;;;;;oBAOY;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;YAGU;EACV,oBAAoB,MAAM;EAC1B,kBAAkB,MAAM;EACxB,cAAc,MAAM;EACpB,iBAAiB,MAAM;EACvB,gCAAgC,MAAM;EACtC,mBAAmB,MAAM;EACzB,8BAA8B,MAAM;EACpC,uBAAuB,MAAM;EAC7B,cAAc,MAAM;EACpB,0BAA0B,MAAM;EAChC,uBAAuB,MAAM;EAC7B,wBAAwB,MAAM;EAC9B,wBAAwB,MAAM;EAC9B,qBAAqB,MAAM;EAC3B,gBAAgB,MAAM;EACtB,sBAAsB;EACtB,iBAAiB,MAAM;EACvB,2BAA2B,MAAM;EACjC,cAAc,MAAM;EACpB,iBAAiB;;YAUP;EACV;;YAGU;EACV;EACA;EACA;EACA;EACA;;YAGU;EACV,OAAO;EACP,QAAQ;;YAGE;EACV,OAAO;EACP,QAAQ;;YAGE;EACV;EACA,
|
|
1
|
+
{"version":3,"file":"events.d.ts","names":["TokenAmount"],"sources":["../../../src/types/events.ts"],"mappings":";;;;;;;oBAOY;EACV;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;YAGU;EACV,oBAAoB,MAAM;EAC1B,kBAAkB,MAAM;EACxB,cAAc,MAAM;EACpB,iBAAiB,MAAM;EACvB,gCAAgC,MAAM;EACtC,mBAAmB,MAAM;EACzB,8BAA8B,MAAM;EACpC,uBAAuB,MAAM;EAC7B,cAAc,MAAM;EACpB,0BAA0B,MAAM;EAChC,uBAAuB,MAAM;EAC7B,wBAAwB,MAAM;EAC9B,wBAAwB,MAAM;EAC9B,qBAAqB,MAAM;EAC3B,gBAAgB,MAAM;EACtB,sBAAsB;EACtB,iBAAiB,MAAM;EACvB,2BAA2B,MAAM;EACjC,cAAc,MAAM;EACpB,iBAAiB;;YAUP;EACV;;YAGU;EACV;EACA;EACA;EACA;EACA;;YAGU;EACV,OAAO;EACP,QAAQ;;YAGE;EACV,OAAO;EACP,QAAQ;;YAGE;EACV;EACA,QAAQA;;YAGE;EACV,SAAS;EACT;;YAGU,sBACT,WAAW;EACV,WAAW;EACX,UAAU,cAAc;EACxB,UAAU,cAAc;WAEpB;YAEI,eACV,gBAAgB,sBAAsB;EAEtC,SAAS;EACT,UAAU,cAAc;EACxB,UAAU,cAAc;EACxB,aAAa;EACb,aAAa;;YAGH;EACV;EACA;;YAGU;EACV;EACA;;YAGU;;EAEV,KAAK;;EAEL,cAAc"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","names":[],"sources":["../../../src/types/token.ts"],"mappings":";;iBAMiB;EACf;EACA;EACA;;EAEA;EACA;EACA;;EAEA;;
|
|
1
|
+
{"version":3,"file":"token.d.ts","names":["TokenAmount","SDKTokenAmount"],"sources":["../../../src/types/token.ts"],"mappings":";;iBAMiB;EACf;EACA;EACA;;EAEA;EACA;EACA;;EAEA;;UAGeA,sBAAoBC,aAAgB"}
|
|
@@ -307,7 +307,37 @@ export interface WidgetConfig {
|
|
|
307
307
|
walletConfig?: WidgetWalletConfig;
|
|
308
308
|
sdkConfig?: WidgetSDKConfig;
|
|
309
309
|
buildUrl?: boolean;
|
|
310
|
+
/**
|
|
311
|
+
* @deprecated Use `storageScopeKey` for persisted state and `queryScopeKey`
|
|
312
|
+
* for the query cache. Still honoured as the fallback for both.
|
|
313
|
+
*/
|
|
310
314
|
keyPrefix?: string;
|
|
315
|
+
/**
|
|
316
|
+
* Namespaces the widget's persisted state in `localStorage`: bookmarks,
|
|
317
|
+
* pinned tokens, recent tokens, chain order and route history, as
|
|
318
|
+
* `keyPrefix` does. Use a different value per widget instance that should
|
|
319
|
+
* keep its own state. Settings keep one shared name.
|
|
320
|
+
*
|
|
321
|
+
* It also scopes the widget's other queries (routes, tokens, balances, …),
|
|
322
|
+
* so instances with different values keep their data apart.
|
|
323
|
+
*
|
|
324
|
+
* Falls back to `keyPrefix`, then to the historical `li.fi-*` names.
|
|
325
|
+
*/
|
|
326
|
+
storageScopeKey?: string;
|
|
327
|
+
/**
|
|
328
|
+
* Scopes the widget's chains and tools queries inside the host's react-query
|
|
329
|
+
* `QueryClient`. Widget instances - and a host app using the
|
|
330
|
+
* `@lifi/widget/queries` factories - that pass the same value
|
|
331
|
+
* share those entries. The other widget queries are scoped by
|
|
332
|
+
* `storageScopeKey`.
|
|
333
|
+
*
|
|
334
|
+
* The keys start with a plain `'chains'` / `'tools'`, as in wagmi, so a host
|
|
335
|
+
* that matches on those roots (for example `setQueriesData({ queryKey:
|
|
336
|
+
* ['chains'] })`) also reaches the widget's entries.
|
|
337
|
+
*
|
|
338
|
+
* Falls back to `keyPrefix`, then to `'li.fi'`.
|
|
339
|
+
*/
|
|
340
|
+
queryScopeKey?: string;
|
|
311
341
|
bridges?: AllowDeny<string>;
|
|
312
342
|
exchanges?: AllowDeny<string>;
|
|
313
343
|
chains?: WidgetChains;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.d.ts","names":[],"sources":["../../../src/types/widget.ts"],"mappings":";;;;;;;;;YAoCY;;YAGA;YACA,yDAKR;YACQ;YACA;EACV,YAAY;;YAEF;iBACK;;;;;;EAMf,QAAQ,YAAY;EACpB;IAAW,MAAM;;;;;;;YAOP,wBAAwB;;YAExB;YAOA,mBAAmB,2BAA2B;YAE9C,aAAa;iBACR;;;;;EAKf;;YAEU,wBAAwB,QAClC,KACE,WAAW;YAeH;EACV;IACE;MACE,SAAS;;IAEX;MACE,SAAS;;;EAGb,QAAQ,QAAQ;EAChB,aAAa;EACb,aAAa;EACb,YAAY;EACZ,kBAAkB;EAClB,wBAAwB;EACxB,SAAS;EACT,aAAa;;iBAGE;EACf;EACA;EACA;EACA;;iBAGe;EACf;EACA;EACA;EACA;EACA;;;;;EAKA;EACA;;;;;EAKA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;EAMA;EACA;;;;;EAKA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;iBAGe;EACf;EACA;;YAGU;EACV;EACA;;;;;;;;;EASA;;iBAGe;EACf,wBAAwB,eAAe;EACvC,WAAW,OAAO;;;;;;;;;EASlB;;;;;EAKA;;iBAGe,wBACP,KACN;EAQF,eAAe,KACb;EAGF,mBAAmB,KAAK;;iBAGT;EACf;EACA;;iBAGe;EACf,WAAW;EACX,SAAS;EACT,WAAW;EACX,SAAS;EACT;EACA;EACA;EACA;EACA;;iBAGe;EACf;EACA;EACA;;;;;EAKA;;;;;EAKA;;;;EAIA,sBAAsB;;;;;;;;;EAStB,cAAc,QAAQ,qBAAqB;;iBAG5B;EACf;EACA;EACA,WAAW;EACX;;iBAGe,UAAU;EACzB,QAAQ;EACR,OAAO;;YAGG;iBACK;EACf,QAAQ,IAAI;EACZ,OAAO,IAAI;;YAGD;EACV,OAAO;EACP,KAAK;IACH;YAEQ,eAAe;EACzB,OAAO,UAAU;EACjB,KAAK,UAAU;IACb,UAAU;YAEF;EACV,QAAQ,UAAU;IAChB;YAEQ;EACV,WAAW;EACX,UAAU;EACV,UAAU;EACV,WAAW;IACT,eAAe;YAEP;EACV,UAAU;IACR,UAAU;YAEF;iBAEK;EACf;EACA,KAAK,QAAQ;;iBAGE;EACf,OAAO;EAEP,UAAU;EACV,YAAY;EACZ;EACA;EACA;EACA;;;;;;;;EAQA,SAAS,OAAO;;YAGN;EAGN;EACA;EACA;;YAGM,kBACV,OAAO,kBAAkB,yBACtB;iBAEY;EACf;EACA;EACA;EACA;EACA,YAAY;EACZ,cAAc;EACd;EACA;EACA;EACA;EAEA,YAAY;EAEZ,gBAAgB;EAChB,oBAAoB;EACpB,6BAA6B;EAC7B,2BAA2B;EAC3B,eAAe;EACf;EACA;EACA,YAAY;EACZ;EAEA,gBAAgB;EAChB;EAEA,UAAU;EACV,OAAO;EACP,cAAc;;;;;;;EAOd,kBAAkB;EAElB,aAAa;EACb,QAAQ;EAER,aAAa;EACb,WAAW;EACX,aAAa;EACb,YAAY;;;;;;;EAOZ;EACA;EAEA,eAAe;EACf,YAAY;EAEZ;
|
|
1
|
+
{"version":3,"file":"widget.d.ts","names":[],"sources":["../../../src/types/widget.ts"],"mappings":";;;;;;;;;YAoCY;;YAGA;YACA,yDAKR;YACQ;YACA;EACV,YAAY;;YAEF;iBACK;;;;;;EAMf,QAAQ,YAAY;EACpB;IAAW,MAAM;;;;;;;YAOP,wBAAwB;;YAExB;YAOA,mBAAmB,2BAA2B;YAE9C,aAAa;iBACR;;;;;EAKf;;YAEU,wBAAwB,QAClC,KACE,WAAW;YAeH;EACV;IACE;MACE,SAAS;;IAEX;MACE,SAAS;;;EAGb,QAAQ,QAAQ;EAChB,aAAa;EACb,aAAa;EACb,YAAY;EACZ,kBAAkB;EAClB,wBAAwB;EACxB,SAAS;EACT,aAAa;;iBAGE;EACf;EACA;EACA;EACA;;iBAGe;EACf;EACA;EACA;EACA;EACA;;;;;EAKA;EACA;;;;;EAKA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;EAMA;EACA;;;;;EAKA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;iBAGe;EACf;EACA;;YAGU;EACV;EACA;;;;;;;;;EASA;;iBAGe;EACf,wBAAwB,eAAe;EACvC,WAAW,OAAO;;;;;;;;;EASlB;;;;;EAKA;;iBAGe,wBACP,KACN;EAQF,eAAe,KACb;EAGF,mBAAmB,KAAK;;iBAGT;EACf;EACA;;iBAGe;EACf,WAAW;EACX,SAAS;EACT,WAAW;EACX,SAAS;EACT;EACA;EACA;EACA;EACA;;iBAGe;EACf;EACA;EACA;;;;;EAKA;;;;;EAKA;;;;EAIA,sBAAsB;;;;;;;;;EAStB,cAAc,QAAQ,qBAAqB;;iBAG5B;EACf;EACA;EACA,WAAW;EACX;;iBAGe,UAAU;EACzB,QAAQ;EACR,OAAO;;YAGG;iBACK;EACf,QAAQ,IAAI;EACZ,OAAO,IAAI;;YAGD;EACV,OAAO;EACP,KAAK;IACH;YAEQ,eAAe;EACzB,OAAO,UAAU;EACjB,KAAK,UAAU;IACb,UAAU;YAEF;EACV,QAAQ,UAAU;IAChB;YAEQ;EACV,WAAW;EACX,UAAU;EACV,UAAU;EACV,WAAW;IACT,eAAe;YAEP;EACV,UAAU;IACR,UAAU;YAEF;iBAEK;EACf;EACA,KAAK,QAAQ;;iBAGE;EACf,OAAO;EAEP,UAAU;EACV,YAAY;EACZ;EACA;EACA;EACA;;;;;;;;EAQA,SAAS,OAAO;;YAGN;EAGN;EACA;EACA;;YAGM,kBACV,OAAO,kBAAkB,yBACtB;iBAEY;EACf;EACA;EACA;EACA;EACA,YAAY;EACZ,cAAc;EACd;EACA;EACA;EACA;EAEA,YAAY;EAEZ,gBAAgB;EAChB,oBAAoB;EACpB,6BAA6B;EAC7B,2BAA2B;EAC3B,eAAe;EACf;EACA;EACA,YAAY;EACZ;EAEA,gBAAgB;EAChB;EAEA,UAAU;EACV,OAAO;EACP,cAAc;;;;;;;EAOd,kBAAkB;EAElB,aAAa;EACb,QAAQ;EAER,aAAa;EACb,WAAW;EACX,aAAa;EACb,YAAY;;;;;;;EAOZ;EACA;EAEA,eAAe;EACf,YAAY;EAEZ;;;;;EAKA;;;;;;;;;;;;EAYA;;;;;;;;;;;;;;EAcA;EAEA,UAAU;EACV,YAAY;EACZ,SAAS;EACT,SAAS;EACT,YAAY;EACZ,oBAAoB;EACpB,eAAe,eAAe,iBAC5B,QAAQ,mBAAmB;EAC7B,YAAY;;;;EAKZ,cAAc;;iBAGC;EACf;;iBAGe,oBACP,KAAK;EACb;EACA;EACA,YAAY;;YAGF,mBAAmB;YAEnB,yBAAyB,UAAU,YAC7C,KAAK,GACL,OAAO,YAAY,IACnB,UAAU;YAGA;EACV,eAAe;;YAGL,UAAU,UAAU;iBAEf;EACf,UAAU;;iBAGK,0BAA0B;EACzC,QAAQ;;iBAGO;EACf,SAAS,QAAQ;;YAGP,cAAc,oBACxB,eACA,2BACA;iBAEe,0BAA0B;EACzC,aAAa,UAAU;EACvB;;;;EAIA;;oBAGU;EACV;EACA;EACA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.js","names":[],"sources":["../../../src/types/widget.ts"],"sourcesContent":["import type {\n BaseToken,\n ChainType,\n ContractCall,\n ExecutionOptions,\n ExtendedChain,\n Order,\n Route,\n RouteOptions,\n SDKConfig,\n StaticToken,\n Token,\n} from '@lifi/sdk'\nimport type { WalletMenuOpenArgs } from '@lifi/wallet-management'\nimport type { WidgetProviderProps } from '@lifi/widget-provider'\nimport type {\n Components,\n PaletteMode,\n PaletteOptions,\n Shape,\n SxProps,\n Theme,\n} from '@mui/material'\nimport type { TypographyVariantsOptions } from '@mui/material/styles'\nimport type {\n CSSProperties,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from 'react'\nimport type {\n LanguageKey,\n LanguageResources,\n} from '../providers/I18nProvider/types.js'\nimport type { DefaultFieldValues } from '../stores/form/types.js'\n\nexport type WidgetVariant = 'compact' | 'wide' | 'drawer'\n\n/** @internal Not part of the public API. */\nexport type InternalWidgetMode = 'limit'\nexport type WidgetMode =\n | 'default'\n | 'split'\n | 'custom'\n | 'refuel'\n | InternalWidgetMode\nexport type SplitMode = 'bridge' | 'swap'\nexport type SplitModeOptions = {\n defaultTab: SplitMode\n}\nexport type CustomMode = 'checkout' | 'deposit'\nexport interface ModeOptions {\n /**\n * Configure split mode behavior:\n * - 'bridge' | 'swap': Single mode without tabs\n * - { defaultTab: 'bridge' | 'swap' }: Tabs mode with configurable default tab\n */\n split?: SplitMode | SplitModeOptions\n custom?: { type: CustomMode }\n}\n\n/**\n * Identity of a header navigation tab. Each key maps to a widget variant, mode and\n * (optionally) mode options; labels are resolved from the key.\n */\nexport type SplitNavigationTabKey = SplitMode\n/** @internal Not part of the public API. */\nexport type InternalNavigationTabKey =\n | 'default'\n | 'private'\n | 'refuel'\n | 'swap-advanced'\n | 'bridge-advanced'\n | 'limit'\nexport type NavigationTabKey = InternalNavigationTabKey | SplitNavigationTabKey\n\nexport type Appearance = PaletteMode | 'system'\nexport interface NavigationProps {\n /**\n * If given, uses a negative margin to counteract the padding on sides for navigation elements like icon buttons.\n * @default true\n */\n edge?: boolean\n}\nexport type WidgetThemeComponents = Partial<\n Pick<\n Components<Theme>,\n | 'MuiAppBar'\n | 'MuiAvatar'\n | 'MuiButton'\n | 'MuiCard'\n | 'MuiDrawer'\n | 'MuiIconButton'\n | 'MuiInputCard'\n | 'MuiNavigationTabs'\n | 'MuiNavigationTab'\n | 'MuiTabs'\n | 'MuiCheckbox'\n >\n>\n\nexport type WidgetTheme = {\n colorSchemes?: {\n light?: {\n palette: PaletteOptions\n }\n dark?: {\n palette: PaletteOptions\n }\n }\n shape?: Partial<Shape>\n typography?: TypographyVariantsOptions\n components?: WidgetThemeComponents\n container?: CSSProperties\n routesContainer?: CSSProperties\n chainSidebarContainer?: CSSProperties\n header?: CSSProperties\n navigation?: NavigationProps\n}\n\nexport interface DisabledUIConfig {\n fromAmount?: boolean\n fromToken?: boolean\n toAddress?: boolean\n toToken?: boolean\n}\n\nexport interface HiddenUIConfig {\n addressBookConnectedWallets?: boolean\n allNetworks?: boolean\n appearance?: boolean\n bridgesSettings?: boolean\n chainSelect?: boolean\n /**\n * Hide the chain sidebar in the `wide` variant. No effect in other variants.\n * @default false\n */\n chainSidebar?: boolean\n contactSupport?: boolean\n /**\n * Hide the drawer close button. Only meaningful when `variant === 'drawer'`.\n * @default false\n */\n drawerCloseButton?: boolean\n fromToken?: boolean\n gasRefuelMessage?: boolean\n hideSmallBalances?: boolean\n history?: boolean\n insufficientGasMessage?: boolean\n integratorStepDetails?: boolean\n language?: boolean\n /**\n * Hide the warning shown when sending to an address with low historical\n * on-chain activity (low transaction count or contract-like behavior).\n * @default false\n */\n lowAddressActivityConfirmation?: boolean\n poweredBy?: boolean\n /**\n * Hide the \"Recent searches\" section in the token select view.\n * @default false\n */\n recentSearches?: boolean\n reverseTokensButton?: boolean\n routeCardPriceImpact?: boolean\n routeTokenDescription?: boolean\n searchTokenInput?: boolean\n toAddress?: boolean\n toToken?: boolean\n walletMenu?: boolean\n}\n\nexport interface RequiredUIConfig {\n accountDeployedMessage?: boolean\n toAddress?: boolean\n}\n\nexport type DefaultUI = {\n transactionDetailsExpanded?: boolean\n navigationHeaderTitleNoWrap?: boolean\n /**\n * Layout for the main form.\n * - `'default'`: the chain/token selectors plus single amount input.\n * - `'cards'`: the redesigned card-based layout — stacked Send/Receive amount\n * cards (`AmountInputCardPair`) with inline token pill selectors and a swap\n * button.\n * @default 'default'\n */\n layout?: 'default' | 'cards'\n}\n\nexport interface WidgetWalletConfig {\n walletEcosystemsOrder?: Record<string, ChainType[]>\n onConnect?(args?: WalletMenuOpenArgs): void\n /**\n * Determines whether the widget should provide partial wallet management functionality.\n *\n * In partial mode, external wallet management will be used for \"opt-out\" providers,\n * while the internal management is applied for any remaining providers that do not opt out.\n * This allows a flexible balance between the integrator's custom wallet menu and the widget's native wallet menu.\n * @default false\n */\n usePartialWalletManagement?: boolean\n /**\n * This option forces the widget to always use internal wallet management ignoring external wallet management contexts\n * @default false\n */\n forceInternalWalletManagement?: boolean\n}\n\nexport interface WidgetSDKConfig\n extends Omit<\n SDKConfig,\n | 'apiKey'\n | 'disableVersionCheck'\n | 'integrator'\n | 'providers'\n | 'routeOptions'\n | 'widgetVersion'\n > {\n routeOptions?: Omit<\n RouteOptions,\n 'bridges' | 'exchanges' | 'fee' | 'referrer' | 'order' | 'slippage'\n >\n executionOptions?: Pick<ExecutionOptions, 'updateTransactionRequestHook'>\n}\n\nexport interface WidgetContractTool {\n name: string\n logoURI: string\n}\n\nexport interface CalculateFeeParams {\n fromChain: ExtendedChain\n toChain: ExtendedChain\n fromToken: Token\n toToken: Token\n fromAddress?: string\n toAddress?: string\n fromAmount?: bigint\n toAmount?: bigint\n slippage?: number\n}\n\nexport interface WidgetFeeConfig {\n name?: string\n logoURI?: string\n fee?: number\n /**\n * Whether to show the fee percentage in the fee details.\n * @default false\n */\n showFeePercentage?: boolean\n /**\n * Whether to show a tooltip with the fee details. Requires `name` or `feeTooltipComponent` to be set.\n * @default false\n */\n showFeeTooltip?: boolean\n /**\n * Custom tooltip component to show with the fee details.\n */\n feeTooltipComponent?: ReactNode\n /**\n * Function to calculate fees before fetching quotes.\n * If provided, this function will be used instead of the `fee` parameter.\n * Only one of `fee` or `calculateFee` should be used.\n *\n * @param params Object containing the fee calculation parameters\n * @returns A promise that resolves to the calculated fee as a number (e.g., 0.03 represents a 3% fee)\n */\n calculateFee?(params: CalculateFeeParams): Promise<number | undefined>\n}\n\nexport interface ToAddress {\n name?: string\n address: string\n chainType: ChainType\n logoURI?: string\n}\n\nexport interface AllowDeny<T> {\n allow?: T[]\n deny?: T[]\n}\n\nexport type AllowDenySetItem = string | number\nexport interface AllowDenySet {\n allow?: Set<AllowDenySetItem>\n deny?: Set<AllowDenySetItem>\n}\n\nexport type AllowDenySets = {\n from?: AllowDenySet\n to?: AllowDenySet\n} & AllowDenySet\n\nexport type AllowDenyItems<T> = {\n from?: AllowDeny<T>\n to?: AllowDeny<T>\n} & AllowDeny<T>\n\nexport type WidgetChains = {\n types?: AllowDeny<ChainType>\n} & AllowDenyItems<number>\n\nexport type WidgetTokens = {\n featured?: StaticToken[]\n include?: Token[]\n popular?: StaticToken[]\n verified?: BaseToken[]\n} & AllowDenyItems<BaseToken>\n\nexport type WidgetLanguages = {\n default?: LanguageKey\n} & AllowDeny<LanguageKey>\n\nexport type PoweredByType = 'default' | 'jumper'\n\nexport interface RouteLabel {\n text: string\n sx?: SxProps<Theme>\n}\n\nexport interface RouteLabelRule {\n label: RouteLabel\n // Matching criteria\n bridges?: AllowDeny<string>\n exchanges?: AllowDeny<string>\n fromChainId?: number[]\n toChainId?: number[]\n fromTokenAddress?: string[]\n toTokenAddress?: string[]\n /**\n * Custom match function evaluated against the route. When provided, its\n * result is AND'd with the other matching criteria — all specified\n * conditions must pass for the label to apply. Use this for matching logic\n * that the built-in fields cannot express (gas costs, step count, route\n * tags, etc.).\n */\n match?: (route: Route) => boolean\n}\n\nexport type ExplorerUrl =\n | string\n | {\n url: string\n txPath?: string\n addressPath?: string\n }\n\nexport type WidgetProvider = (\n props: PropsWithChildren<WidgetProviderProps>\n) => ReactNode\n\nexport interface WidgetConfig {\n fromChain?: number\n toChain?: number\n fromToken?: string\n toToken?: string\n toAddress?: ToAddress\n toAddresses?: ToAddress[]\n fromAmount?: number | string\n minFromAmountUSD?: number\n toAmount?: number | string\n formUpdateKey?: string\n\n providers?: WidgetProvider[]\n\n contractCalls?: ContractCall[]\n contractComponent?: ReactNode\n contractSecondaryComponent?: ReactNode\n contractCompactComponent?: ReactNode\n contractTool?: WidgetContractTool\n integrator: string\n apiKey?: string\n feeConfig?: WidgetFeeConfig\n referrer?: string\n\n routePriority?: Order\n slippage?: number\n\n variant?: WidgetVariant\n mode?: WidgetMode\n modeOptions?: ModeOptions\n /**\n * Header navigation tabs, in order. When set, the widget renders a tab bar\n * and the active tab drives the displayed flow. Each entry is a tab key.\n *\n * @internal Not part of the public API.\n */\n _navigationTabs?: NavigationTabKey[]\n\n appearance?: Appearance\n theme?: WidgetTheme\n\n disabledUI?: DisabledUIConfig\n hiddenUI?: HiddenUIConfig\n requiredUI?: RequiredUIConfig\n defaultUI?: DefaultUI\n /**\n * When true, shows only the recommended route and hides the route\n * selector UI. Distinct from `routePriority`, which sets the SDK\n * ranking order across multiple displayed routes.\n * @default false\n */\n showSingleRoute?: boolean\n useRelayerRoutes?: boolean\n\n walletConfig?: WidgetWalletConfig\n sdkConfig?: WidgetSDKConfig\n\n buildUrl?: boolean\n keyPrefix?: string\n\n bridges?: AllowDeny<string>\n exchanges?: AllowDeny<string>\n chains?: WidgetChains\n tokens?: WidgetTokens\n languages?: WidgetLanguages\n languageResources?: LanguageResources\n explorerUrls?: Record<number, ExplorerUrl[]> &\n Partial<Record<'internal', ExplorerUrl[]>>\n poweredBy?: PoweredByType\n\n /**\n * Custom labels/badges to show on routes based on specified rules\n */\n routeLabels?: RouteLabelRule[]\n}\n\nexport interface FormFieldOptions {\n setUrlSearchParam: boolean\n}\n\nexport interface FieldValues\n extends Omit<DefaultFieldValues, 'fromAmount' | 'toAmount' | 'toAddress'> {\n fromAmount?: number | string\n toAmount?: number | string\n toAddress?: ToAddress | string\n}\n\nexport type FieldNames = keyof FieldValues\n\nexport type SetFieldValueFunction = <K extends FieldNames>(\n key: K,\n value: FieldValues[K],\n options?: FormFieldOptions\n) => void\n\nexport type FormState = {\n setFieldValue: SetFieldValueFunction\n}\n\nexport type FormRef = RefObject<FormState | null>\n\nexport interface FormRefProps {\n formRef?: FormRef\n}\n\nexport interface WidgetConfigProps extends FormRefProps {\n config: WidgetConfig\n}\n\nexport interface WidgetConfigPartialProps {\n config?: Partial<WidgetConfig>\n}\n\nexport type WidgetProps = WidgetDrawerProps &\n WidgetConfig &\n WidgetConfigPartialProps &\n FormRefProps\n\nexport interface WidgetDrawerProps extends WidgetConfigPartialProps {\n elementRef?: RefObject<HTMLDivElement>\n open?: boolean\n /**\n * Make sure to make the onClose callback stable (e.g. using useCallback) to avoid causing re-renders of the entire widget\n */\n onClose?(): void\n}\n\nexport enum ExpansionType {\n Routes = 'routes',\n FromChain = 'fromChain',\n ToChain = 'toChain',\n}\n"],"mappings":";AAieA,IAAY,gBAAL,yBAAA,eAAA;CACL,cAAA,YAAA;CACA,cAAA,eAAA;CACA,cAAA,aAAA;;AACF,EAAA,CAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"widget.js","names":[],"sources":["../../../src/types/widget.ts"],"sourcesContent":["import type {\n BaseToken,\n ChainType,\n ContractCall,\n ExecutionOptions,\n ExtendedChain,\n Order,\n Route,\n RouteOptions,\n SDKConfig,\n StaticToken,\n Token,\n} from '@lifi/sdk'\nimport type { WalletMenuOpenArgs } from '@lifi/wallet-management'\nimport type { WidgetProviderProps } from '@lifi/widget-provider'\nimport type {\n Components,\n PaletteMode,\n PaletteOptions,\n Shape,\n SxProps,\n Theme,\n} from '@mui/material'\nimport type { TypographyVariantsOptions } from '@mui/material/styles'\nimport type {\n CSSProperties,\n PropsWithChildren,\n ReactNode,\n RefObject,\n} from 'react'\nimport type {\n LanguageKey,\n LanguageResources,\n} from '../providers/I18nProvider/types.js'\nimport type { DefaultFieldValues } from '../stores/form/types.js'\n\nexport type WidgetVariant = 'compact' | 'wide' | 'drawer'\n\n/** @internal Not part of the public API. */\nexport type InternalWidgetMode = 'limit'\nexport type WidgetMode =\n | 'default'\n | 'split'\n | 'custom'\n | 'refuel'\n | InternalWidgetMode\nexport type SplitMode = 'bridge' | 'swap'\nexport type SplitModeOptions = {\n defaultTab: SplitMode\n}\nexport type CustomMode = 'checkout' | 'deposit'\nexport interface ModeOptions {\n /**\n * Configure split mode behavior:\n * - 'bridge' | 'swap': Single mode without tabs\n * - { defaultTab: 'bridge' | 'swap' }: Tabs mode with configurable default tab\n */\n split?: SplitMode | SplitModeOptions\n custom?: { type: CustomMode }\n}\n\n/**\n * Identity of a header navigation tab. Each key maps to a widget variant, mode and\n * (optionally) mode options; labels are resolved from the key.\n */\nexport type SplitNavigationTabKey = SplitMode\n/** @internal Not part of the public API. */\nexport type InternalNavigationTabKey =\n | 'default'\n | 'private'\n | 'refuel'\n | 'swap-advanced'\n | 'bridge-advanced'\n | 'limit'\nexport type NavigationTabKey = InternalNavigationTabKey | SplitNavigationTabKey\n\nexport type Appearance = PaletteMode | 'system'\nexport interface NavigationProps {\n /**\n * If given, uses a negative margin to counteract the padding on sides for navigation elements like icon buttons.\n * @default true\n */\n edge?: boolean\n}\nexport type WidgetThemeComponents = Partial<\n Pick<\n Components<Theme>,\n | 'MuiAppBar'\n | 'MuiAvatar'\n | 'MuiButton'\n | 'MuiCard'\n | 'MuiDrawer'\n | 'MuiIconButton'\n | 'MuiInputCard'\n | 'MuiNavigationTabs'\n | 'MuiNavigationTab'\n | 'MuiTabs'\n | 'MuiCheckbox'\n >\n>\n\nexport type WidgetTheme = {\n colorSchemes?: {\n light?: {\n palette: PaletteOptions\n }\n dark?: {\n palette: PaletteOptions\n }\n }\n shape?: Partial<Shape>\n typography?: TypographyVariantsOptions\n components?: WidgetThemeComponents\n container?: CSSProperties\n routesContainer?: CSSProperties\n chainSidebarContainer?: CSSProperties\n header?: CSSProperties\n navigation?: NavigationProps\n}\n\nexport interface DisabledUIConfig {\n fromAmount?: boolean\n fromToken?: boolean\n toAddress?: boolean\n toToken?: boolean\n}\n\nexport interface HiddenUIConfig {\n addressBookConnectedWallets?: boolean\n allNetworks?: boolean\n appearance?: boolean\n bridgesSettings?: boolean\n chainSelect?: boolean\n /**\n * Hide the chain sidebar in the `wide` variant. No effect in other variants.\n * @default false\n */\n chainSidebar?: boolean\n contactSupport?: boolean\n /**\n * Hide the drawer close button. Only meaningful when `variant === 'drawer'`.\n * @default false\n */\n drawerCloseButton?: boolean\n fromToken?: boolean\n gasRefuelMessage?: boolean\n hideSmallBalances?: boolean\n history?: boolean\n insufficientGasMessage?: boolean\n integratorStepDetails?: boolean\n language?: boolean\n /**\n * Hide the warning shown when sending to an address with low historical\n * on-chain activity (low transaction count or contract-like behavior).\n * @default false\n */\n lowAddressActivityConfirmation?: boolean\n poweredBy?: boolean\n /**\n * Hide the \"Recent searches\" section in the token select view.\n * @default false\n */\n recentSearches?: boolean\n reverseTokensButton?: boolean\n routeCardPriceImpact?: boolean\n routeTokenDescription?: boolean\n searchTokenInput?: boolean\n toAddress?: boolean\n toToken?: boolean\n walletMenu?: boolean\n}\n\nexport interface RequiredUIConfig {\n accountDeployedMessage?: boolean\n toAddress?: boolean\n}\n\nexport type DefaultUI = {\n transactionDetailsExpanded?: boolean\n navigationHeaderTitleNoWrap?: boolean\n /**\n * Layout for the main form.\n * - `'default'`: the chain/token selectors plus single amount input.\n * - `'cards'`: the redesigned card-based layout — stacked Send/Receive amount\n * cards (`AmountInputCardPair`) with inline token pill selectors and a swap\n * button.\n * @default 'default'\n */\n layout?: 'default' | 'cards'\n}\n\nexport interface WidgetWalletConfig {\n walletEcosystemsOrder?: Record<string, ChainType[]>\n onConnect?(args?: WalletMenuOpenArgs): void\n /**\n * Determines whether the widget should provide partial wallet management functionality.\n *\n * In partial mode, external wallet management will be used for \"opt-out\" providers,\n * while the internal management is applied for any remaining providers that do not opt out.\n * This allows a flexible balance between the integrator's custom wallet menu and the widget's native wallet menu.\n * @default false\n */\n usePartialWalletManagement?: boolean\n /**\n * This option forces the widget to always use internal wallet management ignoring external wallet management contexts\n * @default false\n */\n forceInternalWalletManagement?: boolean\n}\n\nexport interface WidgetSDKConfig\n extends Omit<\n SDKConfig,\n | 'apiKey'\n | 'disableVersionCheck'\n | 'integrator'\n | 'providers'\n | 'routeOptions'\n | 'widgetVersion'\n > {\n routeOptions?: Omit<\n RouteOptions,\n 'bridges' | 'exchanges' | 'fee' | 'referrer' | 'order' | 'slippage'\n >\n executionOptions?: Pick<ExecutionOptions, 'updateTransactionRequestHook'>\n}\n\nexport interface WidgetContractTool {\n name: string\n logoURI: string\n}\n\nexport interface CalculateFeeParams {\n fromChain: ExtendedChain\n toChain: ExtendedChain\n fromToken: Token\n toToken: Token\n fromAddress?: string\n toAddress?: string\n fromAmount?: bigint\n toAmount?: bigint\n slippage?: number\n}\n\nexport interface WidgetFeeConfig {\n name?: string\n logoURI?: string\n fee?: number\n /**\n * Whether to show the fee percentage in the fee details.\n * @default false\n */\n showFeePercentage?: boolean\n /**\n * Whether to show a tooltip with the fee details. Requires `name` or `feeTooltipComponent` to be set.\n * @default false\n */\n showFeeTooltip?: boolean\n /**\n * Custom tooltip component to show with the fee details.\n */\n feeTooltipComponent?: ReactNode\n /**\n * Function to calculate fees before fetching quotes.\n * If provided, this function will be used instead of the `fee` parameter.\n * Only one of `fee` or `calculateFee` should be used.\n *\n * @param params Object containing the fee calculation parameters\n * @returns A promise that resolves to the calculated fee as a number (e.g., 0.03 represents a 3% fee)\n */\n calculateFee?(params: CalculateFeeParams): Promise<number | undefined>\n}\n\nexport interface ToAddress {\n name?: string\n address: string\n chainType: ChainType\n logoURI?: string\n}\n\nexport interface AllowDeny<T> {\n allow?: T[]\n deny?: T[]\n}\n\nexport type AllowDenySetItem = string | number\nexport interface AllowDenySet {\n allow?: Set<AllowDenySetItem>\n deny?: Set<AllowDenySetItem>\n}\n\nexport type AllowDenySets = {\n from?: AllowDenySet\n to?: AllowDenySet\n} & AllowDenySet\n\nexport type AllowDenyItems<T> = {\n from?: AllowDeny<T>\n to?: AllowDeny<T>\n} & AllowDeny<T>\n\nexport type WidgetChains = {\n types?: AllowDeny<ChainType>\n} & AllowDenyItems<number>\n\nexport type WidgetTokens = {\n featured?: StaticToken[]\n include?: Token[]\n popular?: StaticToken[]\n verified?: BaseToken[]\n} & AllowDenyItems<BaseToken>\n\nexport type WidgetLanguages = {\n default?: LanguageKey\n} & AllowDeny<LanguageKey>\n\nexport type PoweredByType = 'default' | 'jumper'\n\nexport interface RouteLabel {\n text: string\n sx?: SxProps<Theme>\n}\n\nexport interface RouteLabelRule {\n label: RouteLabel\n // Matching criteria\n bridges?: AllowDeny<string>\n exchanges?: AllowDeny<string>\n fromChainId?: number[]\n toChainId?: number[]\n fromTokenAddress?: string[]\n toTokenAddress?: string[]\n /**\n * Custom match function evaluated against the route. When provided, its\n * result is AND'd with the other matching criteria — all specified\n * conditions must pass for the label to apply. Use this for matching logic\n * that the built-in fields cannot express (gas costs, step count, route\n * tags, etc.).\n */\n match?: (route: Route) => boolean\n}\n\nexport type ExplorerUrl =\n | string\n | {\n url: string\n txPath?: string\n addressPath?: string\n }\n\nexport type WidgetProvider = (\n props: PropsWithChildren<WidgetProviderProps>\n) => ReactNode\n\nexport interface WidgetConfig {\n fromChain?: number\n toChain?: number\n fromToken?: string\n toToken?: string\n toAddress?: ToAddress\n toAddresses?: ToAddress[]\n fromAmount?: number | string\n minFromAmountUSD?: number\n toAmount?: number | string\n formUpdateKey?: string\n\n providers?: WidgetProvider[]\n\n contractCalls?: ContractCall[]\n contractComponent?: ReactNode\n contractSecondaryComponent?: ReactNode\n contractCompactComponent?: ReactNode\n contractTool?: WidgetContractTool\n integrator: string\n apiKey?: string\n feeConfig?: WidgetFeeConfig\n referrer?: string\n\n routePriority?: Order\n slippage?: number\n\n variant?: WidgetVariant\n mode?: WidgetMode\n modeOptions?: ModeOptions\n /**\n * Header navigation tabs, in order. When set, the widget renders a tab bar\n * and the active tab drives the displayed flow. Each entry is a tab key.\n *\n * @internal Not part of the public API.\n */\n _navigationTabs?: NavigationTabKey[]\n\n appearance?: Appearance\n theme?: WidgetTheme\n\n disabledUI?: DisabledUIConfig\n hiddenUI?: HiddenUIConfig\n requiredUI?: RequiredUIConfig\n defaultUI?: DefaultUI\n /**\n * When true, shows only the recommended route and hides the route\n * selector UI. Distinct from `routePriority`, which sets the SDK\n * ranking order across multiple displayed routes.\n * @default false\n */\n showSingleRoute?: boolean\n useRelayerRoutes?: boolean\n\n walletConfig?: WidgetWalletConfig\n sdkConfig?: WidgetSDKConfig\n\n buildUrl?: boolean\n /**\n * @deprecated Use `storageScopeKey` for persisted state and `queryScopeKey`\n * for the query cache. Still honoured as the fallback for both.\n */\n keyPrefix?: string\n /**\n * Namespaces the widget's persisted state in `localStorage`: bookmarks,\n * pinned tokens, recent tokens, chain order and route history, as\n * `keyPrefix` does. Use a different value per widget instance that should\n * keep its own state. Settings keep one shared name.\n *\n * It also scopes the widget's other queries (routes, tokens, balances, …),\n * so instances with different values keep their data apart.\n *\n * Falls back to `keyPrefix`, then to the historical `li.fi-*` names.\n */\n storageScopeKey?: string\n /**\n * Scopes the widget's chains and tools queries inside the host's react-query\n * `QueryClient`. Widget instances - and a host app using the\n * `@lifi/widget/queries` factories - that pass the same value\n * share those entries. The other widget queries are scoped by\n * `storageScopeKey`.\n *\n * The keys start with a plain `'chains'` / `'tools'`, as in wagmi, so a host\n * that matches on those roots (for example `setQueriesData({ queryKey:\n * ['chains'] })`) also reaches the widget's entries.\n *\n * Falls back to `keyPrefix`, then to `'li.fi'`.\n */\n queryScopeKey?: string\n\n bridges?: AllowDeny<string>\n exchanges?: AllowDeny<string>\n chains?: WidgetChains\n tokens?: WidgetTokens\n languages?: WidgetLanguages\n languageResources?: LanguageResources\n explorerUrls?: Record<number, ExplorerUrl[]> &\n Partial<Record<'internal', ExplorerUrl[]>>\n poweredBy?: PoweredByType\n\n /**\n * Custom labels/badges to show on routes based on specified rules\n */\n routeLabels?: RouteLabelRule[]\n}\n\nexport interface FormFieldOptions {\n setUrlSearchParam: boolean\n}\n\nexport interface FieldValues\n extends Omit<DefaultFieldValues, 'fromAmount' | 'toAmount' | 'toAddress'> {\n fromAmount?: number | string\n toAmount?: number | string\n toAddress?: ToAddress | string\n}\n\nexport type FieldNames = keyof FieldValues\n\nexport type SetFieldValueFunction = <K extends FieldNames>(\n key: K,\n value: FieldValues[K],\n options?: FormFieldOptions\n) => void\n\nexport type FormState = {\n setFieldValue: SetFieldValueFunction\n}\n\nexport type FormRef = RefObject<FormState | null>\n\nexport interface FormRefProps {\n formRef?: FormRef\n}\n\nexport interface WidgetConfigProps extends FormRefProps {\n config: WidgetConfig\n}\n\nexport interface WidgetConfigPartialProps {\n config?: Partial<WidgetConfig>\n}\n\nexport type WidgetProps = WidgetDrawerProps &\n WidgetConfig &\n WidgetConfigPartialProps &\n FormRefProps\n\nexport interface WidgetDrawerProps extends WidgetConfigPartialProps {\n elementRef?: RefObject<HTMLDivElement>\n open?: boolean\n /**\n * Make sure to make the onClose callback stable (e.g. using useCallback) to avoid causing re-renders of the entire widget\n */\n onClose?(): void\n}\n\nexport enum ExpansionType {\n Routes = 'routes',\n FromChain = 'fromChain',\n ToChain = 'toChain',\n}\n"],"mappings":";AA+fA,IAAY,gBAAL,yBAAA,eAAA;CACL,cAAA,YAAA;CACA,cAAA,eAAA;CACA,cAAA,aAAA;;AACF,EAAA,CAAA,CAAA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isItemAllowed } from "./item.js";
|
|
1
2
|
import { ChainId, ChainType } from "@lifi/sdk";
|
|
2
3
|
//#region src/utils/chainType.ts
|
|
3
4
|
const defaultChainIdsByType = {
|
|
@@ -8,7 +9,37 @@ const defaultChainIdsByType = {
|
|
|
8
9
|
[ChainType.TVM]: ChainId.TRN,
|
|
9
10
|
[ChainType.STL]: ChainId.XLM
|
|
10
11
|
};
|
|
12
|
+
const destinationOnlyChainIds = /* @__PURE__ */ new Set([ChainId.ZEC]);
|
|
13
|
+
const isDestinationOnlyChain = (chainId) => chainId !== void 0 && destinationOnlyChainIds.has(chainId);
|
|
14
|
+
const withDestinationOnlyChains = (chains) => {
|
|
15
|
+
const allow = chains?.from?.allow?.filter((chainId) => !isDestinationOnlyChain(chainId));
|
|
16
|
+
return {
|
|
17
|
+
...chains,
|
|
18
|
+
from: {
|
|
19
|
+
...chains?.from,
|
|
20
|
+
...allow && { allow },
|
|
21
|
+
deny: [...chains?.from?.deny ?? [], ...destinationOnlyChainIds]
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const withServedDestinationChains = (chains, providers) => {
|
|
26
|
+
const unserved = [...destinationOnlyChainIds].filter((chainId) => !providers.some((provider) => provider.chainIds?.some((id) => id === chainId)));
|
|
27
|
+
if (!unserved.length) return chains;
|
|
28
|
+
const allow = chains?.allow?.filter((chainId) => !unserved.includes(chainId));
|
|
29
|
+
return {
|
|
30
|
+
...chains,
|
|
31
|
+
...allow && { allow },
|
|
32
|
+
deny: [...chains?.deny ?? [], ...unserved]
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
const isUnservedDestinationChain = (chainId, chains) => isDestinationOnlyChain(chainId) && !isItemAllowed(chainId, chains);
|
|
36
|
+
const withoutUnservedToChain = (config) => {
|
|
37
|
+
if (!isUnservedDestinationChain(config.toChain, config.chains)) return config;
|
|
38
|
+
const { toChain: _toChain, toToken: _toToken, ...rest } = config;
|
|
39
|
+
return rest;
|
|
40
|
+
};
|
|
41
|
+
const isDestinationAllowedAsSource = (toChainId, chains) => !toChainId || isItemAllowed(toChainId, chains?.from);
|
|
11
42
|
//#endregion
|
|
12
|
-
export { defaultChainIdsByType };
|
|
43
|
+
export { defaultChainIdsByType, isDestinationAllowedAsSource, isDestinationOnlyChain, isUnservedDestinationChain, withDestinationOnlyChains, withServedDestinationChains, withoutUnservedToChain };
|
|
13
44
|
|
|
14
45
|
//# sourceMappingURL=chainType.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chainType.js","names":[],"sources":["../../../src/utils/chainType.ts"],"sourcesContent":["import { ChainId, ChainType } from '@lifi/sdk'\n\nexport const defaultChainIdsByType: Record<ChainType, ChainId> = {\n [ChainType.EVM]: ChainId.ETH,\n [ChainType.SVM]: ChainId.SOL,\n [ChainType.UTXO]: ChainId.BTC,\n [ChainType.MVM]: ChainId.SUI,\n [ChainType.TVM]: ChainId.TRN,\n [ChainType.STL]: ChainId.XLM,\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"chainType.js","names":[],"sources":["../../../src/utils/chainType.ts"],"sourcesContent":["import { ChainId, ChainType, type SDKProvider } from '@lifi/sdk'\nimport type { WidgetChains, WidgetConfig } from '../types/widget.js'\nimport { isItemAllowed } from './item.js'\n\nexport const defaultChainIdsByType: Record<ChainType, ChainId> = {\n [ChainType.EVM]: ChainId.ETH,\n [ChainType.SVM]: ChainId.SOL,\n [ChainType.UTXO]: ChainId.BTC,\n [ChainType.MVM]: ChainId.SUI,\n [ChainType.TVM]: ChainId.TRN,\n [ChainType.STL]: ChainId.XLM,\n}\n\n// No wallet can sign on these chains yet, so a route may only deliver to them.\nconst destinationOnlyChainIds: ReadonlySet<number> = new Set<number>([\n ChainId.ZEC,\n])\n\nexport const isDestinationOnlyChain = (chainId?: number): boolean =>\n chainId !== undefined && destinationOnlyChainIds.has(chainId)\n\nexport const withDestinationOnlyChains = (\n chains: WidgetChains | undefined\n): WidgetChains => {\n const allow = chains?.from?.allow?.filter(\n (chainId) => !isDestinationOnlyChain(chainId)\n )\n return {\n ...chains,\n from: {\n ...chains?.from,\n ...(allow && { allow }),\n deny: [...(chains?.from?.deny ?? []), ...destinationOnlyChainIds],\n },\n }\n}\n\n// A destination-only chain takes a receiver only through a provider that lists it.\nexport const withServedDestinationChains = (\n chains: WidgetChains | undefined,\n providers: readonly Pick<SDKProvider, 'chainIds'>[]\n): WidgetChains | undefined => {\n const unserved = [...destinationOnlyChainIds].filter(\n (chainId) =>\n !providers.some((provider) =>\n provider.chainIds?.some((id) => id === chainId)\n )\n )\n if (!unserved.length) {\n return chains\n }\n const allow = chains?.allow?.filter((chainId) => !unserved.includes(chainId))\n return {\n ...chains,\n ...(allow && { allow }),\n deny: [...(chains?.deny ?? []), ...unserved],\n }\n}\n\n// The form keeps a preset chain that the chain list does not offer.\nexport const isUnservedDestinationChain = (\n chainId: number | undefined,\n chains: WidgetChains | undefined\n): boolean => isDestinationOnlyChain(chainId) && !isItemAllowed(chainId, chains)\n\n// Omitted, not undefined: an own undefined key resets the form field.\nexport const withoutUnservedToChain = <\n T extends Pick<WidgetConfig, 'chains' | 'toChain' | 'toToken'>,\n>(\n config: T\n): T => {\n if (!isUnservedDestinationChain(config.toChain, config.chains)) {\n return config\n }\n const { toChain: _toChain, toToken: _toToken, ...rest } = config\n return rest as T\n}\n\nexport const isDestinationAllowedAsSource = (\n toChainId: number | undefined,\n chains: WidgetChains | undefined\n): boolean => !toChainId || isItemAllowed(toChainId, chains?.from)\n"],"mappings":";;;AAIA,MAAa,wBAAoD;EAC9D,UAAU,MAAM,QAAQ;EACxB,UAAU,MAAM,QAAQ;EACxB,UAAU,OAAO,QAAQ;EACzB,UAAU,MAAM,QAAQ;EACxB,UAAU,MAAM,QAAQ;EACxB,UAAU,MAAM,QAAQ;AAC3B;AAGA,MAAM,0CAA+C,IAAI,IAAY,CACnE,QAAQ,GACV,CAAC;AAED,MAAa,0BAA0B,YACrC,YAAY,KAAA,KAAa,wBAAwB,IAAI,OAAO;AAE9D,MAAa,6BACX,WACiB;CACjB,MAAM,QAAQ,QAAQ,MAAM,OAAO,QAChC,YAAY,CAAC,uBAAuB,OAAO,CAC9C;CACA,OAAO;EACL,GAAG;EACH,MAAM;GACJ,GAAG,QAAQ;GACX,GAAI,SAAS,EAAE,MAAM;GACrB,MAAM,CAAC,GAAI,QAAQ,MAAM,QAAQ,CAAC,GAAI,GAAG,uBAAuB;EAClE;CACF;AACF;AAGA,MAAa,+BACX,QACA,cAC6B;CAC7B,MAAM,WAAW,CAAC,GAAG,uBAAuB,CAAC,CAAC,QAC3C,YACC,CAAC,UAAU,MAAM,aACf,SAAS,UAAU,MAAM,OAAO,OAAO,OAAO,CAChD,CACJ;CACA,IAAI,CAAC,SAAS,QACZ,OAAO;CAET,MAAM,QAAQ,QAAQ,OAAO,QAAQ,YAAY,CAAC,SAAS,SAAS,OAAO,CAAC;CAC5E,OAAO;EACL,GAAG;EACH,GAAI,SAAS,EAAE,MAAM;EACrB,MAAM,CAAC,GAAI,QAAQ,QAAQ,CAAC,GAAI,GAAG,QAAQ;CAC7C;AACF;AAGA,MAAa,8BACX,SACA,WACY,uBAAuB,OAAO,KAAK,CAAC,cAAc,SAAS,MAAM;AAG/E,MAAa,0BAGX,WACM;CACN,IAAI,CAAC,2BAA2B,OAAO,SAAS,OAAO,MAAM,GAC3D,OAAO;CAET,MAAM,EAAE,SAAS,UAAU,SAAS,UAAU,GAAG,SAAS;CAC1D,OAAO;AACT;AAEA,MAAa,gCACX,WACA,WACY,CAAC,aAAa,cAAc,WAAW,QAAQ,IAAI"}
|
|
@@ -6,7 +6,12 @@ const isCustomReceiverBlocked = ({ fromChainType, toChainType, toAddress, signer
|
|
|
6
6
|
if (!toAddress) return Boolean(receiverRequired);
|
|
7
7
|
return toAddress.toLowerCase() !== signerAddress?.toLowerCase();
|
|
8
8
|
};
|
|
9
|
+
const isSignerInvalidReceiver = ({ signerAddress, toAddress, fromChain, toChain, isAddressForChain }) => Boolean(signerAddress && !toAddress && fromChain && toChain && fromChain.chainType === toChain.chainType && !isAddressForChain(signerAddress, toChain));
|
|
10
|
+
const canQuoteWithToAddress = (toAddress, toChain, isAddressForChain) => {
|
|
11
|
+
if (!toAddress) return true;
|
|
12
|
+
return toChain ? isAddressForChain(toAddress, toChain) : false;
|
|
13
|
+
};
|
|
9
14
|
//#endregion
|
|
10
|
-
export { isCustomReceiverBlocked, isCustomReceiverUnsupported };
|
|
15
|
+
export { canQuoteWithToAddress, isCustomReceiverBlocked, isCustomReceiverUnsupported, isSignerInvalidReceiver };
|
|
11
16
|
|
|
12
17
|
//# sourceMappingURL=customReceiver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"customReceiver.js","names":[],"sources":["../../../src/utils/customReceiver.ts"],"sourcesContent":["import { ChainType } from '@lifi/sdk'\n\n// Stellar routes always settle to the account that signs them.\nexport const isCustomReceiverUnsupported = (\n fromChainType?: ChainType,\n toChainType?: ChainType\n): boolean => fromChainType === ChainType.STL && toChainType === ChainType.STL\n\nexport interface CustomReceiverBlockedArgs {\n fromChainType?: ChainType\n toChainType?: ChainType\n toAddress?: string\n signerAddress?: string\n receiverRequired?: boolean\n}\n\nexport const isCustomReceiverBlocked = ({\n fromChainType,\n toChainType,\n toAddress,\n signerAddress,\n receiverRequired,\n}: CustomReceiverBlockedArgs): boolean => {\n if (!isCustomReceiverUnsupported(fromChainType, toChainType)) {\n return false\n }\n if (!toAddress) {\n return Boolean(receiverRequired)\n }\n return toAddress.toLowerCase() !== signerAddress?.toLowerCase()\n}\n"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"customReceiver.js","names":[],"sources":["../../../src/utils/customReceiver.ts"],"sourcesContent":["import { ChainType } from '@lifi/sdk'\nimport type { ChainRef, IsAddressForChain } from '@lifi/widget-provider'\n\n// Stellar routes always settle to the account that signs them.\nexport const isCustomReceiverUnsupported = (\n fromChainType?: ChainType,\n toChainType?: ChainType\n): boolean => fromChainType === ChainType.STL && toChainType === ChainType.STL\n\nexport interface CustomReceiverBlockedArgs {\n fromChainType?: ChainType\n toChainType?: ChainType\n toAddress?: string\n signerAddress?: string\n receiverRequired?: boolean\n}\n\nexport const isCustomReceiverBlocked = ({\n fromChainType,\n toChainType,\n toAddress,\n signerAddress,\n receiverRequired,\n}: CustomReceiverBlockedArgs): boolean => {\n if (!isCustomReceiverUnsupported(fromChainType, toChainType)) {\n return false\n }\n if (!toAddress) {\n return Boolean(receiverRequired)\n }\n return toAddress.toLowerCase() !== signerAddress?.toLowerCase()\n}\n\n// Without a receiver the API delivers to the signer when both chains share a\n// chain type, and a Bitcoin signer cannot receive on ZEC.\nexport const isSignerInvalidReceiver = ({\n signerAddress,\n toAddress,\n fromChain,\n toChain,\n isAddressForChain,\n}: {\n signerAddress: string | undefined\n toAddress: string | undefined\n fromChain: ChainRef | undefined\n toChain: ChainRef | undefined\n isAddressForChain: IsAddressForChain\n}): boolean =>\n Boolean(\n signerAddress &&\n !toAddress &&\n fromChain &&\n toChain &&\n fromChain.chainType === toChain.chainType &&\n !isAddressForChain(signerAddress, toChain)\n )\n\nexport const canQuoteWithToAddress = (\n toAddress: string | undefined,\n toChain: ChainRef | undefined,\n isAddressForChain: IsAddressForChain\n): boolean => {\n if (!toAddress) {\n return true\n }\n return toChain ? isAddressForChain(toAddress, toChain) : false\n}\n"],"mappings":";;AAIA,MAAa,+BACX,eACA,gBACY,kBAAkB,UAAU,OAAO,gBAAgB,UAAU;AAU3E,MAAa,2BAA2B,EACtC,eACA,aACA,WACA,eACA,uBACwC;CACxC,IAAI,CAAC,4BAA4B,eAAe,WAAW,GACzD,OAAO;CAET,IAAI,CAAC,WACH,OAAO,QAAQ,gBAAgB;CAEjC,OAAO,UAAU,YAAY,MAAM,eAAe,YAAY;AAChE;AAIA,MAAa,2BAA2B,EACtC,eACA,WACA,WACA,SACA,wBAQA,QACE,iBACE,CAAC,aACD,aACA,WACA,UAAU,cAAc,QAAQ,aAChC,CAAC,kBAAkB,eAAe,OAAO,CAC7C;AAEF,MAAa,yBACX,WACA,SACA,sBACY;CACZ,IAAI,CAAC,WACH,OAAO;CAET,OAAO,UAAU,kBAAkB,WAAW,OAAO,IAAI;AAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.js","names":[],"sources":["../../../src/utils/queries.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"queries.js","names":[],"sources":["../../../src/utils/queries.ts"],"sourcesContent":["// Legacy keys: callers pass the storage scope, so instances stay apart.\nexport const getQueryKey = (key: string, prefix?: string) =>\n `${prefix || 'li.fi'}-widget-${key}`\n"],"mappings":";AACA,MAAa,eAAe,KAAa,WACvC,GAAG,UAAU,QAAQ,UAAU"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { WidgetConfig } from "../types/widget.js";
|
|
2
|
+
//#region src/utils/scopeKeys.d.ts
|
|
3
|
+
type ScopeKeyConfig = Pick<WidgetConfig, "storageScopeKey" | "queryScopeKey" | "keyPrefix">;
|
|
4
|
+
export declare const resolveStorageScopeKey: (config: Partial<ScopeKeyConfig> | undefined) => string | undefined;
|
|
5
|
+
//#endregion
|
|
6
|
+
//# sourceMappingURL=scopeKeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopeKeys.d.ts","names":[],"sources":["../../../src/utils/scopeKeys.ts"],"mappings":";;KAKK,iBAAiB,KACpB;qBAKW,yBACX,QAAQ,QAAQ"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/utils/scopeKeys.ts
|
|
2
|
+
const defaultQueryScopeKey = "li.fi";
|
|
3
|
+
const resolveStorageScopeKey = (config) => config?.storageScopeKey ?? config?.keyPrefix;
|
|
4
|
+
const resolveQueryScopeKey = (config) => config?.queryScopeKey ?? config?.keyPrefix ?? "li.fi";
|
|
5
|
+
//#endregion
|
|
6
|
+
export { defaultQueryScopeKey, resolveQueryScopeKey, resolveStorageScopeKey };
|
|
7
|
+
|
|
8
|
+
//# sourceMappingURL=scopeKeys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopeKeys.js","names":[],"sources":["../../../src/utils/scopeKeys.ts"],"sourcesContent":["import type { WidgetConfig } from '../types/widget.js'\n\n// Non-empty, so an unconfigured widget never shares a host's unscoped entries.\nexport const defaultQueryScopeKey = 'li.fi'\n\ntype ScopeKeyConfig = Pick<\n WidgetConfig,\n 'storageScopeKey' | 'queryScopeKey' | 'keyPrefix'\n>\n\n// `undefined` keeps the historical `li.fi-*` store names.\nexport const resolveStorageScopeKey = (\n config: Partial<ScopeKeyConfig> | undefined\n): string | undefined => config?.storageScopeKey ?? config?.keyPrefix\n\nexport const resolveQueryScopeKey = (\n config: Partial<ScopeKeyConfig> | undefined\n): string => config?.queryScopeKey ?? config?.keyPrefix ?? defaultQueryScopeKey\n"],"mappings":";AAGA,MAAa,uBAAuB;AAQpC,MAAa,0BACX,WACuB,QAAQ,mBAAmB,QAAQ;AAE5D,MAAa,wBACX,WACW,QAAQ,iBAAiB,QAAQ,aAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lifi/widget",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.0",
|
|
4
4
|
"description": "LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/esm/index.js",
|
|
@@ -21,6 +21,11 @@
|
|
|
21
21
|
"import": "./dist/esm/shared.js",
|
|
22
22
|
"default": "./dist/esm/shared.js"
|
|
23
23
|
},
|
|
24
|
+
"./queries": {
|
|
25
|
+
"types": "./dist/esm/queries/index.d.ts",
|
|
26
|
+
"import": "./dist/esm/queries/index.js",
|
|
27
|
+
"default": "./dist/esm/queries/index.js"
|
|
28
|
+
},
|
|
24
29
|
"./package.json": "./package.json"
|
|
25
30
|
},
|
|
26
31
|
"sideEffects": false,
|
|
@@ -52,19 +57,19 @@
|
|
|
52
57
|
"dependencies": {
|
|
53
58
|
"@emotion/react": "^11.14.0",
|
|
54
59
|
"@emotion/styled": "^11.14.1",
|
|
55
|
-
"@lifi/sdk": "^4.
|
|
56
|
-
"@lifi/wallet-management": "4.3.
|
|
57
|
-
"@lifi/widget-provider": "4.
|
|
60
|
+
"@lifi/sdk": "^4.11.0",
|
|
61
|
+
"@lifi/wallet-management": "4.3.2",
|
|
62
|
+
"@lifi/widget-provider": "4.6.0",
|
|
58
63
|
"@mui/icons-material": "^9.4.0",
|
|
59
64
|
"@mui/material": "^9.4.0",
|
|
60
65
|
"@mui/system": "^9.4.0",
|
|
61
|
-
"@tanstack/react-router": "^1.170.
|
|
66
|
+
"@tanstack/react-router": "^1.170.41",
|
|
62
67
|
"@tanstack/react-virtual": "^3.14.13",
|
|
63
68
|
"eventemitter3": "^5.0.4",
|
|
64
69
|
"i18next": "^26.4.2",
|
|
65
70
|
"microdiff": "^1.6.0",
|
|
66
|
-
"motion": "^
|
|
67
|
-
"react-i18next": "^17.0.
|
|
71
|
+
"motion": "^14.0.0",
|
|
72
|
+
"react-i18next": "^17.0.16",
|
|
68
73
|
"react-intersection-observer": "^11.0.1",
|
|
69
74
|
"react-transition-group": "^4.4.5",
|
|
70
75
|
"zustand": "^5.0.15"
|
|
@@ -82,6 +87,9 @@
|
|
|
82
87
|
],
|
|
83
88
|
"shared": [
|
|
84
89
|
"./dist/esm/shared.d.ts"
|
|
90
|
+
],
|
|
91
|
+
"queries": [
|
|
92
|
+
"./dist/esm/queries/index.d.ts"
|
|
85
93
|
]
|
|
86
94
|
}
|
|
87
95
|
},
|
|
@@ -2,6 +2,8 @@ import type { BoxProps } from '@mui/material'
|
|
|
2
2
|
import type React from 'react'
|
|
3
3
|
import type { JSX } from 'react'
|
|
4
4
|
import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
|
|
5
|
+
import { useFieldValues } from '../../stores/form/useFieldValues.js'
|
|
6
|
+
import { isDestinationAllowedAsSource } from '../../utils/chainType.js'
|
|
5
7
|
import { LimitPriceCard } from '../LimitPriceCard/LimitPriceCard.js'
|
|
6
8
|
import { SwapButton } from '../SwapButton/SwapButton.js'
|
|
7
9
|
import { CardContainer } from './AmountInputCard.style.js'
|
|
@@ -11,8 +13,10 @@ import { SendAmountCard } from './SendAmountCard.js'
|
|
|
11
13
|
export const AmountInputCardPair: React.FC<BoxProps> = (props): JSX.Element => {
|
|
12
14
|
// Refuel's destination is fixed to native gas, so reversing from/to is
|
|
13
15
|
// meaningless — hide the swap button (and the notch mask it sits in).
|
|
14
|
-
const { mode } = useWidgetConfig()
|
|
15
|
-
const
|
|
16
|
+
const { mode, chains } = useWidgetConfig()
|
|
17
|
+
const [toChainId] = useFieldValues('toChain')
|
|
18
|
+
const showSwapButton =
|
|
19
|
+
mode !== 'refuel' && isDestinationAllowedAsSource(toChainId, chains)
|
|
16
20
|
|
|
17
21
|
return (
|
|
18
22
|
<CardContainer {...props}>
|
|
@@ -3,13 +3,17 @@ import { Box } from '@mui/material'
|
|
|
3
3
|
import { ReverseTokensButton } from '../components/ReverseTokensButton/ReverseTokensButton.js'
|
|
4
4
|
import { SelectTokenButton } from '../components/SelectTokenButton/SelectTokenButton.js'
|
|
5
5
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
6
|
+
import { useFieldValues } from '../stores/form/useFieldValues.js'
|
|
7
|
+
import { isDestinationAllowedAsSource } from '../utils/chainType.js'
|
|
6
8
|
import { ReverseTokensButtonEmpty } from './ReverseTokensButton/ReverseTokensButton.style.js'
|
|
7
9
|
|
|
8
10
|
export const SelectChainAndToken: React.FC<BoxProps> = (props) => {
|
|
9
|
-
const { disabledUI, hiddenUI, mode } = useWidgetConfig()
|
|
11
|
+
const { disabledUI, hiddenUI, mode, chains } = useWidgetConfig()
|
|
12
|
+
const [toChainId] = useFieldValues('toChain')
|
|
10
13
|
|
|
11
14
|
const hiddenReverse =
|
|
12
15
|
mode === 'refuel' ||
|
|
16
|
+
!isDestinationAllowedAsSource(toChainId, chains) ||
|
|
13
17
|
disabledUI?.fromToken ||
|
|
14
18
|
disabledUI?.toToken ||
|
|
15
19
|
hiddenUI?.fromToken ||
|