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
@@ -24,7 +24,6 @@ interface SwapProps {
24
24
  onError: (error: Error | string | null) => void
25
25
  onWaitingForWalletConfirm: (props: PrepareSendQuote) => void
26
26
  paymasterUrls?: Array<{ chainId: number; url: string }>
27
- gasless?: boolean
28
27
  setWalletConfirmRetryHandler: (handler: () => Promise<void>) => void
29
28
  quoteProvider?: string
30
29
  fundMethod?: string
@@ -477,15 +477,19 @@ export const TransferPending: React.FC<TransferPendingProps> = ({
477
477
  )}
478
478
 
479
479
  {/* Details Section */}
480
- <div
481
- className={`w-full max-w-sm transition-all duration-500 ease-out delay-200 ${
482
- showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
483
- }`}
484
- >
485
- <div className="mt-4">
486
- <QuoteDetails quote={quote} showContent={true} compact={true} />
480
+ {quote && (
481
+ <div
482
+ className={`w-full max-w-sm transition-all duration-500 ease-out delay-200 ${
483
+ showContent
484
+ ? "opacity-100 translate-y-0"
485
+ : "opacity-0 translate-y-4"
486
+ }`}
487
+ >
488
+ <div className="mt-4">
489
+ <QuoteDetails quote={quote} showContent={true} compact={true} />
490
+ </div>
487
491
  </div>
488
- </div>
492
+ )}
489
493
 
490
494
  {/* Timeout Warning */}
491
495
  {showTimeoutWarning && !showContinueButton && (
@@ -91,7 +91,6 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
91
91
 
92
92
  // Initialize with first option when fee options become available
93
93
  useEffect(() => {
94
- setIsError?.(false)
95
94
  if (pendingFeeOptionConfirmation) {
96
95
  console.log(
97
96
  "[trails-sdk] Pending fee options: ",
@@ -119,7 +118,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
119
118
  }
120
119
  }
121
120
  }
122
- }, [pendingFeeOptionConfirmation, onFeeOptionsLoaded, setIsError])
121
+ }, [pendingFeeOptionConfirmation, onFeeOptionsLoaded])
123
122
 
124
123
  // Handle fee option selection and confirmation
