0xtrails 0.6.6 → 0.7.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 (365) hide show
  1. package/dist/aave.d.ts +10 -2
  2. package/dist/aave.d.ts.map +1 -1
  3. package/dist/analytics.d.ts +26 -0
  4. package/dist/analytics.d.ts.map +1 -1
  5. package/dist/{ccip-CbJrlK-L.js → ccip-fConRNoG.js} +21 -21
  6. package/dist/chains.d.ts +23 -8
  7. package/dist/chains.d.ts.map +1 -1
  8. package/dist/constants.d.ts +5 -5
  9. package/dist/constants.d.ts.map +1 -1
  10. package/dist/customTokens.d.ts +12 -0
  11. package/dist/customTokens.d.ts.map +1 -0
  12. package/dist/decoders.d.ts +2 -2
  13. package/dist/decoders.d.ts.map +1 -1
  14. package/dist/error.d.ts.map +1 -1
  15. package/dist/fees.d.ts +37 -2
  16. package/dist/fees.d.ts.map +1 -1
  17. package/dist/gasless.d.ts +15 -36
  18. package/dist/gasless.d.ts.map +1 -1
  19. package/dist/{index-w7_dK4c5.js → index-BbajxCG_.js} +59269 -77146
  20. package/dist/index.d.ts +8 -6
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +828 -359
  23. package/dist/indexerClient.d.ts.map +1 -1
  24. package/dist/intentReceiptMonitor.d.ts +1 -1
  25. package/dist/intentReceiptMonitor.d.ts.map +1 -1
  26. package/dist/intentReceiptPoller.d.ts +1 -1
  27. package/dist/intentReceiptPoller.d.ts.map +1 -1
  28. package/dist/intents.d.ts +3 -2
  29. package/dist/intents.d.ts.map +1 -1
  30. package/dist/mode.d.ts +1 -1
  31. package/dist/mode.d.ts.map +1 -1
  32. package/dist/mutations.d.ts +2 -2
  33. package/dist/mutations.d.ts.map +1 -1
  34. package/dist/prepareSend.d.ts +2 -2
  35. package/dist/prepareSend.d.ts.map +1 -1
  36. package/dist/prices.d.ts +1 -1
  37. package/dist/prices.d.ts.map +1 -1
  38. package/dist/sequenceWallet.d.ts +2 -2
  39. package/dist/sequenceWallet.d.ts.map +1 -1
  40. package/dist/time.d.ts +6 -0
  41. package/dist/time.d.ts.map +1 -1
  42. package/dist/tokenBalances.d.ts +40 -25
  43. package/dist/tokenBalances.d.ts.map +1 -1
  44. package/dist/tokens.d.ts +54 -14
  45. package/dist/tokens.d.ts.map +1 -1
  46. package/dist/trailsClient.d.ts +1 -1
  47. package/dist/trailsClient.d.ts.map +1 -1
  48. package/dist/trailsRouter.d.ts +2 -1
  49. package/dist/trailsRouter.d.ts.map +1 -1
  50. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts +3 -2
  51. package/dist/transactionIntent/deposits/depositOrchestrator.d.ts.map +1 -1
  52. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts +2 -1
  53. package/dist/transactionIntent/deposits/gaslessDeposit.d.ts.map +1 -1
  54. package/dist/transactionIntent/execution/transactionState.d.ts +1 -1
  55. package/dist/transactionIntent/execution/transactionState.d.ts.map +1 -1
  56. package/dist/transactionIntent/handlers/crossChain.d.ts +5 -3
  57. package/dist/transactionIntent/handlers/crossChain.d.ts.map +1 -1
  58. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts +5 -3
  59. package/dist/transactionIntent/handlers/sameChainSameToken.d.ts.map +1 -1
  60. package/dist/transactionIntent/quote/feeExtractors.d.ts +1 -6
  61. package/dist/transactionIntent/quote/feeExtractors.d.ts.map +1 -1
  62. package/dist/transactionIntent/quote/normalizeQuote.d.ts +4 -2
  63. package/dist/transactionIntent/quote/normalizeQuote.d.ts.map +1 -1
  64. package/dist/transactionIntent/quote/quoteHelpers.d.ts +1 -1
  65. package/dist/transactionIntent/quote/quoteHelpers.d.ts.map +1 -1
  66. package/dist/transactionIntent/types.d.ts +28 -5
  67. package/dist/transactionIntent/types.d.ts.map +1 -1
  68. package/dist/transactionIntent/utils/testnetHelpers.d.ts +0 -1
  69. package/dist/transactionIntent/utils/testnetHelpers.d.ts.map +1 -1
  70. package/dist/transactionIntent/validators.d.ts +0 -2
  71. package/dist/transactionIntent/validators.d.ts.map +1 -1
  72. package/dist/transactions.d.ts +2 -2
  73. package/dist/transactions.d.ts.map +1 -1
  74. package/dist/utils.d.ts +7 -0
  75. package/dist/utils.d.ts.map +1 -1
  76. package/dist/wallets.d.ts +1 -0
  77. package/dist/wallets.d.ts.map +1 -1
  78. package/dist/widget/components/AccountIntentTransactionHistory.d.ts.map +1 -1
  79. package/dist/widget/components/AddressWalletIcon.d.ts +6 -0
  80. package/dist/widget/components/AddressWalletIcon.d.ts.map +1 -0
  81. package/dist/widget/components/ChainFilterDropdown.d.ts +2 -6
  82. package/dist/widget/components/ChainFilterDropdown.d.ts.map +1 -1
  83. package/dist/widget/components/ChainImage.d.ts.map +1 -1
  84. package/dist/widget/components/ChainList.d.ts +0 -5
  85. package/dist/widget/components/ChainList.d.ts.map +1 -1
  86. package/dist/widget/components/ClassicSwap.d.ts +6 -6
  87. package/dist/widget/components/ClassicSwap.d.ts.map +1 -1
  88. package/dist/widget/components/ConnectWallet.d.ts.map +1 -1
  89. package/dist/widget/components/ConnectedWallets.d.ts.map +1 -1
  90. package/dist/widget/components/DebugMenu.d.ts +1 -1
  91. package/dist/widget/components/DebugMenu.d.ts.map +1 -1
  92. package/dist/widget/components/DebugScreensList.d.ts.map +1 -1
  93. package/dist/widget/components/DepositTracker.d.ts.map +1 -1
  94. package/dist/widget/components/Earn.d.ts +5 -5
  95. package/dist/widget/components/Earn.d.ts.map +1 -1
  96. package/dist/widget/components/FeeOption.d.ts +1 -1
  97. package/dist/widget/components/FeeOption.d.ts.map +1 -1
  98. package/dist/widget/components/FeeOptions.d.ts +2 -2
  99. package/dist/widget/components/FeeOptions.d.ts.map +1 -1
  100. package/dist/widget/components/Footer.d.ts +1 -1
  101. package/dist/widget/components/Footer.d.ts.map +1 -1
  102. package/dist/widget/components/Fund.d.ts +5 -5
  103. package/dist/widget/components/Fund.d.ts.map +1 -1
  104. package/dist/widget/components/FundMethods.d.ts +0 -1
  105. package/dist/widget/components/FundMethods.d.ts.map +1 -1
  106. package/dist/widget/components/FundSwap.d.ts +6 -6
  107. package/dist/widget/components/FundSwap.d.ts.map +1 -1
  108. package/dist/widget/components/HookModalContent.d.ts +8 -0
  109. package/dist/widget/components/HookModalContent.d.ts.map +1 -0
  110. package/dist/widget/components/OriginSelectionAmount.d.ts +11 -0
  111. package/dist/widget/components/OriginSelectionAmount.d.ts.map +1 -0
  112. package/dist/widget/components/Pay.d.ts +5 -5
  113. package/dist/widget/components/Pay.d.ts.map +1 -1
  114. package/dist/widget/components/PoolDeposit.d.ts +5 -5
  115. package/dist/widget/components/PoolDeposit.d.ts.map +1 -1
  116. package/dist/widget/components/PoolWithdraw.d.ts +3 -3
  117. package/dist/widget/components/PoolWithdraw.d.ts.map +1 -1
  118. package/dist/widget/components/QuoteDetails.d.ts.map +1 -1
  119. package/dist/widget/components/Receipt.d.ts +2 -1
  120. package/dist/widget/components/Receipt.d.ts.map +1 -1
  121. package/dist/widget/components/RecentTokens.d.ts +4 -4
  122. package/dist/widget/components/RecentTokens.d.ts.map +1 -1
  123. package/dist/widget/components/RecipientSelectorButton.d.ts.map +1 -1
  124. package/dist/widget/components/ShadowPortal.d.ts +6 -0
  125. package/dist/widget/components/ShadowPortal.d.ts.map +1 -0
  126. package/dist/widget/components/Swap.d.ts +6 -6
  127. package/dist/widget/components/Swap.d.ts.map +1 -1
  128. package/dist/widget/components/ThemeProvider.d.ts +1 -1
  129. package/dist/widget/components/ThemeProvider.d.ts.map +1 -1
  130. package/dist/widget/components/TokenList.d.ts +3 -4
  131. package/dist/widget/components/TokenList.d.ts.map +1 -1
  132. package/dist/widget/components/TokenSelector.d.ts +3 -4
  133. package/dist/widget/components/TokenSelector.d.ts.map +1 -1
  134. package/dist/widget/components/Tooltip.d.ts +6 -1
  135. package/dist/widget/components/Tooltip.d.ts.map +1 -1
  136. package/dist/widget/components/TrailsHookModal.d.ts +10 -0
  137. package/dist/widget/components/TrailsHookModal.d.ts.map +1 -0
  138. package/dist/widget/components/WaasFeeOptions.d.ts +3 -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/components/WidgetProviders.d.ts +14 -0
  143. package/dist/widget/components/WidgetProviders.d.ts.map +1 -0
  144. package/dist/widget/css/compiled.css +1 -1
  145. package/dist/widget/hooks/useAddressWalletIcon.d.ts +10 -0
  146. package/dist/widget/hooks/useAddressWalletIcon.d.ts.map +1 -0
  147. package/dist/widget/hooks/useBalanceVisible.d.ts +1 -1
  148. package/dist/widget/hooks/useBalanceVisible.d.ts.map +1 -1
  149. package/dist/widget/hooks/useChainFilter.d.ts +1 -1
  150. package/dist/widget/hooks/useChainFilter.d.ts.map +1 -1
  151. package/dist/widget/hooks/useCheckout.d.ts +13 -1
  152. package/dist/widget/hooks/useCheckout.d.ts.map +1 -1
  153. package/dist/widget/hooks/useConnector.d.ts +4 -0
  154. package/dist/widget/hooks/useConnector.d.ts.map +1 -0
  155. package/dist/widget/hooks/useCurrentScreen.d.ts +1 -1
  156. package/dist/widget/hooks/useCurrentScreen.d.ts.map +1 -1
  157. package/dist/widget/hooks/useCustomTokenFetch.d.ts +19 -0
  158. package/dist/widget/hooks/useCustomTokenFetch.d.ts.map +1 -0
  159. package/dist/widget/hooks/useCustomTokenSearch.d.ts +20 -0
  160. package/dist/widget/hooks/useCustomTokenSearch.d.ts.map +1 -0
  161. package/dist/widget/hooks/useDebounce.d.ts +10 -0
  162. package/dist/widget/hooks/useDebounce.d.ts.map +1 -0
  163. package/dist/widget/hooks/useDebugScreens.d.ts +7 -2
  164. package/dist/widget/hooks/useDebugScreens.d.ts.map +1 -1
  165. package/dist/widget/hooks/useDefaultTokenSelection.d.ts +3 -19
  166. package/dist/widget/hooks/useDefaultTokenSelection.d.ts.map +1 -1
  167. package/dist/widget/hooks/useDestinationSelectedToken.d.ts +1 -14
  168. package/dist/widget/hooks/useDestinationSelectedToken.d.ts.map +1 -1
  169. package/dist/widget/hooks/useEarnPool.d.ts +1 -1
  170. package/dist/widget/hooks/useEarnPool.d.ts.map +1 -1
  171. package/dist/widget/hooks/useIntentTransactionHistory.d.ts.map +1 -1
  172. package/dist/widget/hooks/useIsMobile.d.ts +5 -0
  173. package/dist/widget/hooks/useIsMobile.d.ts.map +1 -0
  174. package/dist/widget/hooks/useMode.d.ts +2 -2
  175. package/dist/widget/hooks/useMode.d.ts.map +1 -1
  176. package/dist/widget/hooks/useOriginSelectedToken.d.ts +2 -15
  177. package/dist/widget/hooks/useOriginSelectedToken.d.ts.map +1 -1
  178. package/dist/widget/hooks/usePayMessage.d.ts.map +1 -1
  179. package/dist/widget/hooks/usePriceImpactWarning.d.ts +1 -1
  180. package/dist/widget/hooks/usePriceImpactWarning.d.ts.map +1 -1
  181. package/dist/widget/hooks/useQuote.d.ts +173 -4
  182. package/dist/widget/hooks/useQuote.d.ts.map +1 -1
  183. package/dist/widget/hooks/useRecentTokens.d.ts +3 -3
  184. package/dist/widget/hooks/useRecentTokens.d.ts.map +1 -1
  185. package/dist/widget/hooks/useRecipients.d.ts +1 -1
  186. package/dist/widget/hooks/useRecipients.d.ts.map +1 -1
  187. package/dist/widget/hooks/useSelectedFeeOption.d.ts +2 -2
  188. package/dist/widget/hooks/useSelectedFeeOption.d.ts.map +1 -1
  189. package/dist/widget/hooks/useSelectedFundMethod.d.ts +1 -1
  190. package/dist/widget/hooks/useSelectedFundMethod.d.ts.map +1 -1
  191. package/dist/widget/hooks/useSelectedRecipient.d.ts +1 -1
  192. package/dist/widget/hooks/useSelectedRecipient.d.ts.map +1 -1
  193. package/dist/widget/hooks/useSendForm.d.ts +9 -31
  194. package/dist/widget/hooks/useSendForm.d.ts.map +1 -1
  195. package/dist/widget/hooks/useSwapAmount.d.ts +1 -1
  196. package/dist/widget/hooks/useSwapAmount.d.ts.map +1 -1
  197. package/dist/widget/hooks/useTheme.d.ts +1 -1
  198. package/dist/widget/hooks/useTheme.d.ts.map +1 -1
  199. package/dist/widget/hooks/useTokenList.d.ts +7 -31
  200. package/dist/widget/hooks/useTokenList.d.ts.map +1 -1
  201. package/dist/widget/hooks/useTrailsSendTransaction.d.ts +83 -0
  202. package/dist/widget/hooks/useTrailsSendTransaction.d.ts.map +1 -0
  203. package/dist/widget/hooks/useWalletConnectUri.d.ts +11 -0
  204. package/dist/widget/hooks/useWalletConnectUri.d.ts.map +1 -0
  205. package/dist/widget/hooks/useWidgetProps.d.ts +5 -0
  206. package/dist/widget/hooks/useWidgetProps.d.ts.map +1 -1
  207. package/dist/widget/index.d.ts +2 -0
  208. package/dist/widget/index.d.ts.map +1 -1
  209. package/dist/widget/index.js +8 -5
  210. package/dist/widget/providers/TrailsModalProvider.d.ts +65 -0
  211. package/dist/widget/providers/TrailsModalProvider.d.ts.map +1 -0
  212. package/dist/widget/providers/TrailsProvider.d.ts +1 -1
  213. package/dist/widget/providers/TrailsProvider.d.ts.map +1 -1
  214. package/dist/widget/types.d.ts +11 -18
  215. package/dist/widget/types.d.ts.map +1 -1
  216. package/dist/widget/widget.d.ts +20 -11
  217. package/dist/widget/widget.d.ts.map +1 -1
  218. package/package.json +45 -49
  219. package/src/aave.ts +387 -138
  220. package/src/analytics.ts +208 -2
  221. package/src/chains.ts +65 -64
  222. package/src/constants.ts +18 -14
  223. package/src/customTokens.ts +151 -0
  224. package/src/decoders.ts +4 -7
  225. package/src/error.ts +7 -3
  226. package/src/fees.ts +239 -125
  227. package/src/gasless.ts +54 -108
  228. package/src/index.ts +29 -9
  229. package/src/indexerClient.ts +2 -0
  230. package/src/intentReceiptMonitor.ts +1 -4
  231. package/src/intentReceiptPoller.ts +2 -2
  232. package/src/intents.ts +16 -5
  233. package/src/mode.ts +1 -1
  234. package/src/mutations.ts +7 -3
  235. package/src/prepareSend.ts +19 -14
  236. package/src/prices.ts +1 -1
  237. package/src/sequenceWallet.ts +2 -2
  238. package/src/time.ts +28 -0
  239. package/src/tokenBalances.ts +348 -153
  240. package/src/tokens.ts +393 -142
  241. package/src/trailsClient.ts +1 -1
  242. package/src/trailsRouter.ts +4 -5
  243. package/src/transactionIntent/deposits/depositOrchestrator.ts +6 -2
  244. package/src/transactionIntent/deposits/gaslessDeposit.ts +13 -7
  245. package/src/transactionIntent/deposits/standardDeposit.ts +1 -1
  246. package/src/transactionIntent/execution/transactionState.ts +1 -1
  247. package/src/transactionIntent/handlers/crossChain.ts +75 -37
  248. package/src/transactionIntent/handlers/sameChainSameToken.ts +66 -20
  249. package/src/transactionIntent/quote/feeExtractors.ts +1 -29
  250. package/src/transactionIntent/quote/normalizeQuote.ts +99 -7
  251. package/src/transactionIntent/quote/quoteHelpers.ts +1 -1
  252. package/src/transactionIntent/types.ts +31 -6
  253. package/src/transactionIntent/utils/testnetHelpers.ts +0 -5
  254. package/src/transactionIntent/validators.ts +0 -30
  255. package/src/transactions.ts +3 -3
  256. package/src/utils.ts +18 -0
  257. package/src/wallets.ts +32 -10
  258. package/src/widget/compiled.css +1 -1
  259. package/src/widget/components/AccountIntentTransactionHistory.tsx +2 -1
  260. package/src/widget/components/AccountIntentTransactionHistoryButton.tsx +2 -2
  261. package/src/widget/components/AddressWalletIcon.tsx +29 -0
  262. package/src/widget/components/ChainFilterDropdown.tsx +2 -8
  263. package/src/widget/components/ChainImage.tsx +8 -5
  264. package/src/widget/components/ChainList.tsx +6 -8
  265. package/src/widget/components/ClassicSwap.tsx +93 -85
  266. package/src/widget/components/ConnectWallet.tsx +1 -2
  267. package/src/widget/components/ConnectedWallets.tsx +17 -4
  268. package/src/widget/components/DebugMenu.tsx +2 -2
  269. package/src/widget/components/DebugScreensList.tsx +0 -1
  270. package/src/widget/components/DepositTracker.tsx +20 -34
  271. package/src/widget/components/Earn.tsx +7 -6
  272. package/src/widget/components/FeeOption.tsx +4 -4
  273. package/src/widget/components/FeeOptions.tsx +19 -39
  274. package/src/widget/components/Footer.tsx +1 -1
  275. package/src/widget/components/Fund.tsx +23 -119
  276. package/src/widget/components/FundMethods.tsx +9 -6
  277. package/src/widget/components/FundSwap.tsx +6 -5
  278. package/src/widget/components/FundingMethodSelectorButton.tsx +2 -2
  279. package/src/widget/components/HookModalContent.tsx +306 -0
  280. package/src/widget/components/Modal.tsx +1 -1
  281. package/src/widget/components/OriginSelectionAmount.tsx +135 -0
  282. package/src/widget/components/Pay.tsx +66 -124
  283. package/src/widget/components/PoolDeposit.tsx +11 -55
  284. package/src/widget/components/PoolWithdraw.tsx +3 -3
  285. package/src/widget/components/QuoteDetails.tsx +473 -728
  286. package/src/widget/components/Receipt.tsx +74 -7
  287. package/src/widget/components/RecentTokens.tsx +8 -8
  288. package/src/widget/components/RecipientSelectorButton.tsx +4 -2
  289. package/src/widget/components/ScreenHeader.tsx +2 -2
  290. package/src/widget/components/SearchInputField.tsx +1 -1
  291. package/src/widget/components/ShadowPortal.tsx +58 -0
  292. package/src/widget/components/Swap.tsx +6 -5
  293. package/src/widget/components/ThemeProvider.tsx +1 -1
  294. package/src/widget/components/TokenList.tsx +3 -4
  295. package/src/widget/components/TokenSelector.tsx +211 -80
  296. package/src/widget/components/Tooltip.tsx +18 -7
  297. package/src/widget/components/TrailsHookModal.tsx +118 -0
  298. package/src/widget/components/WaasFeeOptions.tsx +333 -138
  299. package/src/widget/components/WalletConfirmation.tsx +7 -2
  300. package/src/widget/components/WalletConnect.tsx +197 -235
  301. package/src/widget/components/WidgetProviders.tsx +75 -0
  302. package/src/widget/hooks/useAddressWalletIcon.ts +53 -0
  303. package/src/widget/hooks/useBalanceVisible.tsx +1 -1
  304. package/src/widget/hooks/useChainFilter.tsx +1 -1
  305. package/src/widget/hooks/useCheckout.ts +13 -1
  306. package/src/widget/hooks/useConnector.tsx +18 -0
  307. package/src/widget/hooks/useCurrentScreen.tsx +3 -3
  308. package/src/widget/hooks/useCustomTokenFetch.tsx +72 -0
  309. package/src/widget/hooks/useCustomTokenSearch.tsx +402 -0
  310. package/src/widget/hooks/useDebounce.ts +25 -0
  311. package/src/widget/hooks/useDebugScreens.ts +26 -10
  312. package/src/widget/hooks/useDefaultTokenSelection.tsx +99 -143
  313. package/src/widget/hooks/useDestinationSelectedToken.tsx +1 -14
  314. package/src/widget/hooks/useEarnPool.tsx +1 -1
  315. package/src/widget/hooks/useIntentTransactionHistory.ts +20 -11
  316. package/src/widget/hooks/useIsMobile.tsx +50 -0
  317. package/src/widget/hooks/useMode.ts +2 -3
  318. package/src/widget/hooks/useOriginSelectedToken.tsx +2 -15
  319. package/src/widget/hooks/usePayMessage.tsx +31 -11
  320. package/src/widget/hooks/usePriceImpactWarning.ts +1 -1
  321. package/src/widget/hooks/useQuote.ts +189 -6
  322. package/src/widget/hooks/useRecentTokens.ts +6 -6
  323. package/src/widget/hooks/useRecipients.ts +1 -1
  324. package/src/widget/hooks/useSelectedFeeOption.tsx +2 -2
  325. package/src/widget/hooks/useSelectedFundMethod.tsx +1 -1
  326. package/src/widget/hooks/useSelectedRecipient.tsx +1 -1
  327. package/src/widget/hooks/useSendForm.ts +328 -152
  328. package/src/widget/hooks/useSwapAmount.tsx +1 -1
  329. package/src/widget/hooks/useTheme.tsx +1 -1
  330. package/src/widget/hooks/useTokenList.ts +672 -400
  331. package/src/widget/hooks/useTrailsSendTransaction.ts +949 -0
  332. package/src/widget/hooks/useWalletConnectUri.tsx +228 -0
  333. package/src/widget/hooks/useWidgetProps.tsx +3 -1
  334. package/src/widget/index.tsx +12 -0
  335. package/src/widget/providers/TrailsModalProvider.tsx +195 -0
  336. package/src/widget/providers/TrailsProvider.tsx +9 -3
  337. package/src/widget/types.ts +12 -20
  338. package/src/widget/widget.tsx +598 -385
  339. package/dist/cctp.d.ts +0 -3
  340. package/dist/cctp.d.ts.map +0 -1
  341. package/dist/lifi.d.ts +0 -4
  342. package/dist/lifi.d.ts.map +0 -1
  343. package/dist/meshconnect.d.ts +0 -171
  344. package/dist/meshconnect.d.ts.map +0 -1
  345. package/dist/relaySdk.d.ts +0 -87
  346. package/dist/relaySdk.d.ts.map +0 -1
  347. package/dist/widget/components/MeshConnectExchanges.d.ts +0 -7
  348. package/dist/widget/components/MeshConnectExchanges.d.ts.map +0 -1
  349. package/dist/widget/components/MeshConnectFlow.d.ts +0 -13
  350. package/dist/widget/components/MeshConnectFlow.d.ts.map +0 -1
  351. package/dist/widget/components/MeshConnectIframe.d.ts +0 -15
  352. package/dist/widget/components/MeshConnectIframe.d.ts.map +0 -1
  353. package/dist/widget/components/Receive.d.ts +0 -12
  354. package/dist/widget/components/Receive.d.ts.map +0 -1
  355. package/dist/widget/hooks/useSelectedMeshExchange.d.ts +0 -14
  356. package/dist/widget/hooks/useSelectedMeshExchange.d.ts.map +0 -1
  357. package/src/cctp.ts +0 -54
  358. package/src/lifi.ts +0 -108
  359. package/src/meshconnect.ts +0 -531
  360. package/src/relaySdk.ts +0 -703
  361. package/src/widget/components/MeshConnectExchanges.tsx +0 -290
  362. package/src/widget/components/MeshConnectFlow.tsx +0 -90
  363. package/src/widget/components/MeshConnectIframe.tsx +0 -500
  364. package/src/widget/components/Receive.tsx +0 -175
  365. package/src/widget/hooks/useSelectedMeshExchange.tsx +0 -46
