0xtrails 0.2.6 → 0.4.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 (218) hide show
  1. package/dist/aave.d.ts +2 -0
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/{ccip-Xjh9d1gb.js → ccip-BpQGQiWq.js} +7 -7
  4. package/dist/config.d.ts +0 -5
  5. package/dist/config.d.ts.map +1 -1
  6. package/dist/constants.d.ts +2 -4
  7. package/dist/constants.d.ts.map +1 -1
  8. package/dist/error.d.ts +4 -1
  9. package/dist/error.d.ts.map +1 -1
  10. package/dist/fees.d.ts +2 -2
  11. package/dist/fees.d.ts.map +1 -1
  12. package/dist/{index-BnhdZ8Ho.js → index-DsJM5F-V.js} +46084 -48697
  13. package/dist/index.d.ts +9 -8
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +741 -923
  16. package/dist/intentReceiptMonitor.d.ts +24 -0
  17. package/dist/intentReceiptMonitor.d.ts.map +1 -0
  18. package/dist/intentReceiptPoller.d.ts +69 -0
  19. package/dist/intentReceiptPoller.d.ts.map +1 -0
  20. package/dist/intents.d.ts +15 -11
  21. package/dist/intents.d.ts.map +1 -1
  22. package/dist/morpho.d.ts +6 -5
  23. package/dist/morpho.d.ts.map +1 -1
  24. package/dist/mutations.d.ts +16 -0
  25. package/dist/mutations.d.ts.map +1 -0
  26. package/dist/preconditions.d.ts +5 -4
  27. package/dist/preconditions.d.ts.map +1 -1
  28. package/dist/prepareSend.d.ts +5 -190
  29. package/dist/prepareSend.d.ts.map +1 -1
  30. package/dist/prices.d.ts +9 -6
  31. package/dist/prices.d.ts.map +1 -1
  32. package/dist/sequenceWallet.d.ts +3 -16
  33. package/dist/sequenceWallet.d.ts.map +1 -1
  34. package/dist/tokenBalances.d.ts +17 -13
  35. package/dist/tokenBalances.d.ts.map +1 -1
  36. package/dist/trails.d.ts +24 -40
  37. package/dist/trails.d.ts.map +1 -1
  38. package/dist/trailsClient.d.ts +5 -6
  39. package/dist/trailsClient.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 +2 -1
  85. package/dist/transactions.d.ts.map +1 -1
  86. package/dist/widget/components/AccountSettings.d.ts.map +1 -1
  87. package/dist/widget/components/ClassicSwap.d.ts +0 -1
  88. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  89. package/dist/widget/components/ConfigDisplay.d.ts.map +1 -1
  90. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  91. package/dist/widget/components/DynamicSizeInputField.d.ts +13 -0
  92. package/dist/widget/components/DynamicSizeInputField.d.ts.map +1 -0
  93. package/dist/widget/components/Earn.d.ts +0 -1
  94. package/dist/widget/components/Earn.d.ts.map +1 -1
  95. package/dist/widget/components/FeeOptions.d.ts +5 -13
  96. package/dist/widget/components/FeeOptions.d.ts.map +1 -1
  97. package/dist/widget/components/Fund.d.ts +0 -1
  98. package/dist/widget/components/Fund.d.ts.map +1 -1
  99. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  100. package/dist/widget/components/FundSwap.d.ts +0 -1
  101. package/dist/widget/components/FundSwap.d.ts.map +1 -1
  102. package/dist/widget/components/Pay.d.ts +0 -1
  103. package/dist/widget/components/Pay.d.ts.map +1 -1
  104. package/dist/widget/components/PoolDeposit.d.ts +0 -1
  105. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  106. package/dist/widget/components/PoolWithdraw.d.ts +0 -18
  107. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
  108. package/dist/widget/components/QuoteDetails.d.ts +1 -0
  109. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  110. package/dist/widget/components/Swap.d.ts +0 -1
  111. package/dist/widget/components/Swap.d.ts.map +1 -1
  112. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -1
  113. package/dist/widget/components/WaasFeeOptions.d.ts.map +1 -1
  114. package/dist/widget/css/compiled.css +2 -2
  115. package/dist/widget/hooks/useCheckout.d.ts +17 -4
  116. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  117. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  118. package/dist/widget/hooks/useQuote.d.ts +3 -4
  119. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  120. package/dist/widget/hooks/useSelectedFeeToken.d.ts +1 -0
  121. package/dist/widget/hooks/useSelectedFeeToken.d.ts.map +1 -1
  122. package/dist/widget/hooks/useSendForm.d.ts +3 -4
  123. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  124. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  125. package/dist/widget/hooks/useWalletConnectionContext.d.ts +25 -0
  126. package/dist/widget/hooks/useWalletConnectionContext.d.ts.map +1 -0
  127. package/dist/widget/index.js +1 -1
  128. package/dist/widget/widget.d.ts +12 -7
  129. package/dist/widget/widget.d.ts.map +1 -1
  130. package/package.json +21 -23
  131. package/src/aave.ts +54 -1
  132. package/src/config.ts +57 -58
  133. package/src/constants.ts +8 -9
  134. package/src/error.ts +21 -3
  135. package/src/fees.ts +53 -42
  136. package/src/index.ts +35 -13
  137. package/src/intentReceiptMonitor.ts +102 -0
  138. package/src/intentReceiptPoller.ts +299 -0
  139. package/src/intents.ts +206 -172
  140. package/src/morpho.ts +58 -9
  141. package/src/mutations.ts +129 -0
  142. package/src/preconditions.ts +16 -21
  143. package/src/prepareSend.ts +80 -4514
  144. package/src/prices.ts +26 -22
  145. package/src/relaySdk.ts +2 -2
  146. package/src/sequenceWallet.ts +6 -73
  147. package/src/tokenBalances.ts +175 -69
  148. package/src/trails.ts +230 -722
  149. package/src/trailsClient.ts +10 -23
  150. package/src/transactionIntent/constants.ts +11 -0
  151. package/src/transactionIntent/deposits/depositOrchestrator.ts +210 -0
  152. package/src/transactionIntent/deposits/gaslessDeposit.ts +588 -0
  153. package/src/transactionIntent/deposits/index.ts +3 -0
  154. package/src/transactionIntent/deposits/standardDeposit.ts +379 -0
  155. package/src/transactionIntent/execution/index.ts +1 -0
  156. package/src/transactionIntent/execution/transactionState.ts +35 -0
  157. package/src/transactionIntent/handlers/crossChain.ts +1707 -0
  158. package/src/transactionIntent/handlers/index.ts +3 -0
  159. package/src/transactionIntent/handlers/sameChainDifferentToken.ts +323 -0
  160. package/src/transactionIntent/handlers/sameChainSameToken.ts +712 -0
  161. package/src/transactionIntent/index.ts +9 -0
  162. package/src/transactionIntent/quote/feeExtractors.ts +81 -0
  163. package/src/transactionIntent/quote/index.ts +3 -0
  164. package/src/transactionIntent/quote/normalizeQuote.ts +367 -0
  165. package/src/transactionIntent/quote/quoteHelpers.ts +53 -0
  166. package/src/transactionIntent/types.ts +157 -0
  167. package/src/transactionIntent/utils/balanceChecker.ts +96 -0
  168. package/src/transactionIntent/utils/index.ts +3 -0
  169. package/src/transactionIntent/utils/lifiHelpers.ts +68 -0
  170. package/src/transactionIntent/utils/testnetHelpers.ts +10 -0
  171. package/src/transactionIntent/validators.ts +57 -0
  172. package/src/transactions.ts +36 -53
  173. package/src/widget/compiled.css +2 -2
  174. package/src/widget/components/AccountIntentTransactionHistory.tsx +36 -36
  175. package/src/widget/components/AccountSettings.tsx +23 -6
  176. package/src/widget/components/ClassicSwap.tsx +28 -53
  177. package/src/widget/components/ConfigDisplay.tsx +0 -11
  178. package/src/widget/components/ConnectedWallets.tsx +30 -4
  179. package/src/widget/components/DynamicSizeInputField.tsx +109 -0
  180. package/src/widget/components/Earn.tsx +0 -16
  181. package/src/widget/components/FeeBreakdown.tsx +3 -3
  182. package/src/widget/components/FeeOption.tsx +2 -2
  183. package/src/widget/components/FeeOptions.tsx +151 -112
  184. package/src/widget/components/Fund.tsx +0 -3
  185. package/src/widget/components/FundMethods.tsx +4 -3
  186. package/src/widget/components/FundSwap.tsx +0 -1
  187. package/src/widget/components/Pay.tsx +11 -16
  188. package/src/widget/components/PoolDeposit.tsx +35 -32
  189. package/src/widget/components/PoolWithdraw.tsx +153 -256
  190. package/src/widget/components/QuoteDetails.tsx +899 -494
  191. package/src/widget/components/Swap.tsx +0 -1
  192. package/src/widget/components/TransferPendingVertical.tsx +12 -8
  193. package/src/widget/components/WaasFeeOptions.tsx +23 -7
  194. package/src/widget/components/WalletConfirmation.tsx +1 -1
  195. package/src/widget/hooks/useAmountUsd.ts +9 -9
  196. package/src/widget/hooks/useCheckout.ts +97 -9
  197. package/src/widget/hooks/useDefaultTokenSelection.tsx +27 -21
  198. package/src/widget/hooks/useQuote.ts +86 -33
  199. package/src/widget/hooks/useSelectedFeeToken.tsx +32 -37
  200. package/src/widget/hooks/useSendForm.ts +37 -47
  201. package/src/widget/hooks/useTokenList.ts +34 -26
  202. package/src/widget/hooks/useWalletConnectionContext.tsx +128 -0
  203. package/src/widget/widget.tsx +197 -207
  204. package/dist/apiClient.d.ts +0 -9
  205. package/dist/apiClient.d.ts.map +0 -1
  206. package/dist/intentEntrypoint.d.ts +0 -114
  207. package/dist/intentEntrypoint.d.ts.map +0 -1
  208. package/dist/metaTxnMonitor.d.ts +0 -15
  209. package/dist/metaTxnMonitor.d.ts.map +0 -1
  210. package/dist/metaTxns.d.ts +0 -11
  211. package/dist/metaTxns.d.ts.map +0 -1
  212. package/dist/relayer.d.ts +0 -43
  213. package/dist/relayer.d.ts.map +0 -1
  214. package/src/apiClient.ts +0 -35
  215. package/src/intentEntrypoint.ts +0 -203
  216. package/src/metaTxnMonitor.ts +0 -171
  217. package/src/metaTxns.ts +0 -45
  218. package/src/relayer.ts +0 -289