125
124
  const handleConfirmFee = async (tokenAddress: string | null) => {
@@ -154,7 +153,7 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
154
153
  await navigator.clipboard.writeText(address)
155
154
  setCopiedAddress(address)
156
155
  setTimeout(() => setCopiedAddress(null), 2000)
157
- } catch (error) {
156
+ } catch (_error) {
158
157
  try {
159
158
  const textArea = document.createElement("textarea")
160
159
  textArea.value = address
@@ -204,10 +203,27 @@ export const WaasFeeOptions: React.FC<WaasFeeOptionsProps> = ({
204
203
  if (!hasTokenForFee) {
205
204
  return (
206
205
  <div className="space-y-4 py-6">
207
- <div className="text-center space-y-1">
208
- <p className="text-xs trails-text-muted">
209
- Fund your wallet with one of the following tokens
210
- </p>
206
+ {/* Warning Message */}
207
+ <div className="p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg">
208
+ <div className="flex items-start space-x-2">
209
+ <svg
210
+ className="w-5 h-5 text-red-600 dark:text-red-400 shrink-0 mt-0.5"
211
+ fill="none"
212
+ viewBox="0 0 24 24"
213
+ stroke="currentColor"
214
+ >
215
+ <path
216
+ strokeLinecap="round"
217
+ strokeLinejoin="round"
218
+ strokeWidth={2}
219
+ d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
220
+ />
221
+ </svg>
222
+ <p className="text-sm text-red-800 dark:text-red-200 font-medium">
223
+ No available tokens for fees, please transfer any of these tokens
224
+ to your wallet.
225
+ </p>
226
+ </div>
211
227
  </div>
212
228
 
213
229
  <div className="flex flex-col space-y-2">
@@ -83,7 +83,7 @@ export const WalletConfirmation: React.FC<WalletConfirmationProps> = ({
83
83
  <div
84
84
  className={`mx-auto flex items-center justify-center transition-all duration-500 ease-out relative mb-4 ${showContent ? "transform -translate-y-8" : ""}`}
85
85
  >
86
- {feeOptionsError === true ? (
86
+ {feeOptionsError ? (
87
87
  <ErrorAnimationIcon />
88
88
  ) : retryEnabled ? (
89
89
  <div className={`h-24 w-24`} />
@@ -2,7 +2,7 @@ import { useQuery } from "@tanstack/react-query"
2
2
  import { useTokenPrice } from "../../prices.js"
3
3
  import { formatUsdAmountDisplay } from "../../tokenBalances.js"
4
4
  import { useTokenAddress } from "../../tokens.js"
5
- import { useAPIClient } from "../../apiClient.js"
5
+ import { useTrailsClient } from "../../trailsClient.js"
6
6
 
7
7
  type UseAmountUsdProps = {
8
8
  amount?: string | null
@@ -14,7 +14,7 @@ export function useAmountUsd({ amount, token, chainId }: UseAmountUsdProps): {
14
14
  amountUsd: number | null
15
15
  amountUsdFormatted: string
16
16
  } {
17
- const apiClient = useAPIClient()
17
+ const trailsClient = useTrailsClient()
18
18
  const isTokenAddress = token?.startsWith("0x")
19
19
  const resolvedTokenAddress = useTokenAddress({
20
20
  chainId,
@@ -25,26 +25,26 @@ export function useAmountUsd({ amount, token, chainId }: UseAmountUsdProps): {
25
25
  const { tokenPrice } = useTokenPrice(
26
26
  token && tokenAddress && chainId
27
27
  ? {
28
- tokenId: token,
29
- contractAddress: tokenAddress,
28
+ tokenSymbol: token,
29
+ tokenAddress: tokenAddress,
30
30
  chainId: Number(chainId),
31
31
  }
32
32
  : null,
33
- apiClient,
33
+ trailsClient,
34
34
  )
35
35
 
36
36
  const { data: amountUsd } = useQuery({
37
- queryKey: ["amountUsd", amount, tokenPrice?.price?.value],
37
+ queryKey: ["amountUsd", amount, tokenPrice?.priceUsd],
38
38
  queryFn: () => {
39
- if (!amount || !tokenPrice?.price?.value) {
39
+ if (!amount || !tokenPrice?.priceUsd) {
40
40
  return null
41
41
  }
42
42
 
43
- const tokenPriceValue = tokenPrice.price.value
43
+ const tokenPriceValue = tokenPrice.priceUsd
44
44
  const value = Number(amount) * tokenPriceValue
45
45
  return value
46
46
  },
47
- enabled: !!amount && !!tokenPrice?.price?.value,
47
+ enabled: !!amount && !!tokenPrice?.priceUsd,
48
48
  })
49
49
 
50
50
  return {
@@ -2,13 +2,25 @@ import { useCallback, useRef } from "react"
2
2
  import { getSessionId } from "../../analytics.js"
3
3
  import { logger } from "../../logger.js"
4
4
  import { updatePersistentToast } from "../../toast.js"
5
- import { getPrettifiedErrorMessage } from "../../error.js"
5
+ import {
6
+ getPrettifiedErrorMessage,
7
+ getIsUserRejectionError,
8
+ UserRejectionError,
9
+ getErrorString,
10
+ } from "../../error.js"
11
+ import { invalidateTokenBalancesCache } from "../../tokenBalances.js"
6
12
 
7
13
  export type CheckoutCallbacks = {
8
14
  onCheckoutStart?: (data: { sessionId: string }) => void
9
15
  onCheckoutQuote?: (data: { sessionId: string; quote: any }) => void
16
+ onCheckoutSignatureRequest?: (data: { sessionId: string }) => void
17
+ onCheckoutSignatureConfirmed?: (data: { sessionId: string }) => void
18
+ onCheckoutSignatureRejected?: (data: {
19
+ sessionId: string
20
+ error: unknown
21
+ }) => void
10
22
  onCheckoutComplete?: (data: { sessionId: string }) => void
11
- onCheckoutError?: (data: { sessionId: string; error: string }) => void
23
+ onCheckoutError?: (data: { sessionId: string; error: unknown }) => void
12
24
  onCheckoutStatusUpdate?: (data: {
13
25
  sessionId: string
14
26
  transactionStates: any[]
@@ -18,8 +30,14 @@ export type CheckoutCallbacks = {
18
30
  export type CheckoutOnHandlers = {
19
31
  triggerCheckoutStart: () => void
20
32
  triggerCheckoutQuote: (quote: any) => void
21
- triggerCheckoutComplete: (txStatus: "success" | "fail") => void
22
- triggerCheckoutError: (error: string) => void
33
+ triggerCheckoutSignatureRequest: () => void
34
+ triggerCheckoutSignatureConfirmed: () => void
35
+ triggerCheckoutSignatureRejected: (error: unknown) => void
36
+ triggerCheckoutComplete: (
37
+ txStatus: "success" | "fail",
38
+ accountAddress?: string,
39
+ ) => void
40
+ triggerCheckoutError: (error: unknown) => void
23
41
  triggerCheckoutStatusUpdate: (transactionStates: any[]) => void
24
42
  }
25
43
 
@@ -38,6 +56,9 @@ export type UseCheckoutReturn = {
38
56
  export function useCheckout({
39
57
  onCheckoutStart,
40
58
  onCheckoutQuote,
59
+ onCheckoutSignatureRequest,
60
+ onCheckoutSignatureConfirmed,
61
+ onCheckoutSignatureRejected,
41
62
  onCheckoutComplete,
42
63
  onCheckoutError,
43
64
  onCheckoutStatusUpdate,
@@ -82,8 +103,57 @@ export function useCheckout({
82
103
  [onCheckoutQuote],
83
104
  )
84
105
 
106
+ const triggerCheckoutSignatureRequest = useCallback(() => {
107
+ if (onCheckoutSignatureRequest && sessionIdRef.current) {
108
+ try {
109
+ onCheckoutSignatureRequest({
110
+ sessionId: sessionIdRef.current,
111
+ })
112
+ } catch (error) {
113
+ logger.console.error(
114
+ "[trails-sdk] Error calling onCheckoutSignatureRequest:",
115
+ error,
116
+ )
117
+ }
118
+ }
119
+ }, [onCheckoutSignatureRequest])
120
+
121
+ const triggerCheckoutSignatureConfirmed = useCallback(() => {
122
+ if (onCheckoutSignatureConfirmed && sessionIdRef.current) {
123
+ try {
124
+ onCheckoutSignatureConfirmed({
125
+ sessionId: sessionIdRef.current,
126
+ })
127
+ } catch (error) {
128
+ logger.console.error(
129
+ "[trails-sdk] Error calling onCheckoutSignatureConfirmed:",
130
+ error,
131
+ )
132
+ }
133
+ }
134
+ }, [onCheckoutSignatureConfirmed])
135
+
136
+ const triggerCheckoutSignatureRejected = useCallback(
137
+ (error: unknown) => {
138
+ if (onCheckoutSignatureRejected && sessionIdRef.current) {
139
+ try {
140
+ onCheckoutSignatureRejected({
141
+ sessionId: sessionIdRef.current,
142
+ error,
143
+ })
144
+ } catch (callbackError) {
145
+ logger.console.error(
146
+ "[trails-sdk] Error calling onCheckoutSignatureRejected:",
147
+ callbackError,
148
+ )
149
+ }
150
+ }
151
+ },
152
+ [onCheckoutSignatureRejected],
153
+ )
154
+
85
155
  const triggerCheckoutComplete = useCallback(
86
- (txStatus: "success" | "fail") => {
156
+ (txStatus: "success" | "fail", accountAddress?: string) => {
87
157
  if (onCheckoutComplete && sessionIdRef.current) {
88
158
  try {
89
159
  onCheckoutComplete({
@@ -98,6 +168,9 @@ export function useCheckout({
98
168
  }
99
169
 
100
170
  if (txStatus === "success") {
171
+ // Invalidate token balances cache to trigger a refresh
172
+ invalidateTokenBalancesCache(accountAddress)
173
+
101
174
  updatePersistentToast(
102
175
  "Transaction Complete",
103
176
  "Your transaction has been successfully processed",
@@ -116,12 +189,24 @@ export function useCheckout({
116
189
  )
117
190
 
118
191
  const triggerCheckoutError = useCallback(
119
- (error: string) => {
192
+ (error: unknown) => {
193
+ // Wrap user rejection errors in custom UserRejectionError class
194
+ let processedError = error
195
+ const isUserRejection = getIsUserRejectionError(error)
196
+
197
+ if (isUserRejection) {
198
+ const errorMessage = getErrorString(error)
199
+ processedError = new UserRejectionError(errorMessage)
200
+
201
+ // Trigger signature rejected callback for user rejections
202
+ triggerCheckoutSignatureRejected(processedError)
203
+ }
204
+
120
205
  if (onCheckoutError && sessionIdRef.current) {
121
206
  try {
122
207
  onCheckoutError({
123
208
  sessionId: sessionIdRef.current,
124
- error,
209
+ error: processedError,
125
210
  })
126
211
  } catch (error) {
127
212
  logger.console.error(
@@ -134,13 +219,13 @@ export function useCheckout({
134
219
  updatePersistentToast(
135
220
  "Transaction Failed",
136
221
  getPrettifiedErrorMessage(
137
- error,
222
+ processedError,
138
223
  "An error occurred while processing your transaction",
139
224
  ),
140
225
  "error",
141
226
  )
142
227
  },
143
- [onCheckoutError],
228
+ [onCheckoutError, triggerCheckoutSignatureRejected],
144
229
  )
145
230
 
146
231
  const triggerCheckoutStatusUpdate = useCallback(
@@ -168,6 +253,9 @@ export function useCheckout({
168
253
  checkoutOnHandlers: {
169
254
  triggerCheckoutStart,
170
255
  triggerCheckoutQuote,
256
+ triggerCheckoutSignatureRequest,
257
+ triggerCheckoutSignatureConfirmed,
258
+ triggerCheckoutSignatureRejected,
171
259
  triggerCheckoutComplete,
172
260
  triggerCheckoutError,
173
261
  triggerCheckoutStatusUpdate,
@@ -462,28 +462,34 @@ function useDefaultTokenSelectionInternal(): UseDefaultTokenSelectionReturn {
462
462
 
463
463
  const decimals = destToken?.decimals
464
464
  if (!decimals) {
465
- throw new Error("Decimals not found")
466
- }
467
-
468
- destinationToken = destToken
469
- ? {
470
- id: destToken.chainId,
471
- name: destToken.name,
472
- symbol: destToken.symbol,
473
- balance: "0", // Destination token doesn't have balance yet
474
- imageUrl: destToken.imageUrl || "",
475
- chainId: destToken.chainId,
476
- contractAddress: destToken.contractAddress || zeroAddress,
477
- balanceUsdFormatted: "0",
478
- tokenPriceUsd: 0,
479
- decimals, // Top-level decimals
480
- contractInfo: {
481
- decimals,
482
- symbol: destToken.symbol,
465
+ logger.console.warn(
466
+ "[trails-sdk] Missing decimals for destination token, skipping:",
467
+ {
468
+ token: destToken,
469
+ },
470
+ )
471
+ destinationToken = null
472
+ } else {
473
+ destinationToken = destToken
474
+ ? {
475
+ id: destToken.chainId,
483
476
  name: destToken.name,
484
- },
485
- }
486
- : null
477
+ symbol: destToken.symbol,
478
+ balance: "0", // Destination token doesn't have balance yet
479
+ imageUrl: destToken.imageUrl || "",
480
+ chainId: destToken.chainId,
481
+ contractAddress: destToken.contractAddress || zeroAddress,
482
+ balanceUsdFormatted: "0",
483
+ tokenPriceUsd: 0,
484
+ decimals, // Top-level decimals
485
+ contractInfo: {
486
+ decimals,
487
+ symbol: destToken.symbol,
488
+ name: destToken.name,
489
+ },
490
+ }
491
+ : null
492
+ }
487
493
  }
488
494
 
489
495
  logger.console.log("[trails-sdk] Default token selection:", {
@@ -2,26 +2,25 @@ import { useQuery } from "@tanstack/react-query"
2
2
  import { useRef } from "react"
3
3
  import type { TransactionReceipt } from "viem"
4
4
  import { zeroAddress } from "viem"
5
- import { useAPIClient } from "../../apiClient.js"
6
5
  import { useIndexerGatewayClient } from "../../indexerClient.js"
7
6
  import { getTokenBalancesWithPrices } from "../../tokenBalances.js"
8
7
  import { logger } from "../../logger.js"
9
- import { getSequenceEnv } from "../../config.js"
10
8
  import { useSupportedTokens } from "../../tokens.js"
11
9
  import { useTrailsClient } from "../../trailsClient.js"
12
10
  import { getExplorerUrl } from "../../explorer.js"
13
- import { getFullErrorMessage } from "../../error.js"
11
+ import { getFullErrorMessage, getPrettifiedErrorMessage } from "../../error.js"
14
12
  import { prepareSend } from "../../prepareSend.js"
15
13
  import { abortControllerRegistry } from "../../abortController.js"
16
- import { useRelayers } from "../../relayer.js"
17
14
  import { TradeType } from "../../prepareSend.js"
15
+ import { getChainInfo } from "../../chains.js"
16
+ import type { MetaTxnReceipt } from "../../transactionIntent/types.js"
18
17
  import type { Chain } from "../../chains.js"
19
18
  import type { SupportedToken } from "../../tokens.js"
20
19
  import type { TransactionState } from "../../transactions.js"
21
20
  import type { PrepareSendFees } from "../../prepareSend.js"
22
- import type { MetaTxnReceipt } from "../../relayer.js"
23
- import type { RelayerEnv } from "../../relayer.js"
24
21
  import type { SequenceEnv } from "../../config.js"
22
+ import { getTokenPrice } from "../../prices.js"
23
+ import { useCommitIntent, useExecuteIntent } from "../../mutations.js"
25
24
 
26
25
  export type UseQuoteProps = {
27
26
  walletClient?: any // TODO: fix this, has to do with viem/wagmi versions
@@ -36,7 +35,6 @@ export type UseQuoteProps = {
36
35
  slippageTolerance?: string | number | null
37
36
  onStatusUpdate?: ((transactionStates: TransactionState[]) => void) | null
38
37
  quoteProvider?: string | null
39
- gasless?: boolean
40
38
  paymasterUrl?: string
41
39
  selectedFeeToken?: {
42
40
  tokenAddress: string
@@ -95,10 +93,12 @@ export type UseQuoteReturn = {
95
93
  swap: (() => Promise<SwapReturn | null>) | null
96
94
  isLoadingQuote: boolean
97
95
  quoteError: unknown
96
+ quoteErrorPrettified: string
98
97
  refetchQuote: () => void
99
98
  abort: () => void
100
99
  }
101
100
 
101
+ // TODO: consolidate useSendForm, prepareSend, and useQuote hooks into a single hook
102
102
  export function useQuote({
103
103
  walletClient,
104
104
  fromTokenAddress,
@@ -112,14 +112,12 @@ export function useQuote({
112
112
  slippageTolerance,
113
113
  onStatusUpdate,
114
114
  quoteProvider,
115
- gasless,
116
115
  paymasterUrl,
117
116
  selectedFeeToken,
118
- relayerEnv,
119
117
  nodeGatewayEnv,
120
118
  abortSignal: externalAbortSignal,
121
119
  }: Partial<
122
- UseQuoteProps & { relayerEnv?: RelayerEnv; nodeGatewayEnv?: SequenceEnv }
120
+ UseQuoteProps & { nodeGatewayEnv?: SequenceEnv }
123
121
  > = {}): UseQuoteReturn {
124
122
  // Set node gateway environment override for this quote session
125
123
  if (nodeGatewayEnv) {
@@ -149,18 +147,18 @@ export function useQuote({
149
147
  })()
150
148
  : abortControllerRef.current.signal
151
149
 
152
- const apiClient = useAPIClient()
153
150
  const trailsClient = useTrailsClient()
154
- const { getRelayer } = useRelayers({
155
- env: relayerEnv || (getSequenceEnv() as RelayerEnv),
156
- })
157
151
  const indexerGatewayClient = useIndexerGatewayClient()
158
152
 
159
153
  const { supportedTokens } = useSupportedTokens()
160
154
 
155
+ // Get mutation hooks for passing to prepareSend
156
+ const commitIntentMutation = useCommitIntent()
157
+ const executeIntentMutation = useExecuteIntent()
158
+
161
159
  const { data, isLoading, error, refetch } = useQuery({
162
160
  queryKey: [
163
- "quote",
161
+ "prepareSend",
164
162
  fromTokenAddress,
165
163
  fromChainId,
166
164
  toTokenAddress,
@@ -184,7 +182,6 @@ export function useQuote({
184
182
 
185
183
  if (
186
184
  !walletClient ||
187
- !apiClient ||
188
185
  !trailsClient ||
189
186
  !fromTokenAddress ||
190
187
  !toTokenAddress ||
@@ -198,11 +195,38 @@ export function useQuote({
198
195
  }
199
196
 
200
197
  // Get token balance using async method
201
- const { balances } = await getTokenBalancesWithPrices({
202
- account: walletClient.account!.address,
203
- indexerGatewayClient,
204
- apiClient,
205
- })
198
+ let balances: any[] = []
199
+ try {
200
+ const result = await getTokenBalancesWithPrices({
201
+ account: walletClient.account!.address,
202
+ indexerGatewayClient,
203
+ trailsClient,
204
+ })
205
+ balances = result.balances
206
+ } catch (balanceError) {
207
+ const balanceErrorMessage = getFullErrorMessage(balanceError)
208
+ const isCorsError =
209
+ balanceErrorMessage.includes("Cross-Origin") ||
210
+ balanceErrorMessage.includes("CORS") ||
211
+ balanceErrorMessage.includes("Same Origin Policy")
212
+ const isNetworkError =
213
+ balanceErrorMessage.includes("fetch failed") ||
214
+ balanceErrorMessage.includes("network")
215
+
216
+ if (isCorsError || isNetworkError) {
217
+ logger.console.warn(
218
+ "[trails-sdk] [useQuote] Network or CORS error fetching balances, proceeding with quote using zero balance:",
219
+ {
220
+ error: balanceErrorMessage,
221
+ account: walletClient.account!.address,
222
+ },
223
+ )
224
+ // Continue with empty balances instead of crashing
225
+ balances = []
226
+ } else {
227
+ throw balanceError
228
+ }
229
+ }
206
230
 
207
231
  const originTokenBalance = balances.find(
208
232
  (b) =>
@@ -213,8 +237,6 @@ export function useQuote({
213
237
  )
214
238
 
215
239
  const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
216
- const destinationRelayer = getRelayer(toChainId)
217
- const originRelayer = getRelayer(fromChainId)
218
240
 
219
241
  // Note: Disable this check for now to allow fetching a quote even when the origin balance is zero
220
242
  // if (originTokenBalanceAmount === "0") {
@@ -223,6 +245,34 @@ export function useQuote({
223
245
 
224
246
  // logger.console.log("supportedTokens", supportedTokens)
225
247
 
248
+ // Get native token price for origin chain (for gas cost calculation)
249
+ let originNativeTokenPriceUsd = 0
250
+ try {
251
+ const originChain = getChainInfo(fromChainId)
252
+ const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
253
+ if (nativeTokenSymbol) {
254
+ const nativePrice = await getTokenPrice(trailsClient, {
255
+ tokenSymbol: nativeTokenSymbol,
256
+ tokenAddress: zeroAddress,
257
+ chainId: fromChainId,
258
+ })
259
+ originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
260
+ logger.console.log(
261
+ "[trails-sdk] [useQuote] Origin native token price:",
262
+ {
263
+ chainId: fromChainId,
264
+ symbol: nativeTokenSymbol,
265
+ priceUsd: originNativeTokenPriceUsd,
266
+ },
267
+ )
268
+ }
269
+ } catch (error) {
270
+ logger.console.error(
271
+ "[trails-sdk] [useQuote] Error getting origin native token price:",
272
+ error,
273
+ )
274
+ }
275
+
226
276
  const originToken = supportedTokens?.find(
227
277
  (token) =>
228
278
  token.contractAddress?.toLowerCase() ===
@@ -275,10 +325,7 @@ export function useQuote({
275
325
  destinationTokenSymbol: destinationTokenSymbol,
276
326
  destinationCalldata: toCalldata as string,
277
327
  client: walletClient,
278
- apiClient,
279
328
  trailsClient,
280
- originRelayer,
281
- destinationRelayer,
282
329
  sourceTokenDecimals,
283
330
  destinationTokenDecimals,
284
331
  fee: "0",
@@ -286,10 +333,12 @@ export function useQuote({
286
333
  onTransactionStateChange: onStatusUpdate ?? (() => {}),
287
334
  slippageTolerance: slippageTolerance?.toString(),
288
335
  quoteProvider: quoteProvider,
289
- gasless: gasless ?? false,
290
336
  paymasterUrl: paymasterUrl,
291
337
  selectedFeeToken: selectedFeeToken ?? undefined,
292
338
  abortSignal: combinedAbortSignal,
339
+ originNativeTokenPriceUsd: originNativeTokenPriceUsd,
340
+ commitIntentFn: commitIntentMutation.mutateAsync,
341
+ executeIntentFn: executeIntentMutation.mutateAsync,
293
342
  }
294
343
 
295
344
  logger.console.log("[trails-sdk] options", options)
@@ -325,7 +374,7 @@ export function useQuote({
325
374
 
326
375
  const swap = async (): Promise<SwapReturn> => {
327
376
  const {
328
- originUserTxReceipt,
377
+ depositUserTxnReceipt,
329
378
  destinationMetaTxnReceipt,
330
379
  totalCompletionSeconds,
331
380
  } = await send({
@@ -334,12 +383,12 @@ export function useQuote({
334
383
 
335
384
  return {
336
385
  originTransaction: {
337
- transactionHash: originUserTxReceipt?.transactionHash,
386
+ transactionHash: depositUserTxnReceipt?.transactionHash,
338
387
  explorerUrl: getExplorerUrl({
339
- txHash: originUserTxReceipt?.transactionHash as string,
388
+ txHash: depositUserTxnReceipt?.transactionHash as string,
340
389
  chainId: fromChainId,
341
390
  }),
342
- receipt: originUserTxReceipt,
391
+ receipt: depositUserTxnReceipt,
343
392
  },
344
393
  destinationTransaction: {
345
394
  transactionHash: destinationMetaTxnReceipt?.txnHash,
@@ -368,14 +417,17 @@ export function useQuote({
368
417
  // Prevent unnecessary refetching
369
418
  enabled: Boolean(
370
419
  walletClient &&
371
- apiClient &&
420
+ trailsClient &&
372
421
  fromTokenAddress &&
373
422
  toTokenAddress &&
374
423
  swapAmount &&
375
424
  toRecipient &&
376
425
  fromChainId &&
377
426
  toChainId &&
378
- indexerGatewayClient,
427
+ indexerGatewayClient &&
428
+ // !isLoadingTokens &&
429
+ supportedTokens &&
430
+ supportedTokens.length > 0,
379
431
  ),
380
432
  staleTime: 30 * 1000, // Consider data fresh for 30 seconds
381
433
  refetchOnWindowFocus: false, // Don't refetch when window regains focus
@@ -390,6 +442,7 @@ export function useQuote({
390
442
  swap: data?.swap || null,
391
443
  isLoadingQuote: isLoading,
392
444
  quoteError: error,
445
+ quoteErrorPrettified: getPrettifiedErrorMessage(error),
393
446
  refetchQuote: () => refetch(),
394
447
  abort: () => {
395
448
  logger.console.log("[trails-sdk] useQuote abort() called")