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,588 @@
1
+ import type { Account, Chain, WalletClient } from "viem"
2
+ import {
3
+ createPublicClient,
4
+ ethAddress,
5
+ http,
6
+ maxUint256,
7
+ zeroAddress,
8
+ } from "viem"
9
+ import type {
10
+ TrailsAPIClient,
11
+ GasFeeOptions,
12
+ FeeOption,
13
+ DepositSignature,
14
+ ExecuteIntentResponse,
15
+ } from "@0xsequence/trails-api"
16
+ import type { SelectedFeeToken } from "../types.js"
17
+ import type { CheckoutOnHandlers } from "../../widget/hooks/useCheckout.js"
18
+ import type { TransactionState } from "../../transactions.js"
19
+ import { logger } from "../../logger.js"
20
+ import { attemptSwitchChain } from "../../chainSwitch.js"
21
+ import { getTransactionStateFromReceipt } from "../execution/transactionState.js"
22
+ import {
23
+ getDelegatorSmartAccount,
24
+ getPaymasterGaslessTransaction,
25
+ sendPaymasterGaslessTransaction,
26
+ } from "../../paymasterSend.js"
27
+ import { TRAILS_INTENT_ENTRYPOINT_ADDRESS } from "../../constants.js"
28
+ import {
29
+ getNeedsIntentEntrypointApproval,
30
+ getUserNonce,
31
+ signIntent,
32
+ getPermitSignature,
33
+ } from "../../gasless.js"
34
+
35
+ export async function attemptGaslessDeposit({
36
+ paymasterUrl,
37
+ depositTokenAddress,
38
+ depositTokenAmount,
39
+ depositRecipient,
40
+ onOriginSend,
41
+ walletClient,
42
+ chain,
43
+ account,
44
+ trailsClient,
45
+ feeOptions,
46
+ selectedFeeToken,
47
+ checkoutOnHandlers,
48
+ intentId,
49
+ onTransactionStateChange,
50
+ transactionStates,
51
+ executeIntentFn,
52
+ }: {
53
+ paymasterUrl?: string
54
+ depositTokenAddress: string
55
+ depositTokenAmount: string
56
+ depositRecipient: string
57
+ onOriginSend?: () => void
58
+ walletClient: WalletClient
59
+ chain: Chain
60
+ account: Account
61
+ trailsClient: TrailsAPIClient
62
+ feeOptions?: GasFeeOptions
63
+ selectedFeeToken?: SelectedFeeToken
64
+ abortSignal?: AbortSignal
65
+ checkoutOnHandlers?: CheckoutOnHandlers
66
+ intentId?: string
67
+ onTransactionStateChange?: (transactionStates: TransactionState[]) => void
68
+ transactionStates?: TransactionState[]
69
+ executeIntentFn?: (params: {
70
+ intentId: string
71
+ depositTransactionHash?: string
72
+ depositSignature?: DepositSignature
73
+ }) => Promise<ExecuteIntentResponse>
74
+ }): Promise<void> {
75
+ const originChainId = chain.id
76
+
77
+ logger.console.log(
78
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] attemptGaslessDeposit called with:",
79
+ {
80
+ originChainId,
81
+ depositTokenAddress,
82
+ depositTokenAmount,
83
+ depositRecipient,
84
+ hasFeeOptions: !!feeOptions,
85
+ feeOptionsLength: feeOptions?.feeOptions?.length,
86
+ selectedFeeToken,
87
+ hasSelectedFeeToken: !!selectedFeeToken,
88
+ paymasterUrl,
89
+ },
90
+ )
91
+
92
+ const publicClient = createPublicClient({
93
+ chain,
94
+ transport: http(),
95
+ })
96
+
97
+ logger.console.log("[trails-sdk] [GASLESS-FLOW] Intent entrypoint check:", {
98
+ chainId: chain.id,
99
+ chainName: chain.name,
100
+ intentEntrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
101
+ })
102
+
103
+ // NEW FLOW: Use Intent Entrypoint API with permit2 support
104
+ logger.console.log(
105
+ "[trails-sdk] Using Intent Entrypoint API flow with permit2 support for gasless deposit",
106
+ )
107
+
108
+ // Switch to correct chain before requesting signatures
109
+ logger.console.log(
110
+ "[trails-sdk] [GASLESS-FLOW] Switching to chain before permit/intent signatures",
111
+ { originChainId },
112
+ )
113
+ await attemptSwitchChain({
114
+ walletClient,
115
+ desiredChainId: originChainId,
116
+ })
117
+
118
+ try {
119
+ if (paymasterUrl) {
120
+ logger.console.log(
121
+ "[trails-sdk] [GASLESS-FLOW] doing gasless with paymaster",
122
+ )
123
+
124
+ // Switch to correct chain before requesting signatures
125
+ logger.console.log(
126
+ "[trails-sdk] [GASLESS-FLOW] Switching chain for paymaster flow",
127
+ )
128
+ await attemptSwitchChain({
129
+ walletClient,
130
+ desiredChainId: originChainId,
131
+ })
132
+
133
+ const delegatorSmartAccount = await getDelegatorSmartAccount({
134
+ publicClient,
135
+ })
136
+
137
+ const calls: Array<{
138
+ to: string
139
+ data: string
140
+ value: string
141
+ }> = await getPaymasterGaslessTransaction({
142
+ walletClient,
143
+ chain,
144
+ tokenAddress: depositTokenAddress as `0x${string}`,
145
+ amount: BigInt(depositTokenAmount),
146
+ recipient: depositRecipient as `0x${string}`,
147
+ delegatorSmartAccount,
148
+ })
149
+
150
+ logger.console.log("[trails-sdk] calls", calls)
151
+
152
+ // Trigger signature request callback before prompting wallet
153
+ if (checkoutOnHandlers?.triggerCheckoutSignatureRequest) {
154
+ checkoutOnHandlers.triggerCheckoutSignatureRequest()
155
+ }
156
+
157
+ const txHash = await sendPaymasterGaslessTransaction({
158
+ walletClient,
159
+ publicClient,
160
+ chain,
161
+ paymasterUrl,
162
+ delegatorSmartAccount,
163
+ calls,
164
+ })
165
+
166
+ // Trigger signature confirmed callback after successful signing
167
+ if (checkoutOnHandlers?.triggerCheckoutSignatureConfirmed) {
168
+ checkoutOnHandlers.triggerCheckoutSignatureConfirmed()
169
+ }
170
+
171
+ if (onOriginSend) {
172
+ onOriginSend()
173
+ }
174
+
175
+ // Update transaction state to pending with hash for paymaster flow
176
+ if (transactionStates?.[0] && onTransactionStateChange) {
177
+ transactionStates[0].state = "pending"
178
+ transactionStates[0].transactionHash = txHash
179
+
180
+ try {
181
+ onTransactionStateChange(transactionStates)
182
+ } catch (error) {
183
+ logger.console.error(
184
+ "[trails-sdk] Error calling onTransactionStateChange:",
185
+ error,
186
+ )
187
+ }
188
+ }
189
+
190
+ const receipt = await publicClient.waitForTransactionReceipt({
191
+ hash: txHash as `0x${string}`,
192
+ })
193
+ logger.console.log("[trails-sdk] receipt", receipt)
194
+
195
+ // Update transaction state to confirmed after receipt is obtained
196
+ if (transactionStates?.[0] && onTransactionStateChange && receipt) {
197
+ transactionStates[0] = getTransactionStateFromReceipt(
198
+ receipt,
199
+ chain.id,
200
+ transactionStates[0]?.label,
201
+ )
202
+
203
+ try {
204
+ onTransactionStateChange(transactionStates)
205
+ } catch (error) {
206
+ logger.console.error(
207
+ "[trails-sdk] Error calling onTransactionStateChange:",
208
+ error,
209
+ )
210
+ }
211
+ }
212
+
213
+ return
214
+ }
215
+
216
+ const deadline = Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
217
+ const hasFeeOptions = Boolean(
218
+ feeOptions && feeOptions.feeOptions?.length > 0,
219
+ )
220
+
221
+ // 1. Check if we need approval - check if we have enough allowance for this transaction (deposit + fee if same token)
222
+ let requiredAmount = BigInt(depositTokenAmount)
223
+
224
+ // Match selectedFeeToken by tokenAddress to get the latest fee amount from feeOptions
225
+ let selectedFeeOption: FeeOption | null = null
226
+ if (selectedFeeToken && hasFeeOptions && feeOptions) {
227
+ // Find matching fee option by tokenAddress to get latest amount
228
+ selectedFeeOption =
229
+ feeOptions.feeOptions.find(
230
+ (opt) =>
231
+ opt.tokenAddress?.toLowerCase() ===
232
+ selectedFeeToken.tokenAddress?.toLowerCase(),
233
+ ) || null
234
+ logger.console.log(
235
+ "[trails-sdk] Matched selectedFeeToken to latest fee option:",
236
+ {
237
+ selectedFeeToken,
238
+ matchedOption: selectedFeeOption,
239
+ },
240
+ )
241
+ }
242
+
243
+ // Fallback to first fee option if no match or no selectedFeeToken
244
+ if (!selectedFeeOption && hasFeeOptions && feeOptions) {
245
+ selectedFeeOption = feeOptions.feeOptions[0] || null
246
+ logger.console.log(
247
+ "[trails-sdk] Using first fee option as fallback:",
248
+ selectedFeeOption,
249
+ )
250
+ }
251
+
252
+ // Only include fee in required amount if the fee token is the same as the deposit token
253
+ if (selectedFeeOption?.amount && selectedFeeOption?.tokenAddress) {
254
+ const feeTokenIsSameAsDepositToken =
255
+ selectedFeeOption.tokenAddress.toLowerCase() ===
256
+ depositTokenAddress.toLowerCase()
257
+
258
+ if (feeTokenIsSameAsDepositToken) {
259
+ requiredAmount = requiredAmount + BigInt(selectedFeeOption.amount)
260
+ logger.console.log(
261
+ "[trails-sdk] Fee token matches deposit token, including fee in required approval amount:",
262
+ {
263
+ depositAmount: depositTokenAmount,
264
+ feeAmount: selectedFeeOption.amount,
265
+ feeTokenAddress: selectedFeeOption.tokenAddress,
266
+ depositTokenAddress,
267
+ totalRequired: requiredAmount.toString(),
268
+ },
269
+ )
270
+ } else {
271
+ logger.console.log(
272
+ "[trails-sdk] Fee token differs from deposit token, separate approval will be needed:",
273
+ {
274
+ depositAmount: depositTokenAmount,
275
+ depositTokenAddress,
276
+ feeAmount: selectedFeeOption.amount,
277
+ feeTokenAddress: selectedFeeOption.tokenAddress,
278
+ depositTokenRequired: requiredAmount.toString(),
279
+ },
280
+ )
281
+ }
282
+ }
283
+
284
+ const needsApproval = await getNeedsIntentEntrypointApproval({
285
+ client: publicClient,
286
+ token: depositTokenAddress as `0x${string}`,
287
+ account: account.address,
288
+ entrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
289
+ amount: requiredAmount, // Check if we have enough allowance for this specific transaction
290
+ })
291
+
292
+ logger.console.log(
293
+ "[trails-sdk] [GASLESS-FLOW] Checking permit requirements",
294
+ {
295
+ userAddress: account.address,
296
+ tokenAddress: depositTokenAddress,
297
+ depositAmount: depositTokenAmount,
298
+ requiredAmount: requiredAmount.toString(),
299
+ intentAddress: depositRecipient,
300
+ chainID: originChainId,
301
+ deadline,
302
+ needsApproval,
303
+ },
304
+ )
305
+
306
+ // 2. Get permit signature if approval needed for deposit token
307
+ // Note: Fee payment is handled by the backend/relayer, we only need permit for the deposit token
308
+ let permitSignature: string | undefined
309
+ let permitDeadline: number | undefined
310
+
311
+ if (needsApproval) {
312
+ logger.console.log(
313
+ "[trails-sdk] Getting permit signature for deposit token infinite approval",
314
+ )
315
+
316
+ // Use infinite approval (maxUint256) so user doesn't need to approve again
317
+ const permitAmount = maxUint256
318
+ logger.console.log(
319
+ "[trails-sdk] Using infinite approval for gasless deposits",
320
+ {
321
+ depositAmount: depositTokenAmount,
322
+ depositTokenAddress,
323
+ permitAmount: permitAmount.toString(),
324
+ },
325
+ )
326
+
327
+ const permitSig = await getPermitSignature({
328
+ publicClient,
329
+ walletClient,
330
+ signer: account.address,
331
+ spender: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
332
+ tokenAddress: depositTokenAddress as `0x${string}`,
333
+ amount: permitAmount, // Infinite approval
334
+ chain,
335
+ deadline: BigInt(deadline),
336
+ })
337
+ permitSignature = permitSig.signature
338
+ permitDeadline = Number(permitSig.deadline)
339
+ logger.console.log(
340
+ "[trails-sdk] Deposit token permit signature obtained for infinite approval",
341
+ )
342
+ }
343
+
344
+ // 3. Get current nonce for the user
345
+ logger.console.log("[trails-sdk] Getting user nonce")
346
+ const nonce = await getUserNonce({
347
+ publicClient,
348
+ userAddress: account.address,
349
+ intentEntrypoint: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
350
+ })
351
+ logger.console.log("[trails-sdk] User nonce:", nonce.toString())
352
+
353
+ // 4. Get intent signature
354
+ logger.console.log("[trails-sdk] Requesting intent signature via EIP-712")
355
+ // Get fee collector address from the new schema:
356
+ // Priority: selectedFeeOption.feeCollectorAddress > feeOptions.feeCollectorAddress
357
+ const feeCollectorAddress = (selectedFeeOption?.feeCollectorAddress ||
358
+ feeOptions?.feeCollectorAddress) as `0x${string}` | undefined
359
+
360
+ // Validate that we have a valid fee collector address
361
+ if (!feeCollectorAddress || feeCollectorAddress === zeroAddress) {
362
+ throw new Error(
363
+ "[trails-sdk] Fee collector address not provided by API. Cannot proceed with gasless deposit. " +
364
+ "Please ensure the API is returning feeCollectorAddress in the gasFeeOptions response.",
365
+ )
366
+ }
367
+
368
+ logger.console.log(
369
+ "[trails-sdk] Using fee collector address:",
370
+ feeCollectorAddress,
371
+ )
372
+
373
+ // Trigger signature request callback before prompting wallet
374
+ if (checkoutOnHandlers?.triggerCheckoutSignatureRequest) {
375
+ checkoutOnHandlers.triggerCheckoutSignatureRequest()
376
+ }
377
+
378
+ const { signature: intentSignature } = await signIntent({
379
+ client: walletClient,
380
+ intentParams: {
381
+ user: account.address,
382
+ token: depositTokenAddress as `0x${string}`,
383
+ amount: BigInt(depositTokenAmount),
384
+ intentAddress: depositRecipient as `0x${string}`,
385
+ deadline: BigInt(deadline),
386
+ chainId: originChainId,
387
+ contractAddress: TRAILS_INTENT_ENTRYPOINT_ADDRESS,
388
+ nonce,
389
+ feeAmount: BigInt(selectedFeeOption?.amount || "0"),
390
+ feeCollector: feeCollectorAddress,
391
+ },
392
+ })
393
+ logger.console.log("[trails-sdk] Intent signature received")
394
+
395
+ // Trigger signature confirmed callback after successful signing
396
+ if (checkoutOnHandlers?.triggerCheckoutSignatureConfirmed) {
397
+ checkoutOnHandlers.triggerCheckoutSignatureConfirmed()
398
+ }
399
+
400
+ // 5. Call the deposit endpoint with permit support and optional fee
401
+ logger.console.log(
402
+ "[trails-sdk] Calling executeIntent with depositSignature",
403
+ {
404
+ usePermit: needsApproval,
405
+ hasFee: !!feeOptions,
406
+ hasIntentId: !!intentId,
407
+ },
408
+ )
409
+
410
+ // Validate that we have the intentId
411
+ if (!intentId) {
412
+ throw new Error(
413
+ "[trails-sdk] intentId is required for gasless deposits. " +
414
+ "The calling code must commit the intent first using commitIntent() and pass the intentId.",
415
+ )
416
+ }
417
+
418
+ // Validate that we have a selected fee option
419
+ if (!selectedFeeOption) {
420
+ throw new Error(
421
+ "[trails-sdk] selectedFeeOption is required for gasless deposits",
422
+ )
423
+ }
424
+
425
+ // Build depositSignature for executeIntent with all required fields
426
+ const depositSignature = {
427
+ intentSignature,
428
+ permitSignature: needsApproval ? permitSignature : undefined,
429
+ permitDeadline: needsApproval ? permitDeadline : undefined,
430
+ permitAmount: needsApproval ? maxUint256 : undefined,
431
+ selectedGasFeeOption: selectedFeeOption,
432
+ userNonce: Number(nonce),
433
+ deadline,
434
+ }
435
+
436
+ logger.console.log(
437
+ "[trails-sdk] Executing intent with gasless deposit signature",
438
+ { intentId, depositSignature },
439
+ )
440
+
441
+ // executeIntent will handle submitting to the relayer
442
+ // The backend processes the deposit signature and relays the transaction
443
+ const executeIntentFnToUse =
444
+ executeIntentFn || trailsClient.executeIntent.bind(trailsClient)
445
+ await executeIntentFnToUse({
446
+ intentId,
447
+ depositSignature,
448
+ })
449
+
450
+ logger.console.log(
451
+ "[trails-sdk] Intent execution submitted to backend. Transaction monitoring should happen via intent status polling.",
452
+ )
453
+
454
+ if (onOriginSend) {
455
+ onOriginSend()
456
+ }
457
+
458
+ // Update transaction state to pending for non-paymaster gasless flow
459
+ // Hash will be filled in later by the poller when backend confirms transaction
460
+ if (transactionStates?.[0] && onTransactionStateChange) {
461
+ transactionStates[0].state = "pending"
462
+ // transactionHash remains empty - will be updated by onDepositTransactionFound callback
463
+
464
+ try {
465
+ onTransactionStateChange(transactionStates)
466
+ } catch (error) {
467
+ logger.console.error(
468
+ "[trails-sdk] Error calling onTransactionStateChange:",
469
+ error,
470
+ )
471
+ }
472
+ }
473
+ } catch (error) {
474
+ logger.console.error(
475
+ "[trails-sdk] Error in Intent Entrypoint gasless deposit with permit2:",
476
+ error,
477
+ )
478
+ throw error
479
+ }
480
+ }
481
+
482
+ export function getDoGasless(
483
+ originTokenAddress: string,
484
+ feeOptions?: GasFeeOptions,
485
+ selectedFeeToken?: SelectedFeeToken,
486
+ walletId?: string,
487
+ ): boolean {
488
+ // Don't use gasless flow for sequence-waas wallet
489
+ if (walletId === "sequence-waas") {
490
+ logger.console.log(
491
+ "[trails-sdk] [GASLESS-FLOW] getDoGasless: Skipping gasless flow for sequence-waas wallet",
492
+ )
493
+ return false
494
+ }
495
+
496
+ const hasFeeOptions = Boolean(feeOptions && feeOptions.feeOptions?.length > 0)
497
+
498
+ // Important: The UI passes selectedFeeToken in these states:
499
+ // - null: User explicitly chose "Pay with native gas"
500
+ // - {object}: User selected a fee token OR it was auto-selected
501
+ // - undefined: Should not happen (initial state auto-selects if options exist)
502
+
503
+ // If selectedFeeToken is null, user explicitly chose native gas
504
+ if (selectedFeeToken === null) {
505
+ logger.console.log(
506
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: User explicitly selected native gas (null)",
507
+ )
508
+ return false
509
+ }
510
+
511
+ // If selectedFeeToken is undefined and no fee options, can't do gasless
512
+ if (!selectedFeeToken && !hasFeeOptions) {
513
+ logger.console.log(
514
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: No fee token selected and no fee options available",
515
+ )
516
+ return false
517
+ }
518
+
519
+ // If selectedFeeToken is undefined but fee options exist, use first ERC20 option
520
+ let effectiveFeeToken = selectedFeeToken
521
+ if (!effectiveFeeToken && hasFeeOptions && feeOptions) {
522
+ const firstFeeOption = feeOptions.feeOptions[0]
523
+
524
+ // Check if first option is native gas
525
+ const isFirstOptionNative =
526
+ firstFeeOption?.tokenAddress === zeroAddress ||
527
+ firstFeeOption?.tokenAddress?.toLowerCase() === zeroAddress ||
528
+ firstFeeOption?.tokenAddress === ethAddress ||
529
+ firstFeeOption?.tokenAddress?.toLowerCase() === ethAddress.toLowerCase()
530
+
531
+ if (!isFirstOptionNative && firstFeeOption?.tokenAddress) {
532
+ // First fee option is ERC20, use it
533
+ effectiveFeeToken = firstFeeOption
534
+ logger.console.log(
535
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: No fee token selected, using first ERC20 fee option",
536
+ {
537
+ feeOption: effectiveFeeToken,
538
+ },
539
+ )
540
+ } else {
541
+ logger.console.log(
542
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: First fee option is native gas, skipping gasless",
543
+ )
544
+ return false
545
+ }
546
+ }
547
+
548
+ // Check if the effective fee token is native gas
549
+ const isNativeGasFee =
550
+ !effectiveFeeToken ||
551
+ effectiveFeeToken.tokenAddress === zeroAddress ||
552
+ effectiveFeeToken.tokenAddress?.toLowerCase() === zeroAddress ||
553
+ effectiveFeeToken.tokenAddress === ethAddress ||
554
+ effectiveFeeToken.tokenAddress?.toLowerCase() === ethAddress.toLowerCase()
555
+
556
+ // Don't use gasless if origin token is native (sending ETH)
557
+ if (originTokenAddress === zeroAddress) {
558
+ logger.console.log(
559
+ "[trails-sdk] [GASLESS-FLOW] getDoGasless: Origin token is native, skipping gasless",
560
+ )
561
+ return false
562
+ }
563
+
564
+ // Don't use gasless if fee token is native
565
+ if (isNativeGasFee) {
566
+ logger.console.log(
567
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless: Fee token is native gas, skipping gasless",
568
+ {
569
+ effectiveFeeToken,
570
+ },
571
+ )
572
+ return false
573
+ }
574
+
575
+ // All conditions met, use gasless with ERC20 fee token
576
+ logger.console.log(
577
+ "[trails-sdk] [GASLESS-FLOW] [FEE-SELECT] getDoGasless decision: Using gasless",
578
+ {
579
+ originTokenAddress,
580
+ hasFeeOptions,
581
+ selectedFeeToken,
582
+ effectiveFeeToken,
583
+ feeOptionsCount: feeOptions?.feeOptions?.length || 0,
584
+ },
585
+ )
586
+
587
+ return true
588
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./gaslessDeposit.js"
2
+ export * from "./standardDeposit.js"
3
+ export * from "./depositOrchestrator.js"