@@ -1,19 +1,15 @@
1
1
  import { TrendingUp, ChevronRight, Search, Loader2 } from "lucide-react"
2
2
  import { useEffect, useState, useRef, useMemo } from "react"
3
3
  import type React from "react"
4
- import type { Account, WalletClient } from "viem"
5
- import { createPublicClient, http, parseUnits, formatUnits } from "viem"
4
+ import type { Account, Chain, WalletClient } from "viem"
5
+ import { parseUnits, formatUnits, parseAbi } from "viem"
6
6
  import type { TransactionState } from "../../transactions.js"
7
7
  import type { OnCompleteProps } from "../hooks/useSendForm.js"
8
8
  import type { CheckoutOnHandlers } from "../hooks/useCheckout.js"
9
- import { useSendForm } from "../hooks/useSendForm.js"
10
- import { TradeType } from "../../prepareSend.js"
11
9
  import { useEarnPool } from "../hooks/useEarnPool.js"
12
- import { useMode } from "../hooks/useMode.js"
13
10
  import { useBalanceVisible } from "../hooks/useBalanceVisible.js"
14
11
  import { TokenImage } from "./TokenImage.js"
15
12
  import { EarnPools } from "./EarnPools.js"
16
- import { QuoteDetails } from "./QuoteDetails.js"
17
13
  import { PercentageMaxButtons } from "./PercentageMaxButtons.js"
