0xtrails 0.1.3 → 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 +18 -0
- 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-CWd4g9uZ.js → ccip-dLSEJjCf.js} +55 -55
- package/dist/cctpqueue.d.ts +1 -1
- package/dist/cctpqueue.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 +6 -0
- package/dist/ens.d.ts.map +1 -1
- package/dist/error.d.ts +7 -0
- package/dist/error.d.ts.map +1 -1
- package/dist/{index-BTUBzx4R.js → index-BXbaLmtt.js} +25694 -24507
- package/dist/index.js +2 -2
- package/dist/intents.d.ts +4 -4
- package/dist/intents.d.ts.map +1 -1
- 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 +30 -24
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +1 -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/tokenBalances.d.ts +1 -1
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/trails.d.ts +1 -1
- 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/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 +1 -1
- 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 +1 -1
- package/dist/widget/components/PaySendForm.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/Swap.d.ts +5 -1
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/SwapDisplay.d.ts +9 -0
- package/dist/widget/components/SwapDisplay.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/YellowWarningAnimation.d.ts +2 -0
- package/dist/widget/components/YellowWarningAnimation.d.ts.map +1 -0
- 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 +7 -3
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- 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 +16 -15
- package/src/address.ts +3 -0
- package/src/analytics.ts +105 -4
- package/src/apiClient.ts +1 -1
- package/src/cctpqueue.ts +1 -1
- package/src/constants.ts +3 -0
- package/src/decoders.ts +310 -0
- package/src/ens.ts +16 -1
- package/src/error.ts +86 -1
- package/src/intents.ts +10 -2
- package/src/metaTxns.ts +1 -1
- package/src/mode.ts +1 -1
- package/src/preconditions.ts +1 -1
- package/src/prepareSend.ts +432 -114
- package/src/prices.ts +5 -1
- package/src/proxyCaller.ts +2 -14
- package/src/tokenBalances.ts +21 -17
- package/src/tokens.ts +62 -3
- package/src/trails.ts +2 -2
- package/src/transactions.ts +35 -18
- package/src/utils.ts +28 -0
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/DebugScreensDropdown.tsx +3 -0
- package/src/widget/components/ErrorDisplay.tsx +150 -0
- package/src/widget/components/FundSendForm.tsx +62 -9
- package/src/widget/components/OriginTransferInformation.tsx +59 -0
- package/src/widget/components/PaySendForm.tsx +65 -12
- package/src/widget/components/QRCodeDeposit.tsx +5 -5
- package/src/widget/components/QrCode.tsx +1 -1
- 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/Swap.tsx +206 -85
- package/src/widget/components/SwapDisplay.tsx +68 -0
- package/src/widget/components/TokenSelector.tsx +1 -1
- package/src/widget/components/TransferPendingVertical.tsx +162 -112
- package/src/widget/components/YellowWarningAnimation.tsx +146 -0
- package/src/widget/hooks/useDebugScreens.ts +583 -0
- package/src/widget/hooks/useSendForm.ts +46 -4
- package/src/widget/hooks/useTokenList.ts +8 -27
- package/src/widget/widget.tsx +201 -484
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
|
|
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/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 {
|
|
@@ -432,8 +435,8 @@ export async function getTokenBalances({
|
|
|
432
435
|
queryKey: ["tokenBalances", "summary", account],
|
|
433
436
|
queryFn: () =>
|
|
434
437
|
fetchGetTokenBalancesSummary({ account, indexerGatewayClient }),
|
|
435
|
-
staleTime:
|
|
436
|
-
gcTime:
|
|
438
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds - faster updates for balance changes
|
|
439
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds
|
|
437
440
|
})
|
|
438
441
|
}
|
|
439
442
|
|
|
@@ -727,8 +730,8 @@ export function useHasSufficientBalanceUsd(
|
|
|
727
730
|
})
|
|
728
731
|
: false,
|
|
729
732
|
enabled: !!account && !!targetAmountUsd,
|
|
730
|
-
staleTime:
|
|
731
|
-
gcTime:
|
|
733
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds
|
|
734
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds cache time
|
|
732
735
|
retry: (failureCount, error) => {
|
|
733
736
|
if (error && "status" in error && error.status === 404) return false
|
|
734
737
|
if (failureCount < 2) return true
|
|
@@ -786,8 +789,8 @@ export function useAccountTotalBalanceUsd(account: string): {
|
|
|
786
789
|
})
|
|
787
790
|
: null,
|
|
788
791
|
enabled: !!account,
|
|
789
|
-
staleTime:
|
|
790
|
-
gcTime:
|
|
792
|
+
staleTime: REFRESH_INTERVAL, // 10 seconds - faster updates for balance changes
|
|
793
|
+
gcTime: REFRESH_INTERVAL, // 10 seconds cache time
|
|
791
794
|
retry: (failureCount, error) => {
|
|
792
795
|
if (error && "status" in error && error.status === 404) return false
|
|
793
796
|
if (failureCount < 2) return true
|
|
@@ -796,8 +799,9 @@ export function useAccountTotalBalanceUsd(account: string): {
|
|
|
796
799
|
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000),
|
|
797
800
|
refetchOnWindowFocus: false,
|
|
798
801
|
refetchOnReconnect: true,
|
|
799
|
-
refetchInterval:
|
|
802
|
+
refetchInterval: REFRESH_INTERVAL, // Background refetch every 10 seconds
|
|
800
803
|
refetchIntervalInBackground: true,
|
|
804
|
+
refetchOnMount: true,
|
|
801
805
|
})
|
|
802
806
|
|
|
803
807
|
return {
|
package/src/tokens.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QueryClient, useQuery } from "@tanstack/react-query"
|
|
2
|
-
import { zeroAddress, erc20Abi } from "viem"
|
|
2
|
+
import { zeroAddress, erc20Abi, createPublicClient, http } from "viem"
|
|
3
3
|
import { getChainInfo, getSupportedChains } from "./chains.js"
|
|
4
4
|
import * as chains from "viem/chains"
|
|
5
5
|
import { getRelaySupportedTokens } from "./relaySdk.js"
|
|
@@ -535,6 +535,9 @@ export async function getTokenInfo(
|
|
|
535
535
|
t.contractAddress.toLowerCase() === normalizedAddress,
|
|
536
536
|
)
|
|
537
537
|
|
|
538
|
+
console.log("tokens", tokens)
|
|
539
|
+
console.log("token", token)
|
|
540
|
+
|
|
538
541
|
if (token) {
|
|
539
542
|
// Cache the token info
|
|
540
543
|
setTokenInfoCache(`${chainId}:${normalizedAddress}`, token)
|
|
@@ -542,8 +545,64 @@ export async function getTokenInfo(
|
|
|
542
545
|
return token
|
|
543
546
|
}
|
|
544
547
|
|
|
545
|
-
// If not found in supported tokens,
|
|
546
|
-
|
|
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
|
+
}
|
|
547
606
|
}
|
|
548
607
|
|
|
549
608
|
export async function getTokenAddress(chainId: number, tokenSymbol: 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"
|
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,24 +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
|
-
|
|
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"),
|
|
184
201
|
}
|
|
185
202
|
|
|
186
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
|
+
}
|