0xtrails 0.4.3 → 0.6.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/analytics.d.ts +8 -3
- package/dist/analytics.d.ts.map +1 -1
- package/dist/{ccip-C9CA3tIi.js → ccip-Dw5AN7oU.js} +27 -27
- package/dist/cctp.d.ts +0 -149
- package/dist/cctp.d.ts.map +1 -1
- package/dist/chains.d.ts +31 -4
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +28 -52
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -7
- package/dist/constants.d.ts.map +1 -1
- package/dist/contractUtils.d.ts.map +1 -1
- package/dist/estimate.d.ts.map +1 -1
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts +12 -0
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-CNB57v0n.js → index-BtVUTbEZ.js} +32255 -40547
- package/dist/index.d.ts +13 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +320 -944
- package/dist/indexerClient.d.ts +9 -6
- package/dist/indexerClient.d.ts.map +1 -1
- package/dist/intents.d.ts +0 -18
- package/dist/intents.d.ts.map +1 -1
- package/dist/mutations.d.ts.map +1 -1
- package/dist/paymasterSend.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/sendUserOp.d.ts +0 -18
- package/dist/sendUserOp.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +1 -1
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +10 -8
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trailsClient.d.ts +3 -3
- package/dist/trailsClient.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +4 -5
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +4 -5
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +2 -2
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/execution/transactionState.d.ts +2 -2
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +6 -4
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/index.d.ts +0 -1
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +4 -34
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +2 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +7 -19
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/transactionIntent/utils/index.d.ts +0 -1
- package/dist/transactionIntent/utils/index.d.ts.map +1 -1
- package/dist/transactions.d.ts +6 -18
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +8 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/walletUtils.d.ts +21 -0
- package/dist/walletUtils.d.ts.map +1 -0
- package/dist/wallets.d.ts +33 -240
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
- package/dist/widget/components/FeeOption.d.ts +8 -13
- package/dist/widget/components/FeeOption.d.ts.map +1 -1
- package/dist/widget/components/FeeOptions.d.ts +11 -5
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/NativeGasOption.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeDeposit.d.ts +5 -0
- package/dist/widget/components/QRCodeDeposit.d.ts.map +1 -1
- package/dist/widget/components/QRCodeWalletSelect.d.ts +13 -0
- package/dist/widget/components/QRCodeWalletSelect.d.ts.map +1 -0
- package/dist/widget/components/QrCode.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts +1 -0
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/Toast.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useCheckout.d.ts +15 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
- package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
- package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts +7 -0
- package/dist/widget/hooks/useIsConnectedWalletSmartContract.d.ts.map +1 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts +6 -0
- package/dist/widget/hooks/useIsSequenceWallet.d.ts.map +1 -0
- package/dist/widget/hooks/useQuote.d.ts +6 -11
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
- package/dist/widget/hooks/useSelectedFeeOption.d.ts +30 -0
- package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +6 -15
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.d.ts +1 -0
- package/dist/widget/index.d.ts.map +1 -1
- package/dist/widget/index.js +4 -2
- package/dist/widget/providers/TrailsProvider.d.ts +29 -0
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -0
- package/dist/widget/widget.d.ts +14 -3
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +9 -8
- package/src/analytics.ts +53 -21
- package/src/cctp.ts +0 -1016
- package/src/chains.ts +155 -68
- package/src/config.ts +51 -207
- package/src/constants.ts +1 -13
- package/src/contractUtils.ts +6 -6
- package/src/estimate.ts +3 -6
- package/src/fees.ts +5 -10
- package/src/gasless.ts +45 -0
- package/src/index.ts +18 -40
- package/src/indexerClient.ts +39 -48
- package/src/intents.ts +51 -226
- package/src/mutations.ts +3 -2
- package/src/paymasterSend.ts +2 -5
- package/src/prepareSend.ts +21 -14
- package/src/sendUserOp.ts +3 -64
- package/src/sequenceWallet.ts +1 -2
- package/src/tokenBalances.ts +2 -1
- package/src/tokens.ts +62 -133
- package/src/trailsClient.ts +17 -12
- package/src/transactionIntent/deposits/depositOrchestrator.ts +14 -15
- package/src/transactionIntent/deposits/gaslessDeposit.ts +70 -100
- package/src/transactionIntent/deposits/standardDeposit.ts +22 -28
- package/src/transactionIntent/execution/transactionState.ts +2 -2
- package/src/transactionIntent/handlers/crossChain.ts +179 -381
- package/src/transactionIntent/handlers/index.ts +0 -1
- package/src/transactionIntent/handlers/sameChainSameToken.ts +228 -94
- package/src/transactionIntent/quote/normalizeQuote.ts +4 -6
- package/src/transactionIntent/quote/quoteHelpers.ts +35 -3
- package/src/transactionIntent/types.ts +7 -27
- package/src/transactionIntent/utils/index.ts +0 -1
- package/src/transactions.ts +19 -118
- package/src/umd.tsx +1 -3
- package/src/utils.ts +28 -8
- package/src/walletUtils.ts +42 -0
- package/src/wallets.ts +365 -208
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +78 -4
- package/src/widget/components/AccountSettings.tsx +17 -17
- package/src/widget/components/ChainList.tsx +3 -3
- package/src/widget/components/ClassicSwap.tsx +19 -10
- package/src/widget/components/ConfigDisplay.tsx +19 -59
- package/src/widget/components/FeeOption.tsx +63 -20
- package/src/widget/components/FeeOptions.tsx +54 -123
- package/src/widget/components/NativeGasOption.tsx +3 -1
- package/src/widget/components/Pay.tsx +18 -11
- package/src/widget/components/PoolDeposit.tsx +23 -10
- package/src/widget/components/QRCodeDeposit.tsx +50 -30
- package/src/widget/components/QRCodeWalletSelect.tsx +77 -0
- package/src/widget/components/QrCode.tsx +188 -233
- package/src/widget/components/QuoteDetails.tsx +48 -2
- package/src/widget/components/Receipt.tsx +5 -2
- package/src/widget/components/ScreenHeader.tsx +10 -8
- package/src/widget/components/SlippageToleranceSettings.tsx +63 -14
- package/src/widget/components/Toast.tsx +10 -0
- package/src/widget/components/TokenImage.tsx +56 -13
- package/src/widget/components/WalletConnect.tsx +37 -99
- package/src/widget/hooks/useCheckout.ts +71 -0
- package/src/widget/hooks/useCurrentScreen.tsx +1 -0
- package/src/widget/hooks/useDebugScreens.ts +5 -0
- package/src/widget/hooks/useIntentTransactionHistory.ts +790 -412
- package/src/widget/hooks/useIsConnectedWalletSmartContract.ts +43 -0
- package/src/widget/hooks/useIsSequenceWallet.ts +17 -0
- package/src/widget/hooks/useQuote.ts +27 -34
- package/src/widget/hooks/useRecentTokens.ts +2 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +257 -0
- package/src/widget/hooks/useSendForm.ts +175 -46
- package/src/widget/hooks/useTokenList.ts +15 -2
- package/src/widget/index.tsx +8 -0
- package/src/widget/providers/TrailsProvider.tsx +123 -0
- package/src/widget/widget.tsx +165 -143
- package/dist/cctpqueue.d.ts +0 -18
- package/dist/cctpqueue.d.ts.map +0 -1
- package/dist/preconditions.d.ts +0 -12
- package/dist/preconditions.d.ts.map +0 -1
- package/dist/trails.d.ts +0 -110
- package/dist/trails.d.ts.map +0 -1
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +0 -62
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +0 -1
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +0 -10
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +0 -1
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +0 -33
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +0 -1
- package/src/cctpqueue.ts +0 -66
- package/src/preconditions.ts +0 -47
- package/src/trails.ts +0 -1303
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +0 -323
- package/src/transactionIntent/utils/lifiHelpers.ts +0 -68
- package/src/widget/hooks/useSelectedFeeToken.tsx +0 -288
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { useAccount } from "wagmi"
|
|
3
|
+
import { isSmartContractWallet as checkIsSmartContractWallet } from "../../walletUtils.js"
|
|
4
|
+
import { logger } from "../../logger.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Hook to check if the currently connected wallet is a smart contract.
|
|
8
|
+
* @param chainId - The chain ID to check the wallet on
|
|
9
|
+
* @returns true if the connected wallet is a smart contract, false otherwise
|
|
10
|
+
*/
|
|
11
|
+
export function useIsConnectedWalletSmartContract(chainId?: number): boolean {
|
|
12
|
+
const { address } = useAccount()
|
|
13
|
+
const [isSmartContractWallet, setIsSmartContractWallet] = useState(false)
|
|
14
|
+
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const checkIfContract = async () => {
|
|
17
|
+
if (address && chainId) {
|
|
18
|
+
try {
|
|
19
|
+
const isContract = await checkIsSmartContractWallet(address, chainId)
|
|
20
|
+
setIsSmartContractWallet(isContract)
|
|
21
|
+
} catch (error) {
|
|
22
|
+
logger.console.error(
|
|
23
|
+
"[trails-sdk] Error checking if wallet is contract:",
|
|
24
|
+
error,
|
|
25
|
+
)
|
|
26
|
+
setIsSmartContractWallet(false)
|
|
27
|
+
}
|
|
28
|
+
} else {
|
|
29
|
+
setIsSmartContractWallet(false)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
checkIfContract()
|
|
34
|
+
}, [address, chainId])
|
|
35
|
+
|
|
36
|
+
logger.console.log("[trails-sdk] isSmartContractWallet:", {
|
|
37
|
+
isSmartContractWallet,
|
|
38
|
+
address,
|
|
39
|
+
chainId,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
return isSmartContractWallet
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useMemo } from "react"
|
|
2
|
+
import { useAccount } from "wagmi"
|
|
3
|
+
import { isSequenceWallet as checkIsSequenceWallet } from "../../walletUtils.js"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Hook to check if the currently connected wallet is a Sequence wallet.
|
|
7
|
+
* @returns true if the connected wallet is a Sequence wallet, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
export function useIsSequenceWallet(): boolean {
|
|
10
|
+
const { connector } = useAccount()
|
|
11
|
+
|
|
12
|
+
const isSequenceWallet = useMemo(() => {
|
|
13
|
+
return checkIsSequenceWallet(connector)
|
|
14
|
+
}, [connector])
|
|
15
|
+
|
|
16
|
+
return isSequenceWallet
|
|
17
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQuery } from "@tanstack/react-query"
|
|
2
|
-
import { useRef
|
|
2
|
+
import { useRef } from "react"
|
|
3
3
|
import type { TransactionReceipt } from "viem"
|
|
4
4
|
import { zeroAddress } from "viem"
|
|
5
5
|
import { useIndexerGatewayClient } from "../../indexerClient.js"
|
|
@@ -7,26 +7,23 @@ import { getTokenBalancesWithPrices } from "../../tokenBalances.js"
|
|
|
7
7
|
import { logger } from "../../logger.js"
|
|
8
8
|
import { useSupportedTokens } from "../../tokens.js"
|
|
9
9
|
import { useTrailsClient } from "../../trailsClient.js"
|
|
10
|
+
import { useTrails } from "../../widget/providers/TrailsProvider.js"
|
|
10
11
|
import { getExplorerUrl } from "../../explorer.js"
|
|
11
12
|
import { getFullErrorMessage, getPrettifiedErrorMessage } from "../../error.js"
|
|
12
13
|
import { prepareSend } from "../../prepareSend.js"
|
|
13
14
|
import { abortControllerRegistry } from "../../abortController.js"
|
|
14
15
|
import { TradeType } from "../../prepareSend.js"
|
|
15
16
|
import { getChainInfo } from "../../chains.js"
|
|
16
|
-
import type {
|
|
17
|
-
import type {
|
|
18
|
-
import type {
|
|
19
|
-
MetaTxnReceipt,
|
|
20
|
-
PrepareSendOptions,
|
|
21
|
-
} from "../../transactionIntent/types.js"
|
|
17
|
+
import type { IntentTransaction } from "@0xsequence/trails-api"
|
|
18
|
+
import type { PrepareSendOptions } from "../../transactionIntent/types.js"
|
|
22
19
|
import type { Chain } from "../../chains.js"
|
|
23
20
|
import type { SupportedToken } from "../../tokens.js"
|
|
24
21
|
import type { TransactionState } from "../../transactions.js"
|
|
25
22
|
import type { PrepareSendFees } from "../../prepareSend.js"
|
|
26
|
-
import type { SequenceEnv } from "../../config.js"
|
|
27
23
|
import { getTokenPrice } from "../../prices.js"
|
|
28
24
|
import { useCommitIntent, useExecuteIntent } from "../../mutations.js"
|
|
29
25
|
import type { CheckoutOnHandlers } from "./useCheckout.js"
|
|
26
|
+
import type { FeeOption } from "@0xsequence/trails-api"
|
|
30
27
|
|
|
31
28
|
export type UseQuoteProps = {
|
|
32
29
|
walletClient?: any // TODO: fix this, has to do with viem/wagmi versions
|
|
@@ -71,24 +68,22 @@ export type UseQuoteProps = {
|
|
|
71
68
|
*/
|
|
72
69
|
checkoutOnHandlers?: Partial<CheckoutOnHandlers>
|
|
73
70
|
paymasterUrl?: string
|
|
74
|
-
|
|
75
|
-
tokenAddress: string
|
|
76
|
-
tokenSymbol?: string
|
|
77
|
-
} | null
|
|
71
|
+
selectedFeeOption?: FeeOption | null
|
|
78
72
|
abortSignal?: AbortSignal
|
|
79
73
|
apiKey?: string | null
|
|
74
|
+
nodeGatewayEnv?: "prod" | "dev" | "local" | "cors-anywhere"
|
|
80
75
|
}
|
|
81
76
|
|
|
82
77
|
export type SwapReturn = {
|
|
83
78
|
originTransaction: {
|
|
84
79
|
transactionHash?: string | null
|
|
85
80
|
explorerUrl?: string | null
|
|
86
|
-
receipt: TransactionReceipt |
|
|
81
|
+
receipt: TransactionReceipt | IntentTransaction | null
|
|
87
82
|
}
|
|
88
83
|
destinationTransaction: {
|
|
89
84
|
transactionHash?: string | null
|
|
90
85
|
explorerUrl?: string | null
|
|
91
|
-
receipt:
|
|
86
|
+
receipt: IntentTransaction | null
|
|
92
87
|
}
|
|
93
88
|
totalCompletionSeconds?: number
|
|
94
89
|
}
|
|
@@ -150,13 +145,11 @@ export function useQuote({
|
|
|
150
145
|
checkoutOnHandlers,
|
|
151
146
|
quoteProvider,
|
|
152
147
|
paymasterUrl,
|
|
153
|
-
|
|
148
|
+
selectedFeeOption,
|
|
154
149
|
nodeGatewayEnv,
|
|
155
150
|
abortSignal: externalAbortSignal,
|
|
156
151
|
apiKey,
|
|
157
|
-
}: Partial<
|
|
158
|
-
UseQuoteProps & { nodeGatewayEnv?: SequenceEnv }
|
|
159
|
-
> = {}): UseQuoteReturn {
|
|
152
|
+
}: Partial<UseQuoteProps> = {}): UseQuoteReturn {
|
|
160
153
|
// Set node gateway environment override for this quote session
|
|
161
154
|
if (nodeGatewayEnv) {
|
|
162
155
|
;(globalThis as any).__testNodeGatewayEnv = nodeGatewayEnv
|
|
@@ -185,17 +178,15 @@ export function useQuote({
|
|
|
185
178
|
})()
|
|
186
179
|
: abortControllerRef.current.signal
|
|
187
180
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const indexerGatewayClientConfig = useMemo<IndexerGatewayConfig>(() => {
|
|
192
|
-
return apiKey ? { projectAccessKey: apiKey } : {}
|
|
193
|
-
}, [apiKey])
|
|
181
|
+
const { trailsApiKey, trailsApiUrl, sequenceIndexerUrl } = useTrails()
|
|
182
|
+
// trailsApiKey is the same as sequenceProjectAccessKey
|
|
183
|
+
const sequenceProjectAccessKey = trailsApiKey
|
|
194
184
|
|
|
195
|
-
const trailsClient = useTrailsClient(
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
185
|
+
const trailsClient = useTrailsClient({
|
|
186
|
+
apiKey: trailsApiKey,
|
|
187
|
+
hostname: trailsApiUrl,
|
|
188
|
+
})
|
|
189
|
+
const indexerGatewayClient = useIndexerGatewayClient()
|
|
199
190
|
|
|
200
191
|
const { supportedTokens } = useSupportedTokens()
|
|
201
192
|
|
|
@@ -382,12 +373,14 @@ export function useQuote({
|
|
|
382
373
|
slippageTolerance: slippageTolerance?.toString(),
|
|
383
374
|
quoteProvider: quoteProvider,
|
|
384
375
|
paymasterUrl: paymasterUrl,
|
|
385
|
-
|
|
376
|
+
selectedFeeOption: selectedFeeOption ?? null,
|
|
386
377
|
abortSignal: combinedAbortSignal,
|
|
387
378
|
originNativeTokenPriceUsd: originNativeTokenPriceUsd,
|
|
388
379
|
commitIntentFn: commitIntentMutation.mutateAsync,
|
|
389
380
|
executeIntentFn: executeIntentMutation.mutateAsync,
|
|
390
381
|
checkoutOnHandlers,
|
|
382
|
+
sequenceIndexerUrl,
|
|
383
|
+
sequenceProjectAccessKey,
|
|
391
384
|
}
|
|
392
385
|
|
|
393
386
|
logger.console.log("[trails-sdk] options", options)
|
|
@@ -424,10 +417,10 @@ export function useQuote({
|
|
|
424
417
|
const swap = async (): Promise<SwapReturn> => {
|
|
425
418
|
const {
|
|
426
419
|
depositUserTxnReceipt,
|
|
427
|
-
|
|
420
|
+
destinationIntentTransaction,
|
|
428
421
|
totalCompletionSeconds,
|
|
429
422
|
} = await send({
|
|
430
|
-
|
|
423
|
+
selectedFeeOption: selectedFeeOption ?? null,
|
|
431
424
|
})
|
|
432
425
|
|
|
433
426
|
return {
|
|
@@ -440,12 +433,12 @@ export function useQuote({
|
|
|
440
433
|
receipt: depositUserTxnReceipt,
|
|
441
434
|
},
|
|
442
435
|
destinationTransaction: {
|
|
443
|
-
transactionHash:
|
|
436
|
+
transactionHash: destinationIntentTransaction?.txnHash,
|
|
444
437
|
explorerUrl: getExplorerUrl({
|
|
445
|
-
txHash:
|
|
438
|
+
txHash: destinationIntentTransaction?.txnHash as string,
|
|
446
439
|
chainId: toChainId,
|
|
447
440
|
}),
|
|
448
|
-
receipt:
|
|
441
|
+
receipt: destinationIntentTransaction,
|
|
449
442
|
},
|
|
450
443
|
totalCompletionSeconds,
|
|
451
444
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { JsonEncode } from "@0xsequence/trails-api"
|
|
1
2
|
import { useState, useEffect, useCallback } from "react"
|
|
2
3
|
import type { SupportedToken } from "../../tokens.js"
|
|
3
4
|
import { logger } from "../../logger.js"
|
|
@@ -66,7 +67,7 @@ export function useRecentTokens(accountAddress?: string) {
|
|
|
66
67
|
|
|
67
68
|
// Update storage
|
|
68
69
|
allRecentTokens[accountKey] = accountTokens
|
|
69
|
-
localStorage.setItem(RECENT_TOKENS_KEY,
|
|
70
|
+
localStorage.setItem(RECENT_TOKENS_KEY, JsonEncode(allRecentTokens))
|
|
70
71
|
|
|
71
72
|
// Update state
|
|
72
73
|
setRecentTokens(accountTokens)
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useContext,
|
|
4
|
+
useState,
|
|
5
|
+
useCallback,
|
|
6
|
+
useEffect,
|
|
7
|
+
useMemo,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from "react"
|
|
10
|
+
import type { FeeOption } from "@0xsequence/trails-api"
|
|
11
|
+
import { formatRawAmount, formatUsdAmountDisplay } from "../../tokenBalances.js"
|
|
12
|
+
import { logger } from "../../index.js"
|
|
13
|
+
import { isNativeToken, normalizeAddress } from "../../utils.js"
|
|
14
|
+
import { isAddressEqual } from "viem"
|
|
15
|
+
|
|
16
|
+
const createBalanceKey = (
|
|
17
|
+
chainId?: number,
|
|
18
|
+
tokenAddress?: string | null,
|
|
19
|
+
): string =>
|
|
20
|
+
`${chainId ?? "unknown"}:${
|
|
21
|
+
!tokenAddress || isNativeToken(tokenAddress)
|
|
22
|
+
? "native"
|
|
23
|
+
: normalizeAddress(tokenAddress)
|
|
24
|
+
}`
|
|
25
|
+
|
|
26
|
+
const safeFormatAmountWithSymbol = (option: FeeOption): string => {
|
|
27
|
+
const tokenDecimals =
|
|
28
|
+
typeof option.tokenDecimals === "number" &&
|
|
29
|
+
option.tokenDecimals > 0 &&
|
|
30
|
+
option.tokenDecimals <= 18
|
|
31
|
+
? option.tokenDecimals
|
|
32
|
+
: isNativeToken(option.tokenAddress)
|
|
33
|
+
? 18
|
|
34
|
+
: undefined
|
|
35
|
+
|
|
36
|
+
if (tokenDecimals === undefined) {
|
|
37
|
+
logger.console.warn("[trails-sdk] [FEE-OPTIONS] Missing token decimals", {
|
|
38
|
+
tokenAddress: option.tokenAddress,
|
|
39
|
+
tokenSymbol: option.tokenSymbol,
|
|
40
|
+
})
|
|
41
|
+
return option.tokenSymbol ? `-- ${option.tokenSymbol}` : "--"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const formattedAmount = formatRawAmount(option.amount, tokenDecimals)
|
|
46
|
+
return option.tokenSymbol
|
|
47
|
+
? `${formattedAmount} ${option.tokenSymbol}`
|
|
48
|
+
: formattedAmount
|
|
49
|
+
} catch (error) {
|
|
50
|
+
logger.console.warn(
|
|
51
|
+
"[trails-sdk] [FEE-OPTIONS] Failed to format fee option amount",
|
|
52
|
+
{
|
|
53
|
+
option,
|
|
54
|
+
tokenDecimals,
|
|
55
|
+
error,
|
|
56
|
+
},
|
|
57
|
+
)
|
|
58
|
+
return option.tokenSymbol ? `-- ${option.tokenSymbol}` : "--"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ProcessedFeeOption = FeeOption & {
|
|
63
|
+
notEnoughBalance?: boolean
|
|
64
|
+
tokenImageUrl?: string
|
|
65
|
+
chainId?: number
|
|
66
|
+
amountFormatted: string
|
|
67
|
+
amountUsdDisplay?: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Token type with balance information
|
|
71
|
+
export interface TokenWithBalance {
|
|
72
|
+
chainId: number
|
|
73
|
+
contractAddress?: string
|
|
74
|
+
balance?: string
|
|
75
|
+
imageUrl?: string
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface SelectedFeeOptionContextType {
|
|
79
|
+
selectedFeeOption: FeeOption | null
|
|
80
|
+
setSelectedFeeOption: (token: FeeOption | null) => void
|
|
81
|
+
clearSelectedFeeOption: () => void
|
|
82
|
+
processedFeeOptions: ProcessedFeeOption[]
|
|
83
|
+
setFeeOptions: (
|
|
84
|
+
feeOptions: ReadonlyArray<FeeOption> | null | undefined,
|
|
85
|
+
originChainId: number | undefined,
|
|
86
|
+
availableTokens: TokenWithBalance[],
|
|
87
|
+
) => void
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const SelectedFeeOptionContext = createContext<
|
|
91
|
+
SelectedFeeOptionContextType | undefined
|
|
92
|
+
>(undefined)
|
|
93
|
+
|
|
94
|
+
interface SelectedFeeOptionProviderProps {
|
|
95
|
+
children: ReactNode
|
|
96
|
+
initialToken?: FeeOption | null
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const SelectedFeeOptionProvider: React.FC<
|
|
100
|
+
SelectedFeeOptionProviderProps
|
|
101
|
+
> = ({ children, initialToken = null }) => {
|
|
102
|
+
const [selectedFeeOption, setSelectedFeeOptionInternalRaw] =
|
|
103
|
+
useState<FeeOption | null>(initialToken)
|
|
104
|
+
const [hasUserSelectedFeeOption, setHasUserSelectedFeeOption] =
|
|
105
|
+
useState(false)
|
|
106
|
+
const [feeOptions, setFeeOptionsInternal] = useState<FeeOption[]>([])
|
|
107
|
+
const [originTokenChainId, setOriginTokenChainId] = useState<
|
|
108
|
+
number | undefined
|
|
109
|
+
>(undefined)
|
|
110
|
+
const [availableTokens, setAvailableTokens] = useState<TokenWithBalance[]>([])
|
|
111
|
+
|
|
112
|
+
const tokenBalanceLookup = useMemo(() => {
|
|
113
|
+
const map = new Map<string, TokenWithBalance>()
|
|
114
|
+
for (const token of availableTokens) {
|
|
115
|
+
map.set(
|
|
116
|
+
createBalanceKey(token.chainId, token.contractAddress ?? null),
|
|
117
|
+
token,
|
|
118
|
+
)
|
|
119
|
+
}
|
|
120
|
+
return map
|
|
121
|
+
}, [availableTokens])
|
|
122
|
+
|
|
123
|
+
// Wrapper to track when user makes an explicit selection
|
|
124
|
+
const setSelectedFeeOption = useCallback((token: FeeOption | null) => {
|
|
125
|
+
setSelectedFeeOptionInternalRaw(token)
|
|
126
|
+
setHasUserSelectedFeeOption(true)
|
|
127
|
+
}, [])
|
|
128
|
+
|
|
129
|
+
const clearSelectedFeeOption = useCallback(() => {
|
|
130
|
+
setSelectedFeeOptionInternalRaw(null)
|
|
131
|
+
setHasUserSelectedFeeOption(false)
|
|
132
|
+
}, [])
|
|
133
|
+
|
|
134
|
+
// Process raw fee options with balance checks
|
|
135
|
+
const processedFeeOptions: ProcessedFeeOption[] = useMemo(() => {
|
|
136
|
+
if (!feeOptions.length) {
|
|
137
|
+
return []
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return feeOptions
|
|
141
|
+
.map((option) => {
|
|
142
|
+
const balanceRecord =
|
|
143
|
+
originTokenChainId !== undefined
|
|
144
|
+
? tokenBalanceLookup.get(
|
|
145
|
+
createBalanceKey(originTokenChainId, option.tokenAddress),
|
|
146
|
+
)
|
|
147
|
+
: undefined
|
|
148
|
+
|
|
149
|
+
const hasBalanceInfo =
|
|
150
|
+
Boolean(balanceRecord?.balance) && originTokenChainId !== undefined
|
|
151
|
+
const userBalance = balanceRecord?.balance ?? "0"
|
|
152
|
+
const requiredAmount = option.amount ? option.amount.toString() : "0"
|
|
153
|
+
const notEnoughBalance = hasBalanceInfo
|
|
154
|
+
? BigInt(userBalance) < BigInt(requiredAmount)
|
|
155
|
+
: true
|
|
156
|
+
const amountFormatted = safeFormatAmountWithSymbol(option)
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
...option,
|
|
160
|
+
notEnoughBalance,
|
|
161
|
+
tokenImageUrl: balanceRecord?.imageUrl,
|
|
162
|
+
chainId: balanceRecord?.chainId ?? originTokenChainId,
|
|
163
|
+
amountUsdDisplay: formatUsdAmountDisplay(option.amountUsd ?? 0),
|
|
164
|
+
amountFormatted,
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
.sort(
|
|
168
|
+
(a, b) => Number(!!a.notEnoughBalance) - Number(!!b.notEnoughBalance),
|
|
169
|
+
)
|
|
170
|
+
}, [feeOptions, originTokenChainId, tokenBalanceLookup])
|
|
171
|
+
|
|
172
|
+
// Auto-select first fee option (ERC20 or native gas) with sufficient balance
|
|
173
|
+
// NOTE: If sufficient balance, it will usually resolve to the native gas option because native gas is the first option in the list returned by the API
|
|
174
|
+
useEffect(() => {
|
|
175
|
+
if (processedFeeOptions.length === 0) {
|
|
176
|
+
if (selectedFeeOption !== null) {
|
|
177
|
+
setSelectedFeeOptionInternalRaw(null)
|
|
178
|
+
setHasUserSelectedFeeOption(false)
|
|
179
|
+
}
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const selectionStillValid = selectedFeeOption
|
|
184
|
+
? processedFeeOptions.some((option) =>
|
|
185
|
+
isAddressEqual(
|
|
186
|
+
option.tokenAddress as `0x${string}`,
|
|
187
|
+
selectedFeeOption.tokenAddress as `0x${string}`,
|
|
188
|
+
),
|
|
189
|
+
)
|
|
190
|
+
: false
|
|
191
|
+
|
|
192
|
+
if (selectedFeeOption && !selectionStillValid) {
|
|
193
|
+
setSelectedFeeOptionInternalRaw(null)
|
|
194
|
+
setHasUserSelectedFeeOption(false)
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (!hasUserSelectedFeeOption && !selectedFeeOption) {
|
|
199
|
+
const fallbackOption =
|
|
200
|
+
processedFeeOptions.find((option) => !option.notEnoughBalance) ??
|
|
201
|
+
processedFeeOptions[0] ??
|
|
202
|
+
null
|
|
203
|
+
|
|
204
|
+
// Only fallback if the fallback option is erc20
|
|
205
|
+
if (fallbackOption && !isNativeToken(fallbackOption.tokenAddress)) {
|
|
206
|
+
setSelectedFeeOptionInternalRaw(fallbackOption)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}, [processedFeeOptions, selectedFeeOption, hasUserSelectedFeeOption])
|
|
210
|
+
|
|
211
|
+
// Function to set raw fee options and process them
|
|
212
|
+
const setFeeOptions = useCallback(
|
|
213
|
+
(
|
|
214
|
+
feeOptions: ReadonlyArray<FeeOption> | null | undefined,
|
|
215
|
+
originChainId: number | undefined,
|
|
216
|
+
tokens: TokenWithBalance[],
|
|
217
|
+
) => {
|
|
218
|
+
const normalized = feeOptions ? [...feeOptions] : []
|
|
219
|
+
|
|
220
|
+
setFeeOptionsInternal(normalized)
|
|
221
|
+
setOriginTokenChainId(originChainId)
|
|
222
|
+
setAvailableTokens(tokens)
|
|
223
|
+
|
|
224
|
+
if (normalized.length === 0) {
|
|
225
|
+
setSelectedFeeOptionInternalRaw(null)
|
|
226
|
+
setHasUserSelectedFeeOption(false)
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
[],
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
const value: SelectedFeeOptionContextType = {
|
|
233
|
+
selectedFeeOption,
|
|
234
|
+
setSelectedFeeOption,
|
|
235
|
+
clearSelectedFeeOption,
|
|
236
|
+
processedFeeOptions,
|
|
237
|
+
setFeeOptions,
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<SelectedFeeOptionContext.Provider value={value}>
|
|
242
|
+
{children}
|
|
243
|
+
</SelectedFeeOptionContext.Provider>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export const useSelectedFeeOption = (): SelectedFeeOptionContextType => {
|
|
248
|
+
const context = useContext(SelectedFeeOptionContext)
|
|
249
|
+
|
|
250
|
+
if (context === undefined) {
|
|
251
|
+
throw new Error(
|
|
252
|
+
"useSelectedFeeOption must be used within a SelectedFeeOptionProvider",
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return context
|
|
257
|
+
}
|