18
14
  import { formatTvl } from "../../prices.js"
19
15
  import { getExplorerUrlForAddress } from "../../explorer.js"
@@ -21,38 +17,24 @@ import { getChainInfo } from "../../chains.js"
21
17
  import { useAmountUsd } from "../hooks/useAmountUsd.js"
22
18
  import aaveLogo from "../assets/aave.svg"
23
19
  import morphoLogo from "../assets/morpho.svg"
24
- import type { PrepareSendQuote } from "../../prepareSend.js"
25
20
  import type { SupportedToken } from "../../tokens.js"
26
21
  import { logger } from "../../logger.js"
27
22
  import { generateAaveWithdrawCalldata } from "../../aave.js"
28
23
  import { generateMorphoWithdrawCalldata } from "../../morpho.js"
29
24
  import { formatAmount } from "../../tokenBalances.js"
30
- import { useDynamicInputStyles } from "./DynamicInputStyles.js"
25
+ import { DynamicSizeInputField } from "./DynamicSizeInputField.js"
31
26
  import { TokenDisplayNonSelectable } from "./TokenDisplayNonSelectable.js"
27
+ import { estimateGasCostFormatted, estimateGasLimit } from "../../estimate.js"
28
+ import { sendOriginTransaction } from "../../intents.js"
29
+ import { usePublicClient } from "wagmi"
30
+ import { getTransactionStateFromReceipt } from "../../transactionIntent/index.js"
32
31
 
