0xtrails 0.2.5 → 0.3.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/aave.d.ts +2 -0
- package/dist/aave.d.ts.map +1 -1
- package/dist/abortController.d.ts +8 -0
- package/dist/abortController.d.ts.map +1 -0
- package/dist/{ccip-CXlshvBY.js → ccip-BMB3uDZt.js} +1 -1
- package/dist/config.d.ts +0 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/constants.d.ts +4 -4
- package/dist/constants.d.ts.map +1 -1
- package/dist/error.d.ts +4 -1
- package/dist/error.d.ts.map +1 -1
- package/dist/fees.d.ts +19 -0
- package/dist/fees.d.ts.map +1 -0
- package/dist/{index-_QuyGrjU.js → index-QXPUrZVv.js} +48719 -50852
- package/dist/index.d.ts +9 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +811 -784
- package/dist/intentReceiptMonitor.d.ts +24 -0
- package/dist/intentReceiptMonitor.d.ts.map +1 -0
- package/dist/intentReceiptPoller.d.ts +69 -0
- package/dist/intentReceiptPoller.d.ts.map +1 -0
- package/dist/intents.d.ts +15 -11
- package/dist/intents.d.ts.map +1 -1
- package/dist/morpho.d.ts +6 -5
- package/dist/morpho.d.ts.map +1 -1
- package/dist/mutations.d.ts +16 -0
- package/dist/mutations.d.ts.map +1 -0
- package/dist/preconditions.d.ts +5 -4
- package/dist/preconditions.d.ts.map +1 -1
- package/dist/prepareSend.d.ts +7 -258
- package/dist/prepareSend.d.ts.map +1 -1
- package/dist/prices.d.ts +9 -6
- package/dist/prices.d.ts.map +1 -1
- package/dist/sequenceWallet.d.ts +3 -16
- package/dist/sequenceWallet.d.ts.map +1 -1
- package/dist/tokenBalances.d.ts +17 -13
- package/dist/tokenBalances.d.ts.map +1 -1
- package/dist/trails.d.ts +24 -40
- package/dist/trails.d.ts.map +1 -1
- package/dist/transactionIntent/constants.d.ts +7 -0
- package/dist/transactionIntent/constants.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +44 -0
- package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +30 -0
- package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/index.d.ts +4 -0
- package/dist/transactionIntent/deposits/index.d.ts.map +1 -0
- package/dist/transactionIntent/deposits/standardDeposit.d.ts +30 -0
- package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -0
- package/dist/transactionIntent/execution/index.d.ts +2 -0
- package/dist/transactionIntent/execution/index.d.ts.map +1 -0
- package/dist/transactionIntent/execution/transactionState.d.ts +5 -0
- package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/crossChain.d.ts +82 -0
- package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/index.d.ts +4 -0
- package/dist/transactionIntent/handlers/index.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +62 -0
- package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +1 -0
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +72 -0
- package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -0
- package/dist/transactionIntent/index.d.ts +9 -0
- package/dist/transactionIntent/index.d.ts.map +1 -0
- package/dist/transactionIntent/quote/feeExtractors.d.ts +17 -0
- package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -0
- package/dist/transactionIntent/quote/index.d.ts +4 -0
- package/dist/transactionIntent/quote/index.d.ts.map +1 -0
- package/dist/transactionIntent/quote/normalizeQuote.d.ts +34 -0
- package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -0
- package/dist/transactionIntent/quote/quoteHelpers.d.ts +5 -0
- package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/types.d.ts +131 -0
- package/dist/transactionIntent/types.d.ts.map +1 -0
- package/dist/transactionIntent/utils/balanceChecker.d.ts +18 -0
- package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -0
- package/dist/transactionIntent/utils/index.d.ts +4 -0
- package/dist/transactionIntent/utils/index.d.ts.map +1 -0
- package/dist/transactionIntent/utils/lifiHelpers.d.ts +10 -0
- package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/utils/testnetHelpers.d.ts +3 -0
- package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -0
- package/dist/transactionIntent/validators.d.ts +6 -0
- package/dist/transactionIntent/validators.d.ts.map +1 -0
- package/dist/transactions.d.ts +6 -3
- package/dist/transactions.d.ts.map +1 -1
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
- package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
- package/dist/widget/components/AccountSettings.d.ts.map +1 -1
- package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
- package/dist/widget/components/ClassicSwap.d.ts +2 -3
- package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
- package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
- package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
- package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
- package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
- package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
- package/dist/widget/components/DynamicSizeInputField.d.ts +13 -0
- package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -0
- package/dist/widget/components/Earn.d.ts +2 -3
- package/dist/widget/components/Earn.d.ts.map +1 -1
- package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
- package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
- package/dist/widget/components/FeeBreakdown.d.ts +9 -0
- package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
- package/dist/widget/components/FeeOptions.d.ts +5 -13
- package/dist/widget/components/FeeOptions.d.ts.map +1 -1
- package/dist/widget/components/Fund.d.ts +2 -3
- package/dist/widget/components/Fund.d.ts.map +1 -1
- package/dist/widget/components/FundMethods.d.ts.map +1 -1
- package/dist/widget/components/FundSwap.d.ts +2 -3
- package/dist/widget/components/FundSwap.d.ts.map +1 -1
- package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Identicon.d.ts.map +1 -1
- package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
- package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
- package/dist/widget/components/Modal.d.ts.map +1 -1
- package/dist/widget/components/Pay.d.ts +2 -3
- package/dist/widget/components/Pay.d.ts.map +1 -1
- package/dist/widget/components/PoolDeposit.d.ts +3 -3
- package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
- package/dist/widget/components/PoolWithdraw.d.ts +3 -20
- package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
- package/dist/widget/components/QuoteDetails.d.ts +2 -0
- package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
- package/dist/widget/components/Receipt.d.ts.map +1 -1
- package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
- package/dist/widget/components/Swap.d.ts +2 -3
- package/dist/widget/components/Swap.d.ts.map +1 -1
- package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
- package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
- package/dist/widget/components/TokenSelector.d.ts.map +1 -1
- package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
- package/dist/widget/components/Tooltip.d.ts +9 -0
- package/dist/widget/components/Tooltip.d.ts.map +1 -0
- package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
- package/dist/widget/components/WaasFeeOptions.d.ts +1 -0
- package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
- package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
- package/dist/widget/components/WalletConnect.d.ts.map +1 -1
- package/dist/widget/css/compiled.css +2 -2
- package/dist/widget/hooks/useCheckout.d.ts +17 -4
- package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
- package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
- package/dist/widget/hooks/useQuote.d.ts +82 -0
- package/dist/widget/hooks/useQuote.d.ts.map +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts +1 -0
- package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
- package/dist/widget/hooks/useSendForm.d.ts +5 -6
- package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
- package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
- package/dist/widget/hooks/useWalletConnectionContext.d.ts +25 -0
- package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -0
- package/dist/widget/index.js +2 -2
- package/dist/widget/widget.d.ts +17 -7
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +19 -21
- package/src/aave.ts +54 -1
- package/src/abortController.ts +35 -0
- package/src/config.ts +57 -58
- package/src/constants.ts +11 -9
- package/src/error.ts +21 -3
- package/src/fees.ts +210 -0
- package/src/index.ts +35 -13
- package/src/intentReceiptMonitor.ts +102 -0
- package/src/intentReceiptPoller.ts +299 -0
- package/src/intents.ts +205 -171
- package/src/morpho.ts +58 -9
- package/src/mutations.ts +129 -0
- package/src/preconditions.ts +16 -21
- package/src/prepareSend.ts +92 -4699
- package/src/prices.ts +26 -22
- package/src/relaySdk.ts +2 -2
- package/src/sequenceWallet.ts +6 -73
- package/src/tokenBalances.ts +175 -69
- package/src/trails.ts +230 -722
- package/src/transactionIntent/constants.ts +11 -0
- package/src/transactionIntent/deposits/depositOrchestrator.ts +210 -0
- package/src/transactionIntent/deposits/gaslessDeposit.ts +588 -0
- package/src/transactionIntent/deposits/index.ts +3 -0
- package/src/transactionIntent/deposits/standardDeposit.ts +379 -0
- package/src/transactionIntent/execution/index.ts +1 -0
- package/src/transactionIntent/execution/transactionState.ts +35 -0
- package/src/transactionIntent/handlers/crossChain.ts +1707 -0
- package/src/transactionIntent/handlers/index.ts +3 -0
- package/src/transactionIntent/handlers/sameChainDifferentToken.ts +323 -0
- package/src/transactionIntent/handlers/sameChainSameToken.ts +712 -0
- package/src/transactionIntent/index.ts +9 -0
- package/src/transactionIntent/quote/feeExtractors.ts +81 -0
- package/src/transactionIntent/quote/index.ts +3 -0
- package/src/transactionIntent/quote/normalizeQuote.ts +367 -0
- package/src/transactionIntent/quote/quoteHelpers.ts +53 -0
- package/src/transactionIntent/types.ts +157 -0
- package/src/transactionIntent/utils/balanceChecker.ts +96 -0
- package/src/transactionIntent/utils/index.ts +3 -0
- package/src/transactionIntent/utils/lifiHelpers.ts +68 -0
- package/src/transactionIntent/utils/testnetHelpers.ts +10 -0
- package/src/transactionIntent/validators.ts +57 -0
- package/src/transactions.ts +98 -71
- package/src/widget/compiled.css +2 -2
- package/src/widget/components/AccountIntentTransactionHistory.tsx +36 -36
- package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
- package/src/widget/components/AccountSettings.tsx +70 -41
- package/src/widget/components/ChainFilterDropdown.tsx +24 -3
- package/src/widget/components/ClassicSwap.tsx +44 -107
- package/src/widget/components/ConfigDisplay.tsx +0 -11
- package/src/widget/components/ConnectWallet.tsx +4 -1
- package/src/widget/components/ConnectedWallets.tsx +51 -25
- package/src/widget/components/DynamicInputStyles.tsx +76 -0
- package/src/widget/components/DynamicSizeInputField.tsx +109 -0
- package/src/widget/components/Earn.tsx +34 -45
- package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
- package/src/widget/components/FeeBreakdown.tsx +155 -0
- package/src/widget/components/FeeOption.tsx +2 -2
- package/src/widget/components/FeeOptions.tsx +151 -112
- package/src/widget/components/Fund.tsx +10 -29
- package/src/widget/components/FundMethods.tsx +4 -3
- package/src/widget/components/FundSwap.tsx +2 -3
- package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
- package/src/widget/components/Identicon.tsx +164 -95
- package/src/widget/components/MeshConnectExchanges.tsx +2 -15
- package/src/widget/components/Modal.tsx +0 -12
- package/src/widget/components/Pay.tsx +72 -75
- package/src/widget/components/PoolDeposit.tsx +221 -242
- package/src/widget/components/PoolWithdraw.tsx +347 -469
- package/src/widget/components/PriceImpactWarning.tsx +1 -1
- package/src/widget/components/QuoteDetails.tsx +906 -484
- package/src/widget/components/Receipt.tsx +16 -2
- package/src/widget/components/RecipientSelectorButton.tsx +7 -5
- package/src/widget/components/Recipients.tsx +1 -1
- package/src/widget/components/ScreenHeader.tsx +60 -36
- package/src/widget/components/Swap.tsx +2 -3
- package/src/widget/components/ThemeProvider.tsx +2 -1
- package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
- package/src/widget/components/TokenImage.tsx +1 -1
- package/src/widget/components/TokenSelector.tsx +62 -53
- package/src/widget/components/TokenSelectorButton.tsx +38 -15
- package/src/widget/components/Tooltip.tsx +51 -0
- package/src/widget/components/TransferPendingVertical.tsx +12 -8
- package/src/widget/components/WaasFeeOptions.tsx +139 -4
- package/src/widget/components/WalletConfirmation.tsx +23 -13
- package/src/widget/components/WalletConnect.tsx +93 -29
- package/src/widget/hooks/useAmountUsd.ts +9 -9
- package/src/widget/hooks/useCheckout.ts +97 -9
- package/src/widget/hooks/useDefaultTokenSelection.tsx +27 -21
- package/src/widget/hooks/useQuote.ts +466 -0
- package/src/widget/hooks/useSelectedFeeToken.tsx +32 -37
- package/src/widget/hooks/useSendForm.ts +45 -51
- package/src/widget/hooks/useTokenList.ts +34 -26
- package/src/widget/hooks/useWalletConnectionContext.tsx +128 -0
- package/src/widget/widget.tsx +365 -390
- package/dist/apiClient.d.ts +0 -9
- package/dist/apiClient.d.ts.map +0 -1
- package/dist/intentEntrypoint.d.ts +0 -114
- package/dist/intentEntrypoint.d.ts.map +0 -1
- package/dist/metaTxnMonitor.d.ts +0 -15
- package/dist/metaTxnMonitor.d.ts.map +0 -1
- package/dist/metaTxns.d.ts +0 -11
- package/dist/metaTxns.d.ts.map +0 -1
- package/dist/relayer.d.ts +0 -43
- package/dist/relayer.d.ts.map +0 -1
- package/src/apiClient.ts +0 -35
- package/src/intentEntrypoint.ts +0 -203
- package/src/metaTxnMonitor.ts +0 -171
- package/src/metaTxns.ts +0 -45
- package/src/relayer.ts +0 -289
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { Account, PublicClient } from "viem"
|
|
2
|
+
import { erc20Abi, formatUnits, zeroAddress } from "viem"
|
|
3
|
+
import { InsufficientBalanceError } from "../../error.js"
|
|
4
|
+
import { formatAmount } from "../../tokenBalances.js"
|
|
5
|
+
import { logger } from "../../logger.js"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Check if the account has enough balance for the deposit amount
|
|
9
|
+
*/
|
|
10
|
+
export async function checkAccountBalance({
|
|
11
|
+
account,
|
|
12
|
+
tokenAddress,
|
|
13
|
+
depositAmount,
|
|
14
|
+
publicClient,
|
|
15
|
+
}: {
|
|
16
|
+
account: Account
|
|
17
|
+
tokenAddress: string
|
|
18
|
+
depositAmount: string
|
|
19
|
+
publicClient: PublicClient
|
|
20
|
+
}): Promise<{
|
|
21
|
+
hasEnoughBalance: boolean
|
|
22
|
+
balance: bigint
|
|
23
|
+
requiredAmount: bigint
|
|
24
|
+
balanceFormatted: string
|
|
25
|
+
requiredAmountFormatted: string
|
|
26
|
+
balanceError: Error | null
|
|
27
|
+
}> {
|
|
28
|
+
try {
|
|
29
|
+
let balance: bigint
|
|
30
|
+
|
|
31
|
+
if (tokenAddress === zeroAddress) {
|
|
32
|
+
// Native token balance
|
|
33
|
+
balance = await publicClient.getBalance({ address: account.address })
|
|
34
|
+
} else {
|
|
35
|
+
// ERC20 token balance
|
|
36
|
+
balance = await publicClient.readContract({
|
|
37
|
+
address: tokenAddress as `0x${string}`,
|
|
38
|
+
abi: erc20Abi,
|
|
39
|
+
functionName: "balanceOf",
|
|
40
|
+
args: [account.address],
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const requiredAmount = BigInt(depositAmount)
|
|
45
|
+
|
|
46
|
+
logger.console.log("[trails-sdk] balance", balance)
|
|
47
|
+
logger.console.log("[trails-sdk] requiredAmount", requiredAmount)
|
|
48
|
+
const hasEnoughBalance = balance >= requiredAmount
|
|
49
|
+
logger.console.log("[trails-sdk] hasEnoughBalance", hasEnoughBalance)
|
|
50
|
+
|
|
51
|
+
let balanceFormatted = ""
|
|
52
|
+
let requiredAmountFormatted = ""
|
|
53
|
+
if (tokenAddress === zeroAddress) {
|
|
54
|
+
balanceFormatted = formatUnits(balance, 18)
|
|
55
|
+
requiredAmountFormatted = formatUnits(requiredAmount, 18)
|
|
56
|
+
} else {
|
|
57
|
+
// ERC20 token balance
|
|
58
|
+
const decimals = await publicClient.readContract({
|
|
59
|
+
address: tokenAddress as `0x${string}`,
|
|
60
|
+
abi: erc20Abi,
|
|
61
|
+
functionName: "decimals",
|
|
62
|
+
})
|
|
63
|
+
if (!decimals) {
|
|
64
|
+
throw new Error("Decimals not found")
|
|
65
|
+
}
|
|
66
|
+
balanceFormatted = formatUnits(balance, decimals)
|
|
67
|
+
requiredAmountFormatted = formatUnits(requiredAmount, decimals)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let balanceError = null
|
|
71
|
+
if (!hasEnoughBalance) {
|
|
72
|
+
balanceError = new InsufficientBalanceError(
|
|
73
|
+
`Insufficient balance: Need ${formatAmount(requiredAmountFormatted)} ${tokenAddress} for ${account.address} on ${publicClient.chain?.name} but only have ${formatAmount(balanceFormatted)} ${tokenAddress}`,
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
hasEnoughBalance,
|
|
79
|
+
balance,
|
|
80
|
+
balanceFormatted,
|
|
81
|
+
requiredAmount,
|
|
82
|
+
requiredAmountFormatted,
|
|
83
|
+
balanceError,
|
|
84
|
+
}
|
|
85
|
+
} catch (error) {
|
|
86
|
+
logger.console.error("[trails-sdk] Error checking account balance:", error)
|
|
87
|
+
return {
|
|
88
|
+
hasEnoughBalance: false,
|
|
89
|
+
balance: BigInt(0),
|
|
90
|
+
balanceFormatted: "0",
|
|
91
|
+
requiredAmount: BigInt(0),
|
|
92
|
+
requiredAmountFormatted: "0",
|
|
93
|
+
balanceError: error instanceof Error ? error : null,
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { formatUnits, zeroAddress } from "viem"
|
|
2
|
+
import { calcAmountUsdPrice } from "../../prices.js"
|
|
3
|
+
import { logger } from "../../logger.js"
|
|
4
|
+
|
|
5
|
+
// ETH fee required by some bridges for low token amounts
|
|
6
|
+
// TODO: update backend API to return the native fee requirement, if any
|
|
7
|
+
export function getNeedsLifiNativeFee({
|
|
8
|
+
originTokenAddress,
|
|
9
|
+
destinationTokenAmount,
|
|
10
|
+
destinationTokenDecimals,
|
|
11
|
+
sourceTokenDecimals,
|
|
12
|
+
sourceTokenPriceUsd,
|
|
13
|
+
destinationTokenPriceUsd,
|
|
14
|
+
depositAmount,
|
|
15
|
+
}: {
|
|
16
|
+
originTokenAddress: string
|
|
17
|
+
destinationTokenAmount: string
|
|
18
|
+
destinationTokenDecimals: number
|
|
19
|
+
sourceTokenDecimals: number
|
|
20
|
+
sourceTokenPriceUsd: number | null
|
|
21
|
+
destinationTokenPriceUsd: number | null
|
|
22
|
+
depositAmount: string
|
|
23
|
+
}): boolean {
|
|
24
|
+
let needsNativeFee = false
|
|
25
|
+
if (
|
|
26
|
+
originTokenAddress !== zeroAddress &&
|
|
27
|
+
sourceTokenPriceUsd &&
|
|
28
|
+
destinationTokenPriceUsd &&
|
|
29
|
+
depositAmount &&
|
|
30
|
+
destinationTokenDecimals !== undefined &&
|
|
31
|
+
sourceTokenDecimals !== undefined
|
|
32
|
+
) {
|
|
33
|
+
// Convert from wei to token units using formatUnits
|
|
34
|
+
const destinationAmount = Number(
|
|
35
|
+
formatUnits(BigInt(destinationTokenAmount), destinationTokenDecimals),
|
|
36
|
+
)
|
|
37
|
+
const depositAmountFormatted = Number(
|
|
38
|
+
formatUnits(BigInt(depositAmount), sourceTokenDecimals),
|
|
39
|
+
)
|
|
40
|
+
logger.console.log("[trails-sdk] destinationAmount", destinationAmount)
|
|
41
|
+
logger.console.log(
|
|
42
|
+
"[trails-sdk] depositAmountFormatted",
|
|
43
|
+
depositAmountFormatted,
|
|
44
|
+
)
|
|
45
|
+
const destinationAmountUsd = calcAmountUsdPrice({
|
|
46
|
+
amount: destinationAmount,
|
|
47
|
+
usdPrice: destinationTokenPriceUsd,
|
|
48
|
+
})
|
|
49
|
+
const depositAmountUsd = calcAmountUsdPrice({
|
|
50
|
+
amount: depositAmountFormatted,
|
|
51
|
+
usdPrice: sourceTokenPriceUsd,
|
|
52
|
+
})
|
|
53
|
+
const diff = depositAmountUsd - destinationAmountUsd
|
|
54
|
+
logger.console.log(
|
|
55
|
+
"[trails-sdk] destinationAmountUsd",
|
|
56
|
+
destinationAmountUsd,
|
|
57
|
+
"[trails-sdk] depositAmountUsd",
|
|
58
|
+
depositAmountUsd,
|
|
59
|
+
"[trails-sdk] diff",
|
|
60
|
+
diff,
|
|
61
|
+
)
|
|
62
|
+
if (diff >= 0 && diff <= 0.02) {
|
|
63
|
+
needsNativeFee = true
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return needsNativeFee
|
|
68
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { getQueryParam } from "../../queryParams.js"
|
|
2
|
+
import { getUSDCTokenAddress } from "../../cctp.js"
|
|
3
|
+
|
|
4
|
+
export function isTestnetDebugMode(): boolean {
|
|
5
|
+
return getQueryParam("testnet") === "true"
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getTestnetOriginTokenAddress(testnetChainId: number): string {
|
|
9
|
+
return getUSDCTokenAddress(testnetChainId)!
|
|
10
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { getIsUsdcAddress } from "../cctp.js"
|
|
2
|
+
|
|
3
|
+
export function isSameChain(
|
|
4
|
+
originChainId: number,
|
|
5
|
+
destinationChainId: number,
|
|
6
|
+
): boolean {
|
|
7
|
+
return originChainId?.toString() === destinationChainId?.toString()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function isSameToken(
|
|
11
|
+
originTokenAddress: string,
|
|
12
|
+
destinationTokenAddress: string,
|
|
13
|
+
): boolean {
|
|
14
|
+
return (
|
|
15
|
+
originTokenAddress?.toLowerCase() === destinationTokenAddress?.toLowerCase()
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isSameChainAndToken(
|
|
20
|
+
originChainId: number,
|
|
21
|
+
originTokenAddress: string,
|
|
22
|
+
destinationChainId: number,
|
|
23
|
+
destinationTokenAddress: string,
|
|
24
|
+
): boolean {
|
|
25
|
+
return (
|
|
26
|
+
isSameChain(originChainId, destinationChainId) &&
|
|
27
|
+
isSameToken(originTokenAddress, destinationTokenAddress)
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function shouldUseCctp(
|
|
32
|
+
originTokenAddress: string,
|
|
33
|
+
destinationTokenAddress: string,
|
|
34
|
+
originChainId: number,
|
|
35
|
+
destinationChainId: number,
|
|
36
|
+
) {
|
|
37
|
+
return (
|
|
38
|
+
getIsUsdcAddress(originTokenAddress, originChainId) &&
|
|
39
|
+
getIsUsdcAddress(destinationTokenAddress, destinationChainId)
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function validateCctpDestinationToken(
|
|
44
|
+
destinationTokenAddress: string,
|
|
45
|
+
destinationChainId: number,
|
|
46
|
+
quoteProvider?: string | null,
|
|
47
|
+
): void {
|
|
48
|
+
// If CCTP provider is selected, destination token must be USDC
|
|
49
|
+
if (
|
|
50
|
+
quoteProvider === "cctp" &&
|
|
51
|
+
!getIsUsdcAddress(destinationTokenAddress, destinationChainId)
|
|
52
|
+
) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`CCTP provider requires destination token to be USDC. Current destination token: ${destinationTokenAddress} on chain ${destinationChainId}. Please ensure the destination token is USDC as listed in the Circle CCTP documentation.`,
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/transactions.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { createPublicClient, http } from "viem"
|
|
2
1
|
import { useQuery } from "@tanstack/react-query"
|
|
3
2
|
import { getChainInfo } from "./chains.js"
|
|
4
3
|
import { getSequenceProjectAccessKey } from "./config.js"
|
|
@@ -9,6 +8,7 @@ import { bigintReplacer } from "./utils.js"
|
|
|
9
8
|
import { getExplorerUrl } from "./explorer.js"
|
|
10
9
|
import { SortOrder } from "@0xsequence/trails-api"
|
|
11
10
|
import { getChainIndexerUrl } from "./indexerClient.js"
|
|
11
|
+
import { abortControllerRegistry } from "./abortController.js"
|
|
12
12
|
|
|
13
13
|
export type TransactionStateStatus =
|
|
14
14
|
| "pending"
|
|
@@ -26,6 +26,7 @@ export type TransactionState = {
|
|
|
26
26
|
decodedTrailsTokenSweeperEvents?: TrailsTokenSweeperEvent[]
|
|
27
27
|
decodedGuestModuleEvents?: GuestModuleEvent[]
|
|
28
28
|
refunded?: boolean
|
|
29
|
+
txnMinedAt?: string
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export type TransferType = "SEND" | "RECEIVE"
|
|
@@ -99,6 +100,7 @@ export type GetAccountTransactionHistoryParams = {
|
|
|
99
100
|
pageSize?: number
|
|
100
101
|
includeMetadata?: boolean
|
|
101
102
|
page?: number
|
|
103
|
+
abortSignal?: AbortSignal
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
// Standalone function to calculate time difference between two transactions
|
|
@@ -124,57 +126,25 @@ export async function getTxTimeDiff(
|
|
|
124
126
|
return 0
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
const firstChainInfo = getChainInfo(firstTx.chainId)
|
|
128
|
-
const lastChainInfo = getChainInfo(lastTx.chainId)
|
|
129
|
-
if (!firstChainInfo || !lastChainInfo) return 0
|
|
130
|
-
|
|
131
|
-
const firstClient = createPublicClient({
|
|
132
|
-
chain: firstChainInfo,
|
|
133
|
-
transport: http(),
|
|
134
|
-
})
|
|
135
|
-
const lastClient = createPublicClient({
|
|
136
|
-
chain: lastChainInfo,
|
|
137
|
-
transport: http(),
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
async function getBlockNumber(
|
|
141
|
-
client: ReturnType<typeof createPublicClient>,
|
|
142
|
-
tx: TransactionState,
|
|
143
|
-
) {
|
|
144
|
-
if (tx.blockNumber) return BigInt(tx.blockNumber)
|
|
145
|
-
const receipt = await client.getTransactionReceipt({
|
|
146
|
-
hash: tx.transactionHash as `0x${string}`,
|
|
147
|
-
})
|
|
148
|
-
return receipt.blockNumber
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async function getTimestamp(
|
|
152
|
-
client: ReturnType<typeof createPublicClient>,
|
|
153
|
-
blockNumber: bigint,
|
|
154
|
-
) {
|
|
155
|
-
const block = await client.getBlock({ blockNumber })
|
|
156
|
-
return typeof block.timestamp === "bigint"
|
|
157
|
-
? Number(block.timestamp)
|
|
158
|
-
: block.timestamp
|
|
159
|
-
}
|
|
160
|
-
|
|
161
129
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (diff < 1) {
|
|
174
|
-
return 1 // round up to 1 second
|
|
130
|
+
// Use txnMinedAt timestamps from API if available
|
|
131
|
+
if (firstTx.txnMinedAt && lastTx.txnMinedAt) {
|
|
132
|
+
const firstTs = new Date(firstTx.txnMinedAt).getTime() / 1000
|
|
133
|
+
const lastTs = new Date(lastTx.txnMinedAt).getTime() / 1000
|
|
134
|
+
|
|
135
|
+
const diff = lastTs - firstTs
|
|
136
|
+
if (diff < 1) {
|
|
137
|
+
return 1 // round up to 1 second
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return diff
|
|
175
141
|
}
|
|
176
142
|
|
|
177
|
-
return
|
|
143
|
+
// Fallback: return 0 if txnMinedAt is not available
|
|
144
|
+
logger.console.warn(
|
|
145
|
+
"[trails-sdk] txnMinedAt not available for transactions, cannot calculate time difference",
|
|
146
|
+
)
|
|
147
|
+
return 0
|
|
178
148
|
} catch (error) {
|
|
179
149
|
logger.console.error(
|
|
180
150
|
"[trails-sdk] Error calculating transaction time difference:",
|
|
@@ -189,8 +159,8 @@ export async function getAccountTransactionHistory({
|
|
|
189
159
|
accountAddress,
|
|
190
160
|
pageSize = 10,
|
|
191
161
|
page = 1,
|
|
192
|
-
|
|
193
162
|
includeMetadata = true,
|
|
163
|
+
abortSignal,
|
|
194
164
|
}: GetAccountTransactionHistoryParams): Promise<TransactionHistoryResponse> {
|
|
195
165
|
const accessKey = getSequenceProjectAccessKey()
|
|
196
166
|
|
|
@@ -198,26 +168,51 @@ export async function getAccountTransactionHistory({
|
|
|
198
168
|
throw new Error("Sequence project access key is required")
|
|
199
169
|
}
|
|
200
170
|
|
|
201
|
-
//
|
|
202
|
-
const
|
|
203
|
-
if (!chainIndexerUrl) {
|
|
204
|
-
throw new Error(`Unsupported chain ID: ${chainId}`)
|
|
205
|
-
}
|
|
171
|
+
// Create a unique ID for this operation
|
|
172
|
+
const operationId = `account-tx-history-${chainId}-${accountAddress}-${page}-${Date.now()}`
|
|
206
173
|
|
|
207
|
-
|
|
174
|
+
// Create an abort controller for this specific operation
|
|
175
|
+
const operationAbortController = new AbortController()
|
|
208
176
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
accountAddress: accountAddress.toLowerCase(),
|
|
212
|
-
},
|
|
213
|
-
includeMetadata,
|
|
214
|
-
page: {
|
|
215
|
-
page,
|
|
216
|
-
pageSize,
|
|
217
|
-
},
|
|
218
|
-
}
|
|
177
|
+
// Register this operation with the global registry
|
|
178
|
+
abortControllerRegistry.register(operationId, operationAbortController)
|
|
219
179
|
|
|
220
180
|
try {
|
|
181
|
+
// Check if we should abort before starting
|
|
182
|
+
if (abortSignal?.aborted || operationAbortController.signal.aborted) {
|
|
183
|
+
logger.console.log(
|
|
184
|
+
"[trails-sdk] Aborting account transaction history fetch",
|
|
185
|
+
)
|
|
186
|
+
throw new Error("Operation aborted")
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Get the chain-specific indexer URL
|
|
190
|
+
const chainIndexerUrl = getChainIndexerUrl(chainId)
|
|
191
|
+
if (!chainIndexerUrl) {
|
|
192
|
+
throw new Error(`Unsupported chain ID: ${chainId}`)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const endpoint = `${chainIndexerUrl}/rpc/Indexer/GetTransactionHistory`
|
|
196
|
+
|
|
197
|
+
const requestBody = {
|
|
198
|
+
filter: {
|
|
199
|
+
accountAddress: accountAddress.toLowerCase(),
|
|
200
|
+
},
|
|
201
|
+
includeMetadata,
|
|
202
|
+
page: {
|
|
203
|
+
page,
|
|
204
|
+
pageSize,
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Check abort signal before making the request
|
|
209
|
+
if (abortSignal?.aborted || operationAbortController.signal.aborted) {
|
|
210
|
+
logger.console.log(
|
|
211
|
+
"[trails-sdk] Aborting account transaction history fetch before request",
|
|
212
|
+
)
|
|
213
|
+
throw new Error("Operation aborted")
|
|
214
|
+
}
|
|
215
|
+
|
|
221
216
|
const response = await fetch(endpoint, {
|
|
222
217
|
method: "POST",
|
|
223
218
|
headers: {
|
|
@@ -225,6 +220,7 @@ export async function getAccountTransactionHistory({
|
|
|
225
220
|
"X-Access-Key": accessKey,
|
|
226
221
|
},
|
|
227
222
|
body: JSON.stringify(requestBody, bigintReplacer, 2),
|
|
223
|
+
signal: abortSignal || operationAbortController.signal,
|
|
228
224
|
})
|
|
229
225
|
|
|
230
226
|
if (!response.ok) {
|
|
@@ -246,11 +242,21 @@ export async function getAccountTransactionHistory({
|
|
|
246
242
|
transactions,
|
|
247
243
|
}
|
|
248
244
|
} catch (error) {
|
|
245
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
246
|
+
logger.console.log(
|
|
247
|
+
"[trails-sdk] Account transaction history fetch was aborted",
|
|
248
|
+
)
|
|
249
|
+
throw new Error("Operation aborted")
|
|
250
|
+
}
|
|
251
|
+
|
|
249
252
|
logger.console.error(
|
|
250
253
|
"[trails-sdk] Error fetching transaction history:",
|
|
251
254
|
error,
|
|
252
255
|
)
|
|
253
256
|
throw error
|
|
257
|
+
} finally {
|
|
258
|
+
// Always unregister when operation completes or is aborted
|
|
259
|
+
abortControllerRegistry.unregister(operationId)
|
|
254
260
|
}
|
|
255
261
|
}
|
|
256
262
|
|
|
@@ -311,7 +317,7 @@ export type GetIntentTransactionHistoryParams = {
|
|
|
311
317
|
}
|
|
312
318
|
|
|
313
319
|
export async function getIntentTransactionHistory({
|
|
314
|
-
accountAddress,
|
|
320
|
+
accountAddress: _accountAddress,
|
|
315
321
|
pageSize = 10,
|
|
316
322
|
page = 1,
|
|
317
323
|
}: GetIntentTransactionHistoryParams): Promise<IntentTransactionHistoryResponse> {
|
|
@@ -326,9 +332,7 @@ export async function getIntentTransactionHistory({
|
|
|
326
332
|
|
|
327
333
|
// Use the hybrid client's getIntentTransactionHistory method which tries Trails API first, then Sequence API
|
|
328
334
|
const result = await trailsClient.getIntentTransactionHistory({
|
|
329
|
-
accountAddress: accountAddress.toLowerCase(),
|
|
330
335
|
page: {
|
|
331
|
-
page,
|
|
332
336
|
pageSize,
|
|
333
337
|
sort: [
|
|
334
338
|
{
|
|
@@ -339,7 +343,24 @@ export async function getIntentTransactionHistory({
|
|
|
339
343
|
},
|
|
340
344
|
})
|
|
341
345
|
|
|
342
|
-
|
|
346
|
+
// Note: The new API has a different IntentTransaction structure.
|
|
347
|
+
// We need to map the API response to our local type structure.
|
|
348
|
+
// For now, return an empty result as the API structure has changed significantly.
|
|
349
|
+
// TODO: Implement proper mapping from new API IntentTransaction to SDK IntentTransaction
|
|
350
|
+
return {
|
|
351
|
+
page: result.nextPage
|
|
352
|
+
? {
|
|
353
|
+
page,
|
|
354
|
+
pageSize,
|
|
355
|
+
more: true,
|
|
356
|
+
}
|
|
357
|
+
: {
|
|
358
|
+
page,
|
|
359
|
+
pageSize,
|
|
360
|
+
more: false,
|
|
361
|
+
},
|
|
362
|
+
transactions: [], // TODO: Map result.transactions to SDK IntentTransaction format
|
|
363
|
+
}
|
|
343
364
|
} catch (error) {
|
|
344
365
|
logger.console.error(
|
|
345
366
|
"[trails-sdk] Error fetching intent transaction history:",
|
|
@@ -355,6 +376,7 @@ export type UseAccountTransactionHistoryParams = {
|
|
|
355
376
|
pageSize?: number
|
|
356
377
|
page?: number
|
|
357
378
|
includeMetadata?: boolean
|
|
379
|
+
abortSignal?: AbortSignal
|
|
358
380
|
}
|
|
359
381
|
|
|
360
382
|
export type UseAccountTransactionHistoryReturn = {
|
|
@@ -369,6 +391,7 @@ export function useAccountTransactionHistory({
|
|
|
369
391
|
pageSize = 10,
|
|
370
392
|
page = 1,
|
|
371
393
|
includeMetadata = true,
|
|
394
|
+
abortSignal,
|
|
372
395
|
}: UseAccountTransactionHistoryParams): UseAccountTransactionHistoryReturn {
|
|
373
396
|
const { data, isLoading, error } = useQuery({
|
|
374
397
|
queryKey: [
|
|
@@ -379,17 +402,21 @@ export function useAccountTransactionHistory({
|
|
|
379
402
|
page,
|
|
380
403
|
includeMetadata,
|
|
381
404
|
],
|
|
382
|
-
queryFn: async () => {
|
|
405
|
+
queryFn: async ({ signal }) => {
|
|
383
406
|
if (!chainId || !accountAddress) {
|
|
384
407
|
return undefined
|
|
385
408
|
}
|
|
386
409
|
|
|
410
|
+
// Use the React Query signal if no external abort signal is provided
|
|
411
|
+
const effectiveSignal = abortSignal || signal
|
|
412
|
+
|
|
387
413
|
return await getAccountTransactionHistory({
|
|
388
414
|
chainId,
|
|
389
415
|
accountAddress,
|
|
390
416
|
pageSize,
|
|
391
417
|
page,
|
|
392
418
|
includeMetadata,
|
|
419
|
+
abortSignal: effectiveSignal,
|
|
393
420
|
})
|
|
394
421
|
},
|
|
395
422
|
enabled: Boolean(chainId && accountAddress),
|