0xtrails 0.1.2 → 0.1.4
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/address.d.ts.map +1 -1
- package/dist/analytics.d.ts +86 -1
- package/dist/analytics.d.ts.map +1 -1
- package/dist/apiClient.d.ts +1 -1
- package/dist/apiClient.d.ts.map +1 -1
- package/dist/{ccip-BmFTEOaB.js → ccip-dLSEJjCf.js} +55 -55
- package/dist/cctpqueue.d.ts +1 -1
- package/dist/cctpqueue.d.ts.map +1 -1
- package/dist/chains.d.ts +9 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/decoders.d.ts +58 -0
- package/dist/decoders.d.ts.map +1 -0
- package/dist/ens.d.ts +13 -0
- package/dist/ens.d.ts.map +1 -0
- package/dist/error.d.ts +9 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-BPsVj7zK.js → index-BXbaLmtt.js} +28779 -25738
- package/dist/index.js +2 -2
- package/dist/intents.d.ts +4 -4
- package/dist/intents.d.ts.map +1 -1
- package/dist/lifi.d.ts +4 -0
- package/dist/lifi.d.ts.map +1 -0
- package/dist/metaTxns.d.ts +1 -1
- package/dist/metaTxns.d.ts.map +1 -1
- package/dist/mode.d.ts +1 -1
- package/dist/mode.d.ts.map +1 -1
- package/dist/preconditions.d.ts +1 -1
- package/dist/preconditions.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +32 -24
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +3 -1
- package/dist/prices.d.ts.map +1 -1
- package/dist/proxyCaller.d.ts +0 -1
- package/dist/proxyCaller.d.ts.map +1 -1
- package/dist/relaySdk.d.ts.map +1 -1
- package/dist/relayer.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +2 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +4 -4
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactions.d.ts +4 -0
- package/dist/transactions.d.ts.map +1 -1
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/wallets.d.ts +247 -5
- package/dist/wallets.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts +2 -0
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts +1 -0
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/DebugScreensDropdown.d.ts.map +1 -1
- package/dist/widget/components/ErrorDisplay.d.ts +9 -0
- package/dist/widget/components/ErrorDisplay.d.ts.map +1 -0
- package/dist/widget/components/FundSendForm.d.ts +2 -2
- package/dist/widget/components/FundSendForm.d.ts.map +1 -1
- package/dist/widget/components/OriginTransferInformation.d.ts +10 -0
- package/dist/widget/components/OriginTransferInformation.d.ts.map +1 -0
- package/dist/widget/components/PaySendForm.d.ts +2 -2
- package/dist/widget/components/PaySendForm.d.ts.map +1 -1
- package/dist/widget/components/QrCode.d.ts +1 -1
- 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/Receive.d.ts +12 -0
- package/dist/widget/components/Receive.d.ts.map +1 -0
- package/dist/widget/components/RefundAddressInput.d.ts +13 -0
- package/dist/widget/components/RefundAddressInput.d.ts.map +1 -0
- package/dist/widget/components/Swap.d.ts +47 -0
- package/dist/widget/components/Swap.d.ts.map +1 -0
- package/dist/widget/components/SwapDisplay.d.ts +9 -0
- package/dist/widget/components/SwapDisplay.d.ts.map +1 -0
- package/dist/widget/components/TokenList.d.ts +0 -2
- package/dist/widget/components/TokenList.d.ts.map +1 -1
- package/dist/widget/components/TokenSelector.d.ts +26 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts +2 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/components/WalletConnectionPending.d.ts +12 -0
- package/dist/widget/components/WalletConnectionPending.d.ts.map +1 -0
- package/dist/widget/components/WalletList.d.ts.map +1 -1
- package/dist/widget/components/YellowWarningAnimation.d.ts +2 -0
- package/dist/widget/components/YellowWarningAnimation.d.ts.map +1 -0
- package/dist/widget/hooks/useAmountUsd.d.ts +1 -3
- package/dist/widget/hooks/useAmountUsd.d.ts.map +1 -1
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useDebugScreens.d.ts +22 -0
- package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -0
- package/dist/widget/hooks/useSendForm.d.ts +12 -6
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts +2 -3
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +19 -15
- package/src/aave.ts +13 -13
- package/src/address.ts +3 -0
- package/src/analytics.ts +192 -8
- package/src/apiClient.ts +1 -1
- package/src/cctpqueue.ts +1 -1
- package/src/chains.ts +45 -7
- package/src/constants.ts +7 -4
- package/src/decoders.ts +310 -0
- package/src/ens.ts +32 -0
- package/src/error.ts +101 -1
- package/src/intents.ts +10 -2
- package/src/lifi.ts +58 -0
- package/src/metaTxns.ts +1 -1
- package/src/mode.ts +1 -1
- package/src/morpho.ts +3 -3
- package/src/pools.ts +18 -18
- package/src/preconditions.ts +1 -1
- package/src/prepareSend.ts +463 -113
- package/src/prices.ts +26 -1
- package/src/proxyCaller.ts +2 -14
- package/src/relaySdk.ts +1 -0
- package/src/relayer.ts +8 -0
- package/src/tokenBalances.ts +24 -17
- package/src/tokens.ts +147 -22
- package/src/trails.ts +4 -4
- package/src/transactions.ts +35 -17
- package/src/utils.ts +28 -0
- package/src/wallets.ts +275 -35
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/ChainFilterDropdown.tsx +42 -33
- package/src/widget/components/ChainImage.tsx +1 -1
- package/src/widget/components/ConnectWallet.tsx +92 -128
- package/src/widget/components/DebugScreensDropdown.tsx +6 -0
- package/src/widget/components/ErrorDisplay.tsx +150 -0
- package/src/widget/components/FundSendForm.tsx +78 -11
- package/src/widget/components/OriginTransferInformation.tsx +59 -0
- package/src/widget/components/PaySendForm.tsx +80 -13
- package/src/widget/components/QRCodeDeposit.tsx +6 -6
- package/src/widget/components/QrCode.tsx +278 -17
- package/src/widget/components/QuoteDetails.tsx +93 -25
- package/src/widget/components/Receipt.tsx +296 -103
- package/src/widget/components/Receive.tsx +146 -0
- package/src/widget/components/RecentTokens.tsx +1 -1
- package/src/widget/components/RefundAddressInput.tsx +149 -0
- package/src/widget/components/Swap.tsx +769 -0
- package/src/widget/components/SwapDisplay.tsx +68 -0
- package/src/widget/components/TokenList.tsx +27 -363
- package/src/widget/components/TokenSelector.tsx +405 -0
- package/src/widget/components/TransferPendingVertical.tsx +162 -112
- package/src/widget/components/WalletConnect.tsx +9 -7
- package/src/widget/components/WalletConnectionPending.tsx +157 -0
- package/src/widget/components/WalletList.tsx +6 -5
- package/src/widget/components/YellowWarningAnimation.tsx +146 -0
- package/src/widget/hooks/useAmountUsd.ts +3 -8
- package/src/widget/hooks/useCheckout.ts +3 -2
- package/src/widget/hooks/useDebugScreens.ts +583 -0
- package/src/widget/hooks/useSendForm.ts +111 -35
- package/src/widget/hooks/useTokenList.ts +155 -122
- package/src/widget/widget.tsx +503 -523
package/src/prices.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
SequenceAPIClient,
|
|
3
|
+
Token,
|
|
4
|
+
TokenPrice,
|
|
5
|
+
} from "@0xsequence/trails-api"
|
|
2
6
|
import { QueryClient, useQuery } from "@tanstack/react-query"
|
|
3
7
|
import { zeroAddress } from "viem"
|
|
4
8
|
|
|
@@ -204,3 +208,24 @@ export function formatTvl(tvl: number): string {
|
|
|
204
208
|
if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(1)}K`
|
|
205
209
|
return `$${tvl.toFixed(0)}`
|
|
206
210
|
}
|
|
211
|
+
|
|
212
|
+
// Helper function to validate numeric values
|
|
213
|
+
export const isValidNumeric = (
|
|
214
|
+
value: number | string | null | undefined,
|
|
215
|
+
): boolean => {
|
|
216
|
+
if (value === null || value === undefined || value === "") {
|
|
217
|
+
return true // Empty values are considered valid
|
|
218
|
+
}
|
|
219
|
+
const strValue = String(value).trim()
|
|
220
|
+
return /^\d+(\.\d+)?$/.test(strValue)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export const isValidInteger = (
|
|
224
|
+
value: number | string | null | undefined,
|
|
225
|
+
): boolean => {
|
|
226
|
+
if (value === null || value === undefined || value === "") {
|
|
227
|
+
return true // Empty values are considered valid
|
|
228
|
+
}
|
|
229
|
+
const strValue = String(value).trim()
|
|
230
|
+
return /^\d+$/.test(strValue)
|
|
231
|
+
}
|
package/src/proxyCaller.ts
CHANGED
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
import { encodeFunctionData } from "viem"
|
|
2
|
-
import
|
|
2
|
+
import { TRAILS_BALANCE_INJECTOR_ADDRESS } from "./constants.js"
|
|
3
3
|
|
|
4
4
|
export const TRAILS_CONTRACT_PLACEHOLDER_AMOUNT =
|
|
5
5
|
0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefn
|
|
6
6
|
|
|
7
|
-
const proxyCallers: Record<string, string> = {
|
|
8
|
-
[chains.base.id]: "0x4F54Dc2C6bCa2D01e066fa36f4CFdA96B544DD20",
|
|
9
|
-
[chains.arbitrum.id]: "0x8c070e800D0e0c33A0A4ceef7A91677410ed9444",
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function getProxyCallerAddress(chainId: number) {
|
|
13
|
-
return proxyCallers[chainId]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
7
|
function getAmountOffset(calldata: `0x${string}`, placeholder: bigint): number {
|
|
17
8
|
const hex = placeholder.toString(16).padStart(64, "0")
|
|
18
9
|
const search = hex.toLowerCase()
|
|
@@ -99,10 +90,7 @@ export function wrapCalldataWithProxyCallerIfNeeded({
|
|
|
99
90
|
}
|
|
100
91
|
}
|
|
101
92
|
|
|
102
|
-
const proxyCallerAddress =
|
|
103
|
-
if (!proxyCallerAddress) {
|
|
104
|
-
return null
|
|
105
|
-
}
|
|
93
|
+
const proxyCallerAddress = TRAILS_BALANCE_INJECTOR_ADDRESS
|
|
106
94
|
|
|
107
95
|
const amountOffset = getAmountOffset(
|
|
108
96
|
calldata,
|
package/src/relaySdk.ts
CHANGED
|
@@ -242,6 +242,7 @@ export const relaySupportedChains: Record<number, Chain> = {
|
|
|
242
242
|
[chains.zircuit.id]: chains.zircuit,
|
|
243
243
|
[chains.zksync.id]: chains.zksync,
|
|
244
244
|
[chains.zora.id]: chains.zora,
|
|
245
|
+
[chains.katana.id]: chains.katana,
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
export async function getRelaySupportedChains(): Promise<Chain[]> {
|
package/src/relayer.ts
CHANGED
|
@@ -162,6 +162,10 @@ export function getRelayerUrl(
|
|
|
162
162
|
relayerUrl = "https://v3-xai-relayer.sequence.app"
|
|
163
163
|
} else if (chainId === 56) {
|
|
164
164
|
relayerUrl = "https://v3-bsc-relayer.sequence.app"
|
|
165
|
+
} else if (chainId === 747474) {
|
|
166
|
+
relayerUrl = "https://v3-katana-relayer.sequence.app"
|
|
167
|
+
} else if (chainId === 42793) {
|
|
168
|
+
relayerUrl = "https://v3-etherlink-relayer.sequence.app"
|
|
165
169
|
} else {
|
|
166
170
|
// Fallback to general dev relayer for other chains if V3 is specified but chain not V3-supported
|
|
167
171
|
relayerUrl = `${baseUrl}${getChainInfo(chainId)!.name?.replace(" ", "-")}-relayer.sequence.app`
|
|
@@ -207,6 +211,10 @@ export function getRelayerUrl(
|
|
|
207
211
|
relayerUrl = "https://dev-xai-relayer.sequence.app"
|
|
208
212
|
} else if (chainId === 56) {
|
|
209
213
|
relayerUrl = "https://dev-bsc-relayer.sequence.app"
|
|
214
|
+
} else if (chainId === 747474) {
|
|
215
|
+
relayerUrl = "https://dev-katana-relayer.sequence.app"
|
|
216
|
+
} else if (chainId === 42793) {
|
|
217
|
+
relayerUrl = "https://dev-etherlink-relayer.sequence.app"
|
|
210
218
|
} else {
|
|
211
219
|
// Fallback to general dev relayer for other chains if V3 is specified but chain not V3-supported
|
|
212
220
|
relayerUrl = `${baseUrl}${getChainInfo(chainId)!.name?.replace(" ", "-")}-relayer.sequence.app`
|
package/src/tokenBalances.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type {
|
|
|
7
7
|
TokenBalance,
|
|
8
8
|
} from "@0xsequence/indexer"
|
|
9
9
|
import { ContractVerificationStatus } from "@0xsequence/indexer"
|
|
10
|
-
import type { Page, Price, SequenceAPIClient } from "@0xsequence/api"
|
|
10
|
+
import type { Page, Price, SequenceAPIClient } from "@0xsequence/trails-api"
|
|
11
11
|
import { QueryClient, useQuery } from "@tanstack/react-query"
|
|
12
12
|
import type { Address } from "ox"
|
|
13
13
|
import { useEffect, useState } from "react"
|
|
@@ -18,12 +18,14 @@ import { getTokenPrices, useTokenPrices } from "./prices.js"
|
|
|
18
18
|
|
|
19
19
|
export type { NativeTokenBalance, TokenBalance }
|
|
20
20
|
|
|
21
|
+
const REFRESH_INTERVAL = 10000 // 10 seconds
|
|
22
|
+
|
|
21
23
|
// Initialize query client for token balances
|
|
22
24
|
const tokenBalancesQueryClient = new QueryClient({
|
|
23
25
|
defaultOptions: {
|
|
24
26
|
queries: {
|
|
25
|
-
staleTime:
|
|
26
|
-
gcTime:
|
|
27
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds - faster updates for balance changes
|
|
28
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds
|
|
27
29
|
retry: 2,
|
|
28
30
|
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
|
|
29
31
|
refetchOnWindowFocus: false,
|
|
@@ -167,8 +169,8 @@ export function useTokenBalances(
|
|
|
167
169
|
}
|
|
168
170
|
},
|
|
169
171
|
enabled: !!address && !!indexerClient,
|
|
170
|
-
staleTime:
|
|
171
|
-
gcTime:
|
|
172
|
+
staleTime: 10000, // 10 seconds - faster updates for balance changes
|
|
173
|
+
gcTime: 10000, // 10 seconds cache time
|
|
172
174
|
retry: (failureCount, error) => {
|
|
173
175
|
// Don't retry 404s or network errors after 3 attempts
|
|
174
176
|
if (error && "status" in error && error.status === 404) return false
|
|
@@ -176,10 +178,11 @@ export function useTokenBalances(
|
|
|
176
178
|
return false
|
|
177
179
|
},
|
|
178
180
|
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
|
|
179
|
-
refetchOnWindowFocus:
|
|
181
|
+
refetchOnWindowFocus: true, // Prevent refetch on window focus
|
|
180
182
|
refetchOnReconnect: true, // Refetch on reconnect
|
|
181
|
-
refetchInterval:
|
|
183
|
+
refetchInterval: REFRESH_INTERVAL, // Background refetch every 10 seconds
|
|
182
184
|
refetchIntervalInBackground: true,
|
|
185
|
+
refetchOnMount: true,
|
|
183
186
|
})
|
|
184
187
|
|
|
185
188
|
const { tokenPrices, isLoadingTokenPrices } = useTokenPrices(
|
|
@@ -262,9 +265,9 @@ export function useTokenBalances(
|
|
|
262
265
|
!isLoadingTokenPrices &&
|
|
263
266
|
!!tokenBalancesData &&
|
|
264
267
|
!!tokenPrices,
|
|
265
|
-
staleTime:
|
|
266
|
-
gcTime:
|
|
267
|
-
refetchOnWindowFocus:
|
|
268
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds for sorted tokens
|
|
269
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds cache time
|
|
270
|
+
refetchOnWindowFocus: true,
|
|
268
271
|
})
|
|
269
272
|
|
|
270
273
|
return {
|
|
@@ -283,6 +286,9 @@ export function formatRawAmount(
|
|
|
283
286
|
balance: string | bigint,
|
|
284
287
|
decimals: number = 18,
|
|
285
288
|
): string {
|
|
289
|
+
if (!balance) {
|
|
290
|
+
return "0"
|
|
291
|
+
}
|
|
286
292
|
try {
|
|
287
293
|
const formatted = formatUnits(BigInt(balance), decimals)
|
|
288
294
|
return formatAmount(formatted)
|
|
@@ -429,8 +435,8 @@ export async function getTokenBalances({
|
|
|
429
435
|
queryKey: ["tokenBalances", "summary", account],
|
|
430
436
|
queryFn: () =>
|
|
431
437
|
fetchGetTokenBalancesSummary({ account, indexerGatewayClient }),
|
|
432
|
-
staleTime:
|
|
433
|
-
gcTime:
|
|
438
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds - faster updates for balance changes
|
|
439
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds
|
|
434
440
|
})
|
|
435
441
|
}
|
|
436
442
|
|
|
@@ -724,8 +730,8 @@ export function useHasSufficientBalanceUsd(
|
|
|
724
730
|
})
|
|
725
731
|
: false,
|
|
726
732
|
enabled: !!account && !!targetAmountUsd,
|
|
727
|
-
staleTime:
|
|
728
|
-
gcTime:
|
|
733
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds
|
|
734
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds cache time
|
|
729
735
|
retry: (failureCount, error) => {
|
|
730
736
|
if (error && "status" in error && error.status === 404) return false
|
|
731
737
|
if (failureCount < 2) return true
|
|
@@ -783,8 +789,8 @@ export function useAccountTotalBalanceUsd(account: string): {
|
|
|
783
789
|
})
|
|
784
790
|
: null,
|
|
785
791
|
enabled: !!account,
|
|
786
|
-
staleTime:
|
|
787
|
-
gcTime:
|
|
792
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds - faster updates for balance changes
|
|
793
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds cache time
|
|
788
794
|
retry: (failureCount, error) => {
|
|
789
795
|
if (error && "status" in error && error.status === 404) return false
|
|
790
796
|
if (failureCount < 2) return true
|
|
@@ -793,8 +799,9 @@ export function useAccountTotalBalanceUsd(account: string): {
|
|
|
793
799
|
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
|
|
794
800
|
refetchOnWindowFocus: false,
|
|
795
801
|
refetchOnReconnect: true,
|
|
796
|
-
refetchInterval:
|
|
802
|
+
refetchInterval: REFRESH_INTERVAL, // Background refetch every 10 seconds
|
|
797
803
|
refetchIntervalInBackground: true,
|
|
804
|
+
refetchOnMount: true,
|
|
798
805
|
})
|
|
799
806
|
|
|
800
807
|
return {
|
package/src/tokens.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { QueryClient, useQuery } from "@tanstack/react-query"
|
|
2
|
-
import { zeroAddress, erc20Abi } from "viem"
|
|
3
|
-
import * as chains from "viem/chains"
|
|
2
|
+
import { zeroAddress, erc20Abi, createPublicClient, http } from "viem"
|
|
4
3
|
import { getChainInfo, getSupportedChains } from "./chains.js"
|
|
4
|
+
import * as chains from "viem/chains"
|
|
5
5
|
import { getRelaySupportedTokens } from "./relaySdk.js"
|
|
6
6
|
import { useReadContracts } from "wagmi"
|
|
7
7
|
import { useMemo } from "react"
|
|
@@ -17,6 +17,21 @@ export type SupportedToken = {
|
|
|
17
17
|
imageUrl: string
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
export const commonTokenImages: Record<string, string> = {
|
|
21
|
+
ETH: "https://assets.sequence.info/images/tokens/large/1/0x0000000000000000000000000000000000000000.webp",
|
|
22
|
+
WETH: "https://assets.coingecko.com/coins/images/39723/small/WETH.PNG?1723733967",
|
|
23
|
+
POL: "https://assets.sequence.info/images/tokens/large/137/0x0000000000000000000000000000000000000000.webp",
|
|
24
|
+
USDC: "https://assets.sequence.info/images/tokens/large/1/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.webp",
|
|
25
|
+
USDT: "https://assets.sequence.info/images/tokens/large/1/0xdac17f958d2ee523a2206206994597c13d831ec7.webp",
|
|
26
|
+
DAI: "https://assets.sequence.info/images/tokens/large/1/0x6b175474e89094c44da98b954eedeac495271d0f.webp",
|
|
27
|
+
WBTC: "https://assets.sequence.info/images/tokens/large/1/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599.webp",
|
|
28
|
+
BAT: "https://assets.sequence.info/images/tokens/large/1/0x0d8775f648430679a709e98d2b0cb6250d2887ef.webp",
|
|
29
|
+
ARB: "https://assets.sequence.info/images/tokens/large/42161/0x912ce59144191c1204e64559fe8253a0e49e6548.webp",
|
|
30
|
+
LINK: "https://assets.sequence.info/images/tokens/large/1/0x514910771af9ca656af840dff83e8264ecf986ca.webp",
|
|
31
|
+
XTZ: "https://assets.sequence.info/images/tokens/large/42793/0x0000000000000000000000000000000000000000.webp",
|
|
32
|
+
WXTZ: "https://assets.coingecko.com/coins/images/976/standard/Tezos-logo.png?1696502091",
|
|
33
|
+
}
|
|
34
|
+
|
|
20
35
|
const cacheVersion = "01"
|
|
21
36
|
|
|
22
37
|
// LocalStorage cache utilities for token images
|
|
@@ -303,8 +318,13 @@ export async function getTokenImageUrlOrFallback({
|
|
|
303
318
|
}
|
|
304
319
|
}
|
|
305
320
|
|
|
321
|
+
export async function getAllTokens(): Promise<SupportedToken[]> {
|
|
322
|
+
const relayTokens = (await getRelaySupportedTokens()) as SupportedToken[]
|
|
323
|
+
return relayTokens
|
|
324
|
+
}
|
|
325
|
+
|
|
306
326
|
export async function getSupportedTokens(): Promise<SupportedToken[]> {
|
|
307
|
-
const tokens = await
|
|
327
|
+
const tokens = await getAllTokens()
|
|
308
328
|
for (const token of tokens) {
|
|
309
329
|
if (!token.imageUrl) {
|
|
310
330
|
token.imageUrl = getTokenImageUrl({
|
|
@@ -342,9 +362,13 @@ export async function getSupportedTokens(): Promise<SupportedToken[]> {
|
|
|
342
362
|
|
|
343
363
|
const supportedChains = await getSupportedChains()
|
|
344
364
|
const allTokens = [...tokens, ...additionalTokens]
|
|
345
|
-
const supportedChainTokens = allTokens.filter((token) =>
|
|
346
|
-
|
|
347
|
-
|
|
365
|
+
const supportedChainTokens = allTokens.filter((token) => {
|
|
366
|
+
// Always include Etherlink tokens
|
|
367
|
+
if (token.chainId === chains.etherlink.id) {
|
|
368
|
+
return true
|
|
369
|
+
}
|
|
370
|
+
return supportedChains.some((chain) => chain.id === token.chainId)
|
|
371
|
+
})
|
|
348
372
|
const uniqueTokens = supportedChainTokens.filter(
|
|
349
373
|
(token, index, self) =>
|
|
350
374
|
index ===
|
|
@@ -357,7 +381,9 @@ export async function getSupportedTokens(): Promise<SupportedToken[]> {
|
|
|
357
381
|
)
|
|
358
382
|
|
|
359
383
|
// Sort tokens according to priority order
|
|
360
|
-
|
|
384
|
+
const sortedTokens = sortTokens(uniqueTokens as SupportedToken[])
|
|
385
|
+
|
|
386
|
+
return sortedTokens
|
|
361
387
|
}
|
|
362
388
|
|
|
363
389
|
export function useSupportedTokens({ chainId }: { chainId?: number } = {}): {
|
|
@@ -426,6 +452,7 @@ export const tokenNamePrefixes: Record<string, string> = {
|
|
|
426
452
|
[chains.optimism.id]: "Optimistic",
|
|
427
453
|
[chains.arbitrum.id]: "Arbitrum",
|
|
428
454
|
[chains.polygon.id]: "Polygon",
|
|
455
|
+
[chains.etherlink.id]: "Etherlink",
|
|
429
456
|
}
|
|
430
457
|
|
|
431
458
|
export function getFormatttedTokenName(
|
|
@@ -508,6 +535,9 @@ export async function getTokenInfo(
|
|
|
508
535
|
t.contractAddress.toLowerCase() === normalizedAddress,
|
|
509
536
|
)
|
|
510
537
|
|
|
538
|
+
console.log("tokens", tokens)
|
|
539
|
+
console.log("token", token)
|
|
540
|
+
|
|
511
541
|
if (token) {
|
|
512
542
|
// Cache the token info
|
|
513
543
|
setTokenInfoCache(`${chainId}:${normalizedAddress}`, token)
|
|
@@ -515,8 +545,64 @@ export async function getTokenInfo(
|
|
|
515
545
|
return token
|
|
516
546
|
}
|
|
517
547
|
|
|
518
|
-
// If not found in supported tokens,
|
|
519
|
-
|
|
548
|
+
// If not found in supported tokens, try to fetch on-chain data
|
|
549
|
+
try {
|
|
550
|
+
const chainInfo = getChainInfo(chainId)
|
|
551
|
+
if (!chainInfo) {
|
|
552
|
+
console.warn(`[trails-sdk] Chain info not found for chainId: ${chainId}`)
|
|
553
|
+
return null
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// Create a public client for the specific chain
|
|
557
|
+
const publicClient = createPublicClient({
|
|
558
|
+
chain: chainInfo,
|
|
559
|
+
transport: http(),
|
|
560
|
+
})
|
|
561
|
+
|
|
562
|
+
// Read token data on-chain
|
|
563
|
+
const [name, symbol, decimals] = await Promise.all([
|
|
564
|
+
publicClient.readContract({
|
|
565
|
+
address: normalizedAddress as `0x${string}`,
|
|
566
|
+
abi: erc20Abi,
|
|
567
|
+
functionName: "name",
|
|
568
|
+
}),
|
|
569
|
+
publicClient.readContract({
|
|
570
|
+
address: normalizedAddress as `0x${string}`,
|
|
571
|
+
abi: erc20Abi,
|
|
572
|
+
functionName: "symbol",
|
|
573
|
+
}),
|
|
574
|
+
publicClient.readContract({
|
|
575
|
+
address: normalizedAddress as `0x${string}`,
|
|
576
|
+
abi: erc20Abi,
|
|
577
|
+
functionName: "decimals",
|
|
578
|
+
}),
|
|
579
|
+
])
|
|
580
|
+
|
|
581
|
+
// Create token info from on-chain data
|
|
582
|
+
const onChainTokenInfo: SupportedToken = {
|
|
583
|
+
id: `${symbol}-${chainInfo.name}`,
|
|
584
|
+
name: name,
|
|
585
|
+
symbol: symbol,
|
|
586
|
+
decimals: decimals,
|
|
587
|
+
chainId: chainId,
|
|
588
|
+
contractAddress: normalizedAddress,
|
|
589
|
+
chainName: chainInfo.name,
|
|
590
|
+
imageUrl: getTokenImageUrl({
|
|
591
|
+
chainId,
|
|
592
|
+
contractAddress: normalizedAddress,
|
|
593
|
+
symbol: symbol,
|
|
594
|
+
}),
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Cache the on-chain token info
|
|
598
|
+
setTokenInfoCache(`${chainId}:${normalizedAddress}`, onChainTokenInfo)
|
|
599
|
+
|
|
600
|
+
console.log("[trails-sdk] Fetched token info on-chain:", onChainTokenInfo)
|
|
601
|
+
return onChainTokenInfo
|
|
602
|
+
} catch (error) {
|
|
603
|
+
console.error("[trails-sdk] Error fetching on-chain token info:", error)
|
|
604
|
+
return null
|
|
605
|
+
}
|
|
520
606
|
}
|
|
521
607
|
|
|
522
608
|
export async function getTokenAddress(chainId: number, tokenSymbol: string) {
|
|
@@ -788,21 +874,8 @@ export function useTokenInfo({
|
|
|
788
874
|
}
|
|
789
875
|
}
|
|
790
876
|
|
|
791
|
-
export const commonTokenImages: Record<string, string> = {
|
|
792
|
-
ETH: "https://assets.sequence.info/images/tokens/large/1/0x0000000000000000000000000000000000000000.webp",
|
|
793
|
-
POL: "https://assets.sequence.info/images/tokens/large/137/0x0000000000000000000000000000000000000000.webp",
|
|
794
|
-
USDC: "https://assets.sequence.info/images/tokens/large/1/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48.webp",
|
|
795
|
-
USDT: "https://assets.sequence.info/images/tokens/large/1/0xdac17f958d2ee523a2206206994597c13d831ec7.webp",
|
|
796
|
-
DAI: "https://assets.sequence.info/images/tokens/large/1/0x6b175474e89094c44da98b954eedeac495271d0f.webp",
|
|
797
|
-
WBTC: "https://assets.sequence.info/images/tokens/large/1/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599.webp",
|
|
798
|
-
BAT: "https://assets.sequence.info/images/tokens/large/1/0x0d8775f648430679a709e98d2b0cb6250d2887ef.webp",
|
|
799
|
-
ARB: "https://assets.sequence.info/images/tokens/large/42161/0x912ce59144191c1204e64559fe8253a0e49e6548.webp",
|
|
800
|
-
LINK: "https://assets.sequence.info/images/tokens/large/1/0x514910771af9ca656af840dff83e8264ecf986ca.webp",
|
|
801
|
-
}
|
|
802
|
-
|
|
803
877
|
export const tokenImageSymbolMap: Record<string, string> = {
|
|
804
878
|
ETH: "ETH",
|
|
805
|
-
WETH: "ETH",
|
|
806
879
|
cbETH: "ETH",
|
|
807
880
|
POL: "POL",
|
|
808
881
|
WPOL: "POL",
|
|
@@ -1018,6 +1091,58 @@ export const commonTokens: SupportedToken[] = [
|
|
|
1018
1091
|
chainName: chains.mainnet.name,
|
|
1019
1092
|
imageUrl: commonTokenImages.LINK!,
|
|
1020
1093
|
},
|
|
1094
|
+
|
|
1095
|
+
// Etherlink tokens
|
|
1096
|
+
{
|
|
1097
|
+
id: "XTZ-etherlink",
|
|
1098
|
+
symbol: "XTZ",
|
|
1099
|
+
name: "Tezos",
|
|
1100
|
+
contractAddress: "0x0000000000000000000000000000000000000000",
|
|
1101
|
+
decimals: 18,
|
|
1102
|
+
chainId: chains.etherlink.id,
|
|
1103
|
+
chainName: chains.etherlink.name,
|
|
1104
|
+
imageUrl: commonTokenImages.XTZ as string,
|
|
1105
|
+
},
|
|
1106
|
+
{
|
|
1107
|
+
id: "WXTZ-etherlink",
|
|
1108
|
+
symbol: "WXTZ",
|
|
1109
|
+
name: "Wrapped XTZ",
|
|
1110
|
+
contractAddress: "0xc9B53AB2679f573e480d01e0f49e2B5CFB7a3EAb",
|
|
1111
|
+
decimals: 18,
|
|
1112
|
+
chainId: chains.etherlink.id,
|
|
1113
|
+
chainName: chains.etherlink.name,
|
|
1114
|
+
imageUrl: commonTokenImages.WXTZ as string,
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
id: "USDC-etherlink",
|
|
1118
|
+
symbol: "USDC",
|
|
1119
|
+
name: "USD Coin",
|
|
1120
|
+
contractAddress: "0x796Ea11Fa2dD751eD01b53C372fFDB4AAa8f00F9",
|
|
1121
|
+
decimals: 6,
|
|
1122
|
+
chainId: chains.etherlink.id,
|
|
1123
|
+
chainName: chains.etherlink.name,
|
|
1124
|
+
imageUrl: commonTokenImages.USDC as string,
|
|
1125
|
+
},
|
|
1126
|
+
{
|
|
1127
|
+
id: "WETH-etherlink",
|
|
1128
|
+
symbol: "WETH",
|
|
1129
|
+
name: "Wrapped ETH",
|
|
1130
|
+
contractAddress: "0xfc24f770F94edBca6D6f885E12d4317320BcB401",
|
|
1131
|
+
decimals: 18,
|
|
1132
|
+
chainId: chains.etherlink.id,
|
|
1133
|
+
chainName: chains.etherlink.name,
|
|
1134
|
+
imageUrl: commonTokenImages.WETH as string,
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
id: "USDT-etherlink",
|
|
1138
|
+
symbol: "USDT",
|
|
1139
|
+
name: "Bridged USDT",
|
|
1140
|
+
contractAddress: "0x2C03058C8AFC06713be23e58D2febC8337dbfE6A",
|
|
1141
|
+
decimals: 6,
|
|
1142
|
+
chainId: chains.etherlink.id,
|
|
1143
|
+
chainName: chains.etherlink.name,
|
|
1144
|
+
imageUrl: commonTokenImages.USDT as string,
|
|
1145
|
+
},
|
|
1021
1146
|
]
|
|
1022
1147
|
|
|
1023
1148
|
export const wethAddresses: Record<string, string> = {
|
package/src/trails.ts
CHANGED
|
@@ -4,8 +4,8 @@ import type {
|
|
|
4
4
|
GetIntentConfigReturn,
|
|
5
5
|
IntentCallsPayload,
|
|
6
6
|
IntentPrecondition,
|
|
7
|
-
} from "@0xsequence/api"
|
|
8
|
-
import type { SequenceAPIClient } from "@0xsequence/api"
|
|
7
|
+
} from "@0xsequence/trails-api"
|
|
8
|
+
import type { SequenceAPIClient } from "@0xsequence/trails-api"
|
|
9
9
|
import type { Relayer } from "@0xsequence/wallet-core"
|
|
10
10
|
import { useMutation, useQuery } from "@tanstack/react-query"
|
|
11
11
|
import { Address } from "ox"
|
|
@@ -98,7 +98,7 @@ export type UseTrailsReturn = {
|
|
|
98
98
|
mainSignerAddress: string
|
|
99
99
|
calls: IntentCallsPayload[]
|
|
100
100
|
preconditions: IntentPrecondition[]
|
|
101
|
-
quoteProvider:
|
|
101
|
+
quoteProvider: QuoteProvider
|
|
102
102
|
addressOverrides?: AddressOverrides
|
|
103
103
|
}) => void
|
|
104
104
|
commitIntentConfigPending: boolean
|
|
@@ -109,7 +109,7 @@ export type UseTrailsReturn = {
|
|
|
109
109
|
mainSignerAddress: string
|
|
110
110
|
calls: IntentCallsPayload[]
|
|
111
111
|
preconditions: IntentPrecondition[]
|
|
112
|
-
quoteProvider:
|
|
112
|
+
quoteProvider: QuoteProvider
|
|
113
113
|
addressOverrides?: AddressOverrides
|
|
114
114
|
}
|
|
115
115
|
| undefined
|
package/src/transactions.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createPublicClient, http } from "viem"
|
|
2
2
|
import { getChainInfo } from "./chains.js"
|
|
3
|
-
import { getRpcSequenceProjectAccessKey } from "./config.js"
|
|
3
|
+
import { getRpcSequenceProjectAccessKey, getSequenceEnv } from "./config.js"
|
|
4
|
+
import type { GuestModuleEvent, TrailsTokenSweeperEvent } from "./decoders.js"
|
|
5
|
+
import * as chains from "viem/chains"
|
|
4
6
|
|
|
5
7
|
export type TransactionStateStatus = "pending" | "failed" | "confirmed"
|
|
6
8
|
|
|
@@ -11,6 +13,8 @@ export type TransactionState = {
|
|
|
11
13
|
chainId: number
|
|
12
14
|
state: TransactionStateStatus
|
|
13
15
|
label: string
|
|
16
|
+
decodedTrailsTokenSweeperEvents?: TrailsTokenSweeperEvent[]
|
|
17
|
+
decodedGuestModuleEvents?: GuestModuleEvent[]
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
export type TransferType = "SEND" | "RECEIVE"
|
|
@@ -163,23 +167,37 @@ export async function getTxTimeDiff(
|
|
|
163
167
|
}
|
|
164
168
|
}
|
|
165
169
|
|
|
170
|
+
export function getIndexerUrlChainSlug(chainSlug: string) {
|
|
171
|
+
const env = getSequenceEnv()
|
|
172
|
+
let envPrefix = ""
|
|
173
|
+
|
|
174
|
+
// Only use dev prefix for katana in dev environment, since it's not deployed to prod yet
|
|
175
|
+
if (env === "dev" && chainSlug === "katana") {
|
|
176
|
+
envPrefix = "dev-"
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return `https://${envPrefix}${chainSlug}-indexer.sequence.app`
|
|
180
|
+
}
|
|
181
|
+
|
|
166
182
|
const chainIdToIndexerUrl = {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
421613: "
|
|
183
|
+
[chains.arbitrum.id]: getIndexerUrlChainSlug("arbitrum"),
|
|
184
|
+
[chains.base.id]: getIndexerUrlChainSlug("base"),
|
|
185
|
+
[chains.baseSepolia.id]: getIndexerUrlChainSlug("base-sepolia"),
|
|
186
|
+
[chains.optimism.id]: getIndexerUrlChainSlug("optimism"),
|
|
187
|
+
[chains.polygon.id]: getIndexerUrlChainSlug("polygon"),
|
|
188
|
+
[chains.mainnet.id]: getIndexerUrlChainSlug("mainnet"),
|
|
189
|
+
[chains.apeChain.id]: getIndexerUrlChainSlug("apechain"),
|
|
190
|
+
[chains.arbitrumNova.id]: getIndexerUrlChainSlug("arbitrum-nova"),
|
|
191
|
+
[chains.avalanche.id]: getIndexerUrlChainSlug("avalanche"),
|
|
192
|
+
[chains.b3.id]: getIndexerUrlChainSlug("b3"),
|
|
193
|
+
[chains.blast.id]: getIndexerUrlChainSlug("blast"),
|
|
194
|
+
[chains.gnosis.id]: getIndexerUrlChainSlug("gnosis"),
|
|
195
|
+
[chains.soneium.id]: getIndexerUrlChainSlug("soneium"),
|
|
196
|
+
[chains.xai.id]: getIndexerUrlChainSlug("xai"),
|
|
197
|
+
[chains.bsc.id]: getIndexerUrlChainSlug("bsc"),
|
|
198
|
+
421613: getIndexerUrlChainSlug("arbitrum-nova-sepolia"),
|
|
199
|
+
[chains.etherlink.id]: getIndexerUrlChainSlug("etherlink"),
|
|
200
|
+
[chains.katana.id]: getIndexerUrlChainSlug("katana"),
|
|
183
201
|
}
|
|
184
202
|
|
|
185
203
|
export async function getAccountTransactionHistory({
|
package/src/utils.ts
CHANGED
|
@@ -40,3 +40,31 @@ export function formatElapsed(seconds: number): string {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Calculates and formats time ago from a timestamp
|
|
46
|
+
* @param timestamp - Timestamp in milliseconds
|
|
47
|
+
* @returns Formatted time ago string (e.g., "Sent just now", "Sent 5 minutes ago")
|
|
48
|
+
*/
|
|
49
|
+
export function getTimeAgo(timestamp?: number): string {
|
|
50
|
+
if (!timestamp) return "Sent just now"
|
|
51
|
+
|
|
52
|
+
const now = Date.now()
|
|
53
|
+
const diffInSeconds = Math.floor((now - timestamp) / 1000)
|
|
54
|
+
|
|
55
|
+
if (diffInSeconds < 1) return "Sent just now"
|
|
56
|
+
if (diffInSeconds === 1) return "Sent 1 second ago"
|
|
57
|
+
if (diffInSeconds < 60) return `Sent ${diffInSeconds} seconds ago`
|
|
58
|
+
|
|
59
|
+
const diffInMinutes = Math.floor(diffInSeconds / 60)
|
|
60
|
+
if (diffInMinutes === 1) return "Sent 1 minute ago"
|
|
61
|
+
if (diffInMinutes < 60) return `Sent ${diffInMinutes} minutes ago`
|
|
62
|
+
|
|
63
|
+
const diffInHours = Math.floor(diffInMinutes / 60)
|
|
64
|
+
if (diffInHours === 1) return "Sent 1 hour ago"
|
|
65
|
+
if (diffInHours < 24) return `Sent ${diffInHours} hours ago`
|
|
66
|
+
|
|
67
|
+
const diffInDays = Math.floor(diffInHours / 24)
|
|
68
|
+
if (diffInDays === 1) return "Sent 1 day ago"
|
|
69
|
+
return `Sent ${diffInDays} days ago`
|
|
70
|
+
}
|