0xtrails 0.8.2 → 0.8.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/aave.d.ts.map +1 -1
- package/dist/{ccip-ru_Yzdas.js → ccip-BKavX04a.js} +13 -13
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/fees.d.ts +11 -17
- package/dist/fees.d.ts.map +1 -1
- package/dist/gasless.d.ts.map +1 -1
- package/dist/{index-Si7cO9V7.js → index-D5kULpIU.js} +20430 -20133
- package/dist/index.js +425 -847
- package/dist/intents.d.ts +1 -2
- package/dist/intents.d.ts.map +1 -1
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/recover.d.ts +8 -9
- package/dist/recover.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +51 -0
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/trailsRouter.d.ts +15 -0
- package/dist/trailsRouter.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +1 -3
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +1 -3
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/crossChain.d.ts +2 -4
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +5 -4
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +1 -1
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +1 -1
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
- package/dist/transactionIntent/types.d.ts +11 -18
- package/dist/transactionIntent/types.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +1 -0
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +1 -0
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts +2 -1
- package/dist/widget/components/SlippageToleranceSettings.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +1 -0
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/WidgetProviders.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +1 -1
- package/dist/widget/hooks/useDefaultDestinationToken.d.ts +20 -0
- package/dist/widget/hooks/useDefaultDestinationToken.d.ts.map +1 -0
- package/dist/widget/hooks/{useDefaultTokenSelection.d.ts → useDefaultOriginToken.d.ts} +4 -16
- package/dist/widget/hooks/useDefaultOriginToken.d.ts.map +1 -0
- package/dist/widget/hooks/useQuote.d.ts +94 -35
- package/dist/widget/hooks/useQuote.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +2 -2
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTrailsSendTransaction.d.ts.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/aave.ts +4 -0
- package/src/constants.ts +4 -0
- package/src/fees.ts +47 -72
- package/src/gasless.ts +62 -32
- package/src/intents.ts +1 -3
- package/src/morpho.ts +1 -1
- package/src/prepareSend.ts +42 -6
- package/src/recover.ts +116 -172
- package/src/tokenBalances.ts +301 -1
- package/src/trailsRouter.ts +77 -0
- package/src/transactionIntent/deposits/depositOrchestrator.ts +0 -6
- package/src/transactionIntent/deposits/standardDeposit.ts +167 -184
- package/src/transactionIntent/handlers/crossChain.ts +8 -11
- package/src/transactionIntent/handlers/sameChainSameToken.ts +619 -608
- package/src/transactionIntent/quote/normalizeQuote.ts +32 -46
- package/src/transactionIntent/quote/quoteHelpers.ts +4 -2
- package/src/transactionIntent/types.ts +11 -18
- package/src/widget/compiled.css +1 -1
- package/src/widget/components/AccountIntentTransactionHistory.tsx +50 -18
- package/src/widget/components/ClassicSwap.tsx +158 -63
- package/src/widget/components/DynamicSizeInputField.tsx +2 -0
- package/src/widget/components/Fund.tsx +12 -11
- package/src/widget/components/FundSwap.tsx +1 -0
- package/src/widget/components/Pay.tsx +15 -14
- package/src/widget/components/QuoteDetails.tsx +18 -27
- package/src/widget/components/SlippageToleranceSettings.tsx +55 -25
- package/src/widget/components/Swap.tsx +1 -0
- package/src/widget/components/WidgetProviders.tsx +1 -6
- package/src/widget/hooks/useDefaultDestinationToken.tsx +173 -0
- package/src/widget/hooks/{useDefaultTokenSelection.tsx → useDefaultOriginToken.tsx} +58 -191
- package/src/widget/hooks/useQuote.ts +317 -79
- package/src/widget/hooks/useSendForm.ts +123 -764
- package/src/widget/hooks/useTrailsSendTransaction.ts +0 -2
- package/src/widget/widget.tsx +2 -0
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +0 -1
package/src/gasless.ts
CHANGED
|
@@ -147,51 +147,81 @@ export async function getPermitSignature({
|
|
|
147
147
|
args: [signer],
|
|
148
148
|
})
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
{
|
|
154
|
-
name: "name",
|
|
155
|
-
type: "function",
|
|
156
|
-
stateMutability: "view",
|
|
157
|
-
inputs: [],
|
|
158
|
-
outputs: [{ name: "", type: "string" }],
|
|
159
|
-
},
|
|
160
|
-
],
|
|
161
|
-
functionName: "name",
|
|
162
|
-
})) as string
|
|
150
|
+
// Fetch EIP-5267 eip712Domain() first - this returns the exact domain parameters used by the contract
|
|
151
|
+
let name: string
|
|
152
|
+
let version: string
|
|
163
153
|
|
|
164
|
-
let version = "1" // fallback default
|
|
165
154
|
try {
|
|
166
|
-
|
|
155
|
+
const eip712Domain = (await publicClient.readContract({
|
|
167
156
|
address: tokenAddress as `0x${string}`,
|
|
168
157
|
abi: [
|
|
169
158
|
{
|
|
170
|
-
name: "
|
|
159
|
+
name: "eip712Domain",
|
|
171
160
|
type: "function",
|
|
172
161
|
stateMutability: "view",
|
|
173
162
|
inputs: [],
|
|
174
|
-
outputs: [
|
|
163
|
+
outputs: [
|
|
164
|
+
{ name: "fields", type: "bytes1" },
|
|
165
|
+
{ name: "name", type: "string" },
|
|
166
|
+
{ name: "version", type: "string" },
|
|
167
|
+
{ name: "chainId", type: "uint256" },
|
|
168
|
+
{ name: "verifyingContract", type: "address" },
|
|
169
|
+
{ name: "salt", type: "bytes32" },
|
|
170
|
+
{ name: "extensions", type: "uint256[]" },
|
|
171
|
+
],
|
|
175
172
|
},
|
|
176
173
|
],
|
|
177
|
-
functionName: "
|
|
178
|
-
})) as string
|
|
179
|
-
logger.console.log("[trails-sdk] Token version from contract:", version)
|
|
180
|
-
} catch (error) {
|
|
181
|
-
logger.console.warn(
|
|
182
|
-
"[trails-sdk] Token does not implement version(), defaulting to '1'",
|
|
183
|
-
error,
|
|
184
|
-
)
|
|
185
|
-
}
|
|
174
|
+
functionName: "eip712Domain",
|
|
175
|
+
})) as [string, string, string, bigint, string, string, bigint[]]
|
|
186
176
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
177
|
+
name = eip712Domain[1]
|
|
178
|
+
version = eip712Domain[2]
|
|
179
|
+
logger.console.log(
|
|
180
|
+
"[trails-sdk] EIP-5267 eip712Domain() supported, using domain:",
|
|
181
|
+
{ name, version },
|
|
182
|
+
)
|
|
183
|
+
} catch {
|
|
184
|
+
// EIP-5267 not supported, fall back to reading name() and version()
|
|
191
185
|
logger.console.log(
|
|
192
|
-
"[trails-sdk]
|
|
186
|
+
"[trails-sdk] EIP-5267 not supported, falling back to name()/version()",
|
|
193
187
|
)
|
|
194
|
-
|
|
188
|
+
|
|
189
|
+
name = (await publicClient.readContract({
|
|
190
|
+
address: tokenAddress as `0x${string}`,
|
|
191
|
+
abi: [
|
|
192
|
+
{
|
|
193
|
+
name: "name",
|
|
194
|
+
type: "function",
|
|
195
|
+
stateMutability: "view",
|
|
196
|
+
inputs: [],
|
|
197
|
+
outputs: [{ name: "", type: "string" }],
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
functionName: "name",
|
|
201
|
+
})) as string
|
|
202
|
+
|
|
203
|
+
version = "1" // fallback default EIP-712 version
|
|
204
|
+
try {
|
|
205
|
+
version = (await publicClient.readContract({
|
|
206
|
+
address: tokenAddress as `0x${string}`,
|
|
207
|
+
abi: [
|
|
208
|
+
{
|
|
209
|
+
name: "version",
|
|
210
|
+
type: "function",
|
|
211
|
+
stateMutability: "view",
|
|
212
|
+
inputs: [],
|
|
213
|
+
outputs: [{ name: "", type: "string" }],
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
functionName: "version",
|
|
217
|
+
})) as string
|
|
218
|
+
logger.console.log("[trails-sdk] Token version from contract:", version)
|
|
219
|
+
} catch (error) {
|
|
220
|
+
logger.console.warn(
|
|
221
|
+
"[trails-sdk] Token does not implement version(), defaulting to '1'",
|
|
222
|
+
error,
|
|
223
|
+
)
|
|
224
|
+
}
|
|
195
225
|
}
|
|
196
226
|
|
|
197
227
|
// Log domain parameters for debugging
|
package/src/intents.ts
CHANGED
|
@@ -822,18 +822,16 @@ export function buildCrossChainDepositParams({
|
|
|
822
822
|
originTokenAddress,
|
|
823
823
|
originIntentAddress,
|
|
824
824
|
depositAmount,
|
|
825
|
-
fee,
|
|
826
825
|
originChainId,
|
|
827
826
|
chain,
|
|
828
827
|
}: {
|
|
829
828
|
originTokenAddress: string
|
|
830
829
|
originIntentAddress: string
|
|
831
830
|
depositAmount: string
|
|
832
|
-
fee: string
|
|
833
831
|
originChainId: number
|
|
834
832
|
chain: Chain
|
|
835
833
|
}) {
|
|
836
|
-
const totalAmount = BigInt(depositAmount)
|
|
834
|
+
const totalAmount = BigInt(depositAmount)
|
|
837
835
|
|
|
838
836
|
return {
|
|
839
837
|
to: isNativeToken(originTokenAddress)
|
package/src/morpho.ts
CHANGED
|
@@ -63,7 +63,7 @@ async function fetchAllVaults(): Promise<any[]> {
|
|
|
63
63
|
vaults(
|
|
64
64
|
first: 1000,
|
|
65
65
|
where: {
|
|
66
|
-
chainId_in: [1, 8453, 42161, 137, 10, 100]
|
|
66
|
+
chainId_in: [1, 8453, 42161, 42170, 137, 10, 100, 81457, 56, 660279, 33139, 747474]
|
|
67
67
|
},
|
|
68
68
|
orderBy: TotalAssetsUsd,
|
|
69
69
|
orderDirection: Desc
|
package/src/prepareSend.ts
CHANGED
|
@@ -7,6 +7,8 @@ import { getTokenPrice } from "./prices.js"
|
|
|
7
7
|
import {
|
|
8
8
|
TRAILS_ROUTER_PLACEHOLDER_AMOUNT,
|
|
9
9
|
wrapCalldataWithTrailsRouterIfNeeded,
|
|
10
|
+
calldataHasPlaceholder,
|
|
11
|
+
replacePlaceholderInCalldata,
|
|
10
12
|
} from "./trailsRouter.js"
|
|
11
13
|
import type { TransactionState } from "./transactions.js"
|
|
12
14
|
import { logger } from "./logger.js"
|
|
@@ -62,9 +64,7 @@ export async function prepareSend(
|
|
|
62
64
|
tradeType = TradeType.EXACT_OUTPUT,
|
|
63
65
|
originTokenSymbol,
|
|
64
66
|
destinationTokenSymbol,
|
|
65
|
-
fee,
|
|
66
67
|
client: walletClient,
|
|
67
|
-
dryMode = false,
|
|
68
68
|
trailsClient,
|
|
69
69
|
destinationCalldata,
|
|
70
70
|
onTransactionStateChange,
|
|
@@ -149,6 +149,44 @@ export async function prepareSend(
|
|
|
149
149
|
const isToSameToken = isSameToken(originTokenAddress, destinationTokenAddress)
|
|
150
150
|
const isSameChainSameToken = isToSameChain && isToSameToken
|
|
151
151
|
|
|
152
|
+
// For same-chain same-token with custom calldata:
|
|
153
|
+
// 1. Replace any placeholder in the calldata with the actual swapAmount
|
|
154
|
+
// 2. Use EXACT_OUTPUT trade type to ensure consistent amount handling
|
|
155
|
+
// This handles vault deposits where calldata may have been generated with a placeholder
|
|
156
|
+
const originalHadPlaceholder = calldataHasPlaceholder(destinationCalldata)
|
|
157
|
+
let placeholderWasReplaced = false
|
|
158
|
+
|
|
159
|
+
if (isSameChainSameToken && hasCustomCalldata && originalHadPlaceholder) {
|
|
160
|
+
const calldataBefore = effectiveDestinationCalldata
|
|
161
|
+
// Replace placeholder with actual amount in calldata
|
|
162
|
+
effectiveDestinationCalldata = replacePlaceholderInCalldata(
|
|
163
|
+
effectiveDestinationCalldata || "",
|
|
164
|
+
swapAmount,
|
|
165
|
+
)
|
|
166
|
+
// Verify the placeholder was actually replaced
|
|
167
|
+
placeholderWasReplaced = !calldataHasPlaceholder(
|
|
168
|
+
effectiveDestinationCalldata,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
logger.console.log(
|
|
172
|
+
"[trails-sdk] Same-chain same-token: Replaced placeholder with actual amount in calldata",
|
|
173
|
+
{
|
|
174
|
+
swapAmount,
|
|
175
|
+
placeholderWasReplaced,
|
|
176
|
+
calldataBefore,
|
|
177
|
+
calldataAfter: effectiveDestinationCalldata,
|
|
178
|
+
},
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
logger.console.log("[trails-sdk] Trade type and calldata info:", {
|
|
183
|
+
tradeType,
|
|
184
|
+
isSameChainSameToken,
|
|
185
|
+
hasCustomCalldata,
|
|
186
|
+
originalHadPlaceholder,
|
|
187
|
+
placeholderWasReplaced,
|
|
188
|
+
})
|
|
189
|
+
|
|
152
190
|
if (
|
|
153
191
|
!hasCustomCalldata &&
|
|
154
192
|
tradeType === TradeType.EXACT_INPUT &&
|
|
@@ -414,7 +452,6 @@ export async function prepareSend(
|
|
|
414
452
|
originChainId,
|
|
415
453
|
walletClient,
|
|
416
454
|
onTransactionStateChange,
|
|
417
|
-
dryMode,
|
|
418
455
|
account,
|
|
419
456
|
chain,
|
|
420
457
|
transactionStates,
|
|
@@ -437,6 +474,7 @@ export async function prepareSend(
|
|
|
437
474
|
isSmartWallet,
|
|
438
475
|
trailsApiKey,
|
|
439
476
|
trailsApiUrl,
|
|
477
|
+
tradeType: tradeType,
|
|
440
478
|
})
|
|
441
479
|
}
|
|
442
480
|
|
|
@@ -462,12 +500,10 @@ export async function prepareSend(
|
|
|
462
500
|
publicClient,
|
|
463
501
|
chain,
|
|
464
502
|
account,
|
|
465
|
-
fee,
|
|
466
|
-
dryMode,
|
|
467
503
|
onTransactionStateChange,
|
|
468
504
|
transactionStates,
|
|
469
505
|
slippageTolerance,
|
|
470
|
-
tradeType,
|
|
506
|
+
tradeType: tradeType,
|
|
471
507
|
originNativeTokenPriceUsd,
|
|
472
508
|
swapProvider,
|
|
473
509
|
bridgeProvider,
|
package/src/recover.ts
CHANGED
|
@@ -17,13 +17,14 @@ import { splitSignature } from "./gasless.js"
|
|
|
17
17
|
import { useMemo, useCallback } from "react"
|
|
18
18
|
import { useGetIntent } from "./widget/hooks/useGetIntent.js"
|
|
19
19
|
import {
|
|
20
|
-
|
|
20
|
+
useTokenBalancesForMultipleAccounts,
|
|
21
21
|
getTokenBalanceUsd,
|
|
22
22
|
type Price,
|
|
23
23
|
} from "./tokenBalances.js"
|
|
24
24
|
import { getERC20TransferData } from "./encoders.js"
|
|
25
25
|
import { zeroAddress } from "viem"
|
|
26
26
|
import { useTokenPrices } from "./prices.js"
|
|
27
|
+
import type { Token } from "./tokens.js"
|
|
27
28
|
import type { Payload as WalletPayload } from "@0xsequence/wallet-primitives"
|
|
28
29
|
import { attemptSwitchChain } from "./chainSwitch.js"
|
|
29
30
|
import { decodeGuestModuleEvents } from "./decoders.js"
|
|
@@ -440,15 +441,17 @@ export async function buildRefundTransaction(
|
|
|
440
441
|
|
|
441
442
|
/**
|
|
442
443
|
* Determines the refund call based on token balances at the intent address
|
|
444
|
+
* Uses Token type which has symbol, name, decimals, chainId directly (no contractInfo)
|
|
443
445
|
*/
|
|
444
446
|
export function determineRefundCall(
|
|
445
447
|
tokenBalancesData:
|
|
446
448
|
| {
|
|
447
|
-
|
|
448
|
-
balances?: Array<{
|
|
449
|
+
tokens?: Array<{
|
|
449
450
|
balance?: string
|
|
450
451
|
contractAddress?: string
|
|
451
|
-
|
|
452
|
+
decimals?: number
|
|
453
|
+
chainId?: number
|
|
454
|
+
isNativeToken?: boolean
|
|
452
455
|
}>
|
|
453
456
|
}
|
|
454
457
|
| undefined,
|
|
@@ -467,34 +470,18 @@ export function determineRefundCall(
|
|
|
467
470
|
chainId?: number
|
|
468
471
|
} | null = null
|
|
469
472
|
|
|
470
|
-
// Check native
|
|
471
|
-
if (tokenBalancesData?.
|
|
472
|
-
for (const
|
|
473
|
-
const balance = BigInt(
|
|
473
|
+
// Check all tokens (both native and ERC20)
|
|
474
|
+
if (tokenBalancesData?.tokens) {
|
|
475
|
+
for (const token of tokenBalancesData.tokens) {
|
|
476
|
+
const balance = BigInt(token.balance || "0")
|
|
474
477
|
if (balance > 0n) {
|
|
475
478
|
if (!highestBalanceToken || balance > highestBalanceToken.balance) {
|
|
476
479
|
highestBalanceToken = {
|
|
477
|
-
type: "native",
|
|
480
|
+
type: token.isNativeToken ? "native" : "erc20",
|
|
478
481
|
balance,
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// Check ERC20 token balances
|
|
487
|
-
if (tokenBalancesData?.balances) {
|
|
488
|
-
for (const tokenBalance of tokenBalancesData.balances) {
|
|
489
|
-
const balance = BigInt(tokenBalance.balance || "0")
|
|
490
|
-
if (balance > 0n) {
|
|
491
|
-
if (!highestBalanceToken || balance > highestBalanceToken.balance) {
|
|
492
|
-
highestBalanceToken = {
|
|
493
|
-
type: "erc20",
|
|
494
|
-
balance,
|
|
495
|
-
tokenAddress: tokenBalance.contractAddress,
|
|
496
|
-
decimals: tokenBalance.contractInfo?.decimals,
|
|
497
|
-
chainId: tokenBalance.contractInfo?.chainId,
|
|
482
|
+
tokenAddress: token.contractAddress,
|
|
483
|
+
decimals: token.decimals,
|
|
484
|
+
chainId: token.chainId,
|
|
498
485
|
}
|
|
499
486
|
}
|
|
500
487
|
}
|
|
@@ -581,6 +568,8 @@ export interface UseIntentRecoverReturn {
|
|
|
581
568
|
intentError: Error | null
|
|
582
569
|
balancesError: Error | null
|
|
583
570
|
hasIntentBalance: boolean
|
|
571
|
+
/** Token that will be recovered (the one with highest balance) */
|
|
572
|
+
recoverToken: Token | null
|
|
584
573
|
refetchIntent: () => void
|
|
585
574
|
signPayload: () => Promise<{
|
|
586
575
|
signature: string
|
|
@@ -655,49 +644,41 @@ export function useIntentRecover({
|
|
|
655
644
|
return Address.from(intentData.destinationIntentAddress)
|
|
656
645
|
}, [intentData?.destinationIntentAddress])
|
|
657
646
|
|
|
647
|
+
// Fetch balances for both origin and destination in a single API call
|
|
658
648
|
const {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
} =
|
|
649
|
+
balancesByAccount,
|
|
650
|
+
isLoading: isLoadingBalances,
|
|
651
|
+
error: balanceError,
|
|
652
|
+
} = useTokenBalancesForMultipleAccounts([
|
|
653
|
+
originIntentAddressForBalances,
|
|
654
|
+
destinationIntentAddressForBalances,
|
|
655
|
+
])
|
|
663
656
|
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
657
|
+
// Extract individual account balances
|
|
658
|
+
const originTokenBalancesData = originIntentAddressForBalances
|
|
659
|
+
? balancesByAccount[originIntentAddressForBalances.toLowerCase()]
|
|
660
|
+
?.tokenBalancesData
|
|
661
|
+
: undefined
|
|
662
|
+
const destinationTokenBalancesData = destinationIntentAddressForBalances
|
|
663
|
+
? balancesByAccount[destinationIntentAddressForBalances.toLowerCase()]
|
|
664
|
+
?.tokenBalancesData
|
|
665
|
+
: undefined
|
|
666
|
+
|
|
667
|
+
// balancesError alias for backward compatibility in component return
|
|
668
|
+
const balancesError = balanceError
|
|
669
669
|
|
|
670
670
|
// Get token prices for origin balances
|
|
671
|
+
// Note: Token type already has balance/price fields populated, but we fetch prices
|
|
672
|
+
// separately for more accurate/up-to-date pricing
|
|
671
673
|
const originTokensForPricing = useMemo(() => {
|
|
672
|
-
if (!originTokenBalancesData) return []
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
if (nativeBalance.chainId) {
|
|
681
|
-
tokens.push({
|
|
682
|
-
tokenSymbol: (nativeBalance as any).symbol || "ETH",
|
|
683
|
-
tokenAddress: zeroAddress,
|
|
684
|
-
chainId: nativeBalance.chainId,
|
|
685
|
-
})
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
if (originTokenBalancesData.balances) {
|
|
690
|
-
for (const tokenBalance of originTokenBalancesData.balances) {
|
|
691
|
-
if (tokenBalance.contractInfo?.chainId) {
|
|
692
|
-
tokens.push({
|
|
693
|
-
tokenSymbol: tokenBalance.contractInfo?.symbol || "",
|
|
694
|
-
tokenAddress: tokenBalance.contractAddress || zeroAddress,
|
|
695
|
-
chainId: tokenBalance.contractInfo.chainId,
|
|
696
|
-
})
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
return tokens
|
|
674
|
+
if (!originTokenBalancesData?.tokens) return []
|
|
675
|
+
return originTokenBalancesData.tokens
|
|
676
|
+
.filter((token) => token.chainId !== undefined)
|
|
677
|
+
.map((token) => ({
|
|
678
|
+
tokenSymbol: token.symbol,
|
|
679
|
+
tokenAddress: token.contractAddress || zeroAddress,
|
|
680
|
+
chainId: token.chainId!,
|
|
681
|
+
}))
|
|
701
682
|
}, [originTokenBalancesData])
|
|
702
683
|
|
|
703
684
|
const { tokenPrices: originTokenPrices } = useTokenPrices(
|
|
@@ -706,35 +687,14 @@ export function useIntentRecover({
|
|
|
706
687
|
|
|
707
688
|
// Get token prices for destination balances
|
|
708
689
|
const destinationTokensForPricing = useMemo(() => {
|
|
709
|
-
if (!destinationTokenBalancesData) return []
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
if (nativeBalance.chainId) {
|
|
718
|
-
tokens.push({
|
|
719
|
-
tokenSymbol: (nativeBalance as any).symbol || "ETH",
|
|
720
|
-
tokenAddress: zeroAddress,
|
|
721
|
-
chainId: nativeBalance.chainId,
|
|
722
|
-
})
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (destinationTokenBalancesData.balances) {
|
|
727
|
-
for (const tokenBalance of destinationTokenBalancesData.balances) {
|
|
728
|
-
if (tokenBalance.contractInfo?.chainId) {
|
|
729
|
-
tokens.push({
|
|
730
|
-
tokenSymbol: tokenBalance.contractInfo?.symbol || "",
|
|
731
|
-
tokenAddress: tokenBalance.contractAddress || zeroAddress,
|
|
732
|
-
chainId: tokenBalance.contractInfo.chainId,
|
|
733
|
-
})
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
}
|
|
737
|
-
return tokens
|
|
690
|
+
if (!destinationTokenBalancesData?.tokens) return []
|
|
691
|
+
return destinationTokenBalancesData.tokens
|
|
692
|
+
.filter((token) => token.chainId !== undefined)
|
|
693
|
+
.map((token) => ({
|
|
694
|
+
tokenSymbol: token.symbol,
|
|
695
|
+
tokenAddress: token.contractAddress || zeroAddress,
|
|
696
|
+
chainId: token.chainId!,
|
|
697
|
+
}))
|
|
738
698
|
}, [destinationTokenBalancesData])
|
|
739
699
|
|
|
740
700
|
const { tokenPrices: destinationTokenPrices } = useTokenPrices(
|
|
@@ -746,19 +706,13 @@ export function useIntentRecover({
|
|
|
746
706
|
(
|
|
747
707
|
balancesData:
|
|
748
708
|
| {
|
|
749
|
-
|
|
709
|
+
tokens?: Array<{
|
|
750
710
|
balance?: string
|
|
751
711
|
chainId?: number
|
|
752
|
-
symbol?: string
|
|
753
|
-
}>
|
|
754
|
-
balances?: Array<{
|
|
755
|
-
balance?: string
|
|
756
712
|
contractAddress?: string
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
symbol?: string
|
|
761
|
-
}
|
|
713
|
+
decimals?: number
|
|
714
|
+
isNativeToken?: boolean
|
|
715
|
+
balanceUsd?: number
|
|
762
716
|
}>
|
|
763
717
|
}
|
|
764
718
|
| undefined,
|
|
@@ -773,56 +727,44 @@ export function useIntentRecover({
|
|
|
773
727
|
|
|
774
728
|
let totalUsd = 0
|
|
775
729
|
|
|
776
|
-
// Sum
|
|
777
|
-
if (balancesData.
|
|
778
|
-
for (const
|
|
779
|
-
const
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
p.token.chainId === nativeBalance.chainId &&
|
|
783
|
-
p.priceUsd !== undefined,
|
|
784
|
-
)
|
|
785
|
-
if (priceData?.priceUsd && nativeBalance.balance) {
|
|
786
|
-
const price: Price = {
|
|
787
|
-
value: priceData.priceUsd,
|
|
788
|
-
currency: "USD",
|
|
789
|
-
}
|
|
790
|
-
const usdValue = getTokenBalanceUsd(
|
|
791
|
-
{
|
|
792
|
-
balance: nativeBalance.balance,
|
|
793
|
-
chainId: nativeBalance.chainId,
|
|
794
|
-
} as any,
|
|
795
|
-
price,
|
|
796
|
-
)
|
|
797
|
-
totalUsd += usdValue
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
730
|
+
// Sum all token USD values (both native and ERC20)
|
|
731
|
+
if (balancesData.tokens) {
|
|
732
|
+
for (const token of balancesData.tokens) {
|
|
733
|
+
const tokenAddress = token.isNativeToken
|
|
734
|
+
? zeroAddress
|
|
735
|
+
: token.contractAddress || zeroAddress
|
|
801
736
|
|
|
802
|
-
// Sum ERC20 token USD values
|
|
803
|
-
if (balancesData.balances) {
|
|
804
|
-
for (const tokenBalance of balancesData.balances) {
|
|
805
737
|
const priceData = tokenPrices.find(
|
|
806
738
|
(p) =>
|
|
807
739
|
p.token.tokenAddress?.toLowerCase() ===
|
|
808
|
-
|
|
809
|
-
p.token.chainId ===
|
|
740
|
+
tokenAddress.toLowerCase() &&
|
|
741
|
+
p.token.chainId === token.chainId &&
|
|
810
742
|
p.priceUsd !== undefined,
|
|
811
743
|
)
|
|
812
|
-
|
|
744
|
+
|
|
745
|
+
if (priceData?.priceUsd && token.balance) {
|
|
813
746
|
const price: Price = {
|
|
814
747
|
value: priceData.priceUsd,
|
|
815
748
|
currency: "USD",
|
|
816
749
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
750
|
+
|
|
751
|
+
// Use balanceUsd if already calculated, otherwise calculate
|
|
752
|
+
if (token.balanceUsd !== undefined) {
|
|
753
|
+
totalUsd += token.balanceUsd
|
|
754
|
+
} else {
|
|
755
|
+
// Create a compatible object for getTokenBalanceUsd
|
|
756
|
+
const balanceObj = token.isNativeToken
|
|
757
|
+
? { balance: token.balance, chainId: token.chainId }
|
|
758
|
+
: {
|
|
759
|
+
balance: token.balance,
|
|
760
|
+
contractInfo: {
|
|
761
|
+
decimals: token.decimals,
|
|
762
|
+
chainId: token.chainId,
|
|
763
|
+
},
|
|
764
|
+
}
|
|
765
|
+
const usdValue = getTokenBalanceUsd(balanceObj as any, price)
|
|
766
|
+
totalUsd += usdValue
|
|
767
|
+
}
|
|
826
768
|
}
|
|
827
769
|
}
|
|
828
770
|
}
|
|
@@ -919,9 +861,7 @@ export function useIntentRecover({
|
|
|
919
861
|
calculateTotalUsdBalance,
|
|
920
862
|
])
|
|
921
863
|
|
|
922
|
-
|
|
923
|
-
isLoadingOriginBalances || isLoadingDestinationBalances
|
|
924
|
-
const balancesError = originBalanceError || destinationBalanceError
|
|
864
|
+
// isLoadingBalances and balancesError are already defined above from useTokenBalancesForMultipleAccounts
|
|
925
865
|
|
|
926
866
|
// Check if ANY intent address (origin or destination) has any balance (native or ERC20)
|
|
927
867
|
// This ensures we show the recover button if there are balances in either address
|
|
@@ -930,34 +870,17 @@ export function useIntentRecover({
|
|
|
930
870
|
const checkBalances = (
|
|
931
871
|
balancesData:
|
|
932
872
|
| {
|
|
933
|
-
|
|
934
|
-
balances?: Array<{
|
|
935
|
-
balance?: string
|
|
936
|
-
contractAddress?: string
|
|
937
|
-
contractInfo?: { decimals?: number; chainId?: number }
|
|
938
|
-
}>
|
|
873
|
+
tokens?: Array<{ balance?: string }>
|
|
939
874
|
}
|
|
940
875
|
| undefined,
|
|
941
876
|
): boolean => {
|
|
942
|
-
if (!balancesData) return false
|
|
943
|
-
|
|
944
|
-
// Check native token balances
|
|
945
|
-
if (balancesData.nativeBalances) {
|
|
946
|
-
for (const nativeBalance of balancesData.nativeBalances) {
|
|
947
|
-
const balance = BigInt(nativeBalance.balance || "0")
|
|
948
|
-
if (balance > 0n) {
|
|
949
|
-
return true
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
}
|
|
877
|
+
if (!balancesData?.tokens) return false
|
|
953
878
|
|
|
954
|
-
// Check
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
return true
|
|
960
|
-
}
|
|
879
|
+
// Check all tokens (both native and ERC20)
|
|
880
|
+
for (const token of balancesData.tokens) {
|
|
881
|
+
const balance = BigInt(token.balance || "0")
|
|
882
|
+
if (balance > 0n) {
|
|
883
|
+
return true
|
|
961
884
|
}
|
|
962
885
|
}
|
|
963
886
|
|
|
@@ -971,6 +894,26 @@ export function useIntentRecover({
|
|
|
971
894
|
return originHasBalance || destinationHasBalance
|
|
972
895
|
}, [originTokenBalancesData, destinationTokenBalancesData])
|
|
973
896
|
|
|
897
|
+
// Get the token that will be recovered (highest balance from selected intent address)
|
|
898
|
+
// Get the token that will be recovered (highest balance from selected intent address)
|
|
899
|
+
const recoverToken = useMemo<Token | null>(() => {
|
|
900
|
+
if (!selectedIntentAddress?.tokenBalancesData?.tokens) return null
|
|
901
|
+
|
|
902
|
+
// Find the token with the highest balance
|
|
903
|
+
let highestBalanceToken: Token | null = null
|
|
904
|
+
let highestBalance = 0n
|
|
905
|
+
|
|
906
|
+
for (const token of selectedIntentAddress.tokenBalancesData.tokens) {
|
|
907
|
+
const balance = BigInt(token.balance || "0")
|
|
908
|
+
if (balance > 0n && balance > highestBalance) {
|
|
909
|
+
highestBalance = balance
|
|
910
|
+
highestBalanceToken = token
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
return highestBalanceToken
|
|
915
|
+
}, [selectedIntentAddress?.tokenBalancesData?.tokens])
|
|
916
|
+
|
|
974
917
|
// Get refund address (use walletClient account or provided address)
|
|
975
918
|
// Don't throw during render - validate when methods are called
|
|
976
919
|
const effectiveRefundAddress = useMemo<`0x${string}` | null>(() => {
|
|
@@ -1411,6 +1354,7 @@ export function useIntentRecover({
|
|
|
1411
1354
|
intentError: intentError as Error | null,
|
|
1412
1355
|
balancesError: balancesError as Error | null,
|
|
1413
1356
|
hasIntentBalance,
|
|
1357
|
+
recoverToken,
|
|
1414
1358
|
refetchIntent,
|
|
1415
1359
|
signPayload,
|
|
1416
1360
|
getRecoverTx,
|