@@ -0,0 +1,949 @@
1
+ import { useMutation } from "@tanstack/react-query"
2
+ import { useCallback, useRef } from "react"
3
+ import { useWalletClient, useAccount, useChainId } from "wagmi"
4
+ import { logger } from "../../logger.js"
5
+ import { getFullErrorMessage, getIsUserRejectionError } from "../../error.js"
6
+ import type { UseQuoteProps, SwapReturn } from "./useQuote.js"
7
+ import { prepareSend, TradeType } from "../../prepareSend.js"
8
+ import { useTrailsClient } from "../../trailsClient.js"
9
+ import { useTrails } from "../../widget/providers/TrailsProvider.js"
10
+ import {
11
+ useTrailsModal,
12
+ type HostTransactionDetails,
13
+ type HostTransactionResultLinks,
14
+ type HostTransactionStatus,
15
+ } from "../../widget/providers/TrailsModalProvider.js"
16
+ import { useIndexerGatewayClient } from "../../indexerClient.js"
17
+ import {
18
+ getTokenBalancesWithPrices,
19
+ getHasSufficientBalanceToken,
20
+ } from "../../tokenBalances.js"
21
+ import { useSupportedTokens } from "../../tokens.js"
22
+ import { getChainInfo } from "../../chains.js"
23
+ import { getTokenPrice } from "../../prices.js"
24
+ import { zeroAddress, erc20Abi, type Address, type Hex } from "viem"
25
+ import { useCommitIntent, useExecuteIntent } from "../../mutations.js"
26
+ import { getExplorerUrl } from "../../explorer.js"
27
+ import type { TransactionState } from "../../transactions.js"
28
+
29
+ export type TrailsSendTransactionVariables = {
30
+ to?: Address
31
+ value?: bigint // Native token amount for ORIGIN (wagmi-compatible, sends ETH/native token)
32
+ data?: Hex
33
+ // Destination token requirements (e.g., AAVE deposit needs USDC on Base)
34
+ // Note: Destination can be ERC20 token, so value is NOT needed for destination
35
+ tokenAddress?: Address // Destination token address (ERC20 token required at destination)
36
+ tokenAmount?: string // Destination token amount (in token units, e.g., 3000000 for 3 USDC)
37
+ // Origin token parameters (if not provided, modal will open for selection)
38
+ // Use value for native token origin, OR fromTokenAddress/fromChainId/fromAmount for ERC20 origin
39
+ fromTokenAddress?: Address // Origin token address (ERC20 token to send from)
40
+ fromChainId?: number // Origin chain ID (required if fromTokenAddress is provided)
41
+ fromAmount?: string // Origin token amount (required if fromTokenAddress is provided)
42
+ }
43
+
44
+ export type UseTrailsSendTransactionParameters = Omit<
45
+ UseQuoteProps,
46
+ | "fromTokenAddress"
47
+ | "fromChainId"
48
+ | "toTokenAddress"
49
+ | "toChainId"
50
+ | "swapAmount"
51
+ | "toRecipient"
52
+ | "toCalldata"
53
+ | "tradeType"
54
+ | "selectedFeeOption"
55
+ > & {
56
+ /**
57
+ * Callback fired when the mutation is successful
58
+ */
59
+ onSuccess?: (
60
+ data: SwapReturn,
61
+ variables: TrailsSendTransactionVariables,
62
+ ) => void
63
+ /**
64
+ * Callback fired when the mutation encounters an error
65
+ */
66
+ onError?: (error: Error, variables: TrailsSendTransactionVariables) => void
67
+ /**
68
+ * Callback fired when the mutation is either successfully fetched or encounters an error
69
+ */
70
+ onSettled?: (
71
+ data: SwapReturn | undefined,
72
+ error: Error | null,
73
+ variables: TrailsSendTransactionVariables,
74
+ ) => void
75
+ /**
76
+ * Custom text for the receipt action button (default: "Transact Again")
77
+ */
78
+ receiptActionButtonText?: string
79
+ /**
80
+ * Custom callback when receipt action button is clicked
81
+ */
82
+ onReceiptAction?: () => void
83
+ }
84
+
85
+ export type UseTrailsSendTransactionReturnType = {
86
+ sendTransaction: (
87
+ variables: TrailsSendTransactionVariables,
88
+ callbacks?: {
89
+ onSuccess?: (data: SwapReturn) => void
90
+ onError?: (error: Error) => void
91
+ onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
92
+ },
93
+ ) => void
94
+ sendTransactionAsync: (
95
+ variables: TrailsSendTransactionVariables,
96
+ callbacks?: {
97
+ onSuccess?: (data: SwapReturn) => void
98
+ onError?: (error: Error) => void
99
+ onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
100
+ },
101
+ ) => Promise<SwapReturn>
102
+ retry: () => void
103
+ data: SwapReturn | undefined
104
+ error: Error | null
105
+ isPending: boolean
106
+ isSuccess: boolean
107
+ isError: boolean
108
+ isIdle: boolean
109
+ status: "idle" | "pending" | "error" | "success"
110
+ reset: () => void
111
+ variables: TrailsSendTransactionVariables | undefined
112
+ }
113
+
114
+ /**
115
+ * Hook for creating, signing, and sending transactions to networks using Trails SDK.
116
+ * Provides a one-line replacement for wagmi's `useSendTransaction`.
117
+ *
118
+ * @example
119
+ * ```ts
120
+ * // Simple usage - one line replacement (wagmi-compatible API)
121
+ * const { sendTransaction } = useTrailsSendTransaction()
122
+ *
123
+ * // Send native token (same as wagmi)
124
+ * sendTransaction({
125
+ * to: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
126
+ * value: parseEther('0.01'),
127
+ * })
128
+ *
129
+ * // Deposit 3 USDC to AAVE pool (Trails-specific)
130
+ * // Modal will open for user to select origin token/chain/amount
131
+ * sendTransaction({
132
+ * to: '0xaavePoolAddress',
133
+ * tokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC on Base
134
+ * tokenAmount: '3000000', // 3 USDC (6 decimals)
135
+ * data: '0x...', // AAVE deposit calldata
136
+ * })
137
+ * ```
138
+ */
139
+ export function useTrailsSendTransaction(
140
+ params?: UseTrailsSendTransactionParameters,
141
+ ): UseTrailsSendTransactionReturnType {
142
+ const { data: walletClient } = useWalletClient()
143
+ const { chainId: connectedChainId } = useAccount()
144
+ const chainId = useChainId()
145
+ const trailsClient = useTrailsClient()
146
+ const { trailsApiKey, sequenceIndexerUrl } = useTrails()
147
+ const {
148
+ openModal,
149
+ setPendingSelection,
150
+ setHostTransactionState,
151
+ setHostTransactionQuote,
152
+ setHostTransactionStates,
153
+ setHostTransactionTimestamp,
154
+ hostTransactionState,
155
+ setReceiptActionButtonText,
156
+ setOnReceiptAction,
157
+ retryTransactionRef,
158
+ } = useTrailsModal()
159
+ const indexerGatewayClient = useIndexerGatewayClient()
160
+ const { supportedTokens } = useSupportedTokens()
161
+ const commitIntentMutation = useCommitIntent()
162
+ const executeIntentMutation = useExecuteIntent()
163
+
164
+ // Store last transaction variables for retry
165
+ const lastTransactionVariablesRef =
166
+ useRef<TrailsSendTransactionVariables | null>(null)
167
+
168
+ const mergeHostTransactionState = useCallback(
169
+ (update: {
170
+ status?: HostTransactionStatus
171
+ details?: HostTransactionDetails | null
172
+ error?: string | null
173
+ result?: HostTransactionResultLinks | null
174
+ retryEnabled?: boolean
175
+ }) => {
176
+ setHostTransactionState((prev) => ({
177
+ status: update.status ?? prev.status,
178
+ details:
179
+ update.details === null
180
+ ? undefined
181
+ : update.details
182
+ ? { ...prev.details, ...update.details }
183
+ : prev.details,
184
+ error:
185
+ update.error === null
186
+ ? undefined
187
+ : update.error !== undefined
188
+ ? update.error
189
+ : prev.error,
190
+ result:
191
+ update.result === null
192
+ ? undefined
193
+ : update.result
194
+ ? { ...prev.result, ...update.result }
195
+ : prev.result,
196
+ retryEnabled:
197
+ update.retryEnabled !== undefined
198
+ ? update.retryEnabled
199
+ : prev.retryEnabled,
200
+ }))
201
+ },
202
+ [setHostTransactionState],
203
+ )
204
+
205
+ // Extract transaction execution logic into a reusable function
206
+ const executeTransaction = async (
207
+ variables: TrailsSendTransactionVariables,
208
+ originSelection?: {
209
+ fromTokenAddress: string
210
+ fromChainId: number
211
+ fromAmount?: string
212
+ },
213
+ options?: { trackInWidget?: boolean },
214
+ ): Promise<SwapReturn> => {
215
+ logger.console.log(
216
+ "[trails-sdk] [useTrailsSendTransaction] Executing transaction",
217
+ { variables, originSelection },
218
+ )
219
+
220
+ // Validate required parameters
221
+ if (!walletClient || !walletClient.account) {
222
+ throw new Error(
223
+ "Wallet client not available. Please connect your wallet.",
224
+ )
225
+ }
226
+
227
+ if (!variables.to) {
228
+ throw new Error("Transaction 'to' address is required.")
229
+ }
230
+
231
+ // Determine origin parameters
232
+ let fromTokenAddress: string
233
+ let fromChainId: number
234
+ let fromAmount: string | undefined
235
+
236
+ if (originSelection) {
237
+ // Use user-selected origin parameters (from modal)
238
+ fromTokenAddress = originSelection.fromTokenAddress
239
+ fromChainId = originSelection.fromChainId
240
+ fromAmount = originSelection.fromAmount
241
+ } else if (
242
+ variables.fromTokenAddress &&
243
+ variables.fromChainId &&
244
+ variables.fromAmount
245
+ ) {
246
+ // Use explicitly provided ERC20 token origin parameters
247
+ fromTokenAddress = variables.fromTokenAddress
248
+ fromChainId = variables.fromChainId
249
+ fromAmount = variables.fromAmount
250
+ } else if (variables.to && variables.value !== undefined) {
251
+ // Simple native token send - use current chain
252
+ const currentChainId = connectedChainId || chainId
253
+ if (!currentChainId) {
254
+ throw new Error("Chain ID not available. Please connect your wallet.")
255
+ }
256
+ fromChainId = currentChainId
257
+ fromTokenAddress = zeroAddress
258
+ fromAmount = variables.value.toString()
259
+ } else {
260
+ throw new Error(
261
+ "Origin token parameters are required. Please provide 'value' (native token), or 'fromTokenAddress'/'fromChainId'/'fromAmount' (ERC20 token), or select via modal.",
262
+ )
263
+ }
264
+
265
+ // Determine destination parameters
266
+ const currentChainId = connectedChainId || chainId
267
+ if (!currentChainId) {
268
+ throw new Error("Chain ID not available. Please connect your wallet.")
269
+ }
270
+
271
+ // Use tokenAddress and tokenAmount if provided, otherwise infer from to/value
272
+ let toTokenAddress: string
273
+ let toChainId: number
274
+ let toAmount: string
275
+ let recipient: string
276
+
277
+ if (variables.tokenAddress && variables.tokenAmount) {
278
+ // Destination token requirements specified (e.g., AAVE deposit)
279
+ toTokenAddress = variables.tokenAddress
280
+ // Try to find the token's chainId from supportedTokens, fallback to current chain
281
+ const destToken = supportedTokens?.find(
282
+ (token) =>
283
+ token.contractAddress?.toLowerCase() ===
284
+ variables.tokenAddress?.toLowerCase(),
285
+ )
286
+ toChainId = destToken?.chainId ?? currentChainId
287
+ toAmount = variables.tokenAmount
288
+ recipient = variables.to
289
+ } else if (variables.to && variables.value !== undefined) {
290
+ // Simple native token send
291
+ toTokenAddress = zeroAddress
292
+ toChainId = currentChainId
293
+ toAmount = variables.value.toString()
294
+ recipient = variables.to
295
+ } else {
296
+ throw new Error(
297
+ "Either 'value' or 'tokenAddress'/'tokenAmount' must be provided.",
298
+ )
299
+ }
300
+
301
+ // Determine swap amount based on trade type
302
+ // If tokenAmount is provided, use EXACT_OUTPUT (we need exact amount of destination token)
303
+ // Otherwise, use EXACT_INPUT (we're sending exact amount from origin)
304
+ const tradeType =
305
+ variables.tokenAddress && variables.tokenAmount
306
+ ? TradeType.EXACT_OUTPUT
307
+ : TradeType.EXACT_INPUT
308
+ if (tradeType === TradeType.EXACT_INPUT && !fromAmount) {
309
+ throw new Error(
310
+ "Origin amount is required for this transaction. Please provide 'value' or 'fromAmount'.",
311
+ )
312
+ }
313
+
314
+ const swapAmount =
315
+ tradeType === TradeType.EXACT_OUTPUT ? toAmount : fromAmount!
316
+
317
+ // Get token balances
318
+ let balances: any[] = []
319
+ try {
320
+ const result = await getTokenBalancesWithPrices({
321
+ account: walletClient.account.address,
322
+ indexerGatewayClient,
323
+ trailsClient,
324
+ })
325
+ balances = result.balances
326
+ } catch (balanceError) {
327
+ logger.console.warn(
328
+ "[trails-sdk] [useTrailsSendTransaction] Error fetching balances, proceeding with zero balance",
329
+ balanceError,
330
+ )
331
+ balances = []
332
+ }
333
+
334
+ const originTokenBalance = balances.find(
335
+ (b) =>
336
+ b.chainId === fromChainId &&
337
+ (b.contractAddress?.toLowerCase() === fromTokenAddress?.toLowerCase() ||
338
+ (!b.contractAddress && fromTokenAddress === zeroAddress)),
339
+ )
340
+
341
+ const originTokenBalanceAmount = originTokenBalance?.balance ?? "0"
342
+
343
+ // Get native token price for origin chain
344
+ let originNativeTokenPriceUsd = 0
345
+ try {
346
+ const originChain = getChainInfo(fromChainId)
347
+ const nativeTokenSymbol = originChain?.nativeCurrency?.symbol ?? ""
348
+ if (nativeTokenSymbol) {
349
+ const nativePrice = await getTokenPrice(trailsClient, {
350
+ tokenSymbol: nativeTokenSymbol,
351
+ tokenAddress: zeroAddress,
352
+ chainId: fromChainId,
353
+ })
354
+ originNativeTokenPriceUsd = nativePrice?.priceUsd ?? 0
355
+ }
356
+ } catch (error) {
357
+ logger.console.warn(
358
+ "[trails-sdk] [useTrailsSendTransaction] Error getting native token price",
359
+ error,
360
+ )
361
+ }
362
+
363
+ // Get token info and decimals
364
+ const originToken = supportedTokens?.find(
365
+ (token) =>
366
+ token.contractAddress?.toLowerCase() ===
367
+ fromTokenAddress?.toLowerCase() && token.chainId === fromChainId,
368
+ )
369
+ const destinationToken = supportedTokens?.find(
370
+ (token) =>
371
+ token.contractAddress?.toLowerCase() ===
372
+ toTokenAddress?.toLowerCase() && token.chainId === toChainId,
373
+ )
374
+
375
+ // Get RPC clients - we need to get them dynamically since we don't know chainIds until mutation
376
+ const { getChainRpcClient } = await import("../../chains.js")
377
+ const originPublicClient = getChainRpcClient(fromChainId)
378
+ const destinationPublicClient = getChainRpcClient(toChainId)
379
+
380
+ // Fetch decimals on-chain if not found
381
+ const fetchDecimalsOnChain = async (
382
+ tokenAddress: string,
383
+ chainId: number,
384
+ ): Promise<number | null> => {
385
+ try {
386
+ const publicClient =
387
+ chainId === fromChainId
388
+ ? originPublicClient
389
+ : chainId === toChainId
390
+ ? destinationPublicClient
391
+ : getChainRpcClient(chainId)
392
+
393
+ if (!publicClient) {
394
+ return null
395
+ }
396
+
397
+ if (tokenAddress.toLowerCase() === zeroAddress.toLowerCase()) {
398
+ const chainInfo = getChainInfo(chainId)
399
+ return chainInfo?.nativeCurrency.decimals ?? 18
400
+ }
401
+
402
+ const decimals = await publicClient.readContract({
403
+ address: tokenAddress as `0x${string}`,
404
+ abi: erc20Abi,
405
+ functionName: "decimals",
406
+ })
407
+
408
+ return decimals
409
+ } catch (error) {
410
+ logger.console.error(
411
+ `[trails-sdk] Error fetching decimals on-chain for token ${tokenAddress} on chain ${chainId}:`,
412
+ error,
413
+ )
414
+ return null
415
+ }
416
+ }
417
+
418
+ let sourceTokenDecimals = originToken?.decimals
419
+ if (!sourceTokenDecimals && fromTokenAddress) {
420
+ const onChainDecimals = await fetchDecimalsOnChain(
421
+ fromTokenAddress,
422
+ fromChainId,
423
+ )
424
+ if (onChainDecimals !== null) {
425
+ sourceTokenDecimals = onChainDecimals
426
+ }
427
+ }
428
+ if (!sourceTokenDecimals) {
429
+ // Default to 18 for native/unknown
430
+ sourceTokenDecimals = 18
431
+ }
432
+
433
+ let destinationTokenDecimals = destinationToken?.decimals
434
+ if (!destinationTokenDecimals && toTokenAddress) {
435
+ const onChainDecimals = await fetchDecimalsOnChain(
436
+ toTokenAddress,
437
+ toChainId,
438
+ )
439
+ if (onChainDecimals !== null) {
440
+ destinationTokenDecimals = onChainDecimals
441
+ }
442
+ }
443
+ if (!destinationTokenDecimals) {
444
+ // Default to 18 for native/unknown
445
+ destinationTokenDecimals = 18
446
+ }
447
+
448
+ const destinationTokenSymbol = destinationToken?.symbol ?? ""
449
+ const originTokenSymbol = originToken?.symbol ?? ""
450
+
451
+ const handleTransactionStateChange = (states: TransactionState[]) => {
452
+ if (options?.trackInWidget) {
453
+ setHostTransactionStates(states)
454
+ }
455
+ params?.onStatusUpdate?.(states)
456
+ }
457
+
458
+ // Call prepareSend
459
+ const { send, quote } = await prepareSend({
460
+ account: walletClient.account,
461
+ originTokenAddress: fromTokenAddress,
462
+ originChainId: fromChainId,
463
+ originTokenBalance: originTokenBalanceAmount,
464
+ destinationChainId: toChainId,
465
+ recipient: recipient,
466
+ destinationTokenAddress: toTokenAddress,
467
+ swapAmount: swapAmount,
468
+ tradeType: tradeType,
469
+ originTokenSymbol: originTokenSymbol,
470
+ destinationTokenSymbol: destinationTokenSymbol,
471
+ fee: "0",
472
+ client: walletClient,
473
+ dryMode: false,
474
+ trailsClient,
475
+ destinationCalldata: variables.data
476
+ ? variables.data.toString()
477
+ : undefined,
478
+ onTransactionStateChange: handleTransactionStateChange,
479
+ sourceTokenDecimals,
480
+ destinationTokenDecimals,
481
+ paymasterUrl: params?.paymasterUrl,
482
+ slippageTolerance: params?.slippageTolerance?.toString(),
483
+ originNativeTokenPriceUsd,
484
+ quoteProvider: params?.quoteProvider,
485
+ commitIntentFn: commitIntentMutation.mutateAsync,
486
+ executeIntentFn: executeIntentMutation.mutateAsync,
487
+ checkoutOnHandlers: params?.checkoutOnHandlers,
488
+ sequenceIndexerUrl,
489
+ sequenceProjectAccessKey: trailsApiKey,
490
+ originPublicClient: originPublicClient ?? undefined,
491
+ destinationPublicClient: destinationPublicClient ?? undefined,
492
+ isSmartWallet: params?.isSmartWallet ?? undefined,
493
+ })
494
+
495
+ if (options?.trackInWidget) {
496
+ setHostTransactionQuote(quote ?? null)
497
+ if (!hostTransactionState.details) {
498
+ mergeHostTransactionState({
499
+ details: {
500
+ to: recipient,
501
+ tokenAddress: toTokenAddress,
502
+ tokenAmount:
503
+ tradeType === TradeType.EXACT_OUTPUT ? toAmount : undefined,
504
+ toChainId,
505
+ data: variables.data,
506
+ },
507
+ })
508
+ }
509
+ if (
510
+ !hostTransactionState.status ||
511
+ hostTransactionState.status === "idle"
512
+ ) {
513
+ setHostTransactionTimestamp(Date.now())
514
+ }
515
+ }
516
+
517
+ // Execute the swap
518
+ try {
519
+ // Reset retry flag when starting a new attempt
520
+ if (options?.trackInWidget) {
521
+ mergeHostTransactionState({ retryEnabled: false })
522
+ }
523
+ const {
524
+ depositUserTxnReceipt,
525
+ destinationIntentTransaction,
526
+ totalCompletionSeconds,
527
+ } = await send({
528
+ selectedFeeOption: null,
529
+ // Transition to "pending" when wallet signature is complete
530
+ onOriginSend: () => {
531
+ if (options?.trackInWidget) {
532
+ mergeHostTransactionState({ status: "pending", error: null })
533
+ }
534
+ },
535
+ })
536
+
537
+ if (options?.trackInWidget) {
538
+ mergeHostTransactionState({
539
+ status: "success",
540
+ result: {
541
+ originTxHash: depositUserTxnReceipt?.transactionHash,
542
+ originExplorerUrl: depositUserTxnReceipt?.transactionHash
543
+ ? getExplorerUrl({
544
+ txHash: depositUserTxnReceipt.transactionHash,
545
+ chainId: fromChainId,
546
+ })
547
+ : undefined,
548
+ destinationTxHash: destinationIntentTransaction?.txnHash,
549
+ destinationExplorerUrl: destinationIntentTransaction?.txnHash
550
+ ? getExplorerUrl({
551
+ txHash: destinationIntentTransaction.txnHash,
552
+ chainId: toChainId,
553
+ })
554
+ : undefined,
555
+ },
556
+ })
557
+ }
558
+
559
+ return {
560
+ originTransaction: {
561
+ transactionHash: depositUserTxnReceipt?.transactionHash,
562
+ explorerUrl: getExplorerUrl({
563
+ txHash: depositUserTxnReceipt?.transactionHash as string,
564
+ chainId: fromChainId,
565
+ }),
566
+ receipt: depositUserTxnReceipt,
567
+ },
568
+ destinationTransaction: {
569
+ transactionHash: destinationIntentTransaction?.txnHash,
570
+ explorerUrl: getExplorerUrl({
571
+ txHash: destinationIntentTransaction?.txnHash as string,
572
+ chainId: toChainId,
573
+ }),
574
+ receipt: destinationIntentTransaction,
575
+ },
576
+ totalCompletionSeconds,
577
+ }
578
+ } catch (error) {
579
+ if (options?.trackInWidget) {
580
+ // For user rejection errors, stay on confirmation screen with retry enabled
581
+ const isUserRejection = getIsUserRejectionError(error)
582
+ if (isUserRejection) {
583
+ mergeHostTransactionState({
584
+ status: "confirmation",
585
+ error: null,
586
+ retryEnabled: true,
587
+ })
588
+ } else {
589
+ mergeHostTransactionState({
590
+ status: "error",
591
+ error: getFullErrorMessage(error as Error),
592
+ retryEnabled: false,
593
+ })
594
+ }
595
+ }
596
+ throw error
597
+ }
598
+ }
599
+
600
+ const mutation = useMutation({
601
+ mutationFn: async (
602
+ variables: TrailsSendTransactionVariables,
603
+ ): Promise<SwapReturn> => {
604
+ logger.console.log(
605
+ "[trails-sdk] [useTrailsSendTransaction] Starting transaction",
606
+ variables,
607
+ )
608
+
609
+ // Set receipt customization from params
610
+ setReceiptActionButtonText(
611
+ params?.receiptActionButtonText ?? "Transact Again",
612
+ )
613
+ setOnReceiptAction(params?.onReceiptAction ?? null)
614
+
615
+ // Check if we have origin parameters specified
616
+ const hasNativeTokenOrigin = variables.value !== undefined
617
+ const hasERC20TokenOrigin =
618
+ variables.fromTokenAddress !== undefined &&
619
+ variables.fromChainId !== undefined
620
+ const hasOriginParams = hasNativeTokenOrigin || hasERC20TokenOrigin
621
+
622
+ // Determine destination chain ID
623
+ // Priority: token's chainId (from supportedTokens) > current chain
624
+ let destinationChainId: number | undefined
625
+ if (variables.tokenAddress && supportedTokens) {
626
+ // Find the token's chainId from supportedTokens
627
+ const destToken = supportedTokens.find(
628
+ (token) =>
629
+ token.contractAddress?.toLowerCase() ===
630
+ variables.tokenAddress?.toLowerCase(),
631
+ )
632
+ if (destToken) {
633
+ destinationChainId = destToken.chainId
634
+ }
635
+ }
636
+ if (!destinationChainId) {
637
+ destinationChainId = connectedChainId || chainId
638
+ }
639
+
640
+ // Check balances for origin and destination
641
+ let hasSufficientOriginBalance = true
642
+ let hasSufficientDestinationTokenBalance = true
643
+
644
+ if (walletClient?.account) {
645
+ try {
646
+ // Step 1: Check origin balance FIRST
647
+ // If origin is insufficient, user will need to select a different token via modal
648
+ if (hasOriginParams) {
649
+ let originTokenAddress: string | undefined
650
+ let originChainId: number | undefined
651
+ let originAmount: string | undefined
652
+
653
+ if (variables.value !== undefined) {
654
+ // Native token origin
655
+ originTokenAddress = zeroAddress
656
+ originChainId = connectedChainId || chainId || 1
657
+ originAmount = variables.value.toString()
658
+ } else if (variables.fromTokenAddress && variables.fromChainId) {
659
+ // ERC20 token origin (amount optional for EXACT_OUTPUT)
660
+ originTokenAddress = variables.fromTokenAddress
661
+ originChainId = variables.fromChainId
662
+ originAmount = variables.fromAmount
663
+ }
664
+
665
+ if (
666
+ originTokenAddress &&
667
+ originChainId &&
668
+ originAmount &&
669
+ originAmount !== "0"
670
+ ) {
671
+ hasSufficientOriginBalance = await getHasSufficientBalanceToken({
672
+ account: walletClient.account.address,
673
+ token: originTokenAddress,
674
+ amount: originAmount,
675
+ chainId: originChainId,
676
+ indexerGatewayClient,
677
+ trailsClient,
678
+ })
679
+ logger.console.log(
680
+ "[trails-sdk] [useTrailsSendTransaction] Origin token balance check:",
681
+ {
682
+ tokenAddress: originTokenAddress,
683
+ amount: originAmount,
684
+ chainId: originChainId,
685
+ hasSufficientBalance: hasSufficientOriginBalance,
686
+ },
687
+ )
688
+ }
689
+ }
690
+
691
+ // Step 2: Only check destination token balance if origin is sufficient
692
+ // (otherwise user will open modal to select a different origin token)
693
+ if (
694
+ hasSufficientOriginBalance &&
695
+ variables.tokenAddress &&
696
+ variables.tokenAmount
697
+ ) {
698
+ hasSufficientDestinationTokenBalance =
699
+ await getHasSufficientBalanceToken({
700
+ account: walletClient.account.address,
701
+ token: variables.tokenAddress,
702
+ amount: variables.tokenAmount,
703
+ chainId: destinationChainId,
704
+ indexerGatewayClient,
705
+ trailsClient,
706
+ })
707
+ logger.console.log(
708
+ "[trails-sdk] [useTrailsSendTransaction] Destination token balance check:",
709
+ {
710
+ tokenAddress: variables.tokenAddress,
711
+ tokenAmount: variables.tokenAmount,
712
+ chainId: destinationChainId,
713
+ hasSufficientBalance: hasSufficientDestinationTokenBalance,
714
+ },
715
+ )
716
+
717
+ // Step 3: Gas balance check will be done via QuoteIntent API in prepareSend
718
+ // The API provides comprehensive gas fee information including:
719
+ // - originGas: origin chain gas cost
720
+ // - destinationGas: destination chain gas cost (if applicable)
721
+ // - gasFeeOptions: fee options in different tokens
722
+ // If gas is insufficient, the system will fallback to gasless (handled in prepareSend)
723
+ }
724
+ } catch (balanceError) {
725
+ logger.console.warn(
726
+ "[trails-sdk] [useTrailsSendTransaction] Error checking balances, defaulting to origin selection:",
727
+ balanceError,
728
+ )
729
+ // If balance checks fail, default to opening modal (safe fallback)
730
+ hasSufficientOriginBalance = false
731
+ hasSufficientDestinationTokenBalance = false
732
+ }
733
+ }
734
+
735
+ // Determine if origin selection is needed
736
+ // Origin selection is needed when:
737
+ // 1. Origin parameters are not provided, OR
738
+ // 2. Origin balance is insufficient (user selected origin but doesn't have enough), OR
739
+ // 3. Destination token balance is insufficient (even if gas balance is sufficient)
740
+ // Note: Gas balance checks are done via QuoteIntent API after origin/destination are confirmed
741
+ const needsOriginSelection =
742
+ !hasOriginParams ||
743
+ !hasSufficientOriginBalance ||
744
+ !hasSufficientDestinationTokenBalance
745
+
746
+ logger.console.log(
747
+ "[trails-sdk] [useTrailsSendTransaction] Origin selection decision:",
748
+ {
749
+ hasOriginParams,
750
+ hasSufficientOriginBalance,
751
+ hasSufficientDestinationTokenBalance,
752
+ needsOriginSelection,
753
+ },
754
+ )
755
+
756
+ if (needsOriginSelection) {
757
+ const requireAmountInput = !(
758
+ variables.tokenAddress && variables.tokenAmount
759
+ )
760
+ const baseDetails: HostTransactionDetails = {
761
+ to: variables.to,
762
+ tokenAddress: variables.tokenAddress,
763
+ tokenAmount: variables.tokenAmount,
764
+ toChainId: destinationChainId,
765
+ data: variables.data,
766
+ }
767
+ mergeHostTransactionState({
768
+ status: "awaiting-origin",
769
+ details: baseDetails,
770
+ error: null,
771
+ result: null,
772
+ })
773
+ setHostTransactionQuote(null)
774
+ setHostTransactionStates([])
775
+ setHostTransactionTimestamp(Date.now())
776
+ // Open modal and wait for user selection
777
+ return new Promise<SwapReturn>((resolve, reject) => {
778
+ setPendingSelection({
779
+ resolve: async (selection) => {
780
+ try {
781
+ mergeHostTransactionState({ status: "confirmation" })
782
+ const result = await executeTransaction(variables, selection, {
783
+ trackInWidget: true,
784
+ })
785
+ resolve(result)
786
+ } catch (error) {
787
+ // Don't override state for user rejections - they're handled in executeTransaction
788
+ // and stay on confirmation screen with retry enabled
789
+ const isUserRejection = getIsUserRejectionError(error)
790
+ if (!isUserRejection) {
791
+ mergeHostTransactionState({
792
+ status: "error",
793
+ error: getFullErrorMessage(error as Error),
794
+ })
795
+ }
796
+ reject(error as Error)
797
+ }
798
+ },
799
+ reject: (error) => {
800
+ const rejection =
801
+ error instanceof Error ? error : new Error(String(error))
802
+ mergeHostTransactionState({
803
+ status: "error",
804
+ error: getFullErrorMessage(rejection),
805
+ })
806
+ reject(rejection)
807
+ },
808
+ requireAmountInput,
809
+ })
810
+
811
+ // Open the modal after setting pending selection
812
+ // Use setTimeout to ensure state updates are processed
813
+ setTimeout(() => {
814
+ logger.console.log(
815
+ "[trails-sdk] [useTrailsSendTransaction] Calling openModal()",
816
+ )
817
+ openModal()
818
+ }, 0)
819
+ })
820
+ }
821
+
822
+ // Set up modal for wallet-confirmation, pending, and receipt screens
823
+ const baseDetails: HostTransactionDetails = {
824
+ to: variables.to,
825
+ tokenAddress: variables.tokenAddress,
826
+ tokenAmount: variables.tokenAmount,
827
+ toChainId: destinationChainId,
828
+ data: variables.data,
829
+ }
830
+ mergeHostTransactionState({
831
+ status: "confirmation",
832
+ details: baseDetails,
833
+ error: null,
834
+ result: null,
835
+ })
836
+ setHostTransactionQuote(null)
837
+ setHostTransactionStates([])
838
+ setHostTransactionTimestamp(Date.now())
839
+ openModal()
840
+
841
+ // Execute transaction directly with modal tracking
842
+ return executeTransaction(variables, undefined, { trackInWidget: true })
843
+ },
844
+ onSuccess: (data, variables) => {
845
+ logger.console.log(
846
+ "[trails-sdk] [useTrailsSendTransaction] Transaction successful",
847
+ { data, variables },
848
+ )
849
+ params?.onSuccess?.(data, variables)
850
+ },
851
+ onError: (error, variables) => {
852
+ logger.console.error(
853
+ "[trails-sdk] [useTrailsSendTransaction] Transaction error",
854
+ { error, variables },
855
+ )
856
+ const errorMessage = getFullErrorMessage(error)
857
+ // Don't override state for user rejections - they're handled in executeTransaction
858
+ // and stay on confirmation screen with retry enabled
859
+ const isUserRejection = getIsUserRejectionError(error)
860
+ if (hostTransactionState.status !== "idle" && !isUserRejection) {
861
+ mergeHostTransactionState({
862
+ status: "error",
863
+ error: errorMessage,
864
+ })
865
+ }
866
+ params?.onError?.(new Error(errorMessage), variables)
867
+ },
868
+ onSettled: (data, error, variables) => {
869
+ logger.console.log(
870
+ "[trails-sdk] [useTrailsSendTransaction] Transaction settled",
871
+ { data, error, variables },
872
+ )
873
+ params?.onSettled?.(data, error as Error | null, variables)
874
+ },
875
+ })
876
+
877
+ const sendTransaction = useCallback(
878
+ (
879
+ variables: TrailsSendTransactionVariables,
880
+ callbacks?: {
881
+ onSuccess?: (data: SwapReturn) => void
882
+ onError?: (error: Error) => void
883
+ onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
884
+ },
885
+ ) => {
886
+ mutation.mutate(variables, {
887
+ onSuccess: (data) => {
888
+ callbacks?.onSuccess?.(data)
889
+ },
890
+ onError: (error) => {
891
+ callbacks?.onError?.(error as Error)
892
+ },
893
+ onSettled: (data, error) => {
894
+ callbacks?.onSettled?.(data, error as Error | null)
895
+ },
896
+ })
897
+ },
898
+ [mutation],
899
+ )
900
+
901
+ const sendTransactionAsync = useCallback(
902
+ async (
903
+ variables: TrailsSendTransactionVariables,
904
+ callbacks?: {
905
+ onSuccess?: (data: SwapReturn) => void
906
+ onError?: (error: Error) => void
907
+ onSettled?: (data: SwapReturn | undefined, error: Error | null) => void
908
+ },
909
+ ): Promise<SwapReturn> => {
910
+ return mutation.mutateAsync(variables, {
911
+ onSuccess: (data) => {
912
+ callbacks?.onSuccess?.(data)
913
+ },
914
+ onError: (error) => {
915
+ callbacks?.onError?.(error as Error)
916
+ },
917
+ onSettled: (data, error) => {
918
+ callbacks?.onSettled?.(data, error as Error | null)
919
+ },
920
+ })
921
+ },
922
+ [mutation],
923
+ )
924
+
925
+ // Retry function that re-executes with last variables
926
+ const retry = useCallback(() => {
927
+ if (lastTransactionVariablesRef.current) {
928
+ sendTransaction(lastTransactionVariablesRef.current)
929
+ }
930
+ }, [sendTransaction])
931
+
932
+ // Store retry function in ref so widget can call it (using ref to avoid re-renders)
933
+ retryTransactionRef.current = retry
934
+
935
+ return {
936
+ sendTransaction,
937
+ sendTransactionAsync,
938
+ retry,
939
+ data: mutation.data,
940
+ error: mutation.error as Error | null,
941
+ isPending: mutation.isPending,
942
+ isSuccess: mutation.isSuccess,
943
+ isError: mutation.isError,
944
+ isIdle: mutation.isIdle,
945
+ status: mutation.status,
946
+ reset: mutation.reset,
947
+ variables: mutation.variables,
948
+ }
949
+ }