@lifi/widget 3.21.4-alpha.0 → 3.22.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.
Files changed (132) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/esm/AppProvider.js +2 -3
  3. package/dist/esm/AppProvider.js.map +1 -1
  4. package/dist/esm/components/AppContainer.js +23 -22
  5. package/dist/esm/components/AppContainer.js.map +1 -1
  6. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js +12 -7
  7. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
  8. package/dist/esm/components/BaseTransactionButton/types.d.ts +2 -0
  9. package/dist/esm/components/ChainSelect/ChainSelect.js +3 -1
  10. package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
  11. package/dist/esm/components/ChainSelect/ChainSelect.style.d.ts +3 -1
  12. package/dist/esm/components/ChainSelect/ChainSelect.style.js +23 -9
  13. package/dist/esm/components/ChainSelect/ChainSelect.style.js.map +1 -1
  14. package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.d.ts +8 -0
  15. package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js +20 -0
  16. package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js.map +1 -0
  17. package/dist/esm/components/Messages/WarningMessages.js +3 -0
  18. package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
  19. package/dist/esm/components/Messages/useMessageQueue.js +15 -4
  20. package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
  21. package/dist/esm/components/RouteCard/RouteCard.js +3 -3
  22. package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
  23. package/dist/esm/components/TokenList/TokenListItem.js +2 -2
  24. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  25. package/dist/esm/config/version.d.ts +1 -1
  26. package/dist/esm/config/version.js +1 -1
  27. package/dist/esm/config/version.js.map +1 -1
  28. package/dist/esm/hooks/useAvailableChains.js +3 -2
  29. package/dist/esm/hooks/useAvailableChains.js.map +1 -1
  30. package/dist/esm/hooks/useExplorer.d.ts +0 -1
  31. package/dist/esm/hooks/useExplorer.js +26 -31
  32. package/dist/esm/hooks/useExplorer.js.map +1 -1
  33. package/dist/esm/hooks/useFromTokenSufficiency.js +4 -1
  34. package/dist/esm/hooks/useFromTokenSufficiency.js.map +1 -1
  35. package/dist/esm/hooks/useGasRecommendation.js +9 -1
  36. package/dist/esm/hooks/useGasRecommendation.js.map +1 -1
  37. package/dist/esm/hooks/useGasSufficiency.js +50 -16
  38. package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
  39. package/dist/esm/hooks/useIsBatchingSupported.js +8 -1
  40. package/dist/esm/hooks/useIsBatchingSupported.js.map +1 -1
  41. package/dist/esm/hooks/useIsContractAddress.js +1 -1
  42. package/dist/esm/hooks/useIsContractAddress.js.map +1 -1
  43. package/dist/esm/hooks/useRouteExecution.js +10 -4
  44. package/dist/esm/hooks/useRouteExecution.js.map +1 -1
  45. package/dist/esm/hooks/useRouteRequiredAccountConnection.d.ts +10 -0
  46. package/dist/esm/hooks/useRouteRequiredAccountConnection.js +45 -0
  47. package/dist/esm/hooks/useRouteRequiredAccountConnection.js.map +1 -0
  48. package/dist/esm/hooks/useRoutes.d.ts +1 -1
  49. package/dist/esm/hooks/useRoutes.js +13 -4
  50. package/dist/esm/hooks/useRoutes.js.map +1 -1
  51. package/dist/esm/hooks/useTokenBalance.js +12 -3
  52. package/dist/esm/hooks/useTokenBalance.js.map +1 -1
  53. package/dist/esm/hooks/useTokenBalances.js +4 -1
  54. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  55. package/dist/esm/hooks/useTokenSearch.js +5 -2
  56. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  57. package/dist/esm/hooks/useTokens.js +3 -2
  58. package/dist/esm/hooks/useTokens.js.map +1 -1
  59. package/dist/esm/hooks/useTools.js +3 -2
  60. package/dist/esm/hooks/useTools.js.map +1 -1
  61. package/dist/esm/hooks/useTransactionDetails.js +9 -4
  62. package/dist/esm/hooks/useTransactionDetails.js.map +1 -1
  63. package/dist/esm/hooks/useTransactionHistory.js +7 -1
  64. package/dist/esm/hooks/useTransactionHistory.js.map +1 -1
  65. package/dist/esm/i18n/en.json +6 -4
  66. package/dist/esm/pages/MainPage/ReviewButton.js +1 -1
  67. package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
  68. package/dist/esm/pages/TransactionPage/StartTransactionButton.js +1 -1
  69. package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
  70. package/dist/esm/pages/TransactionPage/StatusBottomSheet.js +26 -43
  71. package/dist/esm/pages/TransactionPage/StatusBottomSheet.js.map +1 -1
  72. package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.d.ts +0 -1
  73. package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.js +4 -11
  74. package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.js.map +1 -1
  75. package/dist/esm/providers/QueryClientProvider.d.ts +2 -0
  76. package/dist/esm/providers/QueryClientProvider.js +9 -0
  77. package/dist/esm/providers/QueryClientProvider.js.map +1 -0
  78. package/dist/esm/providers/WalletProvider/SuiBaseProvider.js +3 -8
  79. package/dist/esm/providers/WalletProvider/SuiBaseProvider.js.map +1 -1
  80. package/dist/esm/stores/form/FormStore.js +5 -12
  81. package/dist/esm/stores/form/FormStore.js.map +1 -1
  82. package/dist/esm/stores/form/useFormRef.js +1 -7
  83. package/dist/esm/stores/form/useFormRef.js.map +1 -1
  84. package/dist/esm/types/widget.d.ts +6 -1
  85. package/dist/esm/utils/queries.d.ts +1 -0
  86. package/dist/esm/utils/queries.js +2 -0
  87. package/dist/esm/utils/queries.js.map +1 -0
  88. package/dist/esm/utils/timer.js +8 -1
  89. package/dist/esm/utils/timer.js.map +1 -1
  90. package/package.json +11 -11
  91. package/package.json.tmp +10 -10
  92. package/src/AppProvider.tsx +2 -3
  93. package/src/components/AppContainer.tsx +24 -23
  94. package/src/components/BaseTransactionButton/BaseTransactionButton.tsx +15 -6
  95. package/src/components/BaseTransactionButton/types.ts +3 -0
  96. package/src/components/ChainSelect/ChainSelect.style.tsx +25 -9
  97. package/src/components/ChainSelect/ChainSelect.tsx +4 -1
  98. package/src/components/Messages/MissingRouteRequiredAccountMessage.tsx +44 -0
  99. package/src/components/Messages/WarningMessages.tsx +9 -0
  100. package/src/components/Messages/useMessageQueue.ts +17 -4
  101. package/src/components/RouteCard/RouteCard.tsx +3 -3
  102. package/src/components/TokenList/TokenListItem.tsx +2 -2
  103. package/src/config/version.ts +1 -1
  104. package/src/hooks/useAvailableChains.ts +4 -2
  105. package/src/hooks/useExplorer.ts +35 -36
  106. package/src/hooks/useFromTokenSufficiency.ts +4 -1
  107. package/src/hooks/useGasRecommendation.ts +9 -1
  108. package/src/hooks/useGasSufficiency.ts +76 -22
  109. package/src/hooks/useIsBatchingSupported.ts +9 -1
  110. package/src/hooks/useIsContractAddress.ts +1 -1
  111. package/src/hooks/useRouteExecution.ts +10 -4
  112. package/src/hooks/useRouteRequiredAccountConnection.ts +58 -0
  113. package/src/hooks/useRoutes.ts +13 -7
  114. package/src/hooks/useTokenBalance.ts +12 -3
  115. package/src/hooks/useTokenBalances.ts +4 -1
  116. package/src/hooks/useTokenSearch.ts +5 -2
  117. package/src/hooks/useTokens.ts +3 -2
  118. package/src/hooks/useTools.ts +3 -2
  119. package/src/hooks/useTransactionDetails.ts +13 -4
  120. package/src/hooks/useTransactionHistory.ts +7 -1
  121. package/src/i18n/en.json +6 -4
  122. package/src/pages/MainPage/ReviewButton.tsx +1 -0
  123. package/src/pages/TransactionPage/StartTransactionButton.tsx +1 -0
  124. package/src/pages/TransactionPage/StatusBottomSheet.style.tsx +4 -12
  125. package/src/pages/TransactionPage/StatusBottomSheet.tsx +47 -77
  126. package/src/providers/QueryClientProvider.tsx +20 -0
  127. package/src/providers/WalletProvider/SuiBaseProvider.tsx +3 -9
  128. package/src/stores/form/FormStore.tsx +4 -15
  129. package/src/stores/form/useFormRef.ts +1 -8
  130. package/src/types/widget.ts +10 -2
  131. package/src/utils/queries.ts +2 -0
  132. package/src/utils/timer.ts +8 -1