33
32
  interface PoolWithdrawProps {
34
33
  account?: Account
35
34
  walletClient?: WalletClient
36
35
  onTransactionStateChange: (transactionStates: TransactionState[]) => void
37
36
  onError: (error: Error | string | null) => void
38
- onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
39
- onConfirm: () => void
40
37
  onComplete: (result: OnCompleteProps) => void
41
- onSend: (amount: string, recipient: string) => void
42
- paymasterUrls?: Array<{ chainId: number; url: string }>
43
- gasless?: boolean
44
- setWalletConfirmRetryHandler: (handler: () => Promise<void>) => void
45
- quoteProvider?: string
46
- fundMethod?: string
47
- onNavigateToMeshConnect?: (
48
- props: {
49
- toTokenSymbol: string
50
- toTokenAmount: string
51
- toChainId: number
52
- toRecipientAddress: string
53
- },
54
- quote?: PrepareSendQuote | null,
55
- ) => void
56
38
  checkoutOnHandlers?: CheckoutOnHandlers
57
39
  recentTokens?: SupportedToken[]
58
40
  onRecentTokenSelect?: (token: SupportedToken) => void
@@ -65,23 +47,14 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
65
47
  walletClient,
66
48
  onTransactionStateChange,
67
49
  onError,
68
- onWaitingForWalletConfirm,
69
- onConfirm,
70
50
  onComplete,
71
- onSend,
72
- paymasterUrls,
73
- gasless,
74
- setWalletConfirmRetryHandler,
75
- quoteProvider,
76
- fundMethod,
77
- onNavigateToMeshConnect,
78
- checkoutOnHandlers,
79
51
  onPoolSelectorStateChange,
80
52
  }) => {
81
- const { mode } = useMode()
82
53
  const { isBalanceVisible } = useBalanceVisible()
83
54
  const { selectedPool, setSelectedPool } = useEarnPool()
55
+ const publicClient = usePublicClient()
84
56
 
57
+ const [amountToWithdraw, setAmountToWithdraw] = useState("")
85
58
  const [showEarnPools, setShowEarnPools] = useState(false)
86
59
  const [amount, setAmount] = useState("")
87
60
  const [aTokenAddress, setATokenAddress] = useState<string | null>(null)
@@ -138,14 +111,8 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
138
111
  )
139
112
  return
140
113
  }
141
-
142
- const publicClient = createPublicClient({
143
- chain,
144
- transport: http(),
145
- })
146
-
147
114
  // Call getReserveAToken on the pool contract to get aToken address
