0xtrails 0.5.0 → 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-DhEkQ6QC.js → ccip-Dw5AN7oU.js} +1 -1
- package/dist/cctp.d.ts +0 -149
- package/dist/cctp.d.ts.map +1 -1
- package/dist/chains.d.ts +28 -3
- package/dist/chains.d.ts.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- 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-MhD2DA7_.js → index-BtVUTbEZ.js} +30984 -38945
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +108 -107
- package/dist/indexerClient.d.ts +2 -2
- package/dist/intents.d.ts +0 -17
- 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/tokenBalances.d.ts.map +1 -1
- package/dist/tokens.d.ts +10 -8
- package/dist/tokens.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 +4 -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 +6 -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 +2 -20
- 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/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/Toast.d.ts.map +1 -1
- package/dist/widget/components/TokenImage.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 +5 -8
- 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.js +1 -1
- package/dist/widget/providers/TrailsProvider.d.ts +23 -12
- package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
- package/dist/widget/widget.d.ts +11 -0
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/analytics.ts +53 -21
- package/src/cctp.ts +0 -1016
- package/src/chains.ts +93 -39
- package/src/config.ts +24 -6
- package/src/constants.ts +1 -4
- 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 +7 -6
- package/src/indexerClient.ts +2 -2
- package/src/intents.ts +52 -206
- package/src/mutations.ts +3 -2
- package/src/paymasterSend.ts +2 -5
- package/src/prepareSend.ts +9 -12
- package/src/sendUserOp.ts +3 -64
- package/src/tokenBalances.ts +2 -1
- package/src/tokens.ts +62 -133
- package/src/trailsClient.ts +1 -1
- 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 +165 -385
- 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 +6 -27
- package/src/transactionIntent/utils/index.ts +0 -1
- package/src/transactions.ts +6 -203
- package/src/umd.tsx +1 -3
- package/src/utils.ts +28 -8
- package/src/walletUtils.ts +42 -0
- package/src/wallets.ts +361 -203
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +73 -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 +1 -1
- 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/Toast.tsx +10 -0
- package/src/widget/components/TokenImage.tsx +56 -13
- 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 +788 -418
- package/src/widget/hooks/useIsConnectedWalletSmartContract.ts +43 -0
- package/src/widget/hooks/useIsSequenceWallet.ts +17 -0
- package/src/widget/hooks/useQuote.ts +16 -17
- package/src/widget/hooks/useRecentTokens.ts +2 -1
- package/src/widget/hooks/useSelectedFeeOption.tsx +257 -0
- package/src/widget/hooks/useSendForm.ts +172 -47
- package/src/widget/hooks/useTokenList.ts +15 -2
- package/src/widget/providers/TrailsProvider.tsx +53 -25
- package/src/widget/widget.tsx +119 -48
- 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/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 -69
- package/src/preconditions.ts +0 -47
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +0 -323
- package/src/transactionIntent/utils/lifiHelpers.ts +0 -68
- package/src/widget/hooks/useSelectedFeeToken.tsx +0 -288
|
@@ -1,14 +1,708 @@
|
|
|
1
1
|
import { useState, useEffect, useCallback } from "react"
|
|
2
2
|
import {
|
|
3
|
-
getIntentTransactionHistory,
|
|
4
3
|
getAccountTransactionHistory,
|
|
5
4
|
type IntentTransaction,
|
|
6
|
-
type IntentTransactionHistoryResponse,
|
|
7
5
|
} from "../../transactions.js"
|
|
8
6
|
import { getTokenInfo, getSupportedTokens } from "../../tokens.js"
|
|
9
7
|
import { getExplorerUrl } from "../../explorer.js"
|
|
10
8
|
import { logger } from "../../logger.js"
|
|
11
9
|
import { useTrails } from "../providers/TrailsProvider.js"
|
|
10
|
+
import { commonTokenImages } from "../../tokens.js"
|
|
11
|
+
import { getTrailsClient } from "../../trailsClient.js"
|
|
12
|
+
import { SortOrder, type IntentSummary } from "@0xsequence/trails-api"
|
|
13
|
+
import {
|
|
14
|
+
decodeTrailsTokenSweeperEvents,
|
|
15
|
+
decodeGuestModuleEvents,
|
|
16
|
+
} from "../../decoders.js"
|
|
17
|
+
import { getPublicRpcClient } from "../../chains.js"
|
|
18
|
+
import { getChainInfo } from "../../chains.js"
|
|
19
|
+
import { isNativeToken } from "../../utils.js"
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Helper Functions
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Maps API status to UI status format
|
|
27
|
+
*/
|
|
28
|
+
function mapApiStatusToUiStatus(apiStatus: string): string {
|
|
29
|
+
const status = apiStatus?.toUpperCase() || "UNKNOWN"
|
|
30
|
+
switch (status) {
|
|
31
|
+
case "SUCCEEDED":
|
|
32
|
+
return "completed"
|
|
33
|
+
case "EXECUTING":
|
|
34
|
+
return "processing"
|
|
35
|
+
case "PENDING":
|
|
36
|
+
return "pending"
|
|
37
|
+
case "FAILED":
|
|
38
|
+
return "failed"
|
|
39
|
+
case "CREATED":
|
|
40
|
+
return "created"
|
|
41
|
+
default:
|
|
42
|
+
return apiStatus?.toLowerCase() || "unknown"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Maps IntentSummary from API to IntentTransaction
|
|
48
|
+
*/
|
|
49
|
+
function mapIntentSummaryToTransaction(
|
|
50
|
+
intent: IntentSummary,
|
|
51
|
+
): IntentTransaction {
|
|
52
|
+
return {
|
|
53
|
+
originIntentAddress: intent.originIntentAddress,
|
|
54
|
+
destinationIntentAddress: intent.destinationIntentAddress,
|
|
55
|
+
mainSigner: intent.ownerAddress,
|
|
56
|
+
metaTxnId: intent.intentId,
|
|
57
|
+
txnHash:
|
|
58
|
+
intent.originTransactionHash ||
|
|
59
|
+
intent.destinationTransactionHash ||
|
|
60
|
+
undefined,
|
|
61
|
+
executionStatus: mapApiStatusToUiStatus(intent.status),
|
|
62
|
+
originChainId: intent.originChainId,
|
|
63
|
+
destinationChainId: intent.destinationChainId,
|
|
64
|
+
originTokenAddress: intent.originTokenAddress,
|
|
65
|
+
originTokenAmount: intent.originTokenAmount.toString(),
|
|
66
|
+
destinationTokenAddress: intent.destinationTokenAddress,
|
|
67
|
+
destinationTokenAmount: intent.destinationTokenAmount.toString(),
|
|
68
|
+
destinationToAddress: intent.ownerAddress,
|
|
69
|
+
createdAt: intent.createdAt,
|
|
70
|
+
originTransactionHash: intent.originTransactionHash,
|
|
71
|
+
destinationTransactionHash: intent.destinationTransactionHash,
|
|
72
|
+
originToken: intent.originTokenMetadata
|
|
73
|
+
? ({
|
|
74
|
+
symbol: intent.originTokenMetadata.symbol || "",
|
|
75
|
+
name: intent.originTokenMetadata.name || "",
|
|
76
|
+
decimals: intent.originTokenMetadata.decimals ?? 18,
|
|
77
|
+
imageUrl: intent.originTokenMetadata.logoUri ?? "",
|
|
78
|
+
chainId: intent.originTokenMetadata.chainId,
|
|
79
|
+
} as {
|
|
80
|
+
symbol: string
|
|
81
|
+
name: string
|
|
82
|
+
decimals: number
|
|
83
|
+
imageUrl: string
|
|
84
|
+
chainId: number
|
|
85
|
+
})
|
|
86
|
+
: undefined,
|
|
87
|
+
destinationToken: intent.destinationTokenMetadata
|
|
88
|
+
? ({
|
|
89
|
+
symbol: intent.destinationTokenMetadata.symbol || "",
|
|
90
|
+
name: intent.destinationTokenMetadata.name || "",
|
|
91
|
+
decimals: intent.destinationTokenMetadata.decimals ?? 18,
|
|
92
|
+
imageUrl: intent.destinationTokenMetadata.logoUri ?? "",
|
|
93
|
+
chainId: intent.destinationTokenMetadata.chainId,
|
|
94
|
+
} as {
|
|
95
|
+
symbol: string
|
|
96
|
+
name: string
|
|
97
|
+
decimals: number
|
|
98
|
+
imageUrl: string
|
|
99
|
+
chainId: number
|
|
100
|
+
})
|
|
101
|
+
: undefined,
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Gets token info for a given token address and chain ID
|
|
107
|
+
*/
|
|
108
|
+
async function getTokenInfoForTransaction(
|
|
109
|
+
tokenAddress: string,
|
|
110
|
+
chainId: number,
|
|
111
|
+
supportedTokens: Awaited<ReturnType<typeof getSupportedTokens>>,
|
|
112
|
+
): Promise<
|
|
113
|
+
| {
|
|
114
|
+
symbol: string
|
|
115
|
+
name: string
|
|
116
|
+
decimals: number
|
|
117
|
+
imageUrl: string
|
|
118
|
+
chainId: number
|
|
119
|
+
}
|
|
120
|
+
| undefined
|
|
121
|
+
> {
|
|
122
|
+
if (isNativeToken(tokenAddress)) {
|
|
123
|
+
const nativeToken = supportedTokens.find(
|
|
124
|
+
(token) =>
|
|
125
|
+
token.contractAddress.toLowerCase() === tokenAddress.toLowerCase() &&
|
|
126
|
+
token.chainId === chainId,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
if (nativeToken) {
|
|
130
|
+
return {
|
|
131
|
+
symbol: nativeToken.symbol,
|
|
132
|
+
name: nativeToken.name,
|
|
133
|
+
decimals: nativeToken.decimals,
|
|
134
|
+
imageUrl: nativeToken.imageUrl,
|
|
135
|
+
chainId: nativeToken.chainId,
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Fallback for native token
|
|
140
|
+
return {
|
|
141
|
+
symbol: "ETH",
|
|
142
|
+
name: "Native Token",
|
|
143
|
+
decimals: 18,
|
|
144
|
+
imageUrl: commonTokenImages.ETH as string,
|
|
145
|
+
chainId,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// For ERC20 tokens, check supported tokens first
|
|
150
|
+
const supportedToken = supportedTokens.find(
|
|
151
|
+
(token) =>
|
|
152
|
+
token.contractAddress.toLowerCase() === tokenAddress.toLowerCase() &&
|
|
153
|
+
token.chainId === chainId,
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
if (supportedToken) {
|
|
157
|
+
return {
|
|
158
|
+
symbol: supportedToken.symbol,
|
|
159
|
+
name: supportedToken.name,
|
|
160
|
+
decimals: supportedToken.decimals,
|
|
161
|
+
imageUrl: supportedToken.imageUrl,
|
|
162
|
+
chainId: supportedToken.chainId,
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Fallback to on-chain lookup
|
|
167
|
+
try {
|
|
168
|
+
const tokenInfo = await getTokenInfo(chainId, tokenAddress)
|
|
169
|
+
if (tokenInfo) {
|
|
170
|
+
return {
|
|
171
|
+
symbol: tokenInfo.symbol,
|
|
172
|
+
name: tokenInfo.name,
|
|
173
|
+
decimals: tokenInfo.decimals,
|
|
174
|
+
imageUrl: tokenInfo.imageUrl,
|
|
175
|
+
chainId: tokenInfo.chainId,
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
} catch (error) {
|
|
179
|
+
logger.console.warn(
|
|
180
|
+
"[trails-sdk] Failed to get token info for:",
|
|
181
|
+
tokenAddress,
|
|
182
|
+
"on chain",
|
|
183
|
+
chainId,
|
|
184
|
+
error,
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return undefined
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Gets origin intent transaction hashes from account history
|
|
193
|
+
*/
|
|
194
|
+
async function getOriginIntentTransactionHashes(
|
|
195
|
+
transaction: IntentTransaction,
|
|
196
|
+
trailsConfig: ReturnType<typeof useTrails>,
|
|
197
|
+
): Promise<{
|
|
198
|
+
originIntentTxHash?: string
|
|
199
|
+
originIntentTxExplorerUrl?: string
|
|
200
|
+
originIntentDepositTxHash?: string
|
|
201
|
+
originIntentDepositTxExplorerUrl?: string
|
|
202
|
+
}> {
|
|
203
|
+
if (
|
|
204
|
+
!transaction.originIntentAddress ||
|
|
205
|
+
!transaction.originChainId ||
|
|
206
|
+
transaction.originTransactionHash
|
|
207
|
+
) {
|
|
208
|
+
return {}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
const originHistory = await getAccountTransactionHistory({
|
|
213
|
+
chainId: transaction.originChainId,
|
|
214
|
+
accountAddress: transaction.originIntentAddress,
|
|
215
|
+
pageSize: 10,
|
|
216
|
+
page: 0,
|
|
217
|
+
includeMetadata: true,
|
|
218
|
+
apiKey: trailsConfig.trailsApiKey || "",
|
|
219
|
+
indexerUrl: trailsConfig.sequenceIndexerUrl!,
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
if (
|
|
223
|
+
!originHistory?.transactions ||
|
|
224
|
+
originHistory.transactions.length === 0
|
|
225
|
+
) {
|
|
226
|
+
return {}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const intentAddress = transaction.originIntentAddress.toLowerCase()
|
|
230
|
+
const result: {
|
|
231
|
+
originIntentTxHash?: string
|
|
232
|
+
originIntentTxExplorerUrl?: string
|
|
233
|
+
originIntentDepositTxHash?: string
|
|
234
|
+
originIntentDepositTxExplorerUrl?: string
|
|
235
|
+
} = {}
|
|
236
|
+
|
|
237
|
+
// Find first deposit tx (transfer TO intent address)
|
|
238
|
+
const depositTx = originHistory.transactions.find((tx) =>
|
|
239
|
+
tx.transfers?.some(
|
|
240
|
+
(transfer) => transfer.to.toLowerCase() === intentAddress,
|
|
241
|
+
),
|
|
242
|
+
)
|
|
243
|
+
if (depositTx) {
|
|
244
|
+
result.originIntentDepositTxHash = depositTx.txnHash
|
|
245
|
+
result.originIntentDepositTxExplorerUrl = getExplorerUrl({
|
|
246
|
+
txHash: depositTx.txnHash,
|
|
247
|
+
chainId: transaction.originChainId,
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Find first action tx (transfer FROM intent address)
|
|
252
|
+
const actionTx = originHistory.transactions.find((tx) =>
|
|
253
|
+
tx.transfers?.some(
|
|
254
|
+
(transfer) => transfer.from.toLowerCase() === intentAddress,
|
|
255
|
+
),
|
|
256
|
+
)
|
|
257
|
+
if (actionTx) {
|
|
258
|
+
result.originIntentTxHash = actionTx.txnHash
|
|
259
|
+
result.originIntentTxExplorerUrl = getExplorerUrl({
|
|
260
|
+
txHash: actionTx.txnHash,
|
|
261
|
+
chainId: transaction.originChainId,
|
|
262
|
+
})
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return result
|
|
266
|
+
} catch (error) {
|
|
267
|
+
logger.console.warn(
|
|
268
|
+
"[trails-sdk] Failed to get origin intent transaction hashes for:",
|
|
269
|
+
transaction.originIntentAddress,
|
|
270
|
+
"on chain",
|
|
271
|
+
transaction.originChainId,
|
|
272
|
+
error,
|
|
273
|
+
)
|
|
274
|
+
return {}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Gets destination intent transaction hashes from account history
|
|
280
|
+
*/
|
|
281
|
+
async function getDestinationIntentTransactionHashes(
|
|
282
|
+
transaction: IntentTransaction,
|
|
283
|
+
isSameIntentAddress: boolean,
|
|
284
|
+
trailsConfig: ReturnType<typeof useTrails>,
|
|
285
|
+
): Promise<{
|
|
286
|
+
destinationIntentTxHash?: string
|
|
287
|
+
destinationIntentTxExplorerUrl?: string
|
|
288
|
+
destinationIntentDepositTxHash?: string
|
|
289
|
+
destinationIntentDepositTxExplorerUrl?: string
|
|
290
|
+
}> {
|
|
291
|
+
if (
|
|
292
|
+
transaction.destinationTransactionHash ||
|
|
293
|
+
isSameIntentAddress ||
|
|
294
|
+
!transaction.destinationIntentAddress ||
|
|
295
|
+
!transaction.destinationChainId
|
|
296
|
+
) {
|
|
297
|
+
return {}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
try {
|
|
301
|
+
const destinationHistory = await getAccountTransactionHistory({
|
|
302
|
+
chainId: transaction.destinationChainId,
|
|
303
|
+
accountAddress: transaction.destinationIntentAddress,
|
|
304
|
+
pageSize: 10,
|
|
305
|
+
page: 0,
|
|
306
|
+
includeMetadata: true,
|
|
307
|
+
apiKey: trailsConfig.trailsApiKey || "",
|
|
308
|
+
indexerUrl: trailsConfig.sequenceIndexerUrl!,
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
if (
|
|
312
|
+
!destinationHistory?.transactions ||
|
|
313
|
+
destinationHistory.transactions.length === 0
|
|
314
|
+
) {
|
|
315
|
+
return {}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const intentAddress = transaction.destinationIntentAddress.toLowerCase()
|
|
319
|
+
const result: {
|
|
320
|
+
destinationIntentTxHash?: string
|
|
321
|
+
destinationIntentTxExplorerUrl?: string
|
|
322
|
+
destinationIntentDepositTxHash?: string
|
|
323
|
+
destinationIntentDepositTxExplorerUrl?: string
|
|
324
|
+
} = {}
|
|
325
|
+
|
|
326
|
+
// Find first deposit tx (transfer TO intent address)
|
|
327
|
+
const depositTx = destinationHistory.transactions.find((tx) =>
|
|
328
|
+
tx.transfers?.some(
|
|
329
|
+
(transfer) => transfer.to.toLowerCase() === intentAddress,
|
|
330
|
+
),
|
|
331
|
+
)
|
|
332
|
+
if (depositTx) {
|
|
333
|
+
result.destinationIntentDepositTxHash = depositTx.txnHash
|
|
334
|
+
result.destinationIntentDepositTxExplorerUrl = getExplorerUrl({
|
|
335
|
+
txHash: depositTx.txnHash,
|
|
336
|
+
chainId: transaction.destinationChainId,
|
|
337
|
+
})
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// Find first action tx (transfer FROM intent address)
|
|
341
|
+
const actionTx = destinationHistory.transactions.find((tx) =>
|
|
342
|
+
tx.transfers?.some(
|
|
343
|
+
(transfer) => transfer.from.toLowerCase() === intentAddress,
|
|
344
|
+
),
|
|
345
|
+
)
|
|
346
|
+
if (actionTx) {
|
|
347
|
+
result.destinationIntentTxHash = actionTx.txnHash
|
|
348
|
+
result.destinationIntentTxExplorerUrl = getExplorerUrl({
|
|
349
|
+
txHash: actionTx.txnHash,
|
|
350
|
+
chainId: transaction.destinationChainId,
|
|
351
|
+
})
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return result
|
|
355
|
+
} catch (error) {
|
|
356
|
+
logger.console.warn(
|
|
357
|
+
"[trails-sdk] Failed to get destination intent transaction hashes for:",
|
|
358
|
+
transaction.destinationIntentAddress,
|
|
359
|
+
"on chain",
|
|
360
|
+
transaction.destinationChainId,
|
|
361
|
+
error,
|
|
362
|
+
)
|
|
363
|
+
return {}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Decodes transaction events to detect refunds or failures
|
|
369
|
+
*/
|
|
370
|
+
async function decodeTransactionEvents(
|
|
371
|
+
transaction: IntentTransaction,
|
|
372
|
+
txHashes: {
|
|
373
|
+
originIntentTxHash?: string
|
|
374
|
+
destinationIntentTxHash?: string
|
|
375
|
+
originIntentDepositTxHash?: string
|
|
376
|
+
destinationIntentDepositTxHash?: string
|
|
377
|
+
},
|
|
378
|
+
): Promise<{ refunded: boolean; failed: boolean }> {
|
|
379
|
+
const isExecuting =
|
|
380
|
+
transaction.executionStatus === "executing" ||
|
|
381
|
+
transaction.executionStatus === "processing"
|
|
382
|
+
const createdAtTime = transaction.createdAt
|
|
383
|
+
? new Date(transaction.createdAt).getTime()
|
|
384
|
+
: null
|
|
385
|
+
const isExecutingOver1Minute =
|
|
386
|
+
isExecuting && createdAtTime && Date.now() - createdAtTime > 60 * 1000
|
|
387
|
+
|
|
388
|
+
if (!isExecutingOver1Minute) {
|
|
389
|
+
return { refunded: false, failed: false }
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Collect all transaction hashes to check
|
|
393
|
+
const txHashesToCheck: Array<{ hash: string; chainId: number }> = []
|
|
394
|
+
|
|
395
|
+
if (txHashes.originIntentTxHash && transaction.originChainId) {
|
|
396
|
+
txHashesToCheck.push({
|
|
397
|
+
hash: txHashes.originIntentTxHash,
|
|
398
|
+
chainId: transaction.originChainId,
|
|
399
|
+
})
|
|
400
|
+
}
|
|
401
|
+
if (txHashes.originIntentDepositTxHash && transaction.originChainId) {
|
|
402
|
+
txHashesToCheck.push({
|
|
403
|
+
hash: txHashes.originIntentDepositTxHash,
|
|
404
|
+
chainId: transaction.originChainId,
|
|
405
|
+
})
|
|
406
|
+
}
|
|
407
|
+
if (txHashes.destinationIntentTxHash && transaction.destinationChainId) {
|
|
408
|
+
txHashesToCheck.push({
|
|
409
|
+
hash: txHashes.destinationIntentTxHash,
|
|
410
|
+
chainId: transaction.destinationChainId,
|
|
411
|
+
})
|
|
412
|
+
}
|
|
413
|
+
if (
|
|
414
|
+
txHashes.destinationIntentDepositTxHash &&
|
|
415
|
+
transaction.destinationChainId
|
|
416
|
+
) {
|
|
417
|
+
txHashesToCheck.push({
|
|
418
|
+
hash: txHashes.destinationIntentDepositTxHash,
|
|
419
|
+
chainId: transaction.destinationChainId,
|
|
420
|
+
})
|
|
421
|
+
}
|
|
422
|
+
if (transaction.originTransactionHash && transaction.originChainId) {
|
|
423
|
+
txHashesToCheck.push({
|
|
424
|
+
hash: transaction.originTransactionHash,
|
|
425
|
+
chainId: transaction.originChainId,
|
|
426
|
+
})
|
|
427
|
+
}
|
|
428
|
+
if (
|
|
429
|
+
transaction.destinationTransactionHash &&
|
|
430
|
+
transaction.destinationChainId
|
|
431
|
+
) {
|
|
432
|
+
txHashesToCheck.push({
|
|
433
|
+
hash: transaction.destinationTransactionHash,
|
|
434
|
+
chainId: transaction.destinationChainId,
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Decode events from all known transaction hashes
|
|
439
|
+
for (const { hash, chainId } of txHashesToCheck) {
|
|
440
|
+
try {
|
|
441
|
+
const chainInfo = getChainInfo(chainId)
|
|
442
|
+
if (!chainInfo) {
|
|
443
|
+
continue
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const publicClient = getPublicRpcClient(chainInfo)
|
|
447
|
+
const receipt = await publicClient.getTransactionReceipt({
|
|
448
|
+
hash: hash as `0x${string}`,
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
// Decode Trails Token Sweeper events (refunds)
|
|
452
|
+
const sweeperEvents = decodeTrailsTokenSweeperEvents(receipt)
|
|
453
|
+
const hasRefund = sweeperEvents.some(
|
|
454
|
+
(event) => event.type === "Refund" || event.type === "RefundAndSweep",
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
// Decode Guest Module events (failures)
|
|
458
|
+
const guestModuleEvents = decodeGuestModuleEvents(receipt)
|
|
459
|
+
const hasCallFailed = guestModuleEvents.some(
|
|
460
|
+
(event) => event.type === "CallFailed",
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
if (hasRefund) {
|
|
464
|
+
logger.console.log("[trails-sdk] Found refund event in transaction", {
|
|
465
|
+
hash,
|
|
466
|
+
chainId,
|
|
467
|
+
})
|
|
468
|
+
return { refunded: true, failed: false }
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (hasCallFailed) {
|
|
472
|
+
logger.console.log(
|
|
473
|
+
"[trails-sdk] Found CallFailed event in transaction",
|
|
474
|
+
{ hash, chainId },
|
|
475
|
+
)
|
|
476
|
+
return { refunded: false, failed: true }
|
|
477
|
+
}
|
|
478
|
+
} catch (error) {
|
|
479
|
+
logger.console.warn(
|
|
480
|
+
"[trails-sdk] Failed to decode events for transaction",
|
|
481
|
+
{ hash, chainId, error },
|
|
482
|
+
)
|
|
483
|
+
// Continue checking other transactions
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return { refunded: false, failed: false }
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Calculates effective execution status based on transaction state and decoded events
|
|
492
|
+
*/
|
|
493
|
+
function getEffectiveExecutionStatus(
|
|
494
|
+
transaction: IntentTransaction,
|
|
495
|
+
txHashes: {
|
|
496
|
+
originIntentTxHash?: string
|
|
497
|
+
destinationIntentTxHash?: string
|
|
498
|
+
originIntentDepositTxHash?: string
|
|
499
|
+
destinationIntentDepositTxHash?: string
|
|
500
|
+
},
|
|
501
|
+
decodedEvents: { refunded: boolean; failed: boolean },
|
|
502
|
+
): string {
|
|
503
|
+
const {
|
|
504
|
+
executionStatus,
|
|
505
|
+
originChainId,
|
|
506
|
+
destinationChainId,
|
|
507
|
+
originIntentAddress,
|
|
508
|
+
destinationIntentAddress,
|
|
509
|
+
createdAt,
|
|
510
|
+
} = transaction
|
|
511
|
+
|
|
512
|
+
// If we decoded a refund, return "refunded"
|
|
513
|
+
if (decodedEvents.refunded) {
|
|
514
|
+
return "refunded"
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// If we decoded a failure, return "failed"
|
|
518
|
+
if (decodedEvents.failed) {
|
|
519
|
+
return "failed"
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// If API provided a status, use it
|
|
523
|
+
if (executionStatus && executionStatus !== "unknown") {
|
|
524
|
+
return executionStatus
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Check if this is a same-chain transaction
|
|
528
|
+
const isSameChain =
|
|
529
|
+
originIntentAddress?.toLowerCase() ===
|
|
530
|
+
destinationIntentAddress?.toLowerCase() &&
|
|
531
|
+
originChainId === destinationChainId
|
|
532
|
+
|
|
533
|
+
// Check if there's no destination
|
|
534
|
+
const hasNoDestination =
|
|
535
|
+
!destinationIntentAddress || !destinationChainId || isSameChain
|
|
536
|
+
|
|
537
|
+
// Check if it's been over 5 minutes since creation
|
|
538
|
+
const isOver5Minutes = createdAt
|
|
539
|
+
? Date.now() - new Date(createdAt).getTime() > 5 * 60 * 1000
|
|
540
|
+
: false
|
|
541
|
+
|
|
542
|
+
// Rule 1: If there's a destination intent tx, it's completed
|
|
543
|
+
if (txHashes.destinationIntentTxHash) {
|
|
544
|
+
return "completed"
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Rule 2: Only origin tx hash exists and no real destination (same-chain case)
|
|
548
|
+
if (txHashes.originIntentTxHash && originChainId && hasNoDestination) {
|
|
549
|
+
return "completed"
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// Rule 3: If there's a deposit but no action yet, status is pending
|
|
553
|
+
if (txHashes.originIntentDepositTxHash && !txHashes.originIntentTxHash) {
|
|
554
|
+
return "pending"
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Rule 4: Cross-chain with origin tx but no destination tx
|
|
558
|
+
if (
|
|
559
|
+
txHashes.originIntentTxHash &&
|
|
560
|
+
!txHashes.destinationIntentTxHash &&
|
|
561
|
+
originChainId &&
|
|
562
|
+
destinationChainId &&
|
|
563
|
+
!isSameChain &&
|
|
564
|
+
destinationIntentAddress
|
|
565
|
+
) {
|
|
566
|
+
return isOver5Minutes ? "failed" : "pending"
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Otherwise, use the original execution status or default to unknown
|
|
570
|
+
return executionStatus || "unknown"
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Enriches a single transaction with token info, transaction hashes, and status
|
|
575
|
+
*/
|
|
576
|
+
async function enrichTransaction(
|
|
577
|
+
transaction: IntentTransaction,
|
|
578
|
+
supportedTokens: Awaited<ReturnType<typeof getSupportedTokens>>,
|
|
579
|
+
trailsConfig: ReturnType<typeof useTrails>,
|
|
580
|
+
): Promise<IntentTransaction> {
|
|
581
|
+
// Get token info
|
|
582
|
+
const originToken =
|
|
583
|
+
transaction.originTokenAddress && transaction.originChainId
|
|
584
|
+
? await getTokenInfoForTransaction(
|
|
585
|
+
transaction.originTokenAddress,
|
|
586
|
+
transaction.originChainId,
|
|
587
|
+
supportedTokens,
|
|
588
|
+
)
|
|
589
|
+
: undefined
|
|
590
|
+
|
|
591
|
+
const destinationToken =
|
|
592
|
+
transaction.destinationTokenAddress && transaction.destinationChainId
|
|
593
|
+
? await getTokenInfoForTransaction(
|
|
594
|
+
transaction.destinationTokenAddress,
|
|
595
|
+
transaction.destinationChainId,
|
|
596
|
+
supportedTokens,
|
|
597
|
+
)
|
|
598
|
+
: undefined
|
|
599
|
+
|
|
600
|
+
// Check if origin and destination are the same
|
|
601
|
+
const isSameIntentAddress =
|
|
602
|
+
transaction.originIntentAddress?.toLowerCase() ===
|
|
603
|
+
transaction.destinationIntentAddress?.toLowerCase() &&
|
|
604
|
+
transaction.originChainId === transaction.destinationChainId
|
|
605
|
+
|
|
606
|
+
// Get transaction hashes from API or fetch from account history
|
|
607
|
+
let originIntentTxHash: string | undefined = transaction.originTransactionHash
|
|
608
|
+
let destinationIntentTxHash: string | undefined =
|
|
609
|
+
transaction.destinationTransactionHash
|
|
610
|
+
let originIntentTxExplorerUrl: string | undefined
|
|
611
|
+
let destinationIntentTxExplorerUrl: string | undefined
|
|
612
|
+
let originIntentDepositTxHash: string | undefined
|
|
613
|
+
let destinationIntentDepositTxHash: string | undefined
|
|
614
|
+
let originIntentDepositTxExplorerUrl: string | undefined
|
|
615
|
+
let destinationIntentDepositTxExplorerUrl: string | undefined
|
|
616
|
+
|
|
617
|
+
// Generate explorer URLs for API-provided transaction hashes
|
|
618
|
+
if (originIntentTxHash && transaction.originChainId) {
|
|
619
|
+
originIntentTxExplorerUrl = getExplorerUrl({
|
|
620
|
+
txHash: originIntentTxHash,
|
|
621
|
+
chainId: transaction.originChainId,
|
|
622
|
+
})
|
|
623
|
+
}
|
|
624
|
+
if (destinationIntentTxHash && transaction.destinationChainId) {
|
|
625
|
+
destinationIntentTxExplorerUrl = getExplorerUrl({
|
|
626
|
+
txHash: destinationIntentTxHash,
|
|
627
|
+
chainId: transaction.destinationChainId,
|
|
628
|
+
})
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Get origin intent transaction hashes if not provided by API
|
|
632
|
+
const originHashes = await getOriginIntentTransactionHashes(
|
|
633
|
+
transaction,
|
|
634
|
+
trailsConfig,
|
|
635
|
+
)
|
|
636
|
+
if (originHashes.originIntentTxHash) {
|
|
637
|
+
originIntentTxHash = originHashes.originIntentTxHash
|
|
638
|
+
originIntentTxExplorerUrl = originHashes.originIntentTxExplorerUrl
|
|
639
|
+
}
|
|
640
|
+
if (originHashes.originIntentDepositTxHash) {
|
|
641
|
+
originIntentDepositTxHash = originHashes.originIntentDepositTxHash
|
|
642
|
+
originIntentDepositTxExplorerUrl =
|
|
643
|
+
originHashes.originIntentDepositTxExplorerUrl
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Get destination intent transaction hashes if not provided by API
|
|
647
|
+
const destinationHashes = await getDestinationIntentTransactionHashes(
|
|
648
|
+
transaction,
|
|
649
|
+
isSameIntentAddress,
|
|
650
|
+
trailsConfig,
|
|
651
|
+
)
|
|
652
|
+
if (destinationHashes.destinationIntentTxHash) {
|
|
653
|
+
destinationIntentTxHash = destinationHashes.destinationIntentTxHash
|
|
654
|
+
destinationIntentTxExplorerUrl =
|
|
655
|
+
destinationHashes.destinationIntentTxExplorerUrl
|
|
656
|
+
}
|
|
657
|
+
if (destinationHashes.destinationIntentDepositTxHash) {
|
|
658
|
+
destinationIntentDepositTxHash =
|
|
659
|
+
destinationHashes.destinationIntentDepositTxHash
|
|
660
|
+
destinationIntentDepositTxExplorerUrl =
|
|
661
|
+
destinationHashes.destinationIntentDepositTxExplorerUrl
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
// Decode events for executing transactions
|
|
665
|
+
const decodedEvents = await decodeTransactionEvents(transaction, {
|
|
666
|
+
originIntentTxHash,
|
|
667
|
+
destinationIntentTxHash,
|
|
668
|
+
originIntentDepositTxHash,
|
|
669
|
+
destinationIntentDepositTxHash,
|
|
670
|
+
})
|
|
671
|
+
|
|
672
|
+
// Calculate effective execution status
|
|
673
|
+
const effectiveExecutionStatus = getEffectiveExecutionStatus(
|
|
674
|
+
transaction,
|
|
675
|
+
{
|
|
676
|
+
originIntentTxHash,
|
|
677
|
+
destinationIntentTxHash,
|
|
678
|
+
originIntentDepositTxHash,
|
|
679
|
+
destinationIntentDepositTxHash,
|
|
680
|
+
},
|
|
681
|
+
decodedEvents,
|
|
682
|
+
)
|
|
683
|
+
|
|
684
|
+
// Return enriched transaction
|
|
685
|
+
return {
|
|
686
|
+
...transaction,
|
|
687
|
+
...(isSameIntentAddress
|
|
688
|
+
? {
|
|
689
|
+
destinationIntentAddress: "",
|
|
690
|
+
destinationChainId: undefined,
|
|
691
|
+
}
|
|
692
|
+
: {}),
|
|
693
|
+
originToken,
|
|
694
|
+
destinationToken,
|
|
695
|
+
originIntentTxHash,
|
|
696
|
+
destinationIntentTxHash,
|
|
697
|
+
originIntentTxExplorerUrl,
|
|
698
|
+
destinationIntentTxExplorerUrl,
|
|
699
|
+
originIntentDepositTxHash,
|
|
700
|
+
destinationIntentDepositTxHash,
|
|
701
|
+
originIntentDepositTxExplorerUrl,
|
|
702
|
+
destinationIntentDepositTxExplorerUrl,
|
|
703
|
+
executionStatus: effectiveExecutionStatus,
|
|
704
|
+
}
|
|
705
|
+
}
|
|
12
706
|
|
|
13
707
|
export type UseIntentTransactionHistoryParams = {
|
|
14
708
|
accountAddress?: string
|
|
@@ -42,6 +736,73 @@ export function useIntentTransactionHistory({
|
|
|
42
736
|
const [page, setPage] = useState(0)
|
|
43
737
|
const [hasMore, setHasMore] = useState(false)
|
|
44
738
|
|
|
739
|
+
/**
|
|
740
|
+
* Fetches intent transaction history from the API
|
|
741
|
+
*/
|
|
742
|
+
const fetchIntentTransactionHistoryFromApi = useCallback(
|
|
743
|
+
async (
|
|
744
|
+
accountAddress: string,
|
|
745
|
+
pageSize: number,
|
|
746
|
+
pageNum: number,
|
|
747
|
+
apiKey: string,
|
|
748
|
+
apiUrl: string,
|
|
749
|
+
) => {
|
|
750
|
+
if (!apiKey) {
|
|
751
|
+
throw new Error("Trails api key is required")
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
const trailsClient = getTrailsClient({ apiKey, hostname: apiUrl })
|
|
755
|
+
|
|
756
|
+
const requestParams = {
|
|
757
|
+
byOwnerAddress: accountAddress,
|
|
758
|
+
page: {
|
|
759
|
+
pageSize,
|
|
760
|
+
sort: [
|
|
761
|
+
{
|
|
762
|
+
column: "created_at",
|
|
763
|
+
order: SortOrder.DESC,
|
|
764
|
+
},
|
|
765
|
+
],
|
|
766
|
+
},
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
logger.console.log(
|
|
770
|
+
"[trails-sdk] getIntentTransactionHistory request:",
|
|
771
|
+
requestParams,
|
|
772
|
+
)
|
|
773
|
+
|
|
774
|
+
const apiResult =
|
|
775
|
+
await trailsClient.getIntentTransactionHistory(requestParams)
|
|
776
|
+
|
|
777
|
+
logger.console.log("[trails-sdk] getIntentTransactionHistory response:", {
|
|
778
|
+
intentCount: apiResult.intents?.length || 0,
|
|
779
|
+
hasNextPage: !!apiResult.nextPage,
|
|
780
|
+
firstIntent: apiResult.intents?.[0],
|
|
781
|
+
})
|
|
782
|
+
|
|
783
|
+
// Map API response to IntentTransaction
|
|
784
|
+
const mappedTransactions: IntentTransaction[] = (
|
|
785
|
+
apiResult.intents || []
|
|
786
|
+
).map(mapIntentSummaryToTransaction)
|
|
787
|
+
|
|
788
|
+
return {
|
|
789
|
+
transactions: mappedTransactions,
|
|
790
|
+
page: apiResult.nextPage
|
|
791
|
+
? {
|
|
792
|
+
page: pageNum,
|
|
793
|
+
pageSize,
|
|
794
|
+
more: apiResult.nextPage.more || false,
|
|
795
|
+
}
|
|
796
|
+
: {
|
|
797
|
+
page: pageNum,
|
|
798
|
+
pageSize,
|
|
799
|
+
more: false,
|
|
800
|
+
},
|
|
801
|
+
}
|
|
802
|
+
},
|
|
803
|
+
[],
|
|
804
|
+
)
|
|
805
|
+
|
|
45
806
|
const fetchTransactions = useCallback(
|
|
46
807
|
async (pageNum: number = 0, append: boolean = false) => {
|
|
47
808
|
if (!accountAddress || !enabled) return
|
|
@@ -50,423 +811,26 @@ export function useIntentTransactionHistory({
|
|
|
50
811
|
setError(null)
|
|
51
812
|
|
|
52
813
|
try {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
(result.transactions || []).map(async (transaction) => {
|
|
65
|
-
let originToken:
|
|
66
|
-
| {
|
|
67
|
-
symbol: string
|
|
68
|
-
name: string
|
|
69
|
-
decimals: number
|
|
70
|
-
imageUrl: string
|
|
71
|
-
chainId: number
|
|
72
|
-
}
|
|
73
|
-
| undefined
|
|
74
|
-
let destinationToken:
|
|
75
|
-
| {
|
|
76
|
-
symbol: string
|
|
77
|
-
name: string
|
|
78
|
-
decimals: number
|
|
79
|
-
imageUrl: string
|
|
80
|
-
chainId: number
|
|
81
|
-
}
|
|
82
|
-
| undefined
|
|
83
|
-
|
|
84
|
-
// Get supported tokens once for lookup
|
|
85
|
-
const supportedTokens = await getSupportedTokens()
|
|
86
|
-
|
|
87
|
-
// Get origin token info
|
|
88
|
-
if (transaction.originTokenAddress && transaction.originChainId) {
|
|
89
|
-
const isNativeOrigin =
|
|
90
|
-
transaction.originTokenAddress ===
|
|
91
|
-
"0x0000000000000000000000000000000000000000"
|
|
92
|
-
|
|
93
|
-
if (isNativeOrigin) {
|
|
94
|
-
// For native tokens, find the matching native token by chain ID and address
|
|
95
|
-
const nativeToken = supportedTokens.find(
|
|
96
|
-
(token) =>
|
|
97
|
-
token.contractAddress.toLowerCase() ===
|
|
98
|
-
transaction.originTokenAddress!.toLowerCase() &&
|
|
99
|
-
token.chainId === transaction.originChainId,
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
if (nativeToken) {
|
|
103
|
-
originToken = {
|
|
104
|
-
symbol: nativeToken.symbol,
|
|
105
|
-
name: nativeToken.name,
|
|
106
|
-
decimals: nativeToken.decimals,
|
|
107
|
-
imageUrl: nativeToken.imageUrl,
|
|
108
|
-
chainId: nativeToken.chainId,
|
|
109
|
-
}
|
|
110
|
-
} else {
|
|
111
|
-
// Fallback for native token - use chain-specific default
|
|
112
|
-
originToken = {
|
|
113
|
-
symbol: "ETH", // Could be improved to detect chain-specific native tokens
|
|
114
|
-
name: "Native Token",
|
|
115
|
-
decimals: 18,
|
|
116
|
-
imageUrl:
|
|
117
|
-
"https://assets.sequence.info/images/tokens/large/1/0x0000000000000000000000000000000000000000.webp",
|
|
118
|
-
chainId: transaction.originChainId,
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
// For ERC20 tokens, first check supported tokens by address and chain
|
|
123
|
-
const supportedToken = supportedTokens.find(
|
|
124
|
-
(token) =>
|
|
125
|
-
token.contractAddress.toLowerCase() ===
|
|
126
|
-
transaction.originTokenAddress!.toLowerCase() &&
|
|
127
|
-
token.chainId === transaction.originChainId,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
if (supportedToken) {
|
|
131
|
-
originToken = {
|
|
132
|
-
symbol: supportedToken.symbol,
|
|
133
|
-
name: supportedToken.name,
|
|
134
|
-
decimals: supportedToken.decimals,
|
|
135
|
-
imageUrl: supportedToken.imageUrl,
|
|
136
|
-
chainId: supportedToken.chainId,
|
|
137
|
-
}
|
|
138
|
-
} else {
|
|
139
|
-
// Fallback to getTokenInfo for on-chain lookup with the specific chain ID
|
|
140
|
-
try {
|
|
141
|
-
const tokenInfo = await getTokenInfo(
|
|
142
|
-
transaction.originChainId,
|
|
143
|
-
transaction.originTokenAddress,
|
|
144
|
-
)
|
|
145
|
-
if (tokenInfo) {
|
|
146
|
-
originToken = {
|
|
147
|
-
symbol: tokenInfo.symbol,
|
|
148
|
-
name: tokenInfo.name,
|
|
149
|
-
decimals: tokenInfo.decimals,
|
|
150
|
-
imageUrl: tokenInfo.imageUrl,
|
|
151
|
-
chainId: tokenInfo.chainId,
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
} catch (error) {
|
|
155
|
-
logger.console.warn(
|
|
156
|
-
"[trails-sdk] Failed to get origin token info for:",
|
|
157
|
-
transaction.originTokenAddress,
|
|
158
|
-
"on chain",
|
|
159
|
-
transaction.originChainId,
|
|
160
|
-
error,
|
|
161
|
-
)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Get destination token info
|
|
168
|
-
if (
|
|
169
|
-
transaction.destinationTokenAddress &&
|
|
170
|
-
transaction.destinationChainId
|
|
171
|
-
) {
|
|
172
|
-
const isNativeDestination =
|
|
173
|
-
transaction.destinationTokenAddress ===
|
|
174
|
-
"0x0000000000000000000000000000000000000000"
|
|
175
|
-
|
|
176
|
-
if (isNativeDestination) {
|
|
177
|
-
// For native tokens, find the matching native token by chain ID and address
|
|
178
|
-
const nativeToken = supportedTokens.find(
|
|
179
|
-
(token) =>
|
|
180
|
-
token.contractAddress.toLowerCase() ===
|
|
181
|
-
transaction.destinationTokenAddress!.toLowerCase() &&
|
|
182
|
-
token.chainId === transaction.destinationChainId,
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
if (nativeToken) {
|
|
186
|
-
destinationToken = {
|
|
187
|
-
symbol: nativeToken.symbol,
|
|
188
|
-
name: nativeToken.name,
|
|
189
|
-
decimals: nativeToken.decimals,
|
|
190
|
-
imageUrl: nativeToken.imageUrl,
|
|
191
|
-
chainId: nativeToken.chainId,
|
|
192
|
-
}
|
|
193
|
-
} else {
|
|
194
|
-
// Fallback for native token - use chain-specific default
|
|
195
|
-
destinationToken = {
|
|
196
|
-
symbol: "ETH", // Could be improved to detect chain-specific native tokens
|
|
197
|
-
name: "Native Token",
|
|
198
|
-
decimals: 18,
|
|
199
|
-
imageUrl:
|
|
200
|
-
"https://assets.sequence.info/images/tokens/large/1/0x0000000000000000000000000000000000000000.webp",
|
|
201
|
-
chainId: transaction.destinationChainId,
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
} else {
|
|
205
|
-
// For ERC20 tokens, first check supported tokens by address and chain
|
|
206
|
-
const supportedToken = supportedTokens.find(
|
|
207
|
-
(token) =>
|
|
208
|
-
token.contractAddress.toLowerCase() ===
|
|
209
|
-
transaction.destinationTokenAddress!.toLowerCase() &&
|
|
210
|
-
token.chainId === transaction.destinationChainId,
|
|
211
|
-
)
|
|
212
|
-
|
|
213
|
-
if (supportedToken) {
|
|
214
|
-
destinationToken = {
|
|
215
|
-
symbol: supportedToken.symbol,
|
|
216
|
-
name: supportedToken.name,
|
|
217
|
-
decimals: supportedToken.decimals,
|
|
218
|
-
imageUrl: supportedToken.imageUrl,
|
|
219
|
-
chainId: supportedToken.chainId,
|
|
220
|
-
}
|
|
221
|
-
} else {
|
|
222
|
-
// Fallback to getTokenInfo for on-chain lookup with the specific chain ID
|
|
223
|
-
try {
|
|
224
|
-
const tokenInfo = await getTokenInfo(
|
|
225
|
-
transaction.destinationChainId,
|
|
226
|
-
transaction.destinationTokenAddress,
|
|
227
|
-
)
|
|
228
|
-
if (tokenInfo) {
|
|
229
|
-
destinationToken = {
|
|
230
|
-
symbol: tokenInfo.symbol,
|
|
231
|
-
name: tokenInfo.name,
|
|
232
|
-
decimals: tokenInfo.decimals,
|
|
233
|
-
imageUrl: tokenInfo.imageUrl,
|
|
234
|
-
chainId: tokenInfo.chainId,
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
} catch (error) {
|
|
238
|
-
logger.console.warn(
|
|
239
|
-
"[trails-sdk] Failed to get destination token info for:",
|
|
240
|
-
transaction.destinationTokenAddress,
|
|
241
|
-
"on chain",
|
|
242
|
-
transaction.destinationChainId,
|
|
243
|
-
error,
|
|
244
|
-
)
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Check if origin and destination are the same
|
|
251
|
-
const isSameIntentAddress =
|
|
252
|
-
transaction.originIntentAddress?.toLowerCase() ===
|
|
253
|
-
transaction.destinationIntentAddress?.toLowerCase() &&
|
|
254
|
-
transaction.originChainId === transaction.destinationChainId
|
|
255
|
-
|
|
256
|
-
// Fetch intent wallet transaction hashes
|
|
257
|
-
let originIntentTxHash: string | undefined
|
|
258
|
-
let destinationIntentTxHash: string | undefined
|
|
259
|
-
let originIntentTxExplorerUrl: string | undefined
|
|
260
|
-
let destinationIntentTxExplorerUrl: string | undefined
|
|
261
|
-
let originIntentDepositTxHash: string | undefined
|
|
262
|
-
let destinationIntentDepositTxHash: string | undefined
|
|
263
|
-
let originIntentDepositTxExplorerUrl: string | undefined
|
|
264
|
-
let destinationIntentDepositTxExplorerUrl: string | undefined
|
|
265
|
-
|
|
266
|
-
// Get origin intent transaction hashes (both deposit and action)
|
|
267
|
-
if (transaction.originIntentAddress && transaction.originChainId) {
|
|
268
|
-
try {
|
|
269
|
-
const originHistory = await getAccountTransactionHistory({
|
|
270
|
-
chainId: transaction.originChainId,
|
|
271
|
-
accountAddress: transaction.originIntentAddress,
|
|
272
|
-
pageSize: 10, // Fetch more to find both deposit and action txs
|
|
273
|
-
page: 0,
|
|
274
|
-
includeMetadata: true, // Need metadata to check transfer direction
|
|
275
|
-
apiKey: trailsConfig.trailsApiKey,
|
|
276
|
-
indexerUrl: trailsConfig.sequenceIndexerUrl!,
|
|
277
|
-
})
|
|
278
|
-
if (
|
|
279
|
-
originHistory?.transactions &&
|
|
280
|
-
originHistory.transactions.length > 0
|
|
281
|
-
) {
|
|
282
|
-
const intentAddress =
|
|
283
|
-
transaction.originIntentAddress.toLowerCase()
|
|
284
|
-
|
|
285
|
-
// Find first deposit tx (transfer TO intent address)
|
|
286
|
-
const depositTx = originHistory.transactions.find((tx) =>
|
|
287
|
-
tx.transfers?.some(
|
|
288
|
-
(transfer) => transfer.to.toLowerCase() === intentAddress,
|
|
289
|
-
),
|
|
290
|
-
)
|
|
291
|
-
if (depositTx) {
|
|
292
|
-
originIntentDepositTxHash = depositTx.txnHash
|
|
293
|
-
originIntentDepositTxExplorerUrl = getExplorerUrl({
|
|
294
|
-
txHash: depositTx.txnHash,
|
|
295
|
-
chainId: transaction.originChainId,
|
|
296
|
-
})
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Find first action tx (transfer FROM intent address)
|
|
300
|
-
const actionTx = originHistory.transactions.find((tx) =>
|
|
301
|
-
tx.transfers?.some(
|
|
302
|
-
(transfer) =>
|
|
303
|
-
transfer.from.toLowerCase() === intentAddress,
|
|
304
|
-
),
|
|
305
|
-
)
|
|
306
|
-
if (actionTx) {
|
|
307
|
-
originIntentTxHash = actionTx.txnHash
|
|
308
|
-
originIntentTxExplorerUrl = getExplorerUrl({
|
|
309
|
-
txHash: actionTx.txnHash,
|
|
310
|
-
chainId: transaction.originChainId,
|
|
311
|
-
})
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
} catch (error) {
|
|
315
|
-
logger.console.warn(
|
|
316
|
-
"[trails-sdk] Failed to get origin intent transaction hashes for:",
|
|
317
|
-
transaction.originIntentAddress,
|
|
318
|
-
"on chain",
|
|
319
|
-
transaction.originChainId,
|
|
320
|
-
error,
|
|
321
|
-
)
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Get destination intent transaction hashes (only if different from origin)
|
|
326
|
-
if (
|
|
327
|
-
!isSameIntentAddress &&
|
|
328
|
-
transaction.destinationIntentAddress &&
|
|
329
|
-
transaction.destinationChainId
|
|
330
|
-
) {
|
|
331
|
-
try {
|
|
332
|
-
const destinationHistory = await getAccountTransactionHistory({
|
|
333
|
-
chainId: transaction.destinationChainId,
|
|
334
|
-
accountAddress: transaction.destinationIntentAddress,
|
|
335
|
-
pageSize: 10, // Fetch more to find both deposit and action txs
|
|
336
|
-
page: 0,
|
|
337
|
-
includeMetadata: true, // Need metadata to check transfer direction
|
|
338
|
-
apiKey: trailsConfig.trailsApiKey,
|
|
339
|
-
indexerUrl: trailsConfig.sequenceIndexerUrl!,
|
|
340
|
-
})
|
|
341
|
-
if (
|
|
342
|
-
destinationHistory?.transactions &&
|
|
343
|
-
destinationHistory.transactions.length > 0
|
|
344
|
-
) {
|
|
345
|
-
const intentAddress =
|
|
346
|
-
transaction.destinationIntentAddress.toLowerCase()
|
|
347
|
-
|
|
348
|
-
// Find first deposit tx (transfer TO intent address)
|
|
349
|
-
const depositTx = destinationHistory.transactions.find((tx) =>
|
|
350
|
-
tx.transfers?.some(
|
|
351
|
-
(transfer) => transfer.to.toLowerCase() === intentAddress,
|
|
352
|
-
),
|
|
353
|
-
)
|
|
354
|
-
if (depositTx) {
|
|
355
|
-
destinationIntentDepositTxHash = depositTx.txnHash
|
|
356
|
-
destinationIntentDepositTxExplorerUrl = getExplorerUrl({
|
|
357
|
-
txHash: depositTx.txnHash,
|
|
358
|
-
chainId: transaction.destinationChainId,
|
|
359
|
-
})
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
// Find first action tx (transfer FROM intent address)
|
|
363
|
-
const actionTx = destinationHistory.transactions.find((tx) =>
|
|
364
|
-
tx.transfers?.some(
|
|
365
|
-
(transfer) =>
|
|
366
|
-
transfer.from.toLowerCase() === intentAddress,
|
|
367
|
-
),
|
|
368
|
-
)
|
|
369
|
-
if (actionTx) {
|
|
370
|
-
destinationIntentTxHash = actionTx.txnHash
|
|
371
|
-
destinationIntentTxExplorerUrl = getExplorerUrl({
|
|
372
|
-
txHash: actionTx.txnHash,
|
|
373
|
-
chainId: transaction.destinationChainId,
|
|
374
|
-
})
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
} catch (error) {
|
|
378
|
-
logger.console.warn(
|
|
379
|
-
"[trails-sdk] Failed to get destination intent transaction hashes for:",
|
|
380
|
-
transaction.destinationIntentAddress,
|
|
381
|
-
"on chain",
|
|
382
|
-
transaction.destinationChainId,
|
|
383
|
-
error,
|
|
384
|
-
)
|
|
385
|
-
}
|
|
386
|
-
}
|
|
814
|
+
const apiKey = trailsConfig.trailsApiKey || ""
|
|
815
|
+
const apiUrl = trailsConfig.trailsApiUrl!
|
|
816
|
+
|
|
817
|
+
// Fetch intent transaction history from API
|
|
818
|
+
const result = await fetchIntentTransactionHistoryFromApi(
|
|
819
|
+
accountAddress,
|
|
820
|
+
pageSize,
|
|
821
|
+
pageNum,
|
|
822
|
+
apiKey,
|
|
823
|
+
apiUrl,
|
|
824
|
+
)
|
|
387
825
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
const {
|
|
391
|
-
executionStatus,
|
|
392
|
-
originChainId,
|
|
393
|
-
destinationChainId,
|
|
394
|
-
originIntentAddress,
|
|
395
|
-
destinationIntentAddress,
|
|
396
|
-
createdAt,
|
|
397
|
-
} = transaction
|
|
398
|
-
|
|
399
|
-
// Check if this is a same-chain transaction (same address and chain)
|
|
400
|
-
const isSameChain =
|
|
401
|
-
originIntentAddress?.toLowerCase() ===
|
|
402
|
-
destinationIntentAddress?.toLowerCase() &&
|
|
403
|
-
originChainId === destinationChainId
|
|
404
|
-
|
|
405
|
-
// Check if there's no destination (same-chain or no destination intent)
|
|
406
|
-
const hasNoDestination =
|
|
407
|
-
!destinationIntentAddress || !destinationChainId || isSameChain
|
|
408
|
-
|
|
409
|
-
// Check if it's been over 5 minutes since creation
|
|
410
|
-
const isOver5Minutes = createdAt
|
|
411
|
-
? Date.now() - new Date(createdAt).getTime() > 5 * 60 * 1000
|
|
412
|
-
: false
|
|
413
|
-
|
|
414
|
-
// Rule 1: If there's a destination intent tx, it's completed
|
|
415
|
-
if (destinationIntentTxHash) {
|
|
416
|
-
return "completed"
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// Rule 2: Only origin tx hash exists and no real destination (same-chain case)
|
|
420
|
-
if (originIntentTxHash && originChainId && hasNoDestination) {
|
|
421
|
-
return "completed"
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// Rule 3: If there's a deposit but no action yet, status is pending
|
|
425
|
-
if (originIntentDepositTxHash && !originIntentTxHash) {
|
|
426
|
-
return "pending"
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
// Rule 4: Cross-chain with origin tx but no destination tx
|
|
430
|
-
// If over 5 minutes, consider it failed; otherwise pending
|
|
431
|
-
if (
|
|
432
|
-
originIntentTxHash &&
|
|
433
|
-
!destinationIntentTxHash &&
|
|
434
|
-
originChainId &&
|
|
435
|
-
destinationChainId &&
|
|
436
|
-
!isSameChain &&
|
|
437
|
-
destinationIntentAddress
|
|
438
|
-
) {
|
|
439
|
-
return isOver5Minutes ? "failed" : "pending"
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
// Otherwise, use the original execution status
|
|
443
|
-
return executionStatus || "unknown"
|
|
444
|
-
}
|
|
826
|
+
// Get supported tokens once for all transactions
|
|
827
|
+
const supportedTokens = await getSupportedTokens()
|
|
445
828
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
...(isSameIntentAddress
|
|
452
|
-
? {
|
|
453
|
-
destinationIntentAddress: "",
|
|
454
|
-
destinationChainId: undefined,
|
|
455
|
-
}
|
|
456
|
-
: {}),
|
|
457
|
-
originToken,
|
|
458
|
-
destinationToken,
|
|
459
|
-
originIntentTxHash,
|
|
460
|
-
destinationIntentTxHash,
|
|
461
|
-
originIntentTxExplorerUrl,
|
|
462
|
-
destinationIntentTxExplorerUrl,
|
|
463
|
-
originIntentDepositTxHash,
|
|
464
|
-
destinationIntentDepositTxHash,
|
|
465
|
-
originIntentDepositTxExplorerUrl,
|
|
466
|
-
destinationIntentDepositTxExplorerUrl,
|
|
467
|
-
executionStatus: effectiveExecutionStatus,
|
|
468
|
-
}
|
|
469
|
-
}),
|
|
829
|
+
// Enrich transactions with token information, transaction hashes, and status
|
|
830
|
+
const enrichedTransactions = await Promise.all(
|
|
831
|
+
(result.transactions || []).map(async (transaction) =>
|
|
832
|
+
enrichTransaction(transaction, supportedTokens, trailsConfig),
|
|
833
|
+
),
|
|
470
834
|
)
|
|
471
835
|
|
|
472
836
|
if (append) {
|
|
@@ -491,7 +855,13 @@ export function useIntentTransactionHistory({
|
|
|
491
855
|
setLoading(false)
|
|
492
856
|
}
|
|
493
857
|
},
|
|
494
|
-
[
|
|
858
|
+
[
|
|
859
|
+
accountAddress,
|
|
860
|
+
enabled,
|
|
861
|
+
pageSize,
|
|
862
|
+
trailsConfig,
|
|
863
|
+
fetchIntentTransactionHistoryFromApi,
|
|
864
|
+
],
|
|
495
865
|
)
|
|
496
866
|
|
|
497
867
|
const refetch = () => {
|