@@ -4,6 +4,7 @@ import { useAccount } from '@lifi/wallet-management'
4
4
  import { useMutation, useQueryClient } from '@tanstack/react-query'
5
5
  import { useCallback, useEffect, useRef } from 'react'
6
6
  import { shallow } from 'zustand/shallow'
7
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
7
8
  import {
8
9
  useRouteExecutionStore,
9
10
  useRouteExecutionStoreContext,
@@ -15,6 +16,7 @@ import {
15
16
  isRouteFailed,
16
17
  } from '../stores/routes/utils.js'
17
18
  import { WidgetEvent } from '../types/events.js'
19
+ import { getQueryKey } from '../utils/queries.js'
18
20
  import { useWidgetEvents } from './useWidgetEvents.js'
19
21
 
20
22
  interface RouteExecutionProps {
@@ -34,6 +36,7 @@ export const useRouteExecution = ({
34
36
  const queryClient = useQueryClient()
35
37
  const { account } = useAccount()
36
38
  const resumedAfterMount = useRef(false)
39
+ const { keyPrefix } = useWidgetConfig()
37
40
  const emitter = useWidgetEvents()
38
41
  const routeExecutionStoreContext = useRouteExecutionStoreContext()
39
42
  const routeExecution = useRouteExecutionStore(
@@ -73,16 +76,16 @@ export const useRouteExecution = ({
73
76
  if (executionCompleted || executionFailed) {
74
77
  const invalidateKeys = [
75
78
  [
76
- 'token-balances',
79
+ getQueryKey('token-balances', keyPrefix),
77
80
  clonedUpdatedRoute.fromAddress,
78
81
  clonedUpdatedRoute.fromChainId,
79
82
  ],
80
83
  [
81
- 'token-balances',
84
+ getQueryKey('token-balances', keyPrefix),
82
85
  clonedUpdatedRoute.toAddress,
83
86
  clonedUpdatedRoute.toChainId,
84
87
  ],
85
- ['transaction-history'],
88
+ [getQueryKey('transaction-history', keyPrefix)],
86
89
  ]
87
90
  for (const key of invalidateKeys) {
88
91
  queryClient.invalidateQueries(
@@ -121,7 +124,10 @@ export const useRouteExecution = ({
121
124
  if (!routeExecution?.route) {
122
125
  throw new Error('Execution route not found.')
123
126
  }
124
- queryClient.removeQueries({ queryKey: ['routes'], exact: false })
127
+ queryClient.removeQueries({
128
+ queryKey: [getQueryKey('routes', keyPrefix)],
129
+ exact: false,
130
+ })
125
131
  return executeRoute(routeExecution.route, {
126
132
  updateRouteHook,
127
133
  acceptExchangeRateUpdateHook,
@@ -0,0 +1,58 @@
1
+ import type { ExtendedChain, Route } from '@lifi/sdk'
2
+ import { useAccount } from '@lifi/wallet-management'
3
+ import { useMemo } from 'react'
4
+ import { useFieldValues } from '../stores/form/useFieldValues.js'
5
+ import { useChain } from './useChain.js'
6
+
7
+ export const useRouteRequiredAccountConnection = (
8
+ route?: Route,
9
+ chain?: ExtendedChain
10
+ ) => {
11
+ const { account, accounts } = useAccount({ chainType: chain?.chainType })
12
+ const [toAddress] = useFieldValues('toAddress')
13
+ const { getChainById } = useChain()
14
+
15
+ return useMemo(() => {
16
+ if (!route?.steps.length) {
17
+ return {
18
+ connected: account.isConnected,
19
+ }
20
+ }
21
+
22
+ const connectedChainTypes = new Map(
23
+ accounts
24
+ .filter((account) => account.isConnected && account.address)
25
+ .map((account) => [account.chainType, account])
26
+ )
27
+
28
+ if (!connectedChainTypes.size) {
29
+ return {
30
+ connected: false,
31
+ }
32
+ }
33
+
34
+ for (const step of route.steps) {
35
+ const chain = getChainById(step.action.fromChainId)
36
+ if (!chain) {
37
+ continue
38
+ }
39
+
40
+ const connectedAccount = connectedChainTypes.get(chain.chainType)
41
+ const isToAddressSatisfied = toAddress
42
+ ? connectedAccount?.address === step.action.fromAddress
43
+ : true
44
+
45
+ if (!connectedAccount || !isToAddressSatisfied) {
46
+ return {
47
+ connected: false,
48
+ missingChain: chain,
49
+ missingAccountAddress: !isToAddressSatisfied
50
+ ? step.action.fromAddress
51
+ : undefined,
52
+ }
53
+ }
54
+ }
55
+
56
+ return { connected: true }
57
+ }, [account.isConnected, route, accounts, getChainById, toAddress])
58
+ }
@@ -19,6 +19,7 @@ import { useSettings } from '../stores/settings/useSettings.js'
19
19
  import { defaultSlippage } from '../stores/settings/useSettingsStore.js'
20
20
  import { WidgetEvent } from '../types/events.js'
21
21
  import { getChainTypeFromAddress } from '../utils/chainType.js'
22
+ import { getQueryKey } from '../utils/queries.js'
22
23
  import { useChain } from './useChain.js'
23
24
  import { useDebouncedWatch } from './useDebouncedWatch.js'
24
25
  import { useGasRefuel } from './useGasRefuel.js'
@@ -43,6 +44,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
43
44
  fee,
44
45
  feeConfig,
45
46
  useRelayerRoutes,
47
+ keyPrefix,
46
48
  } = useWidgetConfig()
47
49
  const setExecutableRoute = useSetExecutableRoute()
48
50
  const queryClient = useQueryClient()
@@ -135,7 +137,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
135
137
 
136
138
  // Some values should be strictly typed and isEnabled ensures that
137
139
  const queryKey = [
138
- 'routes',
140
+ getQueryKey('routes', keyPrefix),
139
141
  account.address,
140
142
  fromChain?.id as number,
141
143
  fromToken?.address as string,
@@ -399,7 +401,13 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
399
401
  const { fromToken, toToken } = routesResult.routes[0]
400
402
  ;[fromToken, toToken].forEach((token) => {
401
403
  queryClient.setQueriesData<Token[]>(
402
- { queryKey: ['token-balances', fromAddress, token.chainId] },
404
+ {
405
+ queryKey: [
406
+ getQueryKey('token-balances', keyPrefix),
407
+ fromAddress,
408
+ token.chainId,
409
+ ],
410
+ },
403
411
  (data) => {
404
412
  if (data) {
405
413
  const clonedData = [...data]
@@ -464,11 +472,9 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
464
472
 
465
473
  const setReviewableRoute = (route: Route) => {
466
474
  const queryDataKey = queryKey.toSpliced(queryKey.length - 1, 1, route.id)
467
- queryClient.setQueryData(
468
- queryDataKey,
469
- { routes: [route] },
470
- { updatedAt: dataUpdatedAt || Date.now() }
471
- )
475
+ queryClient.setQueryData(queryDataKey, [route], {
476
+ updatedAt: dataUpdatedAt || Date.now(),
477
+ })
472
478
  setExecutableRoute(route)
473
479
  }
474
480
 
@@ -1,21 +1,24 @@
1
1
  import { type Token, type TokenAmount, getTokenBalances } from '@lifi/sdk'
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query'
3
3
  import { useCallback, useMemo } from 'react'
4
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
5
+ import { getQueryKey } from '../utils/queries.js'
4
6
 
5
7
  const defaultRefetchInterval = 30_000
6
8
 
7
9
  export const useTokenBalance = (accountAddress?: string, token?: Token) => {
8
10
  const queryClient = useQueryClient()
11
+ const { keyPrefix } = useWidgetConfig()
9
12
 
10
13
  const tokenBalanceQueryKey = useMemo(
11
14
  () =>
12
15
  [
13
- 'token-balance',
16
+ getQueryKey('token-balance', keyPrefix),
14
17
  accountAddress,
15
18
  token?.chainId,
16
19
  token?.address,
17
20
  ] as const,
18
- [token?.address, token?.chainId, accountAddress]
21
+ [token?.address, token?.chainId, accountAddress, keyPrefix]
19
22
  )
20
23
 
21
24
  const { data, isLoading, refetch } = useQuery({
@@ -45,7 +48,13 @@ export const useTokenBalance = (accountAddress?: string, token?: Token) => {
45
48
  }
46
49
 
47
50
  queryClient.setQueriesData<TokenAmount[]>(
48
- { queryKey: ['token-balances', accountAddress, tokenChainId] },
51
+ {
52
+ queryKey: [
53
+ getQueryKey('token-balances', keyPrefix),
54
+ accountAddress,
55
+ tokenChainId,
56
+ ],
57
+ },
49
58
  (data) => {
50
59
  if (data) {
51
60
  const clonedData = [...data]
@@ -2,7 +2,9 @@ import { getTokenBalances } from '@lifi/sdk'
2
2
  import { useAccount } from '@lifi/wallet-management'
3
3
  import { useQuery } from '@tanstack/react-query'
4
4
  import { formatUnits } from 'viem'
5
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
5
6
  import type { TokenAmount } from '../types/token.js'
7
+ import { getQueryKey } from '../utils/queries.js'
6
8
  import { useTokens } from './useTokens.js'
7
9
 
8
10
  const defaultRefetchInterval = 32_000
@@ -11,6 +13,7 @@ export const useTokenBalances = (selectedChainId?: number) => {
11
13
  const { tokens, featuredTokens, popularTokens, chain, isLoading } =
12
14
  useTokens(selectedChainId)
13
15
  const { account } = useAccount({ chainType: chain?.chainType })
16
+ const { keyPrefix } = useWidgetConfig()
14
17
 
15
18
  const isBalanceLoadingEnabled =
16
19
  Boolean(account.address) &&
@@ -23,7 +26,7 @@ export const useTokenBalances = (selectedChainId?: number) => {
23
26
  refetch,
24
27
  } = useQuery({
25
28
  queryKey: [
26
- 'token-balances',
29
+ getQueryKey('token-balances', keyPrefix),
27
30
  account.address,
28
31
  selectedChainId,
29
32
  tokens?.length,
@@ -1,6 +1,8 @@
1
1
  import { type ChainId, type TokensResponse, getToken } from '@lifi/sdk'
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query'
3
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
3
4
  import type { TokenAmount } from '../types/token.js'
5
+ import { getQueryKey } from '../utils/queries.js'
4
6
 
5
7
  export const useTokenSearch = (
6
8
  chainId?: number,
@@ -8,8 +10,9 @@ export const useTokenSearch = (
8
10
  enabled?: boolean
9
11
  ) => {
10
12
  const queryClient = useQueryClient()
13
+ const { keyPrefix } = useWidgetConfig()
11
14
  const { data, isLoading } = useQuery({
12
- queryKey: ['token-search', chainId, tokenQuery],
15
+ queryKey: [getQueryKey('token-search', keyPrefix), chainId, tokenQuery],
13
16
  queryFn: async ({ queryKey: [, chainId, tokenQuery], signal }) => {
14
17
  const token = await getToken(chainId as ChainId, tokenQuery as string, {
15
18
  signal,
@@ -17,7 +20,7 @@ export const useTokenSearch = (
17
20
 
18
21
  if (token) {
19
22
  queryClient.setQueriesData<TokensResponse>(
20
- { queryKey: ['tokens'] },
23
+ { queryKey: [getQueryKey('tokens', keyPrefix)] },
21
24
  (data) => {
22
25
  if (
23
26
  data &&
@@ -3,12 +3,13 @@ import { useQuery } from '@tanstack/react-query'
3
3
  import { useMemo } from 'react'
4
4
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
5
5
  import type { TokenAmount } from '../types/token.js'
6
+ import { getQueryKey } from '../utils/queries.js'
6
7
  import { useChains } from './useChains.js'
7
8
 
8
9
  export const useTokens = (selectedChainId?: number) => {
9
- const { tokens: configTokens } = useWidgetConfig()
10
+ const { tokens: configTokens, keyPrefix } = useWidgetConfig()
10
11
  const { data, isLoading } = useQuery({
11
- queryKey: ['tokens'],
12
+ queryKey: [getQueryKey('tokens', keyPrefix)],
12
13
  queryFn: () =>
13
14
  getTokens({
14
15
  chainTypes: [
@@ -3,12 +3,13 @@ import { useQuery } from '@tanstack/react-query'
3
3
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
4
4
  import { useSettingsStore } from '../stores/settings/useSettingsStore.js'
5
5
  import { isItemAllowed } from '../utils/item.js'
6
+ import { getQueryKey } from '../utils/queries.js'
6
7
 
7
8
  export const useTools = () => {
8
- const { bridges, exchanges } = useWidgetConfig()
9
+ const { bridges, exchanges, keyPrefix } = useWidgetConfig()
9
10
  const { data } = useQuery({
10
11
  queryKey: [
11
- 'tools',
12
+ getQueryKey('tools', keyPrefix),
12
13
  bridges?.allow,
13
14
  bridges?.deny,
14
15
  exchanges?.allow,
@@ -6,18 +6,27 @@ import {
6
6
  useQuery,
7
7
  useQueryClient,
8
8
  } from '@tanstack/react-query'
9
+ import { useMemo } from 'react'
10
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
11
+ import { getQueryKey } from '../utils/queries.js'
9
12
 
10
13
  export const useTransactionDetails = (transactionHash?: string) => {
11
14
  const { account, accounts } = useAccount()
12
15
  const queryClient = useQueryClient()
16
+ const { keyPrefix } = useWidgetConfig()
17
+
18
+ const transactionHistoryQueryKey = useMemo(
19
+ () => getQueryKey('transaction-history', keyPrefix),
20
+ [keyPrefix]
21
+ )
13
22
 
14
23
  const { data, isLoading } = useQuery({
15
- queryKey: ['transaction-history', transactionHash],
24
+ queryKey: [transactionHistoryQueryKey, transactionHash],
16
25
  queryFn: async ({ queryKey: [, transactionHash], signal }) => {
17
26
  if (transactionHash) {
18
27
  for (const account of accounts) {
19
28
  const cachedHistory = queryClient.getQueryData<StatusResponse[]>([
20
- 'transaction-history',
29
+ transactionHistoryQueryKey,
21
30
  account.address,
22
31
  ])
23
32
 
@@ -41,7 +50,7 @@ export const useTransactionDetails = (transactionHash?: string) => {
41
50
 
42
51
  if (fromAddress) {
43
52
  queryClient.setQueryData<StatusResponse[]>(
44
- ['transaction-history', fromAddress],
53
+ [transactionHistoryQueryKey, fromAddress],
45
54
  (data) => {
46
55
  return [...data!, transaction!]
47
56
  }
@@ -57,7 +66,7 @@ export const useTransactionDetails = (transactionHash?: string) => {
57
66
  for (const account of accounts) {
58
67
  const transaction = queryClient
59
68
  .getQueryData<StatusResponse[]>([
60
- 'transaction-history',
69
+ transactionHistoryQueryKey,
61
70
  account.address,
62
71
  ])
63
72
  ?.find((t) => t.sending.txHash === transactionHash)
@@ -3,13 +3,19 @@ import { type ExtendedTransactionInfo, getTransactionHistory } from '@lifi/sdk'
3
3
  import { useAccount } from '@lifi/wallet-management'
4
4
  import type { QueryFunction } from '@tanstack/react-query'
5
5
  import { useQueries } from '@tanstack/react-query'
6
+ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
7
+ import { getQueryKey } from '../utils/queries.js'
6
8
 
7
9
  export const useTransactionHistory = () => {
8
10
  const { accounts } = useAccount()
11
+ const { keyPrefix } = useWidgetConfig()
9
12
 
10
13
  const { data, isLoading } = useQueries({
11
14
  queries: accounts.map((account) => ({
12
- queryKey: ['transaction-history', account.address],
15
+ queryKey: [
16
+ getQueryKey('transaction-history', keyPrefix),
17
+ account.address,
18
+ ],
13
19
  queryFn: (async ({ queryKey: [, accountAddress], signal }) => {
14
20
  if (!accountAddress) {
15
21
  return []
package/src/i18n/en.json CHANGED
@@ -21,6 +21,7 @@
21
21
  "close": "Close",
22
22
  "confirm": "Confirm",
23
23
  "connectAnotherWallet": "Connect another wallet",
24
+ "connectChainWallet": "Connect {{chain}} wallet",
24
25
  "connectWallet": "Connect wallet",
25
26
  "contactSupport": "Contact support",
26
27
  "continue": "Continue",
@@ -67,7 +68,9 @@
67
68
  "gas": "Gas",
68
69
  "payWith": "Pay with",
69
70
  "receive": "Receive",
71
+ "received": "Received",
70
72
  "recentWallets": "Recent wallets",
73
+ "refunded": "Refunded",
71
74
  "selectChain": "Select chain",
72
75
  "selectWallet": "Select your wallet",
73
76
  "send": "Send",
@@ -91,7 +94,8 @@
91
94
  "emptyTokenList": "We couldn't find tokens on {{chainName}} chain or you don't have any. Please search by contract address if your token doesn't appear or choose another chain.",
92
95
  "emptyTransactionHistory": "Transaction history is only stored locally and will be deleted if you clear your browser data.",
93
96
  "routeNotFound": "Reasons for that could be: low liquidity, amount selected is too low, gas costs are too high or there are no routes for the selected combination.",
94
- "toAddressIsRequired": "The destination wallet address is required to proceed with the transfer."
97
+ "toAddressIsRequired": "The destination wallet address is required to proceed with the transfer.",
98
+ "missingRouteRequiredAccount": "Connect your {{chainName}} wallet to proceed. {{address}}"
95
99
  },
96
100
  "title": {
97
101
  "autoRefuel": "Get {{chainName}} gas",
@@ -102,9 +106,7 @@
102
106
  },
103
107
  "success": {
104
108
  "message": {
105
- "exchangePartiallySuccessful": "We've tried to complete the transaction, but {{tool}} couldn't proceed due to either slippage settings or lack of liquidity for the {{tokenSymbol}} token.",
106
- "exchangeSuccessful": "There are now {{amount, numberExt}} {{tokenSymbol}} in {{walletAddress}} wallet on {{chainName}} chain.",
107
- "checkoutSuccessful": "You now own {{assetName}} in {{walletAddress}} wallet on {{chainName}} chain."
109
+ "exchangePartiallySuccessful": "We've tried to complete the transaction, but {{tool}} couldn't proceed due to either slippage settings or lack of liquidity for the {{tokenSymbol}} token."
108
110
  },
109
111
  "title": {
110
112
  "bridgePartiallySuccessful": "Bridge partially successful",
@@ -73,6 +73,7 @@ export const ReviewButton: React.FC = () => {
73
73
  text={getButtonText()}
74
74
  onClick={handleClick}
75
75
  disabled={currentRoute && requiredToAddress && !toAddress}
76
+ route={currentRoute}
76
77
  />
77
78
  )
78
79
  }
@@ -21,6 +21,7 @@ export const StartTransactionButton: React.FC<StartTransactionButtonProps> = ({
21
21
  text={text}
22
22
  disabled={hasNonGasMessages}
23
23
  loading={isLoading || loading}
24
+ route={route}
24
25
  />
25
26
  )
26
27
  }
@@ -52,23 +52,15 @@ export const IconCircle = styled(Box, {
52
52
  return {
53
53
  backgroundColor: `rgba(${color} / ${alphaValue})`,
54
54
  borderRadius: '50%',
55
- width: 64,
56
- height: 64,
55
+ width: 72,
56
+ height: 72,
57
57
  display: 'grid',
58
58
  position: 'relative',
59
59
  placeItems: 'center',
60
60
  '& > svg': {
61
61
  color: `color-mix(in srgb, rgb(${color}) ${(1 - darkenValue) * 100}%, black)`,
62
- width: 32,
63
- height: 32,
62
+ width: 36,
63
+ height: 36,
64
64
  },
65
65
  }
66
66
  })
67
-
68
- export const MessageSkeletonContainer = styled(Box)(({ theme }) => ({
69
- display: 'flex',
70
- flexDirection: 'column',
71
- height: 64,
72
- gap: theme.spacing(0.5),
73
- paddingTop: theme.spacing(1),
74
- }))
@@ -2,17 +2,18 @@ import Done from '@mui/icons-material/Done'
2
2
  import ErrorRounded from '@mui/icons-material/ErrorRounded'
3
3
  import InfoRounded from '@mui/icons-material/InfoRounded'
4
4
  import WarningRounded from '@mui/icons-material/WarningRounded'
5
- import { Box, Button, Skeleton, Typography } from '@mui/material'
5
+ import { Box, Button, Typography } from '@mui/material'
6
6
  import { useCallback, useEffect, useRef } from 'react'
7
7
  import { useTranslation } from 'react-i18next'
8
8
  import { BottomSheet } from '../../components/BottomSheet/BottomSheet.js'
9
9
  import type { BottomSheetBase } from '../../components/BottomSheet/types.js'
10
+ import { Card } from '../../components/Card/Card.js'
11
+ import { CardTitle } from '../../components/Card/CardTitle.js'
10
12
  import { Token } from '../../components/Token/Token.js'
11
13
  import { useAvailableChains } from '../../hooks/useAvailableChains.js'
12
14
  import { useNavigateBack } from '../../hooks/useNavigateBack.js'
13
15
  import { getProcessMessage } from '../../hooks/useProcessMessage.js'
14
16
  import { useSetContentHeight } from '../../hooks/useSetContentHeight.js'
15
- import { useTokenBalance } from '../../hooks/useTokenBalance.js'
16
17
  import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
17
18
  import { useFieldActions } from '../../stores/form/useFieldActions.js'
18
19
  import {
@@ -23,24 +24,12 @@ import { getSourceTxHash } from '../../stores/routes/utils.js'
23
24
  import { hasEnumFlag } from '../../utils/enum.js'
24
25
  import { formatTokenAmount } from '../../utils/format.js'
25
26
  import { navigationRoutes } from '../../utils/navigationRoutes.js'
26
- import { shortenAddress } from '../../utils/wallet.js'
27
- import {
28
- CenterContainer,
29
- IconCircle,
30
- MessageSkeletonContainer,
31
- } from './StatusBottomSheet.style.js'
27
+ import { CenterContainer, IconCircle } from './StatusBottomSheet.style.js'
32
28
 
33
29
  interface StatusBottomSheetContentProps extends RouteExecution {
34
30
  onClose(): void
35
31
  }
36
32
 
37
- const MessageSkeleton = () => (
38
- <MessageSkeletonContainer>
39
- <Skeleton height={24} variant="text" width="92%" />
40
- <Skeleton height={24} variant="text" width="56%" />
41
- </MessageSkeletonContainer>
42
- )
43
-
44
33
  export const StatusBottomSheet: React.FC<RouteExecution> = ({
45
34
  status,
46
35
  route,
@@ -97,11 +86,6 @@ export const StatusBottomSheetContent: React.FC<
97
86
  ),
98
87
  }
99
88
 
100
- const { token, refetch, refetchNewBalance } = useTokenBalance(
101
- route.toAddress,
102
- toToken
103
- )
104
-
105
89
  const cleanFields = () => {
106
90
  setFieldValue('fromAmount', '')
107
91
  setFieldValue('toAmount', '')
@@ -160,7 +144,7 @@ export const StatusBottomSheetContent: React.FC<
160
144
 
161
145
  let title: string | undefined
162
146
  let primaryMessage: string | undefined
163
- let secondaryMessage: string | undefined
147
+ let failedMessage: string | undefined
164
148
  let handlePrimaryButton = handleDone
165
149
  switch (status) {
166
150
  case RouteExecutionStatus.Done: {
@@ -170,14 +154,6 @@ export const StatusBottomSheetContent: React.FC<
170
154
  `success.title.${subvariantOptions?.custom ?? 'checkout'}Successful`
171
155
  )
172
156
  : t(`success.title.${transactionType}Successful`)
173
- if (token) {
174
- primaryMessage = t('success.message.exchangeSuccessful', {
175
- amount: formatTokenAmount(token.amount, token.decimals),
176
- tokenSymbol: token.symbol,
177
- chainName: getChainById(toToken.chainId)?.name,
178
- walletAddress: shortenAddress(route.toAddress),
179
- })
180
- }
181
157
  handlePrimaryButton = handleDone
182
158
  break
183
159
  }
@@ -187,14 +163,6 @@ export const StatusBottomSheetContent: React.FC<
187
163
  tool: route.steps.at(-1)?.toolDetails.name,
188
164
  tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,
189
165
  })
190
- if (token) {
191
- secondaryMessage = t('success.message.exchangeSuccessful', {
192
- amount: formatTokenAmount(token.amount, token.decimals),
193
- tokenSymbol: token.symbol,
194
- chainName: getChainById(toToken.chainId)?.name,
195
- walletAddress: shortenAddress(route.toAddress),
196
- })
197
- }
198
166
  handlePrimaryButton = handlePartialDone
199
167
  break
200
168
  }
@@ -204,14 +172,6 @@ export const StatusBottomSheetContent: React.FC<
204
172
  tool: route.steps.at(-1)?.toolDetails.name,
205
173
  tokenSymbol: route.steps.at(-1)?.action.toToken.symbol,
206
174
  })
207
- if (token) {
208
- secondaryMessage = t('success.message.exchangeSuccessful', {
209
- amount: formatTokenAmount(token.amount, token.decimals),
210
- tokenSymbol: token.symbol,
211
- chainName: getChainById(toToken.chainId)?.name,
212
- walletAddress: shortenAddress(route.toAddress),
213
- })
214
- }
215
175
  break
216
176
  }
217
177
  case RouteExecutionStatus.Failed: {
@@ -226,7 +186,7 @@ export const StatusBottomSheetContent: React.FC<
226
186
  }
227
187
  const processMessage = getProcessMessage(t, getChainById, step, process)
228
188
  title = processMessage.title
229
- primaryMessage = processMessage.message
189
+ failedMessage = processMessage.message
230
190
  handlePrimaryButton = handleClose
231
191
  break
232
192
  }
@@ -234,14 +194,6 @@ export const StatusBottomSheetContent: React.FC<
234
194
  break
235
195
  }
236
196
 
237
- useEffect(() => {
238
- const hasSuccessFlag = hasEnumFlag(status, RouteExecutionStatus.Done)
239
- if (hasSuccessFlag) {
240
- refetchNewBalance()
241
- refetch()
242
- }
243
- }, [refetch, refetchNewBalance, status])
244
-
245
197
  const showContractComponent =
246
198
  subvariant === 'custom' &&
247
199
  hasEnumFlag(status, RouteExecutionStatus.Done) &&
@@ -289,36 +241,54 @@ export const StatusBottomSheetContent: React.FC<
289
241
  </CenterContainer>
290
242
  {showContractComponent ? (
291
243
  contractCompactComponent || contractSecondaryComponent
292
- ) : (
293
- <CenterContainer>
294
- {hasEnumFlag(status, RouteExecutionStatus.Done) ? (
295
- <Token token={toToken} py={1} disableDescription />
296
- ) : null}
297
- </CenterContainer>
298
- )}
299
- {!showContractComponent ? (
300
- primaryMessage ? (
301
- <Typography
302
- sx={{
303
- py: 1,
304
- }}
305
- >
306
- {primaryMessage}
307
- </Typography>
308
- ) : (
309
- <MessageSkeleton />
310
- )
311
- ) : null}
312
- {secondaryMessage ? (
244
+ ) : hasEnumFlag(status, RouteExecutionStatus.Failed) && failedMessage ? (
313
245
  <Typography
314
246
  sx={{
315
247
  py: 1,
316
248
  }}
317
249
  >
318
- {secondaryMessage}
250
+ {failedMessage}
319
251
  </Typography>
252
+ ) : hasEnumFlag(status, RouteExecutionStatus.Done) ? (
253
+ <Box
254
+ sx={{
255
+ display: 'flex',
256
+ flexDirection: 'column',
257
+ gap: 2,
258
+ marginTop: 2,
259
+ marginBottom: VcComponent ? 2 : 3,
260
+ }}
261
+ >
262
+ <Card
263
+ sx={{
264
+ display: 'flex',
265
+ flexDirection: 'column',
266
+ gap: 2,
267
+ padding: 2,
268
+ }}
269
+ >
270
+ <CardTitle sx={{ padding: 0 }}>
271
+ {hasEnumFlag(status, RouteExecutionStatus.Refunded)
272
+ ? t('header.refunded')
273
+ : t('header.received')}
274
+ </CardTitle>
275
+ <Token token={toToken} disableDescription={false} />
276
+ {primaryMessage && (
277
+ <Typography
278
+ sx={{
279
+ color: 'text.secondary',
280
+ fontSize: '12px',
281
+ lineHeight: '16px',
282
+ fontWeight: 500,
283
+ }}
284
+ >
285
+ {primaryMessage}
286
+ </Typography>
287
+ )}
288
+ </Card>
289
+ {VcComponent ? <VcComponent route={route} /> : null}
290
+ </Box>
320
291
  ) : null}
321
- {VcComponent ? <VcComponent route={route} /> : null}
322
292
  <Box sx={{ display: 'flex', marginTop: 2, gap: 1.5 }}>
323
293
  {hasEnumFlag(status, RouteExecutionStatus.Done) ? (
324
294
  <Button variant="text" onClick={handleSeeDetails} fullWidth>