148
- const aTokenAddr = (await publicClient.readContract({
115
+ const aTokenAddr = (await publicClient?.readContract({
149
116
  address: selectedPool.depositAddress as `0x${string}`,
150
117
  abi: [
151
118
  {
@@ -182,7 +149,7 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
182
149
  }
183
150
 
184
151
  fetchATokenAddress()
185
- }, [selectedPool])
152
+ }, [publicClient, selectedPool])
186
153
 
187
154
  // Fetch pool balance (aToken balance for Aave, pool contract balance for Morpho, pool token balance for others)
188
155
  useEffect(() => {
@@ -218,11 +185,6 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
218
185
  return
219
186
  }
220
187
 
221
- const publicClient = createPublicClient({
222
- chain,
223
- transport: http(),
224
- })
225
-
226
188
  // Determine which token address to query
227
189
  let tokenToQuery: string
228
190
  if (selectedPool.protocol === "Aave" && aTokenAddress) {
@@ -242,7 +204,7 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
242
204
  })
243
205
 
244
206
  // Fetch balance using balanceOf
245
- const balance = (await publicClient.readContract({
207
+ const balance = (await publicClient?.readContract({
246
208
  address: tokenToQuery as `0x${string}`,
247
209
  abi: [
248
210
  {
@@ -258,7 +220,7 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
258
220
  })) as bigint
259
221
 
260
222
  // Fetch decimals
261
- const decimals = (await publicClient.readContract({
223
+ const decimals = (await publicClient?.readContract({
262
224
  address: tokenToQuery as `0x${string}`,
263
225
  abi: [
264
226
  {
@@ -301,7 +263,7 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
301
263
  }
302
264
 
303
265
  fetchPoolBalance()
304
- }, [selectedPool, aTokenAddress, account])
266
+ }, [publicClient, selectedPool, aTokenAddress, account])
305
267
 
306
268
  // Generate withdraw calldata dynamically based on user's entered amount
307
269
  const withdrawCalldata = useMemo(() => {
@@ -341,9 +303,9 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
341
303
  )
342
304
  } else if (isMorpho) {
343
305
  calldata = generateMorphoWithdrawCalldata(
344
- selectedPool.token.address, // underlying asset (e.g., USDC)
345
- amountWei, // actual amount to withdraw in wei
346
- account.address, // recipient (user's wallet)
306
+ amountWei, // amount of underlying assets to withdraw in wei
307
+ account.address, // receiver (user's wallet)
308
+ account.address, // owner (user's wallet - owns the shares)
347
309
  )
348
310
  } else {
349
311
  return undefined
@@ -369,127 +331,6 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
369
331
  }
370
332
  }, [selectedPool, amount, account?.address])
371
333
 
372
- // Convert pool to token format for useSendForm
373
- // For Aave, use the aToken address
374
- // For Morpho, use the pool contract address
375
- // For others, use the underlying token address
376
- const poolToken = useMemo(() => {
377
- if (!selectedPool) {
378
- logger.console.log("[pool-withdraw] No pool selected, poolToken is null")
379
- return null
380
- }
381
-
382
- const isAave = selectedPool.protocol === "Aave"
383
- const isMorpho = selectedPool.protocol === "Morpho"
384
-
385
- let contractAddressToUse: string
386
- if (isAave && aTokenAddress) {
387
- contractAddressToUse = aTokenAddress
388
- } else if (isMorpho) {
389
- contractAddressToUse = selectedPool.depositAddress
390
- } else {
391
- contractAddressToUse = selectedPool.token.address
392
- }
393
-
394
- logger.console.log("[pool-withdraw] Constructing poolToken object:", {
395
- poolName: selectedPool.name,
396
- protocol: selectedPool.protocol,
397
- isAave,
398
- isMorpho,
399
- aTokenAddress,
400
- depositAddress: selectedPool.depositAddress,
401
- underlyingTokenAddress: selectedPool.token.address,
402
- willUseAddress: contractAddressToUse,
403
- })
404
-
405
- const token = {
406
- symbol: selectedPool.token.symbol,
407
- imageUrl: selectedPool.token.logoUrl,
408
- chainId: selectedPool.chainId,
409
- contractAddress: contractAddressToUse,
410
- decimals: selectedPool.token.decimals || 18,
411
- contractInfo: {
412
- decimals: selectedPool.token.decimals || 18,
413
- contractAddress: contractAddressToUse,
414
- symbol: selectedPool.token.symbol,
415
- name: selectedPool.token.name || selectedPool.token.symbol,
416
- },
417
- } as any
418
-
419
- logger.console.log("[pool-withdraw] ✅ Constructed poolToken:", token)
420
-
421
- return token
422
- }, [selectedPool, aTokenAddress])
423
-
424
- // Use useSendForm for quote functionality
425
- // Transaction is always sent TO the pool contract (depositAddress)
426
- // For Aave, withdraw() calldata specifies the recipient (user's address)
427
- // Set up source token (aToken for Aave, pool shares for Morpho)
428
- const finalSelectedToken = poolToken
429
- ? {
430
- chainId: selectedPool?.chainId,
431
- ...poolToken,
432
- }
433
- : null
434
-
435
- // Log what we're passing to useSendForm
436
- useEffect(() => {
437
- logger.console.log("[pool-withdraw] useSendForm configuration:", {
438
- hasAccount: !!account,
439
- accountAddress: account?.address,
440
- toRecipient: selectedPool?.depositAddress,
441
- toChainId: selectedPool?.chainId,
442
- toToken: finalSelectedToken?.contractAddress, // Use aToken/pool address as destination token
443
- hasCalldata: !!withdrawCalldata,
444
- calldataLength: withdrawCalldata?.length,
445
- selectedToken: finalSelectedToken,
446
- selectedTokenChainId: finalSelectedToken?.chainId,
447
- selectedTokenAddress: finalSelectedToken?.contractAddress,
448
- tradeType: "EXACT_INPUT",
449
- amount: amount,
450
- isSameChain: selectedPool?.chainId === finalSelectedToken?.chainId,
451
- willBeSameToken: true, // toToken is same as selectedToken's contractAddress
452
- })
453
- }, [account, selectedPool, withdrawCalldata, finalSelectedToken, amount])
454
-
455
- const {
456
- balanceFormatted: _unusedBalanceFormatted, // Not used, we fetch balance separately
457
- isLoadingQuote,
458
- prepareSendQuote,
459
- setAmount: setSendFormAmount,
460
- handleSubmit,
461
- isSubmitting,
462
- buttonText,
463
- isValidRecipient,
464
- selectedDestToken: returnedDestToken, // Get the destination token set by useSendForm
465
- setSelectedDestinationChain, // Function to set destination chain
466
- supportedChains, // Available chains
467
- } = useSendForm({
468
- account,
469
- toAmount: undefined,
470
- toRecipient: selectedPool?.depositAddress, // Always the pool contract address
471
- toChainId: selectedPool?.chainId,
472
- toToken: finalSelectedToken?.contractAddress, // aToken address (Aave) or pool address (Morpho)
473
- toCalldata: withdrawCalldata, // Aave/Morpho withdraw calldata
474
- walletClient,
475
- onTransactionStateChange,
476
- onError,
477
- onWaitingForWalletConfirm,
478
- paymasterUrls,
479
- gasless,
480
- onConfirm,
481
- onComplete,
482
- onSend,
483
- selectedToken: finalSelectedToken, // Source token (what we're withdrawing from)
484
- setWalletConfirmRetryHandler,
485
- tradeType: TradeType.EXACT_INPUT, // User specifies exact input amount to withdraw
486
- quoteProvider,
487
- fundMethod,
488
- mode,
489
- onNavigateToMeshConnect,
490
- checkoutOnHandlers,
491
- })
492
-
493
334
  // Calculate USD value using the underlying token (for pool tokens like aBasUSDC)
494
335
  const { amountUsdFormatted: underlyingTokenUsdDisplay } = useAmountUsd({
495
336
  amount: amount,
@@ -506,43 +347,6 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
506
347
  })
507
348
  }, [poolBalance, isLoadingBalance])
508
349
 
509
- // Log the destination token returned from useSendForm
510
- useEffect(() => {
511
- logger.console.log("[pool-withdraw] Destination token from useSendForm:", {
512
- symbol: returnedDestToken?.symbol,
513
- name: returnedDestToken?.name,
514
- decimals: returnedDestToken?.decimals,
515
- sourceTokenAddress: finalSelectedToken?.contractAddress,
516
- })
517
- }, [returnedDestToken, finalSelectedToken])
518
-
519
- // Set destination chain to match the pool's chain (same-chain transaction)
520
- useEffect(() => {
521
- if (selectedPool && supportedChains && setSelectedDestinationChain) {
522
- const destinationChain = supportedChains.find(
523
- (chain) => chain.id === selectedPool.chainId,
524
- )
525
-
526
- if (destinationChain) {
527
- logger.console.log("[pool-withdraw] Setting destination chain:", {
528
- chainId: destinationChain.id,
529
- chainName: destinationChain.name,
530
- poolChainId: selectedPool.chainId,
531
- isSameChain: true,
532
- })
533
- setSelectedDestinationChain(destinationChain)
534
- } else {
535
- logger.console.warn(
536
- "[pool-withdraw] Destination chain not found in supported chains:",
537
- {
538
- poolChainId: selectedPool.chainId,
539
- supportedChainIds: supportedChains.map((c) => c.id),
540
- },
541
- )
542
- }
543
- }
544
- }, [selectedPool, supportedChains, setSelectedDestinationChain])
545
-
546
350
  // Auto-focus input field on component mount
547
351
  useEffect(() => {
548
352
  if (inputRef.current) {
@@ -553,19 +357,82 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
553
357
  // Notify parent component about pool selector visibility
554
358
  useEffect(() => {
555
359
  if (onPoolSelectorStateChange) {
556
- // Only hide tabs when showing EarnPools selector
360
+ // Hide tabs when showing EarnPools selector (no token selector in withdraw)
557
361
  onPoolSelectorStateChange(showEarnPools)
558
362
  }
559
363
  }, [showEarnPools, onPoolSelectorStateChange])
560
364
 
561
- const handleAmountChange = (value: string) => {
562
- // Validate decimal places (max 8 decimals)
563
- const decimalMatch = value.match(/^\d*\.?\d{0,8}$/)
564
- if (!decimalMatch && value !== "") {
565
- return // Don't update if more than 8 decimals
365
+ const [gasCostFormatted, setGasCostFormatted] = useState("")
366
+
367
+ // For Aave, check if wallet has enough aTokens in order to withdraw
368
+ const [hasEnoughATokens, setHasEnoughATokens] = useState<boolean | null>(null)
369
+ useEffect(() => {
370
+ if (
371
+ publicClient &&
372
+ selectedPool &&
373
+ selectedPool.protocol === "Aave" &&
374
+ amountToWithdraw
375
+ ) {
376
+ try {
377
+ const checkHasEnoughATokens = async () => {
378
+ const aTokenAddress = selectedPool.token.address
379
+ const decimals = selectedPool.token.decimals || 18
380
+ const aTokenBalance = await publicClient?.readContract({
381
+ address: aTokenAddress as `0x${string}`,
382
+ abi: parseAbi([
383
+ "function balanceOf(address) view returns (uint256)",
384
+ ]),
385
+ functionName: "balanceOf",
386
+ args: [account?.address as `0x${string}`],
387
+ })
388
+ const aTokenBalanceFormatted = formatUnits(aTokenBalance, decimals)
389
+ setHasEnoughATokens(aTokenBalanceFormatted >= amountToWithdraw)
390
+ }
391
+ checkHasEnoughATokens()
392
+ } catch (error) {
393
+ logger.console.error(
394
+ "[pool-withdraw] ❌ Error checking has enough aTokens:",
395
+ error,
396
+ )
397
+ }
398
+ }
399
+ }, [publicClient, selectedPool, account, amountToWithdraw])
400
+
401
+ // Estimate gas when pool selected and amount is set
402
+ useEffect(() => {
403
+ const estimateGas = async () => {
404
+ if (publicClient && selectedPool && amountToWithdraw) {
405
+ try {
406
+ const gasLimit = await estimateGasLimit(publicClient, {
407
+ account: account?.address as `0x${string}`,
408
+ to: selectedPool.depositAddress as `0x${string}`,
409
+ data: withdrawCalldata as `0x${string}`,
410
+ value: 0n,
411
+ })
412
+ const gasCostFormatted = await estimateGasCostFormatted(
413
+ publicClient,
414
+ gasLimit || 100_000n,
415
+ 18,
416
+ )
417
+ setGasCostFormatted(gasCostFormatted)
418
+ } catch (error) {
419
+ logger.console.error(
420
+ "[pool-withdraw] ❌ Error estimating gas:",
421
+ error,
422
+ )
423
+ }
424
+ } else {
425
+ logger.console.error(
426
+ "[pool-withdraw] ❌ Error estimating gas: no public client or selected pool or amount to withdraw",
427
+ )
428
+ }
566
429
  }
430
+ estimateGas()
431
+ }, [publicClient, selectedPool, withdrawCalldata, account, amountToWithdraw])
432
+
433
+ const handleAmountChange = (value: string) => {
567
434
  setAmount(value)
568
- setSendFormAmount(value) // Sync with useSendForm for quote functionality
435
+ setAmountToWithdraw(value) // Sync with useSendForm for quote functionality
569
436
  }
570
437
 
571
438
  const handlePoolSelect = (pool: any) => {
@@ -577,14 +444,65 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
577
444
  // Handle amount selection from percentage buttons
578
445
  const handleAmountSelect = (selectedAmount: string) => {
579
446
  setAmount(selectedAmount)
580
- setSendFormAmount(selectedAmount)
447
+ setAmountToWithdraw(selectedAmount)
581
448
  }
582
449
 
583
- // Dynamic font size based on input length
584
- const inputStyles = useDynamicInputStyles({
585
- inputValue: amount,
586
- variant: "default",
587
- })
450
+ const [isLoadingWithdraw, setIsLoadingWithdraw] = useState(false)
451
+
452
+ const handleSubmit = async (e: React.FormEvent) => {
453
+ e.preventDefault()
454
+ if (!account || !walletClient) {
455
+ throw new Error("No account or wallet client found")
456
+ }
457
+
458
+ try {
459
+ setIsLoadingWithdraw(true)
460
+
461
+ // Create initial pending state
462
+ const initialState: TransactionState = {
463
+ transactionHash: "", // Will be set after tx is sent
464
+ explorerUrl: "",
465
+ chainId: selectedPool?.chainId as number,
466
+ state: "pending",
467
+ label: "Withdraw",
468
+ }
469
+ onTransactionStateChange([initialState])
470
+
471
+ const txHash = await sendOriginTransaction(account, walletClient, {
472
+ to: selectedPool?.depositAddress as `0x${string}`,
473
+ data: withdrawCalldata as `0x${string}`,
474
+ value: 0n,
475
+ chain: walletClient.chain as Chain,
476
+ })
477
+
478
+ const receipt = await publicClient!.waitForTransactionReceipt({
479
+ hash: txHash,
480
+ })
481
+
482
+ // Convert receipt to TransactionState
483
+ const finalState = getTransactionStateFromReceipt(
484
+ receipt,
485
+ selectedPool?.chainId as number,
486
+ "Withdraw",
487
+ )
488
+
489
+ onTransactionStateChange([finalState])
490
+
491
+ // Navigate to receipt screen
492
+ onComplete({ transactionStates: [finalState] })
493
+
494
+ setIsLoadingWithdraw(false)
495
+ } catch (error) {
496
+ logger.console.error(
497
+ "[pool-withdraw] ❌ Error submitting withdraw:",
498
+ error,
499
+ )
500
+ setIsLoadingWithdraw(false)
501
+ onError(
502
+ error instanceof Error ? error.message : "Failed to withdraw from pool",
503
+ )
504
+ }
505
+ }
588
506
 
589
507
  // Get chain info for selected pool
590
508
  const chainInfo = useMemo(() => {
@@ -741,22 +659,13 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
741
659
  {/* Amount Input */}
742
660
  <div className="flex-1">
743
661
  <div className="flex items-center space-x-2">
744
- <input
662
+ <DynamicSizeInputField
745
663
  ref={inputRef}
746
- id="amount"
747
- type="text"
748
664
  value={amount}
749
665
  onChange={(e) => handleAmountChange(e.target.value)}
750
- placeholder={"0"}
751
- className={`w-full bg-transparent font-bold trails-text-primary placeholder:trails-text-muted border-none outline-none ${
752
- isLoadingQuote ? "animate-pulse" : ""
753
- }`}
754
- style={inputStyles}
755
- inputMode="decimal"
666
+ isLoading={isLoadingWithdraw}
667
+ variant="default"
756
668
  />
757
- {isLoadingQuote && (
758
- <div className="animate-spin rounded-full h-4 w-4 border-solid border-b-2 trails-primary" />
759
- )}
760
669
  </div>
761
670
  </div>
762
671
 
@@ -808,7 +717,7 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
808
717
  <PercentageMaxButtons
809
718
  userBalance={poolBalance || undefined}
810
719
  isNativeToken={false} // Pool tokens are never native tokens
811
- gasCostFormatted={prepareSendQuote?.gasCostFormatted}
720
+ gasCostFormatted={gasCostFormatted}
812
721
  chainId={selectedPool.chainId}
813
722
  onAmountSelect={handleAmountSelect}
814
723
  className="opacity-100"
@@ -819,7 +728,7 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
819
728
  </div>
820
729
  )}
821
730
 
822
- {prepareSendQuote?.noSufficientBalance ? (
731
+ {hasEnoughATokens === false ? (
823
732
  <div className="px-2 py-3 rounded-lg bg-amber-500/10 border border-solid border-amber-500/30">
824
733
  <div className="flex items-center space-x-2">
825
734
  <svg
@@ -843,35 +752,23 @@ export const PoolWithdraw: React.FC<PoolWithdrawProps> = ({
843
752
  </div>
844
753
  ) : null}
845
754
 
846
- {/* Quote Details */}
847
- {prepareSendQuote && (
848
- <div className="mb-4">
849
- <QuoteDetails quote={prepareSendQuote} showContent={true} />
850
- </div>
851
- )}
852
-
853
755
  {selectedPool && (
854
756
  <form onSubmit={handleSubmit}>
855
757
  <button
856
758
  type="submit"
857
759
  disabled={
858
- !amount ||
859
- !isValidRecipient ||
860
- isSubmitting ||
861
- isLoadingQuote ||
862
- !prepareSendQuote ||
863
- prepareSendQuote?.noSufficientBalance
760
+ !amount || isLoadingWithdraw || hasEnoughATokens === false
864
761
  }
865
762
  className={`w-full font-semibold py-4 px-4 trails-border-radius-button transition-colors bg-blue-500 hover:bg-blue-600 disabled:bg-gray-300 text-white disabled:text-gray-500 disabled:cursor-not-allowed cursor-pointer relative`}
866
763
  >
867
- {isSubmitting ? (
764
+ {isLoadingWithdraw ? (
868
765
  <div className="flex items-center justify-center">
869
766
  <Loader2
870
767
  className={`w-5 h-5 animate-spin mr-2 ${"text-gray-400"}`}
871
768
  />
872
- <span>{buttonText}</span>
769
+ <span>Processing...</span>
873
770
  </div>
874
- ) : prepareSendQuote?.noSufficientBalance ? (
771
+ ) : hasEnoughATokens === false ? (
875
772
  "Insufficient Balance"
876
773
  ) : (
877
774
  "Withdraw"