@lifi/widget 3.17.1 → 3.18.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/CHANGELOG.md +14 -0
- package/dist/esm/components/Card/CardLabel.d.ts +1 -1
- package/dist/esm/components/Card/CardLabel.js +14 -3
- package/dist/esm/components/Card/CardLabel.js.map +1 -1
- package/dist/esm/components/FeeBreakdownTooltip.d.ts +1 -0
- package/dist/esm/components/FeeBreakdownTooltip.js +3 -3
- package/dist/esm/components/FeeBreakdownTooltip.js.map +1 -1
- package/dist/esm/components/Messages/WarningMessages.d.ts +1 -0
- package/dist/esm/components/Messages/WarningMessages.js +4 -4
- package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
- package/dist/esm/components/Messages/useMessageQueue.d.ts +2 -2
- package/dist/esm/components/Messages/useMessageQueue.js +5 -4
- package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCard.js +11 -5
- package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCardEssentials.js +9 -5
- package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
- package/dist/esm/components/Routes/RoutesExpanded.js +1 -4
- package/dist/esm/components/Routes/RoutesExpanded.js.map +1 -1
- package/dist/esm/components/Step/StepProcess.js +2 -1
- package/dist/esm/components/Step/StepProcess.js.map +1 -1
- package/dist/esm/components/StepActions/StepActions.js +20 -15
- package/dist/esm/components/StepActions/StepActions.js.map +1 -1
- package/dist/esm/components/StepActions/types.d.ts +1 -0
- package/dist/esm/components/Timer/RouteTimer.js +11 -2
- package/dist/esm/components/Timer/RouteTimer.js.map +1 -1
- package/dist/esm/components/Timer/StepTimer.js +11 -2
- package/dist/esm/components/Timer/StepTimer.js.map +1 -1
- package/dist/esm/components/Token/Token.js +1 -1
- package/dist/esm/components/Token/Token.js.map +1 -1
- package/dist/esm/components/TransactionDetails.js +20 -14
- package/dist/esm/components/TransactionDetails.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/hooks/useGasRefuel.js +2 -2
- package/dist/esm/hooks/useGasRefuel.js.map +1 -1
- package/dist/esm/hooks/useGasSufficiency.js +17 -3
- package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
- package/dist/esm/hooks/useIsBatchingSupported.d.ts +5 -0
- package/dist/esm/hooks/useIsBatchingSupported.js +19 -0
- package/dist/esm/hooks/useIsBatchingSupported.js.map +1 -0
- package/dist/esm/hooks/useProcessMessage.js +22 -6
- package/dist/esm/hooks/useProcessMessage.js.map +1 -1
- package/dist/esm/hooks/useRoutes.d.ts +3 -3
- package/dist/esm/hooks/useRoutes.js +119 -70
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/i18n/en.json +29 -17
- package/dist/esm/pages/MainPage/ReviewButton.js +1 -4
- package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
- package/dist/esm/pages/RoutesPage/RoutesPage.js +1 -4
- package/dist/esm/pages/RoutesPage/RoutesPage.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js +6 -2
- package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionPage.js +1 -1
- package/dist/esm/pages/TransactionPage/TransactionPage.js.map +1 -1
- package/dist/esm/providers/WalletProvider/SDKProviders.js +2 -15
- package/dist/esm/providers/WalletProvider/SDKProviders.js.map +1 -1
- package/dist/esm/types/widget.d.ts +3 -1
- package/dist/esm/types/widget.js +1 -0
- package/dist/esm/types/widget.js.map +1 -1
- package/dist/esm/utils/timer.d.ts +7 -0
- package/dist/esm/utils/timer.js +16 -0
- package/dist/esm/utils/timer.js.map +1 -0
- package/package.json +10 -10
- package/package.json.tmp +90 -0
- package/src/components/Card/CardLabel.tsx +29 -4
- package/src/components/FeeBreakdownTooltip.tsx +5 -2
- package/src/components/Messages/WarningMessages.tsx +5 -3
- package/src/components/Messages/useMessageQueue.ts +5 -4
- package/src/components/RouteCard/RouteCard.tsx +23 -8
- package/src/components/RouteCard/RouteCardEssentials.tsx +13 -5
- package/src/components/Routes/RoutesExpanded.tsx +1 -5
- package/src/components/Step/StepProcess.tsx +2 -1
- package/src/components/StepActions/StepActions.tsx +18 -6
- package/src/components/StepActions/types.ts +1 -0
- package/src/components/Timer/RouteTimer.tsx +13 -2
- package/src/components/Timer/StepTimer.tsx +15 -5
- package/src/components/Token/Token.tsx +1 -1
- package/src/components/TransactionDetails.tsx +51 -23
- package/src/config/version.ts +1 -1
- package/src/hooks/useGasRefuel.ts +2 -2
- package/src/hooks/useGasSufficiency.ts +23 -7
- package/src/hooks/useIsBatchingSupported.ts +24 -0
- package/src/hooks/useProcessMessage.ts +26 -5
- package/src/hooks/useRoutes.ts +148 -78
- package/src/i18n/en.json +29 -17
- package/src/pages/MainPage/ReviewButton.tsx +1 -6
- package/src/pages/RoutesPage/RoutesPage.tsx +2 -5
- package/src/pages/TransactionPage/StartTransactionButton.tsx +1 -1
- package/src/pages/TransactionPage/TokenValueBottomSheet.tsx +9 -2
- package/src/pages/TransactionPage/TransactionPage.tsx +1 -1
- package/src/providers/WalletProvider/SDKProviders.tsx +2 -16
- package/src/types/widget.ts +2 -0
- package/src/utils/timer.ts +28 -0
- package/dist/esm/components/Messages/GasMessage.d.ts +0 -7
- package/dist/esm/components/Messages/GasMessage.js +0 -13
- package/dist/esm/components/Messages/GasMessage.js.map +0 -1
- package/dist/esm/providers/WalletProvider/getSafeMultisigConfig.d.ts +0 -8
- package/dist/esm/providers/WalletProvider/getSafeMultisigConfig.js +0 -95
- package/dist/esm/providers/WalletProvider/getSafeMultisigConfig.js.map +0 -1
- package/src/components/Messages/GasMessage.tsx +0 -35
- package/src/providers/WalletProvider/getSafeMultisigConfig.ts +0 -144
package/src/hooks/useRoutes.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import type { Route,
|
|
2
|
-
import {
|
|
1
|
+
import type { Route, Token } from '@lifi/sdk'
|
|
2
|
+
import {
|
|
3
|
+
ChainType,
|
|
4
|
+
LiFiErrorCode,
|
|
5
|
+
convertQuoteToRoute,
|
|
6
|
+
getContractCallsQuote,
|
|
7
|
+
getRelayerQuote,
|
|
8
|
+
getRoutes,
|
|
9
|
+
isRelayerStep,
|
|
10
|
+
} from '@lifi/sdk'
|
|
3
11
|
import { useAccount } from '@lifi/wallet-management'
|
|
4
12
|
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
|
5
13
|
import { parseUnits } from 'viem'
|
|
@@ -13,7 +21,7 @@ import { getChainTypeFromAddress } from '../utils/chainType.js'
|
|
|
13
21
|
import { useChain } from './useChain.js'
|
|
14
22
|
import { useDebouncedWatch } from './useDebouncedWatch.js'
|
|
15
23
|
import { useGasRefuel } from './useGasRefuel.js'
|
|
16
|
-
import {
|
|
24
|
+
import { useIsBatchingSupported } from './useIsBatchingSupported.js'
|
|
17
25
|
import { useSwapOnly } from './useSwapOnly.js'
|
|
18
26
|
import { useToken } from './useToken.js'
|
|
19
27
|
import { useWidgetEvents } from './useWidgetEvents.js'
|
|
@@ -33,6 +41,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
33
41
|
exchanges,
|
|
34
42
|
fee,
|
|
35
43
|
feeConfig,
|
|
44
|
+
useRelayerRoutes,
|
|
36
45
|
} = useWidgetConfig()
|
|
37
46
|
const setExecutableRoute = useSetExecutableRoute()
|
|
38
47
|
const queryClient = useQueryClient()
|
|
@@ -77,12 +86,12 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
77
86
|
const { token: toToken } = useToken(toChainId, toTokenAddress)
|
|
78
87
|
const { chain: fromChain } = useChain(fromChainId)
|
|
79
88
|
const { chain: toChain } = useChain(toChainId)
|
|
80
|
-
const { isCompatibleDestinationAccount } =
|
|
81
|
-
useIsCompatibleDestinationAccount(observableRoute)
|
|
82
89
|
const { enabled: enabledRefuel, fromAmount: gasRecommendationFromAmount } =
|
|
83
90
|
useGasRefuel()
|
|
84
91
|
|
|
85
92
|
const { account } = useAccount({ chainType: fromChain?.chainType })
|
|
93
|
+
const { isBatchingSupported, isBatchingSupportedLoading } =
|
|
94
|
+
useIsBatchingSupported(fromChain, account.address)
|
|
86
95
|
|
|
87
96
|
const hasAmount = Number(fromTokenAmount) > 0 || Number(toTokenAmount) > 0
|
|
88
97
|
|
|
@@ -110,29 +119,28 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
110
119
|
exchanges?.allow?.length || exchanges?.deny?.length
|
|
111
120
|
? enabledExchanges
|
|
112
121
|
: undefined
|
|
113
|
-
const allowSwitchChain =
|
|
114
|
-
? sdkConfig?.routeOptions?.allowSwitchChain
|
|
115
|
-
: false
|
|
122
|
+
const allowSwitchChain = sdkConfig?.routeOptions?.allowSwitchChain
|
|
116
123
|
|
|
117
124
|
const isEnabled =
|
|
118
|
-
Boolean(Number(
|
|
119
|
-
Boolean(Number(
|
|
125
|
+
Boolean(Number(fromChain?.id)) &&
|
|
126
|
+
Boolean(Number(toChain?.id)) &&
|
|
120
127
|
Boolean(fromToken?.address) &&
|
|
121
128
|
Boolean(toToken?.address) &&
|
|
122
129
|
!Number.isNaN(slippage) &&
|
|
123
130
|
hasAmount &&
|
|
124
131
|
isToAddressSatisfied &&
|
|
125
|
-
contractCallQuoteEnabled
|
|
132
|
+
contractCallQuoteEnabled &&
|
|
133
|
+
!isBatchingSupportedLoading
|
|
126
134
|
|
|
127
135
|
// Some values should be strictly typed and isEnabled ensures that
|
|
128
136
|
const queryKey = [
|
|
129
137
|
'routes',
|
|
130
138
|
account.address,
|
|
131
|
-
|
|
139
|
+
fromChain?.id as number,
|
|
132
140
|
fromToken?.address as string,
|
|
133
141
|
fromTokenAmount,
|
|
134
142
|
toWalletAddress,
|
|
135
|
-
|
|
143
|
+
toChain?.id as number,
|
|
136
144
|
toToken?.address as string,
|
|
137
145
|
toTokenAmount,
|
|
138
146
|
contractCalls,
|
|
@@ -148,6 +156,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
148
156
|
enabledRefuel && enabledAutoRefuel,
|
|
149
157
|
gasRecommendationFromAmount,
|
|
150
158
|
feeConfig?.fee || fee,
|
|
159
|
+
!!isBatchingSupported,
|
|
151
160
|
observableRoute?.id,
|
|
152
161
|
] as const
|
|
153
162
|
|
|
@@ -178,6 +187,8 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
178
187
|
enabledRefuel,
|
|
179
188
|
gasRecommendationFromAmount,
|
|
180
189
|
fee,
|
|
190
|
+
isBatchingSupported,
|
|
191
|
+
// _observableRouteId must be the last element in the query key
|
|
181
192
|
_observableRouteId,
|
|
182
193
|
],
|
|
183
194
|
signal,
|
|
@@ -266,27 +277,9 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
266
277
|
contractCallQuote.toolDetails = toolDetails
|
|
267
278
|
}
|
|
268
279
|
|
|
269
|
-
const route: Route =
|
|
270
|
-
id: crypto.randomUUID(),
|
|
271
|
-
fromChainId: contractCallQuote.action.fromChainId,
|
|
272
|
-
fromAmountUSD: contractCallQuote.estimate.fromAmountUSD || '',
|
|
273
|
-
fromAmount: contractCallQuote.action.fromAmount,
|
|
274
|
-
fromToken: contractCallQuote.action.fromToken,
|
|
275
|
-
fromAddress: contractCallQuote.action.fromAddress,
|
|
276
|
-
toChainId: contractCallQuote.action.toChainId,
|
|
277
|
-
toAmountUSD: contractCallQuote.estimate.toAmountUSD || '',
|
|
278
|
-
toAmount: contractCallQuote.estimate.toAmount,
|
|
279
|
-
toAmountMin: contractCallQuote.estimate.toAmountMin,
|
|
280
|
-
toToken: toToken!,
|
|
281
|
-
toAddress:
|
|
282
|
-
contractCallQuote.action.toAddress ||
|
|
283
|
-
contractCallQuote.action.fromAddress,
|
|
284
|
-
gasCostUSD: contractCallQuote.estimate.gasCosts?.[0].amountUSD,
|
|
285
|
-
steps: [contractCallQuote],
|
|
286
|
-
insurance: { state: 'NOT_INSURABLE', feeAmountUsd: '0' },
|
|
287
|
-
}
|
|
280
|
+
const route: Route = convertQuoteToRoute(contractCallQuote)
|
|
288
281
|
|
|
289
|
-
return
|
|
282
|
+
return [route]
|
|
290
283
|
}
|
|
291
284
|
|
|
292
285
|
// Prevent sending a request for the same chain token combinations.
|
|
@@ -294,50 +287,116 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
294
287
|
return
|
|
295
288
|
}
|
|
296
289
|
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
290
|
+
const isObservableRelayerRoute =
|
|
291
|
+
observableRoute?.steps?.some(isRelayerStep)
|
|
292
|
+
|
|
293
|
+
const shouldUseMainRoutes =
|
|
294
|
+
!observableRoute || !isObservableRelayerRoute
|
|
295
|
+
const shouldUseRelayerQuote =
|
|
296
|
+
fromAddress &&
|
|
297
|
+
fromChain?.chainType === ChainType.EVM &&
|
|
298
|
+
fromChain.permit2 &&
|
|
299
|
+
fromChain.permit2Proxy &&
|
|
300
|
+
fromChain.relayerSupported &&
|
|
301
|
+
fromChain.nativeToken.address !== fromTokenAddress &&
|
|
302
|
+
useRelayerRoutes &&
|
|
303
|
+
!isBatchingSupported &&
|
|
304
|
+
(!observableRoute || isObservableRelayerRoute)
|
|
305
|
+
|
|
306
|
+
const [routesResult, relayerRouteResult] = await Promise.all([
|
|
307
|
+
shouldUseMainRoutes
|
|
308
|
+
? getRoutes(
|
|
309
|
+
{
|
|
310
|
+
fromAddress,
|
|
311
|
+
fromAmount: fromAmount.toString(),
|
|
312
|
+
fromChainId,
|
|
313
|
+
fromTokenAddress,
|
|
314
|
+
toAddress,
|
|
315
|
+
toChainId,
|
|
316
|
+
toTokenAddress,
|
|
317
|
+
fromAmountForGas:
|
|
318
|
+
enabledRefuel && gasRecommendationFromAmount
|
|
319
|
+
? gasRecommendationFromAmount
|
|
320
|
+
: undefined,
|
|
321
|
+
options: {
|
|
322
|
+
allowSwitchChain:
|
|
323
|
+
subvariant === 'refuel' ? false : allowSwitchChain,
|
|
324
|
+
bridges:
|
|
325
|
+
allowBridges?.length || disabledBridges.length
|
|
326
|
+
? {
|
|
327
|
+
allow: allowBridges,
|
|
328
|
+
deny: disabledBridges.length
|
|
329
|
+
? disabledBridges
|
|
330
|
+
: undefined,
|
|
331
|
+
}
|
|
319
332
|
: undefined,
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
333
|
+
exchanges:
|
|
334
|
+
allowExchanges?.length || disabledExchanges.length
|
|
335
|
+
? {
|
|
336
|
+
allow: allowExchanges,
|
|
337
|
+
deny: disabledExchanges.length
|
|
338
|
+
? disabledExchanges
|
|
339
|
+
: undefined,
|
|
340
|
+
}
|
|
328
341
|
: undefined,
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
342
|
+
order: routePriority,
|
|
343
|
+
slippage: formattedSlippage,
|
|
344
|
+
fee: calculatedFee || fee,
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
{ signal }
|
|
348
|
+
)
|
|
349
|
+
: Promise.resolve(null),
|
|
350
|
+
shouldUseRelayerQuote
|
|
351
|
+
? getRelayerQuote(
|
|
352
|
+
{
|
|
353
|
+
fromAddress,
|
|
354
|
+
fromAmount: fromAmount.toString(),
|
|
355
|
+
fromChain: fromChainId,
|
|
356
|
+
fromToken: fromTokenAddress,
|
|
357
|
+
toAddress,
|
|
358
|
+
toChain: toChainId,
|
|
359
|
+
toToken: toTokenAddress,
|
|
360
|
+
fromAmountForGas:
|
|
361
|
+
enabledRefuel && gasRecommendationFromAmount
|
|
362
|
+
? gasRecommendationFromAmount
|
|
363
|
+
: undefined,
|
|
364
|
+
order: routePriority,
|
|
365
|
+
slippage: formattedSlippage,
|
|
366
|
+
fee: calculatedFee || fee,
|
|
367
|
+
...(allowBridges?.length || disabledBridges.length
|
|
368
|
+
? {
|
|
369
|
+
allowBridges: allowBridges,
|
|
370
|
+
denyBridges: disabledBridges.length
|
|
371
|
+
? disabledBridges
|
|
372
|
+
: undefined,
|
|
373
|
+
}
|
|
374
|
+
: undefined),
|
|
375
|
+
...(allowExchanges?.length || disabledExchanges.length
|
|
376
|
+
? {
|
|
377
|
+
allowExchanges: allowExchanges,
|
|
378
|
+
denyExchanges: disabledExchanges.length
|
|
379
|
+
? disabledExchanges
|
|
380
|
+
: undefined,
|
|
381
|
+
}
|
|
382
|
+
: undefined),
|
|
383
|
+
},
|
|
384
|
+
{ signal }
|
|
385
|
+
)
|
|
386
|
+
.then((response) => {
|
|
387
|
+
const quote = {
|
|
388
|
+
...response.quote,
|
|
389
|
+
permits: response.permits,
|
|
390
|
+
}
|
|
391
|
+
return convertQuoteToRoute(quote)
|
|
392
|
+
})
|
|
393
|
+
.catch(() => null)
|
|
394
|
+
: Promise.resolve(null),
|
|
395
|
+
])
|
|
396
|
+
|
|
397
|
+
if (routesResult?.routes[0] && fromAddress) {
|
|
339
398
|
// Update local tokens cache to keep priceUSD in sync
|
|
340
|
-
const { fromToken, toToken } =
|
|
399
|
+
const { fromToken, toToken } = routesResult.routes[0]
|
|
341
400
|
;[fromToken, toToken].forEach((token) => {
|
|
342
401
|
queryClient.setQueriesData<Token[]>(
|
|
343
402
|
{ queryKey: ['token-balances', fromAddress, token.chainId] },
|
|
@@ -357,8 +416,16 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
357
416
|
)
|
|
358
417
|
})
|
|
359
418
|
}
|
|
360
|
-
|
|
361
|
-
|
|
419
|
+
|
|
420
|
+
const routes = routesResult?.routes ?? []
|
|
421
|
+
|
|
422
|
+
// Add relayer route if available
|
|
423
|
+
if (relayerRouteResult) {
|
|
424
|
+
routes.splice(1, 0, relayerRouteResult)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
emitter.emit(WidgetEvent.AvailableRoutes, routes)
|
|
428
|
+
return routes
|
|
362
429
|
},
|
|
363
430
|
enabled: isEnabled,
|
|
364
431
|
staleTime: refetchTime,
|
|
@@ -369,7 +436,10 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
369
436
|
)
|
|
370
437
|
},
|
|
371
438
|
retry(failureCount, error: any) {
|
|
372
|
-
if (
|
|
439
|
+
if (process.env.NODE_ENV === 'development') {
|
|
440
|
+
console.warn('Route query failed:', { failureCount, error })
|
|
441
|
+
}
|
|
442
|
+
if (failureCount >= 3) {
|
|
373
443
|
return false
|
|
374
444
|
}
|
|
375
445
|
if (error?.code === LiFiErrorCode.NotFound) {
|
|
@@ -390,7 +460,7 @@ export const useRoutes = ({ observableRoute }: RoutesProps = {}) => {
|
|
|
390
460
|
}
|
|
391
461
|
|
|
392
462
|
return {
|
|
393
|
-
routes: data
|
|
463
|
+
routes: data,
|
|
394
464
|
isLoading: isEnabled && isLoading,
|
|
395
465
|
isFetching,
|
|
396
466
|
isFetched,
|
package/src/i18n/en.json
CHANGED
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"success": {
|
|
103
103
|
"message": {
|
|
104
104
|
"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.",
|
|
105
|
-
"exchangeSuccessful": "There are now {{amount,
|
|
105
|
+
"exchangeSuccessful": "There are now {{amount, numberExt}} {{tokenSymbol}} in {{walletAddress}} wallet on {{chainName}} chain.",
|
|
106
106
|
"checkoutSuccessful": "You now own {{assetName}} in {{walletAddress}} wallet on {{chainName}} chain."
|
|
107
107
|
},
|
|
108
108
|
"title": {
|
|
@@ -117,8 +117,7 @@
|
|
|
117
117
|
},
|
|
118
118
|
"warning": {
|
|
119
119
|
"message": {
|
|
120
|
-
"accountNotDeployedMessage": "Smart contract account
|
|
121
|
-
"noAddressActivity": "This address has never been used on this network. Please verify you're sending to the correct address to prevent potential loss of funds.",
|
|
120
|
+
"accountNotDeployedMessage": "Smart contract account doesn't exist on the destination chain. Sending funds to a non-existent smart contract account can result in permanent loss.",
|
|
122
121
|
"lowAddressActivity": "This address has low activity on {{chainName}} network. Please verify you're sending to the correct address and network to prevent potential loss of funds.",
|
|
123
122
|
"deleteActiveTransactions": "Active transactions are only stored locally and can't be recovered if you delete them.",
|
|
124
123
|
"deleteTransactionHistory": "Transaction history is only stored locally and can't be recovered if you delete it.",
|
|
@@ -146,12 +145,13 @@
|
|
|
146
145
|
"message": {
|
|
147
146
|
"allowanceRequired": "Transfer amount for {{tokenSymbol}} exceeds your current allowance. Please increase your allowance and try again.",
|
|
148
147
|
"insufficientFunds": "You don't have enough gas to cover the cost of the transaction.",
|
|
149
|
-
"remainInYourWallet": "{{amount,
|
|
150
|
-
"signatureRejected": "Your signature is required to complete the transaction. {{amount,
|
|
148
|
+
"remainInYourWallet": "{{amount, numberExt}} {{tokenSymbol}} on {{chainName}} remain in your wallet.",
|
|
149
|
+
"signatureRejected": "Your signature is required to complete the transaction. {{amount, numberExt}} {{tokenSymbol}} on {{chainName}} remain in your wallet.",
|
|
151
150
|
"slippageThreshold": "The slippage is larger than the defined threshold. Please request a new quote.",
|
|
152
151
|
"transactionCanceled": "Transaction was canceled.",
|
|
153
152
|
"transactionConflict": "Transaction couldn't be processed because it's conflicting with another pending transaction using the same funds. Please wait for the pending transaction to be confirmed or check your transaction history before trying again.",
|
|
154
153
|
"transactionExpired": "The block height has exceeded the maximum allowed limit or blockhash is no longer recent enough.",
|
|
154
|
+
"transactionRejected": "The transaction was rejected due to an internal wallet error. Please try again or request a new quote.",
|
|
155
155
|
"transactionFailed": "Please check the block explorer for more information.",
|
|
156
156
|
"transactionNotSent": "Transaction was not sent.",
|
|
157
157
|
"transactionSimulationFailed": "The transaction could not be executed in simulation.",
|
|
@@ -173,6 +173,7 @@
|
|
|
173
173
|
"transactionConflict": "Transaction conflict",
|
|
174
174
|
"transactionExpired": "Transaction expired",
|
|
175
175
|
"transactionFailed": "Transaction failed",
|
|
176
|
+
"transactionRejected": "Transaction rejected",
|
|
176
177
|
"transactionSimulationFailed": "Transaction simulation failed",
|
|
177
178
|
"transactionUnderpriced": "Transaction is underpriced",
|
|
178
179
|
"transactionUnprepared": "Unable to prepare transaction",
|
|
@@ -186,13 +187,14 @@
|
|
|
186
187
|
},
|
|
187
188
|
"tooltip": {
|
|
188
189
|
"deselectAll": "Deselect all",
|
|
189
|
-
"estimatedTime": "
|
|
190
|
+
"estimatedTime": "Time to complete the swap or bridge transaction, excluding chain switching and token approval.",
|
|
190
191
|
"feeCollection": "The fee is applied to selected token pairs and ensures the best experience with {{tool}}.",
|
|
191
192
|
"minReceived": "The estimated minimum amount may change until the swapping/bridging transaction is signed. For 2-step transfers, this applies until the second step transaction is signed.",
|
|
192
193
|
"notFound": {
|
|
193
194
|
"text": "We couldn't find this page.",
|
|
194
195
|
"title": "404"
|
|
195
196
|
},
|
|
197
|
+
"relayerService": "We handle the gas, so you can transfer assets without holding native tokens. Network costs are included in the transfer.",
|
|
196
198
|
"numberOfSteps": "Each exchange step can contain 1-2 transactions that require a signature.",
|
|
197
199
|
"priceImpact": "The estimated value difference between the source and destination tokens.",
|
|
198
200
|
"progressToNextUpdate": "Quotes will update in {{value}} seconds. <0/> Click here to update now.",
|
|
@@ -209,7 +211,9 @@
|
|
|
209
211
|
"featuredTokens": "Featured tokens",
|
|
210
212
|
"fees": {
|
|
211
213
|
"defaultIntegrator": "Integrator fee",
|
|
214
|
+
"relayerService": "Gasless service",
|
|
212
215
|
"estimated": "estimated costs",
|
|
216
|
+
"free": "Free",
|
|
213
217
|
"integrator": "{{tool}} fee",
|
|
214
218
|
"network": "Network cost",
|
|
215
219
|
"paid": "paid costs",
|
|
@@ -226,9 +230,9 @@
|
|
|
226
230
|
"priceImpact": "Price impact",
|
|
227
231
|
"process": {
|
|
228
232
|
"bridge": {
|
|
229
|
-
"actionRequired": "
|
|
233
|
+
"actionRequired": "Sign bridge transaction",
|
|
230
234
|
"done": "Bridge transaction confirmed",
|
|
231
|
-
"pending": "
|
|
235
|
+
"pending": "Bridge transaction pending",
|
|
232
236
|
"started": "Preparing bridge transaction"
|
|
233
237
|
},
|
|
234
238
|
"checkout": {
|
|
@@ -244,19 +248,26 @@
|
|
|
244
248
|
"refunded": "Bridge transaction refunded"
|
|
245
249
|
},
|
|
246
250
|
"swap": {
|
|
247
|
-
"actionRequired": "
|
|
251
|
+
"actionRequired": "Sign swap transaction",
|
|
248
252
|
"done": "Swap completed",
|
|
249
|
-
"pending": "
|
|
253
|
+
"pending": "Swap transaction pending",
|
|
250
254
|
"started": "Preparing swap transaction"
|
|
251
255
|
},
|
|
252
256
|
"switchChain": {
|
|
253
|
-
"actionRequired": "
|
|
254
|
-
"done": "Chain switched
|
|
257
|
+
"actionRequired": "Confirm chain switch",
|
|
258
|
+
"done": "Chain switched"
|
|
259
|
+
},
|
|
260
|
+
"permit": {
|
|
261
|
+
"actionRequired": "Sign permit message",
|
|
262
|
+
"done": "Permit message signed",
|
|
263
|
+
"pending": "Waiting for permit message",
|
|
264
|
+
"started": "Preparing transaction"
|
|
255
265
|
},
|
|
256
266
|
"tokenAllowance": {
|
|
257
|
-
"
|
|
258
|
-
"
|
|
259
|
-
"
|
|
267
|
+
"actionRequired": "Approve {{tokenSymbol}} spending",
|
|
268
|
+
"done": "{{tokenSymbol}} spending approved",
|
|
269
|
+
"pending": "{{tokenSymbol}} approval pending",
|
|
270
|
+
"started": "Preparing approval transaction"
|
|
260
271
|
}
|
|
261
272
|
},
|
|
262
273
|
"quotedAmount": "Quoted amount",
|
|
@@ -284,11 +295,12 @@
|
|
|
284
295
|
"transferId": "Transfer ID",
|
|
285
296
|
"tags": {
|
|
286
297
|
"cheapest": "Best Return",
|
|
287
|
-
"fastest": "Fastest"
|
|
298
|
+
"fastest": "Fastest",
|
|
299
|
+
"gasless": "Gasless"
|
|
288
300
|
},
|
|
289
301
|
"to": "To",
|
|
290
302
|
"tokenOnChain": "{{tokenSymbol}} on {{chainName}}",
|
|
291
|
-
"tokenOnChainAmount": "{{amount,
|
|
303
|
+
"tokenOnChainAmount": "{{amount, numberExt}} {{tokenSymbol}} on {{chainName}}",
|
|
292
304
|
"tokenSearch": "Search by token name or address",
|
|
293
305
|
"valueLoss": "Value loss",
|
|
294
306
|
"searchChains": "Search by chain name",
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { useTranslation } from 'react-i18next'
|
|
2
2
|
import { useNavigate } from 'react-router-dom'
|
|
3
3
|
import { BaseTransactionButton } from '../../components/BaseTransactionButton/BaseTransactionButton.js'
|
|
4
|
-
import { useIsCompatibleDestinationAccount } from '../../hooks/useIsCompatibleDestinationAccount.js'
|
|
5
4
|
import { useRoutes } from '../../hooks/useRoutes.js'
|
|
6
5
|
import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js'
|
|
7
6
|
import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
|
|
@@ -17,7 +16,6 @@ export const ReviewButton: React.FC = () => {
|
|
|
17
16
|
const { subvariant, subvariantOptions } = useWidgetConfig()
|
|
18
17
|
const splitState = useSplitSubvariantStore((state) => state.state)
|
|
19
18
|
const { toAddress, requiredToAddress } = useToAddressRequirements()
|
|
20
|
-
const { isCompatibleDestinationAccount } = useIsCompatibleDestinationAccount()
|
|
21
19
|
const { routes, setReviewableRoute } = useRoutes()
|
|
22
20
|
|
|
23
21
|
const currentRoute = routes?.[0]
|
|
@@ -74,10 +72,7 @@ export const ReviewButton: React.FC = () => {
|
|
|
74
72
|
<BaseTransactionButton
|
|
75
73
|
text={getButtonText()}
|
|
76
74
|
onClick={handleClick}
|
|
77
|
-
disabled={
|
|
78
|
-
(currentRoute && requiredToAddress && !toAddress) ||
|
|
79
|
-
!isCompatibleDestinationAccount
|
|
80
|
-
}
|
|
75
|
+
disabled={currentRoute && requiredToAddress && !toAddress}
|
|
81
76
|
/>
|
|
82
77
|
)
|
|
83
78
|
}
|
|
@@ -8,7 +8,6 @@ import { RouteCard } from '../../components/RouteCard/RouteCard.js'
|
|
|
8
8
|
import { RouteCardSkeleton } from '../../components/RouteCard/RouteCardSkeleton.js'
|
|
9
9
|
import { RouteNotFoundCard } from '../../components/RouteCard/RouteNotFoundCard.js'
|
|
10
10
|
import { useHeader } from '../../hooks/useHeader.js'
|
|
11
|
-
import { useIsCompatibleDestinationAccount } from '../../hooks/useIsCompatibleDestinationAccount.js'
|
|
12
11
|
import { useNavigateBack } from '../../hooks/useNavigateBack.js'
|
|
13
12
|
import { useRoutes } from '../../hooks/useRoutes.js'
|
|
14
13
|
import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js'
|
|
@@ -35,7 +34,6 @@ export const RoutesPage: React.FC<BoxProps> = () => {
|
|
|
35
34
|
const { account } = useAccount({ chainType: fromChain?.chainType })
|
|
36
35
|
const [toAddress] = useFieldValues('toAddress')
|
|
37
36
|
const { requiredToAddress } = useToAddressRequirements()
|
|
38
|
-
const { isCompatibleDestinationAccount } = useIsCompatibleDestinationAccount()
|
|
39
37
|
|
|
40
38
|
const headerAction = useMemo(
|
|
41
39
|
() => (
|
|
@@ -66,9 +64,8 @@ export const RoutesPage: React.FC<BoxProps> = () => {
|
|
|
66
64
|
|
|
67
65
|
const routeNotFound = !routes?.length && !isLoading && !isFetching
|
|
68
66
|
|
|
69
|
-
const toAddressUnsatisfied =
|
|
70
|
-
|
|
71
|
-
!isCompatibleDestinationAccount
|
|
67
|
+
const toAddressUnsatisfied = routes?.[0] && requiredToAddress && !toAddress
|
|
68
|
+
|
|
72
69
|
const allowInteraction = account.isConnected && !toAddressUnsatisfied
|
|
73
70
|
|
|
74
71
|
return (
|
|
@@ -8,7 +8,7 @@ export const StartTransactionButton: React.FC<StartTransactionButtonProps> = ({
|
|
|
8
8
|
text,
|
|
9
9
|
loading,
|
|
10
10
|
}) => {
|
|
11
|
-
const { hasMessages, isLoading } = useMessageQueue(route)
|
|
11
|
+
const { hasMessages, isLoading } = useMessageQueue(route, true)
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<BaseTransactionButton
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Route } from '@lifi/sdk'
|
|
2
|
+
import { isRelayerStep } from '@lifi/sdk'
|
|
2
3
|
import { WarningRounded } from '@mui/icons-material'
|
|
3
4
|
import { Box, Button, Typography } from '@mui/material'
|
|
4
5
|
import type { MutableRefObject } from 'react'
|
|
@@ -50,6 +51,7 @@ const TokenValueBottomSheetContent: React.FC<TokenValueBottomSheetProps> = ({
|
|
|
50
51
|
getAccumulatedFeeCostsBreakdown(route)
|
|
51
52
|
const fromAmountUSD = Number.parseFloat(route.fromAmountUSD)
|
|
52
53
|
const toAmountUSD = Number.parseFloat(route.toAmountUSD)
|
|
54
|
+
const hasRelayerSupport = route.steps.some(isRelayerStep)
|
|
53
55
|
return (
|
|
54
56
|
<Box
|
|
55
57
|
ref={ref}
|
|
@@ -102,13 +104,18 @@ const TokenValueBottomSheetContent: React.FC<TokenValueBottomSheetProps> = ({
|
|
|
102
104
|
}}
|
|
103
105
|
>
|
|
104
106
|
<Typography>{t('main.fees.network')}</Typography>
|
|
105
|
-
<FeeBreakdownTooltip
|
|
107
|
+
<FeeBreakdownTooltip
|
|
108
|
+
gasCosts={gasCosts}
|
|
109
|
+
relayerSupport={hasRelayerSupport}
|
|
110
|
+
>
|
|
106
111
|
<Typography
|
|
107
112
|
sx={{
|
|
108
113
|
fontWeight: 600,
|
|
109
114
|
}}
|
|
110
115
|
>
|
|
111
|
-
{
|
|
116
|
+
{hasRelayerSupport
|
|
117
|
+
? t('main.fees.free')
|
|
118
|
+
: t('format.currency', { value: gasCostUSD })}
|
|
112
119
|
</Typography>
|
|
113
120
|
</FeeBreakdownTooltip>
|
|
114
121
|
</Box>
|
|
@@ -207,7 +207,7 @@ export const TransactionPage: React.FC = () => {
|
|
|
207
207
|
{status === RouteExecutionStatus.Idle ||
|
|
208
208
|
status === RouteExecutionStatus.Failed ? (
|
|
209
209
|
<>
|
|
210
|
-
<WarningMessages mt={2} route={route} />
|
|
210
|
+
<WarningMessages mt={2} route={route} allowInteraction />
|
|
211
211
|
<Box
|
|
212
212
|
sx={{
|
|
213
213
|
mt: 2,
|
|
@@ -5,20 +5,18 @@ import { ChainType, EVM, Solana, UTXO, config } from '@lifi/sdk'
|
|
|
5
5
|
import type { SignerWalletAdapter } from '@solana/wallet-adapter-base'
|
|
6
6
|
import { useWallet } from '@solana/wallet-adapter-react'
|
|
7
7
|
import { useEffect } from 'react'
|
|
8
|
-
import {
|
|
8
|
+
import { useConfig as useWagmiConfig } from 'wagmi'
|
|
9
9
|
import {
|
|
10
10
|
getConnectorClient as getWagmiConnectorClient,
|
|
11
11
|
switchChain,
|
|
12
12
|
} from 'wagmi/actions'
|
|
13
13
|
import { useWidgetConfig } from '../WidgetProvider/WidgetProvider.js'
|
|
14
|
-
import { getSafeMultisigConfig } from './getSafeMultisigConfig.js'
|
|
15
14
|
|
|
16
15
|
export const SDKProviders = () => {
|
|
17
16
|
const { sdkConfig } = useWidgetConfig()
|
|
18
17
|
const { wallet } = useWallet()
|
|
19
18
|
const wagmiConfig = useWagmiConfig()
|
|
20
19
|
const bigmiConfig = useBigmiConfig()
|
|
21
|
-
const account = useAccount({ config: wagmiConfig })
|
|
22
20
|
|
|
23
21
|
useEffect(() => {
|
|
24
22
|
// Configure SDK Providers
|
|
@@ -33,11 +31,6 @@ export const SDKProviders = () => {
|
|
|
33
31
|
(provider) => provider.type === ChainType.UTXO
|
|
34
32
|
)
|
|
35
33
|
if (!hasConfiguredEVMProvider) {
|
|
36
|
-
// TODO: refactor this in favor of EIP-5792: Wallet Call API
|
|
37
|
-
const multisig =
|
|
38
|
-
account.connector?.id === 'safe'
|
|
39
|
-
? getSafeMultisigConfig(account.connector)
|
|
40
|
-
: undefined
|
|
41
34
|
providers.push(
|
|
42
35
|
EVM({
|
|
43
36
|
getWalletClient: () => getWagmiConnectorClient(wagmiConfig),
|
|
@@ -45,7 +38,6 @@ export const SDKProviders = () => {
|
|
|
45
38
|
const chain = await switchChain(wagmiConfig, { chainId })
|
|
46
39
|
return getWagmiConnectorClient(wagmiConfig, { chainId: chain.id })
|
|
47
40
|
},
|
|
48
|
-
multisig,
|
|
49
41
|
})
|
|
50
42
|
)
|
|
51
43
|
}
|
|
@@ -69,13 +61,7 @@ export const SDKProviders = () => {
|
|
|
69
61
|
providers.push(...sdkConfig.providers)
|
|
70
62
|
}
|
|
71
63
|
config.setProviders(providers)
|
|
72
|
-
}, [
|
|
73
|
-
account.connector,
|
|
74
|
-
bigmiConfig,
|
|
75
|
-
sdkConfig?.providers,
|
|
76
|
-
wagmiConfig,
|
|
77
|
-
wallet?.adapter,
|
|
78
|
-
])
|
|
64
|
+
}, [bigmiConfig, sdkConfig?.providers, wagmiConfig, wallet?.adapter])
|
|
79
65
|
|
|
80
66
|
return null
|
|
81
67
|
}
|
package/src/types/widget.ts
CHANGED
|
@@ -95,6 +95,7 @@ export enum HiddenUI {
|
|
|
95
95
|
WalletMenu = 'walletMenu',
|
|
96
96
|
IntegratorStepDetails = 'integratorStepDetails',
|
|
97
97
|
ReverseTokensButton = 'reverseTokensButton',
|
|
98
|
+
RouteTokenDescription = 'routeTokenDescription',
|
|
98
99
|
}
|
|
99
100
|
export type HiddenUIType = `${HiddenUI}`
|
|
100
101
|
|
|
@@ -245,6 +246,7 @@ export interface WidgetConfig {
|
|
|
245
246
|
hiddenUI?: HiddenUIType[]
|
|
246
247
|
requiredUI?: RequiredUIType[]
|
|
247
248
|
useRecommendedRoute?: boolean
|
|
249
|
+
useRelayerRoutes?: boolean
|
|
248
250
|
|
|
249
251
|
walletConfig?: WidgetWalletConfig
|
|
250
252
|
sdkConfig?: WidgetSDKConfig
|