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.
Files changed (267) hide show
  1. package/dist/aave.d.ts +2 -0
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/abortController.d.ts +8 -0
  4. package/dist/abortController.d.ts.map +1 -0
  5. package/dist/{ccip-CXlshvBY.js → ccip-BMB3uDZt.js} +1 -1
  6. package/dist/config.d.ts +0 -5
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/constants.d.ts +4 -4
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/error.d.ts +4 -1
  11. package/dist/error.d.ts.map +1 -1
  12. package/dist/fees.d.ts +19 -0
  13. package/dist/fees.d.ts.map +1 -0
  14. package/dist/{index-_QuyGrjU.js → index-QXPUrZVv.js} +48719 -50852
  15. package/dist/index.d.ts +9 -8
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +811 -784
  18. package/dist/intentReceiptMonitor.d.ts +24 -0
  19. package/dist/intentReceiptMonitor.d.ts.map +1 -0
  20. package/dist/intentReceiptPoller.d.ts +69 -0
  21. package/dist/intentReceiptPoller.d.ts.map +1 -0
  22. package/dist/intents.d.ts +15 -11
  23. package/dist/intents.d.ts.map +1 -1
  24. package/dist/morpho.d.ts +6 -5
  25. package/dist/morpho.d.ts.map +1 -1
  26. package/dist/mutations.d.ts +16 -0
  27. package/dist/mutations.d.ts.map +1 -0
  28. package/dist/preconditions.d.ts +5 -4
  29. package/dist/preconditions.d.ts.map +1 -1
  30. package/dist/prepareSend.d.ts +7 -258
  31. package/dist/prepareSend.d.ts.map +1 -1
  32. package/dist/prices.d.ts +9 -6
  33. package/dist/prices.d.ts.map +1 -1
  34. package/dist/sequenceWallet.d.ts +3 -16
  35. package/dist/sequenceWallet.d.ts.map +1 -1
  36. package/dist/tokenBalances.d.ts +17 -13
  37. package/dist/tokenBalances.d.ts.map +1 -1
  38. package/dist/trails.d.ts +24 -40
  39. package/dist/trails.d.ts.map +1 -1
  40. package/dist/transactionIntent/constants.d.ts +7 -0
  41. package/dist/transactionIntent/constants.d.ts.map +1 -0
  42. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +44 -0
  43. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -0
  44. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +30 -0
  45. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -0
  46. package/dist/transactionIntent/deposits/index.d.ts +4 -0
  47. package/dist/transactionIntent/deposits/index.d.ts.map +1 -0
  48. package/dist/transactionIntent/deposits/standardDeposit.d.ts +30 -0
  49. package/dist/transactionIntent/deposits/standardDeposit.d.ts.map +1 -0
  50. package/dist/transactionIntent/execution/index.d.ts +2 -0
  51. package/dist/transactionIntent/execution/index.d.ts.map +1 -0
  52. package/dist/transactionIntent/execution/transactionState.d.ts +5 -0
  53. package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -0
  54. package/dist/transactionIntent/handlers/crossChain.d.ts +82 -0
  55. package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -0
  56. package/dist/transactionIntent/handlers/index.d.ts +4 -0
  57. package/dist/transactionIntent/handlers/index.d.ts.map +1 -0
  58. package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts +62 -0
  59. package/dist/transactionIntent/handlers/sameChainDifferentToken.d.ts.map +1 -0
  60. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +72 -0
  61. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -0
  62. package/dist/transactionIntent/index.d.ts +9 -0
  63. package/dist/transactionIntent/index.d.ts.map +1 -0
  64. package/dist/transactionIntent/quote/feeExtractors.d.ts +17 -0
  65. package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -0
  66. package/dist/transactionIntent/quote/index.d.ts +4 -0
  67. package/dist/transactionIntent/quote/index.d.ts.map +1 -0
  68. package/dist/transactionIntent/quote/normalizeQuote.d.ts +34 -0
  69. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -0
  70. package/dist/transactionIntent/quote/quoteHelpers.d.ts +5 -0
  71. package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -0
  72. package/dist/transactionIntent/types.d.ts +131 -0
  73. package/dist/transactionIntent/types.d.ts.map +1 -0
  74. package/dist/transactionIntent/utils/balanceChecker.d.ts +18 -0
  75. package/dist/transactionIntent/utils/balanceChecker.d.ts.map +1 -0
  76. package/dist/transactionIntent/utils/index.d.ts +4 -0
  77. package/dist/transactionIntent/utils/index.d.ts.map +1 -0
  78. package/dist/transactionIntent/utils/lifiHelpers.d.ts +10 -0
  79. package/dist/transactionIntent/utils/lifiHelpers.d.ts.map +1 -0
  80. package/dist/transactionIntent/utils/testnetHelpers.d.ts +3 -0
  81. package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -0
  82. package/dist/transactionIntent/validators.d.ts +6 -0
  83. package/dist/transactionIntent/validators.d.ts.map +1 -0
  84. package/dist/transactions.d.ts +6 -3
  85. package/dist/transactions.d.ts.map +1 -1
  86. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts +4 -0
  87. package/dist/widget/components/AccountIntentTransactionHistoryButton.d.ts.map +1 -0
  88. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  89. package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
  90. package/dist/widget/components/ClassicSwap.d.ts +2 -3
  91. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  92. package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
  93. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  94. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  95. package/dist/widget/components/DynamicInputStyles.d.ts +18 -0
  96. package/dist/widget/components/DynamicInputStyles.d.ts.map +1 -0
  97. package/dist/widget/components/DynamicSizeInputField.d.ts +13 -0
  98. package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -0
  99. package/dist/widget/components/Earn.d.ts +2 -3
  100. package/dist/widget/components/Earn.d.ts.map +1 -1
  101. package/dist/widget/components/ErrorAnimationIcon.d.ts +2 -0
  102. package/dist/widget/components/ErrorAnimationIcon.d.ts.map +1 -0
  103. package/dist/widget/components/FeeBreakdown.d.ts +9 -0
  104. package/dist/widget/components/FeeBreakdown.d.ts.map +1 -0
  105. package/dist/widget/components/FeeOptions.d.ts +5 -13
  106. package/dist/widget/components/FeeOptions.d.ts.map +1 -1
  107. package/dist/widget/components/Fund.d.ts +2 -3
  108. package/dist/widget/components/Fund.d.ts.map +1 -1
  109. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  110. package/dist/widget/components/FundSwap.d.ts +2 -3
  111. package/dist/widget/components/FundSwap.d.ts.map +1 -1
  112. package/dist/widget/components/FundingMethodSelectorButton.d.ts.map +1 -1
  113. package/dist/widget/components/Identicon.d.ts.map +1 -1
  114. package/dist/widget/components/MeshConnectExchanges.d.ts +0 -3
  115. package/dist/widget/components/MeshConnectExchanges.d.ts.map +1 -1
  116. package/dist/widget/components/Modal.d.ts.map +1 -1
  117. package/dist/widget/components/Pay.d.ts +2 -3
  118. package/dist/widget/components/Pay.d.ts.map +1 -1
  119. package/dist/widget/components/PoolDeposit.d.ts +3 -3
  120. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  121. package/dist/widget/components/PoolWithdraw.d.ts +3 -20
  122. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
  123. package/dist/widget/components/QuoteDetails.d.ts +2 -0
  124. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  125. package/dist/widget/components/Receipt.d.ts.map +1 -1
  126. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
  127. package/dist/widget/components/ScreenHeader.d.ts.map +1 -1
  128. package/dist/widget/components/Swap.d.ts +2 -3
  129. package/dist/widget/components/Swap.d.ts.map +1 -1
  130. package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
  131. package/dist/widget/components/TokenDisplayNonSelectable.d.ts +11 -0
  132. package/dist/widget/components/TokenDisplayNonSelectable.d.ts.map +1 -0
  133. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  134. package/dist/widget/components/TokenSelectorButton.d.ts.map +1 -1
  135. package/dist/widget/components/Tooltip.d.ts +9 -0
  136. package/dist/widget/components/Tooltip.d.ts.map +1 -0
  137. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  138. package/dist/widget/components/WaasFeeOptions.d.ts +1 -0
  139. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
  140. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -1
  141. package/dist/widget/components/WalletConnect.d.ts.map +1 -1
  142. package/dist/widget/css/compiled.css +2 -2
  143. package/dist/widget/hooks/useCheckout.d.ts +17 -4
  144. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  145. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  146. package/dist/widget/hooks/useQuote.d.ts +82 -0
  147. package/dist/widget/hooks/useQuote.d.ts.map +1 -0
  148. package/dist/widget/hooks/useSelectedFeeToken.d.ts +1 -0
  149. package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
  150. package/dist/widget/hooks/useSendForm.d.ts +5 -6
  151. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  152. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  153. package/dist/widget/hooks/useWalletConnectionContext.d.ts +25 -0
  154. package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -0
  155. package/dist/widget/index.js +2 -2
  156. package/dist/widget/widget.d.ts +17 -7
  157. package/dist/widget/widget.d.ts.map +1 -1
  158. package/package.json +19 -21
  159. package/src/aave.ts +54 -1
  160. package/src/abortController.ts +35 -0
  161. package/src/config.ts +57 -58
  162. package/src/constants.ts +11 -9
  163. package/src/error.ts +21 -3
  164. package/src/fees.ts +210 -0
  165. package/src/index.ts +35 -13
  166. package/src/intentReceiptMonitor.ts +102 -0
  167. package/src/intentReceiptPoller.ts +299 -0
  168. package/src/intents.ts +205 -171
  169. package/src/morpho.ts +58 -9
  170. package/src/mutations.ts +129 -0
  171. package/src/preconditions.ts +16 -21
  172. package/src/prepareSend.ts +92 -4699
  173. package/src/prices.ts +26 -22
  174. package/src/relaySdk.ts +2 -2
  175. package/src/sequenceWallet.ts +6 -73
  176. package/src/tokenBalances.ts +175 -69
  177. package/src/trails.ts +230 -722
  178. package/src/transactionIntent/constants.ts +11 -0
  179. package/src/transactionIntent/deposits/depositOrchestrator.ts +210 -0
  180. package/src/transactionIntent/deposits/gaslessDeposit.ts +588 -0
  181. package/src/transactionIntent/deposits/index.ts +3 -0
  182. package/src/transactionIntent/deposits/standardDeposit.ts +379 -0
  183. package/src/transactionIntent/execution/index.ts +1 -0
  184. package/src/transactionIntent/execution/transactionState.ts +35 -0
  185. package/src/transactionIntent/handlers/crossChain.ts +1707 -0
  186. package/src/transactionIntent/handlers/index.ts +3 -0
  187. package/src/transactionIntent/handlers/sameChainDifferentToken.ts +323 -0
  188. package/src/transactionIntent/handlers/sameChainSameToken.ts +712 -0
  189. package/src/transactionIntent/index.ts +9 -0
  190. package/src/transactionIntent/quote/feeExtractors.ts +81 -0
  191. package/src/transactionIntent/quote/index.ts +3 -0
  192. package/src/transactionIntent/quote/normalizeQuote.ts +367 -0
  193. package/src/transactionIntent/quote/quoteHelpers.ts +53 -0
  194. package/src/transactionIntent/types.ts +157 -0
  195. package/src/transactionIntent/utils/balanceChecker.ts +96 -0
  196. package/src/transactionIntent/utils/index.ts +3 -0
  197. package/src/transactionIntent/utils/lifiHelpers.ts +68 -0
  198. package/src/transactionIntent/utils/testnetHelpers.ts +10 -0
  199. package/src/transactionIntent/validators.ts +57 -0
  200. package/src/transactions.ts +98 -71
  201. package/src/widget/compiled.css +2 -2
  202. package/src/widget/components/AccountIntentTransactionHistory.tsx +36 -36
  203. package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +22 -0
  204. package/src/widget/components/AccountSettings.tsx +70 -41
  205. package/src/widget/components/ChainFilterDropdown.tsx +24 -3
  206. package/src/widget/components/ClassicSwap.tsx +44 -107
  207. package/src/widget/components/ConfigDisplay.tsx +0 -11
  208. package/src/widget/components/ConnectWallet.tsx +4 -1
  209. package/src/widget/components/ConnectedWallets.tsx +51 -25
  210. package/src/widget/components/DynamicInputStyles.tsx +76 -0
  211. package/src/widget/components/DynamicSizeInputField.tsx +109 -0
  212. package/src/widget/components/Earn.tsx +34 -45
  213. package/src/widget/components/ErrorAnimationIcon.tsx +130 -0
  214. package/src/widget/components/FeeBreakdown.tsx +155 -0
  215. package/src/widget/components/FeeOption.tsx +2 -2
  216. package/src/widget/components/FeeOptions.tsx +151 -112
  217. package/src/widget/components/Fund.tsx +10 -29
  218. package/src/widget/components/FundMethods.tsx +4 -3
  219. package/src/widget/components/FundSwap.tsx +2 -3
  220. package/src/widget/components/FundingMethodSelectorButton.tsx +24 -14
  221. package/src/widget/components/Identicon.tsx +164 -95
  222. package/src/widget/components/MeshConnectExchanges.tsx +2 -15
  223. package/src/widget/components/Modal.tsx +0 -12
  224. package/src/widget/components/Pay.tsx +72 -75
  225. package/src/widget/components/PoolDeposit.tsx +221 -242
  226. package/src/widget/components/PoolWithdraw.tsx +347 -469
  227. package/src/widget/components/PriceImpactWarning.tsx +1 -1
  228. package/src/widget/components/QuoteDetails.tsx +906 -484
  229. package/src/widget/components/Receipt.tsx +16 -2
  230. package/src/widget/components/RecipientSelectorButton.tsx +7 -5
  231. package/src/widget/components/Recipients.tsx +1 -1
  232. package/src/widget/components/ScreenHeader.tsx +60 -36
  233. package/src/widget/components/Swap.tsx +2 -3
  234. package/src/widget/components/ThemeProvider.tsx +2 -1
  235. package/src/widget/components/TokenDisplayNonSelectable.tsx +40 -0
  236. package/src/widget/components/TokenImage.tsx +1 -1
  237. package/src/widget/components/TokenSelector.tsx +62 -53
  238. package/src/widget/components/TokenSelectorButton.tsx +38 -15
  239. package/src/widget/components/Tooltip.tsx +51 -0
  240. package/src/widget/components/TransferPendingVertical.tsx +12 -8
  241. package/src/widget/components/WaasFeeOptions.tsx +139 -4
  242. package/src/widget/components/WalletConfirmation.tsx +23 -13
  243. package/src/widget/components/WalletConnect.tsx +93 -29
  244. package/src/widget/hooks/useAmountUsd.ts +9 -9
  245. package/src/widget/hooks/useCheckout.ts +97 -9
  246. package/src/widget/hooks/useDefaultTokenSelection.tsx +27 -21
  247. package/src/widget/hooks/useQuote.ts +466 -0
  248. package/src/widget/hooks/useSelectedFeeToken.tsx +32 -37
  249. package/src/widget/hooks/useSendForm.ts +45 -51
  250. package/src/widget/hooks/useTokenList.ts +34 -26
  251. package/src/widget/hooks/useWalletConnectionContext.tsx +128 -0
  252. package/src/widget/widget.tsx +365 -390
  253. package/dist/apiClient.d.ts +0 -9
  254. package/dist/apiClient.d.ts.map +0 -1
  255. package/dist/intentEntrypoint.d.ts +0 -114
  256. package/dist/intentEntrypoint.d.ts.map +0 -1
  257. package/dist/metaTxnMonitor.d.ts +0 -15
  258. package/dist/metaTxnMonitor.d.ts.map +0 -1
  259. package/dist/metaTxns.d.ts +0 -11
  260. package/dist/metaTxns.d.ts.map +0 -1
  261. package/dist/relayer.d.ts +0 -43
  262. package/dist/relayer.d.ts.map +0 -1
  263. package/src/apiClient.ts +0 -35
  264. package/src/intentEntrypoint.ts +0 -203
  265. package/src/metaTxnMonitor.ts +0 -171
  266. package/src/metaTxns.ts +0 -45
  267. 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,3 @@
1
+ export * from "./testnetHelpers.js"
2
+ export * from "./balanceChecker.js"
3
+ export * from "./lifiHelpers.js"
@@ -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
+ }
@@ -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
- const [firstBlockNumber, lastBlockNumber] = await Promise.all([
163
- getBlockNumber(firstClient, firstTx),
164
- getBlockNumber(lastClient, lastTx),
165
- ])
166
-
167
- const [firstTs, lastTs] = await Promise.all([
168
- getTimestamp(firstClient, firstBlockNumber),
169
- getTimestamp(lastClient, lastBlockNumber),
170
- ])
171
-
172
- const diff = lastTs - firstTs
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 diff
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
- // Get the chain-specific indexer URL
202
- const chainIndexerUrl = getChainIndexerUrl(chainId)
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
- const endpoint = `${chainIndexerUrl}/rpc/Indexer/GetTransactionHistory`
174
+ // Create an abort controller for this specific operation
175
+ const operationAbortController = new AbortController()
208
176
 
209
- const requestBody = {
210
- filter: {
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
- return result
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),