0xtrails 0.0.1 → 0.0.2

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 (359) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +42 -0
  3. package/dist/abi.d.ts +37 -0
  4. package/dist/abi.d.ts.map +1 -0
  5. package/dist/abi.js +36 -0
  6. package/dist/apiClient.d.ts +9 -0
  7. package/dist/apiClient.d.ts.map +1 -0
  8. package/dist/apiClient.js +18 -0
  9. package/dist/buffer.d.ts +3 -0
  10. package/dist/buffer.d.ts.map +1 -0
  11. package/dist/buffer.js +8 -0
  12. package/dist/cctp.d.ts +84 -0
  13. package/dist/cctp.d.ts.map +1 -0
  14. package/dist/cctp.js +401 -0
  15. package/dist/chainSwitch.d.ts +7 -0
  16. package/dist/chainSwitch.d.ts.map +1 -0
  17. package/dist/chainSwitch.js +33 -0
  18. package/dist/chains.d.ts +13 -0
  19. package/dist/chains.d.ts.map +1 -0
  20. package/dist/chains.js +95 -0
  21. package/dist/constants.d.ts +11 -0
  22. package/dist/constants.d.ts.map +1 -0
  23. package/dist/constants.js +16 -0
  24. package/dist/encoders.d.ts +7 -0
  25. package/dist/encoders.d.ts.map +1 -0
  26. package/dist/encoders.js +8 -0
  27. package/dist/error.d.ts +2 -0
  28. package/dist/error.d.ts.map +1 -0
  29. package/dist/error.js +12 -0
  30. package/dist/explorer.d.ts +12 -0
  31. package/dist/explorer.d.ts.map +1 -0
  32. package/dist/explorer.js +18 -0
  33. package/dist/gasless.d.ts +116 -0
  34. package/dist/gasless.d.ts.map +1 -0
  35. package/dist/gasless.js +297 -0
  36. package/dist/index.d.ts +13 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +9 -0
  39. package/dist/indexerClient.d.ts +9 -0
  40. package/dist/indexerClient.d.ts.map +1 -0
  41. package/dist/indexerClient.js +18 -0
  42. package/dist/intents.d.ts +83 -0
  43. package/dist/intents.d.ts.map +1 -0
  44. package/dist/intents.js +288 -0
  45. package/dist/metaTxnMonitor.d.ts +14 -0
  46. package/dist/metaTxnMonitor.d.ts.map +1 -0
  47. package/dist/metaTxnMonitor.js +121 -0
  48. package/dist/metaTxns.d.ts +6 -0
  49. package/dist/metaTxns.d.ts.map +1 -0
  50. package/dist/metaTxns.js +4 -0
  51. package/dist/paymasterSend.d.ts +90 -0
  52. package/dist/paymasterSend.d.ts.map +1 -0
  53. package/dist/paymasterSend.js +329 -0
  54. package/dist/preconditions.d.ts +11 -0
  55. package/dist/preconditions.d.ts.map +1 -0
  56. package/dist/preconditions.js +29 -0
  57. package/dist/prepareSend.d.ts +102 -0
  58. package/dist/prepareSend.d.ts.map +1 -0
  59. package/dist/prepareSend.js +1080 -0
  60. package/dist/prices.d.ts +18 -0
  61. package/dist/prices.d.ts.map +1 -0
  62. package/dist/prices.js +142 -0
  63. package/dist/queryParams.d.ts +9 -0
  64. package/dist/queryParams.d.ts.map +1 -0
  65. package/dist/queryParams.js +66 -0
  66. package/dist/relaySdk.d.ts +65 -0
  67. package/dist/relaySdk.d.ts.map +1 -0
  68. package/dist/relaySdk.js +314 -0
  69. package/dist/relayer.d.ts +23 -0
  70. package/dist/relayer.d.ts.map +1 -0
  71. package/dist/relayer.js +230 -0
  72. package/dist/sendUserOp.d.ts +140 -0
  73. package/dist/sendUserOp.d.ts.map +1 -0
  74. package/dist/sendUserOp.js +388 -0
  75. package/dist/sequenceWallet.d.ts +79 -0
  76. package/dist/sequenceWallet.d.ts.map +1 -0
  77. package/dist/sequenceWallet.js +374 -0
  78. package/dist/theme.d.ts +3 -0
  79. package/dist/theme.d.ts.map +1 -0
  80. package/dist/theme.js +1 -0
  81. package/dist/toSimpleSmartAccount.d.ts +95 -0
  82. package/dist/toSimpleSmartAccount.d.ts.map +1 -0
  83. package/dist/toSimpleSmartAccount.js +373 -0
  84. package/dist/tokenBalances.d.ts +118 -0
  85. package/dist/tokenBalances.d.ts.map +1 -0
  86. package/dist/tokenBalances.js +492 -0
  87. package/dist/tokens.d.ts +50 -0
  88. package/dist/tokens.d.ts.map +1 -0
  89. package/dist/tokens.js +356 -0
  90. package/dist/trails.d.ts +128 -0
  91. package/dist/trails.d.ts.map +1 -0
  92. package/dist/trails.js +1031 -0
  93. package/dist/umd/trails.min.js +12610 -0
  94. package/dist/umd/trails.min.js.map +1 -0
  95. package/dist/umd.d.ts +24 -0
  96. package/dist/umd.d.ts.map +1 -0
  97. package/dist/utils.d.ts +5 -0
  98. package/dist/utils.d.ts.map +1 -0
  99. package/dist/utils.js +9 -0
  100. package/dist/widget/ConstantsUtil-B-_-u8aQ.js +6 -0
  101. package/dist/widget/add-hVLs3ldJ.js +20 -0
  102. package/dist/widget/all-wallets-Cwxnx4BT.js +11 -0
  103. package/dist/widget/app-store-CAAVQjW0.js +22 -0
  104. package/dist/widget/apple-C3BSbglw.js +23 -0
  105. package/dist/widget/arrow-bottom-circle-BGU9MmsZ.js +16 -0
  106. package/dist/widget/arrow-bottom-hS_SA8Gp.js +13 -0
  107. package/dist/widget/arrow-left-CJZanWz7.js +13 -0
  108. package/dist/widget/arrow-right-C1qL8EMd.js +13 -0
  109. package/dist/widget/arrow-top-CbuCmbQs.js +13 -0
  110. package/dist/widget/bank-CXBEEGbb.js +19 -0
  111. package/dist/widget/bin-Dqzv3zCZ.js +9 -0
  112. package/dist/widget/bitcoin-4y3sovZp.js +18 -0
  113. package/dist/widget/browser-DyOl4_8m.js +1413 -0
  114. package/dist/widget/browser-t7Fh0sEU.js +19 -0
  115. package/dist/widget/card-Bo4CZkTs.js +19 -0
  116. package/dist/widget/ccip-BynehMIN.js +232 -0
  117. package/dist/widget/checkmark-DV6OKvnY.js +16 -0
  118. package/dist/widget/checkmark-bold-CAp1-IQ2.js +13 -0
  119. package/dist/widget/chevron-bottom-BjzsVzk9.js +13 -0
  120. package/dist/widget/chevron-left-CQZBDCiR.js +13 -0
  121. package/dist/widget/chevron-right-Dhg4zeZM.js +13 -0
  122. package/dist/widget/chevron-top-CDQmfJef.js +13 -0
  123. package/dist/widget/chrome-store-BNaC_b6w.js +66 -0
  124. package/dist/widget/circle-BC_GBj91.js +9 -0
  125. package/dist/widget/clock-BmF8-4a0.js +13 -0
  126. package/dist/widget/close-Bf61nZ8o.js +13 -0
  127. package/dist/widget/coinPlaceholder-7cZW2058.js +13 -0
  128. package/dist/widget/compass-CFC3yhnW.js +13 -0
  129. package/dist/widget/components/ChainImage.d.ts +8 -0
  130. package/dist/widget/components/ChainImage.d.ts.map +1 -0
  131. package/dist/widget/components/ChainImage.js +6 -0
  132. package/dist/widget/components/ConnectWallet.d.ts +18 -0
  133. package/dist/widget/components/ConnectWallet.d.ts.map +1 -0
  134. package/dist/widget/components/ConnectWallet.js +66 -0
  135. package/dist/widget/components/DebugScreensDropdown.d.ts +9 -0
  136. package/dist/widget/components/DebugScreensDropdown.d.ts.map +1 -0
  137. package/dist/widget/components/DebugScreensDropdown.js +40 -0
  138. package/dist/widget/components/FeeOptions.d.ts +17 -0
  139. package/dist/widget/components/FeeOptions.d.ts.map +1 -0
  140. package/dist/widget/components/FeeOptions.js +65 -0
  141. package/dist/widget/components/Footer.d.ts +9 -0
  142. package/dist/widget/components/Footer.d.ts.map +1 -0
  143. package/dist/widget/components/Footer.js +13 -0
  144. package/dist/widget/components/GreenCheckAnimation.d.ts +2 -0
  145. package/dist/widget/components/GreenCheckAnimation.d.ts.map +1 -0
  146. package/dist/widget/components/GreenCheckAnimation.js +74 -0
  147. package/dist/widget/components/Modal.d.ts +11 -0
  148. package/dist/widget/components/Modal.d.ts.map +1 -0
  149. package/dist/widget/components/Modal.js +36 -0
  150. package/dist/widget/components/Receipt.d.ts +13 -0
  151. package/dist/widget/components/Receipt.d.ts.map +1 -0
  152. package/dist/widget/components/Receipt.js +36 -0
  153. package/dist/widget/components/SendForm.d.ts +44 -0
  154. package/dist/widget/components/SendForm.d.ts.map +1 -0
  155. package/dist/widget/components/SendForm.js +177 -0
  156. package/dist/widget/components/TokenImage.d.ts +10 -0
  157. package/dist/widget/components/TokenImage.d.ts.map +1 -0
  158. package/dist/widget/components/TokenImage.js +8 -0
  159. package/dist/widget/components/TokenList.d.ts +16 -0
  160. package/dist/widget/components/TokenList.d.ts.map +1 -0
  161. package/dist/widget/components/TokenList.js +39 -0
  162. package/dist/widget/components/TransferPending.d.ts +11 -0
  163. package/dist/widget/components/TransferPending.d.ts.map +1 -0
  164. package/dist/widget/components/TransferPending.js +77 -0
  165. package/dist/widget/components/TransferPendingVertical.d.ts +18 -0
  166. package/dist/widget/components/TransferPendingVertical.d.ts.map +1 -0
  167. package/dist/widget/components/TransferPendingVertical.js +183 -0
  168. package/dist/widget/components/WalletConfirmation.d.ts +18 -0
  169. package/dist/widget/components/WalletConfirmation.d.ts.map +1 -0
  170. package/dist/widget/components/WalletConfirmation.js +22 -0
  171. package/dist/widget/config.d.ts +4 -0
  172. package/dist/widget/config.d.ts.map +1 -0
  173. package/dist/widget/config.js +3 -0
  174. package/dist/widget/copy-e0xXvKN0.js +20 -0
  175. package/dist/widget/cursor-CqM3v0xJ.js +8 -0
  176. package/dist/widget/cursor-transparent-CUQpdsCG.js +17 -0
  177. package/dist/widget/desktop-DUDGIRpM.js +14 -0
  178. package/dist/widget/disconnect-DUFST9QQ.js +13 -0
  179. package/dist/widget/discord-C1cj365Z.js +22 -0
  180. package/dist/widget/email-BHhmb_lX.js +703 -0
  181. package/dist/widget/embedded-wallet-CuuC4eah.js +467 -0
  182. package/dist/widget/ethereum-CfmBVfeB.js +15 -0
  183. package/dist/widget/etherscan-BSiynDhW.js +11 -0
  184. package/dist/widget/exclamation-triangle-DEiFNpHw.js +9 -0
  185. package/dist/widget/extension-mRmfCDxo.js +13 -0
  186. package/dist/widget/external-link-B4xMIVnW.js +13 -0
  187. package/dist/widget/facebook-CBAZStBR.js +31 -0
  188. package/dist/widget/farcaster-LHDEDf5S.js +17 -0
  189. package/dist/widget/filters-CBijuvFv.js +13 -0
  190. package/dist/widget/github-C3ILD420.js +23 -0
  191. package/dist/widget/google-CSj73POX.js +23 -0
  192. package/dist/widget/help-circle-2hdG5IdB.js +17 -0
  193. package/dist/widget/hooks/useAmountUsd.d.ts +13 -0
  194. package/dist/widget/hooks/useAmountUsd.d.ts.map +1 -0
  195. package/dist/widget/hooks/useAmountUsd.js +35 -0
  196. package/dist/widget/hooks/useSendForm.d.ts +125 -0
  197. package/dist/widget/hooks/useSendForm.d.ts.map +1 -0
  198. package/dist/widget/hooks/useSendForm.js +450 -0
  199. package/dist/widget/hooks/useTokenList.d.ts +52 -0
  200. package/dist/widget/hooks/useTokenList.d.ts.map +1 -0
  201. package/dist/widget/hooks/useTokenList.js +252 -0
  202. package/dist/widget/id-ByYSrwsd.js +17 -0
  203. package/dist/widget/if-defined-DRXJEhv7.js +752 -0
  204. package/dist/widget/image-C90L4Rf6.js +9 -0
  205. package/dist/widget/index-B3SlQ9v3.js +46 -0
  206. package/dist/widget/index-B8LPuLXQ.js +78 -0
  207. package/dist/widget/index-BDbworWA.js +171 -0
  208. package/dist/widget/index-BTlDgFSK.js +98 -0
  209. package/dist/widget/index-BUCcjXbd.js +306 -0
  210. package/dist/widget/index-BZ34edi2.js +1055 -0
  211. package/dist/widget/index-BiCU29wK.js +147 -0
  212. package/dist/widget/index-BlmqIKsY.js +266 -0
  213. package/dist/widget/index-BlviH5nG.js +55 -0
  214. package/dist/widget/index-Bwd5X3fS.js +8306 -0
  215. package/dist/widget/index-C5gmknHK.js +78 -0
  216. package/dist/widget/index-CD6dBcRj.js +76 -0
  217. package/dist/widget/index-CDlhy529.js +63 -0
  218. package/dist/widget/index-CHXa5ke-.js +59 -0
  219. package/dist/widget/index-CK94R-H7.js +22498 -0
  220. package/dist/widget/index-CQzo3m3x.js +182 -0
  221. package/dist/widget/index-CRT8cAwG.js +325 -0
  222. package/dist/widget/index-CY7Lt2Yu.js +310 -0
  223. package/dist/widget/index-CiKfAu1E.js +79 -0
  224. package/dist/widget/index-CkCu6rMi.js +258 -0
  225. package/dist/widget/index-CngLTu_R.js +517 -0
  226. package/dist/widget/index-CsMV8-em.js +2577 -0
  227. package/dist/widget/index-Cu2Wva8v.js +200 -0
  228. package/dist/widget/index-DKBxLTEF.js +240 -0
  229. package/dist/widget/index-DQEVT3dx.js +511 -0
  230. package/dist/widget/index-DU2HcCis.js +200 -0
  231. package/dist/widget/index-DutZGWNW.js +321 -0
  232. package/dist/widget/index-O0glArmc.js +182 -0
  233. package/dist/widget/index-O8FmRjKe.js +63719 -0
  234. package/dist/widget/index-RtKXrB6I.js +576 -0
  235. package/dist/widget/index-TIYtS0gE.js +88 -0
  236. package/dist/widget/index-dQNJvWHs.js +66 -0
  237. package/dist/widget/index-wmEwdsq7.js +909 -0
  238. package/dist/widget/index.d.ts +3 -0
  239. package/dist/widget/index.d.ts.map +1 -0
  240. package/dist/widget/index.js +2 -0
  241. package/dist/widget/info-DMPChDjV.js +8 -0
  242. package/dist/widget/info-circle-DAvS_7nY.js +17 -0
  243. package/dist/widget/lightbulb-DnZ9mNEs.js +8 -0
  244. package/dist/widget/lit-html-BRjl1r6K.js +243 -0
  245. package/dist/widget/mail-DpaVSOP8.js +13 -0
  246. package/dist/widget/mobile-CRvdyu7I.js +14 -0
  247. package/dist/widget/more-C5VqW9PR.js +16 -0
  248. package/dist/widget/network-placeholder-CZ0vApma.js +19 -0
  249. package/dist/widget/nftPlaceholder-7jjIK2bT.js +13 -0
  250. package/dist/widget/off-4mHjJLLX.js +9 -0
  251. package/dist/widget/onramp-Bc0ozVsw.js +929 -0
  252. package/dist/widget/play-store-Uocul8nC.js +37 -0
  253. package/dist/widget/plus-DrYF7siO.js +18 -0
  254. package/dist/widget/prepareSend-BQJmzM5B.js +54987 -0
  255. package/dist/widget/qr-code-DcnGMUB3.js +11 -0
  256. package/dist/widget/receive-fvIVd7R_.js +184 -0
  257. package/dist/widget/recycle-horizontal-DrDwXC4D.js +14 -0
  258. package/dist/widget/ref-CXNmEjML.js +41 -0
  259. package/dist/widget/refresh-OK9lIPLS.js +13 -0
  260. package/dist/widget/reown-logo-C-Qn7mS3.js +17 -0
  261. package/dist/widget/search-DZqv1oKg.js +13 -0
  262. package/dist/widget/send-CJlmI-xe.js +1039 -0
  263. package/dist/widget/send-otoEC8uU.js +20 -0
  264. package/dist/widget/socials-BJciurWF.js +599 -0
  265. package/dist/widget/solana-Bv5Hs_0T.js +18 -0
  266. package/dist/widget/swapHorizontal-BzOPGV37.js +13 -0
  267. package/dist/widget/swapHorizontalBold-axyHnSmj.js +13 -0
  268. package/dist/widget/swapHorizontalMedium-C6YOPfPz.js +21 -0
  269. package/dist/widget/swapHorizontalRoundedBold-yVcLbWNT.js +13 -0
  270. package/dist/widget/swapVertical-BDjxt9pE.js +13 -0
  271. package/dist/widget/swaps-DEWNj4kd.js +1637 -0
  272. package/dist/widget/telegram-BQJD7dlP.js +21 -0
  273. package/dist/widget/three-dots-DW9jmSMG.js +10 -0
  274. package/dist/widget/transactions-uCseGQQt.js +38 -0
  275. package/dist/widget/twitch-XugxDfOE.js +23 -0
  276. package/dist/widget/twitterIcon-DQVObQUL.js +11 -0
  277. package/dist/widget/types.d.ts +51 -0
  278. package/dist/widget/types.d.ts.map +1 -0
  279. package/dist/widget/types.js +1 -0
  280. package/dist/widget/verify-DpMYHxLf.js +13 -0
  281. package/dist/widget/verify-filled-KpEL6ZJ_.js +13 -0
  282. package/dist/widget/w3m-modal-C8e-6Kba.js +1047 -0
  283. package/dist/widget/wallet-D8ssEB0o.js +13 -0
  284. package/dist/widget/wallet-placeholder-HtAy21Wc.js +19 -0
  285. package/dist/widget/walletconnect-Bp_4XfrY.js +37 -0
  286. package/dist/widget/warning-circle-FgYS7P7n.js +17 -0
  287. package/dist/widget/widget/index.js +7 -0
  288. package/dist/widget/widget.d.ts +47 -0
  289. package/dist/widget/widget.d.ts.map +1 -0
  290. package/dist/widget/widget.js +932 -0
  291. package/dist/widget/x-DlZBoP9k.js +17 -0
  292. package/dist/widget/x-mark-Ba9pt-_h.js +8 -0
  293. package/package.json +102 -8
  294. package/src/abi.ts +38 -0
  295. package/src/apiClient.ts +32 -0
  296. package/src/buffer.ts +10 -0
  297. package/src/cctp.ts +579 -0
  298. package/src/chainSwitch.ts +55 -0
  299. package/src/chains.ts +124 -0
  300. package/src/constants.ts +26 -0
  301. package/src/encoders.ts +20 -0
  302. package/src/error.ts +15 -0
  303. package/src/explorer.ts +37 -0
  304. package/src/gasless.ts +545 -0
  305. package/src/index.ts +48 -0
  306. package/src/indexerClient.ts +36 -0
  307. package/src/intents.ts +537 -0
  308. package/src/metaTxnMonitor.ts +163 -0
  309. package/src/metaTxns.ts +21 -0
  310. package/src/paymasterSend.ts +503 -0
  311. package/src/preconditions.ts +52 -0
  312. package/src/prepareSend.ts +1849 -0
  313. package/src/prices.ts +186 -0
  314. package/src/queryParams.ts +80 -0
  315. package/src/relaySdk.ts +481 -0
  316. package/src/relayer.ts +255 -0
  317. package/src/sendUserOp.ts +570 -0
  318. package/src/sequenceWallet.ts +579 -0
  319. package/src/theme.ts +2 -0
  320. package/src/toSimpleSmartAccount.ts +567 -0
  321. package/src/tokenBalances.ts +760 -0
  322. package/src/tokens.ts +471 -0
  323. package/src/trails.ts +1591 -0
  324. package/src/types.d.ts +11 -0
  325. package/src/umd.tsx +49 -0
  326. package/src/utils.ts +16 -0
  327. package/src/vite-env.d.ts +4 -0
  328. package/src/widget/assets/MetaMask-icon-fox-with-margins.svg +31 -0
  329. package/src/widget/assets/MetaMask-icon-fox.svg +26 -0
  330. package/src/widget/assets/MetaMask-logo-black.svg +3 -0
  331. package/src/widget/assets/MetaMask-logo-white.svg +16 -0
  332. package/src/widget/assets/Privy_Brandmark_Black.svg +9 -0
  333. package/src/widget/assets/Privy_Brandmark_White.svg +9 -0
  334. package/src/widget/assets/Trails-logo-black.svg +11 -0
  335. package/src/widget/assets/Trails-logo-white.svg +11 -0
  336. package/src/widget/components/ChainImage.tsx +28 -0
  337. package/src/widget/components/ConnectWallet.tsx +206 -0
  338. package/src/widget/components/DebugScreensDropdown.tsx +88 -0
  339. package/src/widget/components/FeeOptions.tsx +199 -0
  340. package/src/widget/components/Footer.tsx +51 -0
  341. package/src/widget/components/GreenCheckAnimation.tsx +119 -0
  342. package/src/widget/components/Modal.tsx +97 -0
  343. package/src/widget/components/Receipt.tsx +237 -0
  344. package/src/widget/components/SendForm.tsx +695 -0
  345. package/src/widget/components/TokenImage.tsx +37 -0
  346. package/src/widget/components/TokenList.tsx +287 -0
  347. package/src/widget/components/TransferPending.tsx +204 -0
  348. package/src/widget/components/TransferPendingVertical.tsx +412 -0
  349. package/src/widget/components/WalletConfirmation.tsx +172 -0
  350. package/src/widget/config.ts +5 -0
  351. package/src/widget/hooks/useAmountUsd.ts +59 -0
  352. package/src/widget/hooks/useSendForm.ts +715 -0
  353. package/src/widget/hooks/useTokenList.ts +397 -0
  354. package/src/widget/index.css +2 -0
  355. package/src/widget/index.tsx +8 -0
  356. package/src/widget/types/svg.d.ts +8 -0
  357. package/src/widget/types.ts +59 -0
  358. package/src/widget/widget.tsx +1438 -0
  359. package/index.js +0 -1
@@ -0,0 +1,1080 @@
1
+ import { useQuery } from "@tanstack/react-query";
2
+ import { createPublicClient, createWalletClient, decodeFunctionData, erc20Abi, formatUnits, http, parseUnits, zeroAddress, } from "viem";
3
+ import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
4
+ import { useAPIClient } from "./apiClient.js";
5
+ import { cctpTransfer, getIsUsdcAddress, getMessageTransmitter, getMintUSDCData, } from "./cctp.js";
6
+ import { attemptSwitchChain } from "./chainSwitch.js";
7
+ import { getChainInfo, getTestnetChainInfo } from "./chains.js";
8
+ import { intentEntrypoints, DEFAULT_USE_V3_RELAYERS } from "./constants.js";
9
+ import { getERC20TransferData } from "./encoders.js";
10
+ import { getExplorerUrl } from "./explorer.js";
11
+ import { getDepositToIntentCalls, getPermitCalls, getPermitSignature, } from "./gasless.js";
12
+ import { useIndexerGatewayClient } from "./indexerClient.js";
13
+ import { commitIntentConfig, getIntentCallsPayloads as getIntentCallsPayloadsFromIntents, sendOriginTransaction, } from "./intents.js";
14
+ import { getMetaTxStatus } from "./metaTxnMonitor.js";
15
+ import { relayerSendMetaTx } from "./metaTxns.js";
16
+ import { getDelegatorSmartAccount, getPaymasterGaslessTransaction, sendPaymasterGaslessTransaction, } from "./paymasterSend.js";
17
+ import { findFirstPreconditionForChainId } from "./preconditions.js";
18
+ import { useTokenPrice } from "./prices.js";
19
+ import { getQueryParam } from "./queryParams.js";
20
+ import { useRelayers } from "./relayer.js";
21
+ import { executeSimpleRelayTransaction, getRelaySDKQuote, getTxHashFromRelayResult, } from "./relaySdk.js";
22
+ import { getFeeOptions, sequenceSendTransaction, simpleCreateSequenceWallet, } from "./sequenceWallet.js";
23
+ import { useAccountTokenBalance } from "./tokenBalances.js";
24
+ import { useSupportedTokens } from "./tokens.js";
25
+ import { requestWithTimeout } from "./utils.js";
26
+ export function getIsToSameChain(originChainId, destinationChainId) {
27
+ return originChainId?.toString() === destinationChainId?.toString();
28
+ }
29
+ export function getIsToSameToken(originTokenAddress, destinationTokenAddress) {
30
+ return (originTokenAddress?.toLowerCase() === destinationTokenAddress?.toLowerCase());
31
+ }
32
+ export function getIsToSameChainAndToken(originChainId, originTokenAddress, destinationChainId, destinationTokenAddress) {
33
+ return (getIsToSameChain(originChainId, destinationChainId) &&
34
+ getIsToSameToken(originTokenAddress, destinationTokenAddress));
35
+ }
36
+ export function getUseCctp(originTokenAddress, destinationTokenAddress, originChainId, destinationChainId) {
37
+ return (getIsUsdcAddress(originTokenAddress, originChainId) &&
38
+ getIsUsdcAddress(destinationTokenAddress, destinationChainId));
39
+ }
40
+ function isTestnetDebugMode() {
41
+ return getQueryParam("testnet") === "true";
42
+ }
43
+ function getTestnetOriginTokenAddress() {
44
+ return "0x036CbD53842c5426634e7929541eC2318f3dCF7e";
45
+ }
46
+ function getIntentArgs(mainSignerAddress, originChainId, originTokenAddress, originTokenAmount, destinationChainId, destinationTokenAddress, destinationTokenAmount, destinationTokenSymbol, recipient, destinationCalldata) {
47
+ const _destinationCalldata = destinationCalldata ||
48
+ (destinationTokenAddress === zeroAddress
49
+ ? "0x"
50
+ : getERC20TransferData({
51
+ recipient,
52
+ amount: BigInt(destinationTokenAmount),
53
+ }));
54
+ const _destinationToAddress = destinationCalldata
55
+ ? recipient
56
+ : destinationTokenAddress === zeroAddress
57
+ ? recipient
58
+ : destinationTokenAddress;
59
+ const _destinationCallValue = destinationTokenAddress === zeroAddress ? destinationTokenAmount : "0";
60
+ const intentArgs = {
61
+ userAddress: mainSignerAddress,
62
+ originChainId,
63
+ originTokenAddress,
64
+ originTokenAmount: originTokenAddress === destinationTokenAddress
65
+ ? destinationTokenAmount
66
+ : originTokenAmount, // max amount
67
+ destinationChainId,
68
+ destinationToAddress: _destinationToAddress,
69
+ destinationTokenAddress: destinationTokenAddress,
70
+ destinationTokenAmount: destinationTokenAmount,
71
+ destinationTokenSymbol: destinationTokenSymbol,
72
+ destinationCallData: _destinationCalldata,
73
+ destinationCallValue: _destinationCallValue,
74
+ };
75
+ return intentArgs;
76
+ }
77
+ export async function prepareSend(options) {
78
+ const { account, originTokenAddress, originChainId, originTokenAmount, // account balance
79
+ destinationChainId, recipient, destinationTokenAddress, destinationTokenAmount, destinationTokenSymbol, fee, client: walletClient, dryMode = false, apiClient, originRelayer, destinationRelayer, destinationCalldata, onTransactionStateChange, sourceTokenPriceUsd, destinationTokenPriceUsd, sourceTokenDecimals, destinationTokenDecimals, paymasterUrl, gasless = false, relayerConfig, sequenceProjectAccessKey, } = options;
80
+ if (!walletClient) {
81
+ throw new Error("Wallet client not provided");
82
+ }
83
+ const chain = getChainInfo(originChainId);
84
+ if (!chain) {
85
+ throw new Error(`Chain ${originChainId} not found`);
86
+ }
87
+ const isToSameChain = getIsToSameChain(originChainId, destinationChainId);
88
+ const isToSameToken = getIsToSameToken(originTokenAddress, destinationTokenAddress);
89
+ console.log("[trails-sdk] isToSameChain", isToSameChain);
90
+ console.log("[trails-sdk] isToSameToken", isToSameToken);
91
+ const publicClient = createPublicClient({
92
+ chain,
93
+ transport: http(),
94
+ });
95
+ const mainSignerAddress = account.address;
96
+ const transactionStates = [];
97
+ // origin tx
98
+ transactionStates.push({
99
+ transactionHash: "",
100
+ explorerUrl: "",
101
+ chainId: originChainId,
102
+ state: "pending",
103
+ label: isToSameChain && isToSameToken
104
+ ? "Execute"
105
+ : isToSameChain && !isToSameToken
106
+ ? "Swap"
107
+ : "Transfer",
108
+ });
109
+ if (!isToSameChain) {
110
+ // swap + bridge tx
111
+ transactionStates.push({
112
+ transactionHash: "",
113
+ explorerUrl: "",
114
+ chainId: originChainId,
115
+ state: "pending",
116
+ label: isToSameToken ? "Bridge" : "Swap & Bridge",
117
+ });
118
+ // destination tx
119
+ transactionStates.push({
120
+ transactionHash: "",
121
+ explorerUrl: "",
122
+ chainId: destinationChainId,
123
+ state: "pending",
124
+ label: "Execute",
125
+ });
126
+ }
127
+ if (isToSameChain && !isToSameToken) {
128
+ return await sendHandlerForSameChainDifferentToken({
129
+ originTokenAddress,
130
+ destinationTokenAmount,
131
+ destinationTokenAddress,
132
+ destinationCalldata,
133
+ recipient,
134
+ originChainId,
135
+ walletClient,
136
+ publicClient,
137
+ account,
138
+ });
139
+ }
140
+ if (isToSameToken && isToSameChain) {
141
+ return await sendHandlerForSameChainSameToken({
142
+ originTokenAddress,
143
+ destinationTokenAmount,
144
+ destinationCalldata,
145
+ recipient,
146
+ originChainId,
147
+ walletClient,
148
+ publicClient,
149
+ onTransactionStateChange,
150
+ dryMode,
151
+ account,
152
+ chain,
153
+ });
154
+ }
155
+ return await sendHandlerForDifferentChainDifferentToken({
156
+ mainSignerAddress,
157
+ originChainId,
158
+ originTokenAddress,
159
+ originTokenAmount,
160
+ destinationChainId,
161
+ destinationTokenAddress,
162
+ destinationTokenAmount,
163
+ destinationTokenSymbol,
164
+ recipient,
165
+ destinationCalldata,
166
+ apiClient,
167
+ sourceTokenPriceUsd,
168
+ destinationTokenPriceUsd,
169
+ sourceTokenDecimals,
170
+ destinationTokenDecimals,
171
+ gasless,
172
+ paymasterUrl,
173
+ originRelayer,
174
+ destinationRelayer,
175
+ sequenceProjectAccessKey,
176
+ relayerConfig,
177
+ walletClient,
178
+ publicClient,
179
+ chain,
180
+ account,
181
+ fee,
182
+ dryMode,
183
+ onTransactionStateChange,
184
+ transactionStates,
185
+ });
186
+ }
187
+ async function sendHandlerForDifferentChainDifferentToken({ mainSignerAddress, originChainId, originTokenAddress, originTokenAmount, destinationChainId, destinationTokenAddress, destinationTokenAmount, destinationTokenSymbol, recipient, destinationCalldata, apiClient, sourceTokenPriceUsd, destinationTokenPriceUsd, sourceTokenDecimals, destinationTokenDecimals, gasless, paymasterUrl, originRelayer, destinationRelayer, sequenceProjectAccessKey, relayerConfig, walletClient, publicClient, chain, account, fee, dryMode, onTransactionStateChange, transactionStates, }) {
188
+ const testnet = isTestnetDebugMode();
189
+ const useCctp = getUseCctp(originTokenAddress, destinationTokenAddress, originChainId, destinationChainId);
190
+ if (useCctp && testnet) {
191
+ const amount = destinationTokenAmount;
192
+ return {
193
+ intentAddress: "",
194
+ originSendAmount: amount,
195
+ send: async (onOriginSend) => {
196
+ const originChain = testnet ? getTestnetChainInfo(chain) : chain;
197
+ const destinationChain = testnet
198
+ ? getTestnetChainInfo(destinationChainId)
199
+ : getChainInfo(destinationChainId);
200
+ if (!originChain || !destinationChain) {
201
+ throw new Error("Invalid chain");
202
+ }
203
+ console.log("[trails-sdk] originChain", originChain);
204
+ console.log("[trails-sdk] destinationChain", destinationChain);
205
+ const originPublicClient = createPublicClient({
206
+ chain: originChain,
207
+ transport: http(),
208
+ });
209
+ const { txHash, attestation } = await cctpTransfer({
210
+ walletClient,
211
+ originChain,
212
+ destinationChain,
213
+ amount: BigInt(destinationTokenAmount),
214
+ });
215
+ if (!attestation) {
216
+ throw new Error("Failed to retrieve attestation");
217
+ }
218
+ if (onOriginSend) {
219
+ onOriginSend();
220
+ }
221
+ console.log("[trails-sdk] waiting for tx", txHash);
222
+ const receipt = await originPublicClient.waitForTransactionReceipt({
223
+ hash: txHash,
224
+ });
225
+ console.log("[trails-sdk] tx receipt", receipt);
226
+ transactionStates[0] = getTransactionStateFromReceipt(receipt, originChain.id, "Transfer");
227
+ transactionStates[1] = getTransactionStateFromReceipt(receipt, originChain.id, "Bridge");
228
+ onTransactionStateChange(transactionStates);
229
+ const tokenMessenger = getMessageTransmitter(destinationChain.id);
230
+ console.log("[trails-sdk] tokenMessenger", tokenMessenger);
231
+ const calls = [
232
+ await getMintUSDCData({
233
+ tokenMessenger,
234
+ attestation,
235
+ }),
236
+ ];
237
+ console.log("[trails-sdk] calls", calls);
238
+ const delegatorPrivateKey = generatePrivateKey();
239
+ const delegatorAccount = privateKeyToAccount(delegatorPrivateKey);
240
+ const delegatorClient = createWalletClient({
241
+ account: delegatorAccount,
242
+ chain: destinationChain,
243
+ transport: http(),
244
+ });
245
+ const destinationPublicClient = createPublicClient({
246
+ chain: destinationChain,
247
+ transport: http(),
248
+ });
249
+ console.log("[trails-sdk] delegatorClient", delegatorClient);
250
+ const sequenceWalletAddress = await simpleCreateSequenceWallet(delegatorAccount, relayerConfig, sequenceProjectAccessKey);
251
+ console.log("[trails-sdk] sequenceWalletAddress", sequenceWalletAddress);
252
+ const sequenceTxHash = await sequenceSendTransaction(sequenceWalletAddress, delegatorClient, destinationPublicClient, calls, destinationChain, relayerConfig, sequenceProjectAccessKey);
253
+ const destinationReceipt = await destinationPublicClient.waitForTransactionReceipt({
254
+ hash: sequenceTxHash,
255
+ });
256
+ console.log("[trails-sdk] destinationReceipt", destinationReceipt);
257
+ transactionStates[2] = getTransactionStateFromReceipt(destinationReceipt, destinationChain.id, "Receive");
258
+ onTransactionStateChange(transactionStates);
259
+ return {
260
+ originUserTxReceipt: receipt,
261
+ originMetaTxnReceipt: null,
262
+ destinationMetaTxnReceipt: null,
263
+ };
264
+ },
265
+ };
266
+ }
267
+ const intentArgs = getIntentArgs(mainSignerAddress, originChainId, originTokenAddress, originTokenAmount, destinationChainId, destinationTokenAddress, destinationTokenAmount, destinationTokenSymbol, recipient, destinationCalldata);
268
+ console.log("[trails-sdk] Creating intent with args:", intentArgs);
269
+ const intent = await getIntentCallsPayloadsFromIntents(apiClient, intentArgs);
270
+ console.log("[trails-sdk] Got intent:", intent);
271
+ if (!intent) {
272
+ throw new Error("Invalid intent");
273
+ }
274
+ if (!intent.preconditions?.length || !intent.calls?.length) {
275
+ throw new Error("Invalid intent");
276
+ }
277
+ const intentAddress = intent.originIntentAddress;
278
+ console.log("[trails-sdk] intent address:", intentAddress.toString());
279
+ await commitIntentConfig(apiClient, mainSignerAddress, intent.calls, intent.preconditions);
280
+ console.log("[trails-sdk] Committed intent config");
281
+ const firstPrecondition = findFirstPreconditionForChainId(intent.preconditions, originChainId);
282
+ if (!firstPrecondition) {
283
+ throw new Error("No precondition found for origin chain");
284
+ }
285
+ const firstPreconditionMin = firstPrecondition?.data?.min?.toString();
286
+ const depositAmount = firstPreconditionMin;
287
+ const hasEnoughBalance = await checkAccountBalance({
288
+ account,
289
+ tokenAddress: originTokenAddress,
290
+ depositAmount,
291
+ publicClient,
292
+ });
293
+ if (!hasEnoughBalance) {
294
+ throw new Error("Account does not have enough balance for deposit");
295
+ }
296
+ return {
297
+ intentAddress,
298
+ originSendAmount: depositAmount,
299
+ send: async (onOriginSend) => {
300
+ console.log("[trails-sdk] sending origin transaction");
301
+ const needsNativeFee = getNeedsLifiNativeFee({
302
+ originTokenAddress,
303
+ destinationTokenAmount,
304
+ destinationTokenDecimals,
305
+ sourceTokenDecimals,
306
+ sourceTokenPriceUsd: sourceTokenPriceUsd ?? null,
307
+ destinationTokenPriceUsd: destinationTokenPriceUsd ?? null,
308
+ depositAmount,
309
+ });
310
+ console.log("[trails-sdk] needsNativeFee", needsNativeFee);
311
+ console.log("[trails-sdk] sourceTokenPriceUsd", sourceTokenPriceUsd);
312
+ console.log("[trails-sdk] destinationTokenPriceUsd", destinationTokenPriceUsd);
313
+ console.log("[trails-sdk] sourceTokenDecimals", sourceTokenDecimals);
314
+ console.log("[trails-sdk] destinationTokenDecimals", destinationTokenDecimals);
315
+ // const originCallParams = {
316
+ // to:
317
+ // originTokenAddress === zeroAddress
318
+ // ? firstPreconditionAddress
319
+ // : originTokenAddress,
320
+ // data:
321
+ // originTokenAddress === zeroAddress
322
+ // ? "0x"
323
+ // : getERC20TransferData({
324
+ // recipient: firstPreconditionAddress,
325
+ // amount: BigInt(firstPreconditionMin) + BigInt(fee),
326
+ // }),
327
+ // value:
328
+ // originTokenAddress === zeroAddress
329
+ // ? BigInt(firstPreconditionMin) + BigInt(fee)
330
+ // : "0",
331
+ // chainId: originChainId,
332
+ // chain,
333
+ // }
334
+ let originUserTxReceipt = null;
335
+ let originMetaTxnReceipt = null;
336
+ let destinationMetaTxnReceipt = null;
337
+ const testnet = isTestnetDebugMode();
338
+ const testnetOriginTokenAddress = getTestnetOriginTokenAddress();
339
+ const chainToUse = testnet ? getTestnetChainInfo(chain) : chain;
340
+ console.log("[trails-sdk] testnet", testnet);
341
+ originUserTxReceipt = await attemptUserDepositTx({
342
+ originTokenAddress: testnet
343
+ ? testnetOriginTokenAddress
344
+ : originTokenAddress,
345
+ gasless,
346
+ paymasterUrl,
347
+ chain: chainToUse,
348
+ account,
349
+ relayerConfig,
350
+ sequenceProjectAccessKey,
351
+ originRelayer,
352
+ firstPreconditionMin,
353
+ intentAddress,
354
+ onOriginSend,
355
+ publicClient,
356
+ walletClient,
357
+ destinationTokenDecimals,
358
+ sourceTokenDecimals,
359
+ fee,
360
+ dryMode,
361
+ sourceTokenPriceUsd: sourceTokenPriceUsd ?? null,
362
+ destinationTokenPriceUsd: destinationTokenPriceUsd ?? null,
363
+ destinationTokenAmount,
364
+ });
365
+ if (!originUserTxReceipt) {
366
+ throw new Error("Failed to send origin transaction");
367
+ }
368
+ transactionStates[0] = getTransactionStateFromReceipt(originUserTxReceipt, originChainId, "Transfer");
369
+ onTransactionStateChange(transactionStates);
370
+ if (intent.metaTxns[0] && intent.preconditions[0]) {
371
+ originMetaTxnReceipt = await sendMetaTxAndWaitForReceipt({
372
+ metaTx: intent.metaTxns[0],
373
+ relayer: originRelayer,
374
+ precondition: intent.preconditions[0],
375
+ });
376
+ if (originMetaTxnReceipt) {
377
+ transactionStates[1] = getTransactionStateFromReceipt(originMetaTxnReceipt, originChainId, "Swap & Bridge");
378
+ onTransactionStateChange(transactionStates);
379
+ }
380
+ }
381
+ if (intent.metaTxns[1] && intent.preconditions[1]) {
382
+ destinationMetaTxnReceipt = await sendMetaTxAndWaitForReceipt({
383
+ metaTx: intent.metaTxns[1],
384
+ relayer: destinationRelayer,
385
+ precondition: intent.preconditions[1],
386
+ });
387
+ if (destinationMetaTxnReceipt) {
388
+ transactionStates[2] = getTransactionStateFromReceipt(destinationMetaTxnReceipt, destinationChainId, "Execute");
389
+ onTransactionStateChange(transactionStates);
390
+ }
391
+ }
392
+ return {
393
+ originUserTxReceipt,
394
+ originMetaTxnReceipt,
395
+ destinationMetaTxnReceipt,
396
+ };
397
+ },
398
+ };
399
+ }
400
+ async function sendHandlerForSameChainSameToken({ originTokenAddress, destinationTokenAmount, destinationCalldata, recipient, originChainId, walletClient, publicClient, onTransactionStateChange, dryMode, account, chain, }) {
401
+ console.log("[trails-sdk] isToSameToken && isToSameChain");
402
+ const hasEnoughBalance = await checkAccountBalance({
403
+ account,
404
+ tokenAddress: originTokenAddress,
405
+ depositAmount: destinationTokenAmount,
406
+ publicClient,
407
+ });
408
+ if (!hasEnoughBalance) {
409
+ throw new Error("Account does not have enough balance for deposit");
410
+ }
411
+ return {
412
+ originSendAmount: destinationTokenAmount,
413
+ send: async (onOriginSend) => {
414
+ const originCallParams = {
415
+ to: destinationCalldata
416
+ ? recipient
417
+ : originTokenAddress === zeroAddress
418
+ ? recipient
419
+ : originTokenAddress,
420
+ data: destinationCalldata ||
421
+ (originTokenAddress === zeroAddress
422
+ ? "0x"
423
+ : getERC20TransferData({
424
+ recipient,
425
+ amount: BigInt(destinationTokenAmount),
426
+ })),
427
+ value: originTokenAddress === zeroAddress
428
+ ? BigInt(destinationTokenAmount)
429
+ : "0",
430
+ chainId: originChainId,
431
+ chain,
432
+ };
433
+ console.log("[trails-sdk] origin call params", originCallParams);
434
+ let originUserTxReceipt = null;
435
+ const originMetaTxnReceipt = null;
436
+ const destinationMetaTxnReceipt = null;
437
+ await attemptSwitchChain({
438
+ walletClient,
439
+ desiredChainId: originChainId,
440
+ });
441
+ if (!dryMode) {
442
+ onTransactionStateChange([
443
+ {
444
+ transactionHash: "",
445
+ explorerUrl: "",
446
+ chainId: originChainId,
447
+ state: "pending",
448
+ label: "Execute",
449
+ },
450
+ ]);
451
+ console.log("[trails-sdk] origin call params", originCallParams);
452
+ const txHash = await sendOriginTransaction(account, walletClient, originCallParams); // TODO: Add proper type
453
+ console.log("[trails-sdk] origin tx", txHash);
454
+ if (onOriginSend) {
455
+ onOriginSend();
456
+ }
457
+ // Wait for transaction receipt
458
+ const receipt = await publicClient.waitForTransactionReceipt({
459
+ hash: txHash,
460
+ });
461
+ console.log("[trails-sdk] receipt", receipt);
462
+ originUserTxReceipt = receipt;
463
+ onTransactionStateChange([
464
+ getTransactionStateFromReceipt(originUserTxReceipt, originChainId, "Swap"),
465
+ ]);
466
+ }
467
+ return {
468
+ originUserTxReceipt,
469
+ originMetaTxnReceipt,
470
+ destinationMetaTxnReceipt,
471
+ };
472
+ },
473
+ };
474
+ }
475
+ async function sendHandlerForSameChainDifferentToken({ originTokenAddress, destinationTokenAmount, destinationTokenAddress, destinationCalldata, recipient, originChainId, walletClient, publicClient, account, }) {
476
+ const destinationTxs = [];
477
+ if (destinationCalldata) {
478
+ destinationTxs.push({
479
+ to: recipient,
480
+ value: destinationTokenAddress === zeroAddress ? destinationTokenAmount : "0",
481
+ data: destinationCalldata,
482
+ });
483
+ }
484
+ const quote = await getRelaySDKQuote({
485
+ wallet: walletClient,
486
+ chainId: originChainId,
487
+ amount: destinationTokenAmount,
488
+ currency: originTokenAddress,
489
+ toCurrency: destinationTokenAddress,
490
+ txs: destinationTxs,
491
+ });
492
+ console.log("[trails-sdk] relaysdk quote", quote);
493
+ let depositAmount = "0";
494
+ try {
495
+ depositAmount = quote.steps?.[0]?.items?.[0]?.data?.value;
496
+ if (originTokenAddress !== zeroAddress) {
497
+ const decoded = decodeFunctionData({
498
+ abi: erc20Abi,
499
+ data: quote.steps?.[0]?.items?.[0]?.data?.data,
500
+ });
501
+ if (decoded.functionName === "approve") {
502
+ depositAmount = decoded.args[1].toString();
503
+ }
504
+ if (decoded.functionName === "transfer") {
505
+ depositAmount = decoded.args[1].toString();
506
+ }
507
+ }
508
+ }
509
+ catch (error) {
510
+ console.error("[trails-sdk] Error decoding function data:", error);
511
+ }
512
+ const hasEnoughBalance = await checkAccountBalance({
513
+ account,
514
+ tokenAddress: originTokenAddress,
515
+ depositAmount,
516
+ publicClient,
517
+ });
518
+ if (!hasEnoughBalance) {
519
+ throw new Error("Account does not have enough balance for deposit");
520
+ }
521
+ return {
522
+ originSendAmount: depositAmount,
523
+ send: async (onOriginSend) => {
524
+ await attemptSwitchChain({
525
+ walletClient,
526
+ desiredChainId: originChainId,
527
+ });
528
+ const result = await executeSimpleRelayTransaction(quote, walletClient);
529
+ console.log("[trails-sdk] relaysdk result", result);
530
+ const txHash = getTxHashFromRelayResult(result);
531
+ if (onOriginSend) {
532
+ onOriginSend();
533
+ }
534
+ const originUserTxReceipt = await publicClient.waitForTransactionReceipt({
535
+ hash: txHash,
536
+ });
537
+ return {
538
+ originUserTxReceipt: originUserTxReceipt,
539
+ originMetaTxnReceipt: null,
540
+ destinationMetaTxnReceipt: null,
541
+ };
542
+ },
543
+ };
544
+ }
545
+ async function attemptGaslessDeposit({ paymasterUrl, depositTokenAddress, depositTokenAmount, depositRecipient, onOriginSend, walletClient, chain, account, relayerConfig, sequenceProjectAccessKey, originRelayer, }) {
546
+ let originUserTxReceipt = null;
547
+ const originChainId = chain.id;
548
+ console.log("[trails-sdk] originChainId", originChainId);
549
+ const publicClient = createPublicClient({
550
+ chain,
551
+ transport: http(),
552
+ });
553
+ const intentEntrypoint = intentEntrypoints[chain.id];
554
+ console.log("[trails-sdk] intentEntrypoint", intentEntrypoint);
555
+ let calls = [];
556
+ if (paymasterUrl) {
557
+ console.log("[trails-sdk] doing gasless with paymaster");
558
+ const delegatorSmartAccount = await getDelegatorSmartAccount({
559
+ publicClient,
560
+ });
561
+ if (intentEntrypoint) {
562
+ calls = await getDepositToIntentCalls({
563
+ publicClient,
564
+ walletClient,
565
+ account,
566
+ intentEntrypoint,
567
+ depositTokenAddress: depositTokenAddress,
568
+ depositTokenAmount: BigInt(depositTokenAmount),
569
+ depositRecipient: depositRecipient,
570
+ chain,
571
+ });
572
+ }
573
+ else {
574
+ calls = await getPaymasterGaslessTransaction({
575
+ walletClient,
576
+ chain,
577
+ tokenAddress: depositTokenAddress,
578
+ amount: BigInt(depositTokenAmount),
579
+ recipient: depositRecipient,
580
+ delegatorSmartAccount,
581
+ });
582
+ }
583
+ console.log("[trails-sdk] calls", calls);
584
+ const txHash = await sendPaymasterGaslessTransaction({
585
+ walletClient,
586
+ publicClient,
587
+ chain,
588
+ paymasterUrl,
589
+ delegatorSmartAccount,
590
+ calls,
591
+ });
592
+ if (onOriginSend) {
593
+ onOriginSend();
594
+ }
595
+ const receipt = await publicClient.waitForTransactionReceipt({
596
+ hash: txHash,
597
+ });
598
+ console.log("[trails-sdk] receipt", receipt);
599
+ originUserTxReceipt = receipt;
600
+ }
601
+ else {
602
+ console.log("[trails-sdk] doing gasless with sequence wallet");
603
+ const delegatorPrivateKey = generatePrivateKey();
604
+ const delegatorAccount = privateKeyToAccount(delegatorPrivateKey);
605
+ const delegatorClient = createWalletClient({
606
+ account: delegatorAccount,
607
+ chain,
608
+ transport: http(),
609
+ });
610
+ console.log("[trails-sdk] attempting to switch chain");
611
+ await attemptSwitchChain({
612
+ walletClient,
613
+ desiredChainId: originChainId,
614
+ });
615
+ console.log("[trails-sdk] creating sequence wallet");
616
+ const sequenceWalletAddress = await simpleCreateSequenceWallet(delegatorAccount, relayerConfig, sequenceProjectAccessKey);
617
+ console.log("[trails-sdk] sequenceWalletAddress", sequenceWalletAddress);
618
+ if (intentEntrypoint) {
619
+ calls = await getDepositToIntentCalls({
620
+ publicClient,
621
+ walletClient,
622
+ account,
623
+ intentEntrypoint,
624
+ depositTokenAddress: depositTokenAddress,
625
+ depositTokenAmount: BigInt(depositTokenAmount),
626
+ depositRecipient: depositRecipient,
627
+ chain,
628
+ });
629
+ }
630
+ else {
631
+ const { signature, deadline } = await getPermitSignature({
632
+ publicClient,
633
+ walletClient,
634
+ signer: account.address,
635
+ spender: sequenceWalletAddress,
636
+ tokenAddress: depositTokenAddress,
637
+ amount: BigInt(depositTokenAmount),
638
+ chain,
639
+ });
640
+ calls = getPermitCalls(account.address, sequenceWalletAddress, BigInt(depositTokenAmount), deadline, signature, depositRecipient, depositTokenAddress);
641
+ }
642
+ console.log("[trails-sdk] calls", calls);
643
+ const feeOptions = await getFeeOptions(originRelayer, sequenceWalletAddress, originChainId, calls.map((call) => ({
644
+ to: call.to,
645
+ value: BigInt(call.value),
646
+ data: call.data,
647
+ gasLimit: BigInt(0),
648
+ delegateCall: false,
649
+ onlyFallback: false,
650
+ behaviorOnError: "revert",
651
+ })));
652
+ console.log("[trails-sdk] feeOptions", feeOptions);
653
+ const sequenceTxHash = await sequenceSendTransaction(sequenceWalletAddress, delegatorClient, publicClient, calls, chain, relayerConfig, sequenceProjectAccessKey);
654
+ console.log("[trails-sdk] sequenceTxHash", sequenceTxHash);
655
+ if (onOriginSend) {
656
+ onOriginSend();
657
+ }
658
+ const receipt = await publicClient.waitForTransactionReceipt({
659
+ hash: sequenceTxHash,
660
+ });
661
+ console.log("[trails-sdk] receipt", receipt);
662
+ originUserTxReceipt = receipt;
663
+ }
664
+ return originUserTxReceipt;
665
+ }
666
+ export async function attemptNonGaslessUserDeposit({ originTokenAddress, firstPreconditionMin, onOriginSend, publicClient, walletClient, originChainId, chain, account, fee, dryMode, sourceTokenPriceUsd, destinationTokenPriceUsd, destinationTokenAmount, destinationTokenDecimals, sourceTokenDecimals, intentAddress, }) {
667
+ let originUserTxReceipt = null;
668
+ const needsNativeFee = await getNeedsLifiNativeFee({
669
+ originTokenAddress,
670
+ destinationTokenAmount,
671
+ destinationTokenDecimals,
672
+ sourceTokenDecimals,
673
+ sourceTokenPriceUsd: sourceTokenPriceUsd ?? null,
674
+ destinationTokenPriceUsd: destinationTokenPriceUsd ?? null,
675
+ depositAmount: firstPreconditionMin,
676
+ });
677
+ let nativeFee = parseUnits("0.00005", 18).toString();
678
+ if (originChainId === 137) {
679
+ nativeFee = parseUnits("1.5", 18).toString();
680
+ }
681
+ console.log("[trails-sdk] needsNativeFee", needsNativeFee);
682
+ const originCallParams = {
683
+ to: originTokenAddress === zeroAddress ? intentAddress : originTokenAddress,
684
+ data: originTokenAddress === zeroAddress
685
+ ? "0x"
686
+ : getERC20TransferData({
687
+ recipient: intentAddress,
688
+ amount: BigInt(firstPreconditionMin) + BigInt(fee),
689
+ }),
690
+ value: originTokenAddress === zeroAddress
691
+ ? BigInt(firstPreconditionMin) + BigInt(fee)
692
+ : "0",
693
+ chainId: originChainId,
694
+ chain,
695
+ };
696
+ await attemptSwitchChain({
697
+ walletClient,
698
+ desiredChainId: originChainId,
699
+ });
700
+ let useSendCalls = false;
701
+ const moreThan1Tx = needsNativeFee;
702
+ if (moreThan1Tx) {
703
+ try {
704
+ // the reason for the timeout is some users experience this call to hang indefinitely on metamask on all chains.
705
+ // not sure why this is happening, but it happens.
706
+ const capabilities = await requestWithTimeout(walletClient, [
707
+ {
708
+ method: "wallet_getCapabilities",
709
+ params: [account.address],
710
+ },
711
+ ], 10000);
712
+ console.log("[trails-sdk] capabilities", capabilities);
713
+ // Check if the chain supports atomic transactions
714
+ const chainHex = `0x${originChainId.toString(16)}`;
715
+ const chainCapabilities = capabilities[chainHex];
716
+ useSendCalls = chainCapabilities?.atomic?.status === "supported";
717
+ }
718
+ catch (error) {
719
+ console.error("[trails-sdk] Error getting capabilities", error);
720
+ }
721
+ }
722
+ if (dryMode) {
723
+ console.log("[trails-sdk] dry mode, skipping send calls");
724
+ }
725
+ if (useSendCalls) {
726
+ console.log("[trails-sdk] using sendCalls");
727
+ }
728
+ else {
729
+ console.log("[trails-sdk] using sendTransaction");
730
+ }
731
+ if (useSendCalls) {
732
+ if (!dryMode) {
733
+ const calls = [];
734
+ if (needsNativeFee) {
735
+ calls.push({
736
+ to: intentAddress,
737
+ data: "0x00",
738
+ value: `0x${BigInt(nativeFee).toString(16)}`,
739
+ });
740
+ }
741
+ // Add the origin call
742
+ calls.push({
743
+ to: originCallParams.to,
744
+ data: originCallParams.data,
745
+ value: originCallParams.value
746
+ ? `0x${BigInt(originCallParams.value).toString(16)}`
747
+ : "0x0",
748
+ });
749
+ // Send the batched call via EIP-7702
750
+ const result = (await walletClient.request({
751
+ method: "wallet_sendCalls",
752
+ params: [
753
+ {
754
+ version: "2.0.0",
755
+ chainId: `0x${originChainId.toString(16)}`,
756
+ atomicRequired: true,
757
+ calls,
758
+ },
759
+ ],
760
+ }));
761
+ console.log("[trails-sdk] sendCalls result", result);
762
+ const requestId = result.requestId || result.id;
763
+ // Poll to check if the tx has been submitted
764
+ let txHash;
765
+ while (!txHash) {
766
+ const status = (await walletClient.request({
767
+ method: "wallet_getCallsStatus",
768
+ params: [requestId],
769
+ }));
770
+ console.log("[trails-sdk] getCallsStatus result", status);
771
+ const receipt = status?.receipts?.[0];
772
+ if (status.status === 200 && receipt?.transactionHash) {
773
+ txHash = receipt.transactionHash;
774
+ break;
775
+ }
776
+ else if (status.status === 500) {
777
+ throw new Error(`Transaction failed: ${status.error}`);
778
+ }
779
+ // wait a bit before polling again
780
+ await new Promise((r) => setTimeout(r, 2000));
781
+ }
782
+ if (onOriginSend) {
783
+ onOriginSend();
784
+ }
785
+ const receipt = await publicClient.waitForTransactionReceipt({
786
+ hash: txHash,
787
+ });
788
+ console.log("[trails-sdk] receipt", receipt);
789
+ originUserTxReceipt = receipt;
790
+ }
791
+ }
792
+ else {
793
+ if (!dryMode) {
794
+ if (needsNativeFee) {
795
+ const tx0 = await sendOriginTransaction(account, walletClient, {
796
+ to: intentAddress,
797
+ data: "0x00",
798
+ value: nativeFee,
799
+ chainId: originChainId,
800
+ chain,
801
+ }); // TODO: Add proper type
802
+ console.log("[trails-sdk] origin tx", tx0);
803
+ // Wait for transaction receipt
804
+ const feeReceipt = await publicClient.waitForTransactionReceipt({
805
+ hash: tx0,
806
+ });
807
+ console.log("[trails-sdk] nativeFeeReceipt", feeReceipt);
808
+ }
809
+ const tx = await sendOriginTransaction(account, walletClient, originCallParams); // TODO: Add proper type
810
+ console.log("[trails-sdk] origin tx", tx);
811
+ if (onOriginSend) {
812
+ onOriginSend();
813
+ }
814
+ // Wait for transaction receipt
815
+ const receipt = await publicClient.waitForTransactionReceipt({
816
+ hash: tx,
817
+ });
818
+ console.log("[trails-sdk] receipt", receipt);
819
+ originUserTxReceipt = receipt;
820
+ }
821
+ }
822
+ return originUserTxReceipt;
823
+ }
824
+ async function attemptUserDepositTx({ originTokenAddress, gasless, paymasterUrl, chain, account, relayerConfig, sequenceProjectAccessKey, originRelayer, firstPreconditionMin, intentAddress, onOriginSend, publicClient, walletClient, destinationTokenDecimals, sourceTokenDecimals, fee, dryMode, sourceTokenPriceUsd, destinationTokenPriceUsd, destinationTokenAmount, }) {
825
+ let originUserTxReceipt = null;
826
+ const originChainId = chain.id;
827
+ const doGasless = getDoGasless(originTokenAddress, gasless, paymasterUrl);
828
+ console.log("[trails-sdk] doGasless", doGasless, paymasterUrl);
829
+ if (doGasless) {
830
+ try {
831
+ originUserTxReceipt = await attemptGaslessDeposit({
832
+ paymasterUrl,
833
+ depositTokenAddress: originTokenAddress,
834
+ depositTokenAmount: firstPreconditionMin,
835
+ depositRecipient: intentAddress,
836
+ onOriginSend,
837
+ walletClient,
838
+ chain,
839
+ account,
840
+ relayerConfig,
841
+ sequenceProjectAccessKey,
842
+ originRelayer,
843
+ });
844
+ }
845
+ catch (error) {
846
+ console.log("[trails-sdk] gassless attempt failed", error);
847
+ }
848
+ }
849
+ // If gasless attempt failed, try to send a regular transaction
850
+ if (!originUserTxReceipt) {
851
+ originUserTxReceipt = await attemptNonGaslessUserDeposit({
852
+ originTokenAddress,
853
+ firstPreconditionMin,
854
+ intentAddress,
855
+ onOriginSend,
856
+ publicClient,
857
+ walletClient,
858
+ originChainId,
859
+ chain,
860
+ account,
861
+ fee,
862
+ dryMode,
863
+ sourceTokenPriceUsd,
864
+ destinationTokenPriceUsd,
865
+ destinationTokenAmount,
866
+ destinationTokenDecimals,
867
+ sourceTokenDecimals,
868
+ });
869
+ }
870
+ return originUserTxReceipt;
871
+ }
872
+ export function getDoGasless(originTokenAddress, gasless, paymasterUrl) {
873
+ return Boolean(originTokenAddress !== zeroAddress && (gasless || paymasterUrl));
874
+ }
875
+ function getTransactionStateFromReceipt(receipt, chainId, label) {
876
+ let txHash = "";
877
+ let state = "pending";
878
+ if ("transactionHash" in receipt) {
879
+ txHash = receipt.transactionHash;
880
+ state = receipt.status === "success" ? "confirmed" : "failed";
881
+ }
882
+ else if ("txnHash" in receipt) {
883
+ txHash = receipt.txnHash;
884
+ state = receipt.status === "SUCCEEDED" ? "confirmed" : "failed";
885
+ }
886
+ return {
887
+ transactionHash: txHash,
888
+ explorerUrl: getExplorerUrl({ txHash, chainId }),
889
+ chainId,
890
+ state,
891
+ label,
892
+ };
893
+ }
894
+ async function sendMetaTxAndWaitForReceipt({ metaTx, relayer, precondition, }) {
895
+ let originMetaTxnReceipt = null;
896
+ console.log("[trails-sdk] metaTx", metaTx);
897
+ const opHash = await relayerSendMetaTx(relayer, metaTx, [precondition]);
898
+ console.log("[trails-sdk] opHash", opHash);
899
+ // eslint-disable-next-line no-constant-condition
900
+ while (true) {
901
+ console.log("[trails-sdk] polling status", metaTx.id, BigInt(metaTx.chainId));
902
+ const receipt = await getMetaTxStatus(relayer, metaTx.id, Number(metaTx.chainId));
903
+ console.log("[trails-sdk] status", receipt);
904
+ if (receipt?.transactionHash) {
905
+ originMetaTxnReceipt = receipt.data?.receipt;
906
+ break;
907
+ }
908
+ await new Promise((resolve) => setTimeout(resolve, 1000));
909
+ }
910
+ return originMetaTxnReceipt;
911
+ }
912
+ /**
913
+ * Check if the account has enough balance for the deposit amount
914
+ */
915
+ async function checkAccountBalance({ account, tokenAddress, depositAmount, publicClient, }) {
916
+ try {
917
+ let balance;
918
+ if (tokenAddress === zeroAddress) {
919
+ // Native token balance
920
+ balance = await publicClient.getBalance({ address: account.address });
921
+ }
922
+ else {
923
+ // ERC20 token balance
924
+ balance = await publicClient.readContract({
925
+ address: tokenAddress,
926
+ abi: erc20Abi,
927
+ functionName: "balanceOf",
928
+ args: [account.address],
929
+ });
930
+ }
931
+ const requiredAmount = BigInt(depositAmount);
932
+ console.log("[trails-sdk] balance", balance);
933
+ console.log("[trails-sdk] requiredAmount", requiredAmount);
934
+ return balance >= requiredAmount;
935
+ }
936
+ catch (error) {
937
+ console.error("[trails-sdk] Error checking account balance:", error);
938
+ return false;
939
+ }
940
+ }
941
+ // ETH fee required by some bridges for low token amounts
942
+ // TODO: update backend API to return the native fee requirement, if any
943
+ function getNeedsLifiNativeFee({ originTokenAddress, destinationTokenAmount, destinationTokenDecimals, sourceTokenDecimals, sourceTokenPriceUsd, destinationTokenPriceUsd, depositAmount, }) {
944
+ let needsNativeFee = false;
945
+ if (originTokenAddress !== zeroAddress &&
946
+ sourceTokenPriceUsd &&
947
+ destinationTokenPriceUsd &&
948
+ depositAmount &&
949
+ destinationTokenDecimals !== undefined &&
950
+ sourceTokenDecimals !== undefined) {
951
+ // Convert from wei to token units using formatUnits
952
+ const destinationAmount = Number(formatUnits(BigInt(destinationTokenAmount), destinationTokenDecimals));
953
+ const depositAmountFormatted = Number(formatUnits(BigInt(depositAmount), destinationTokenDecimals));
954
+ console.log("[trails-sdk] destinationAmount", destinationAmount);
955
+ console.log("[trails-sdk] depositAmountFormatted", depositAmountFormatted);
956
+ const destinationAmountUsd = destinationAmount * destinationTokenPriceUsd;
957
+ const depositAmountUsd = depositAmountFormatted * sourceTokenPriceUsd;
958
+ const diff = depositAmountUsd - destinationAmountUsd;
959
+ console.log("[trails-sdk] destinationAmountUsd", destinationAmountUsd, "[trails-sdk] depositAmountUsd", depositAmountUsd, "[trails-sdk] diff", diff);
960
+ if (diff >= 0 && diff <= 0.02) {
961
+ needsNativeFee = true;
962
+ }
963
+ }
964
+ return needsNativeFee;
965
+ }
966
+ export function useQuote({ walletClient, fromTokenAddress, fromChainId, toTokenAddress, toChainId, toAmount, toRecipient, } = {}) {
967
+ const apiClient = useAPIClient();
968
+ const { getRelayer } = useRelayers({
969
+ env: "dev",
970
+ useV3Relayers: DEFAULT_USE_V3_RELAYERS,
971
+ });
972
+ const indexerGatewayClient = useIndexerGatewayClient();
973
+ const { supportedTokens } = useSupportedTokens();
974
+ const { tokenBalance: originTokenBalance } = useAccountTokenBalance({
975
+ account: walletClient?.account?.address,
976
+ token: fromTokenAddress,
977
+ chainId: fromChainId,
978
+ indexerGatewayClient,
979
+ apiClient,
980
+ });
981
+ const destToken = toTokenAddress && toChainId
982
+ ? {
983
+ tokenId: toTokenAddress,
984
+ chainId: toChainId,
985
+ contractAddress: toTokenAddress,
986
+ }
987
+ : null;
988
+ const { tokenPrice: destinationTokenPrice } = useTokenPrice(destToken, apiClient);
989
+ const { data, isLoading, error } = useQuery({
990
+ queryKey: [
991
+ "quote",
992
+ fromTokenAddress,
993
+ fromChainId,
994
+ toTokenAddress,
995
+ toChainId,
996
+ toAmount?.toString(),
997
+ toRecipient,
998
+ ],
999
+ queryFn: async () => {
1000
+ if (!walletClient ||
1001
+ !apiClient ||
1002
+ !fromTokenAddress ||
1003
+ !toTokenAddress ||
1004
+ !toAmount ||
1005
+ !toRecipient ||
1006
+ !fromChainId ||
1007
+ !toChainId) {
1008
+ return null;
1009
+ }
1010
+ const originTokenAmount = originTokenBalance?.balance ?? "0";
1011
+ const sequenceProjectAccessKey = "";
1012
+ const destinationRelayer = getRelayer(toChainId);
1013
+ const originRelayer = getRelayer(fromChainId);
1014
+ console.log("originRelayer", originRelayer);
1015
+ console.log("destinationRelayer", destinationRelayer);
1016
+ const sourceTokenPriceUsd = originTokenBalance?.price?.value ?? 0;
1017
+ const destinationTokenPriceUsd = destinationTokenPrice?.price?.value ?? 0;
1018
+ const originToken = supportedTokens?.find((token) => token.contractAddress === fromTokenAddress &&
1019
+ token.chainId === fromChainId);
1020
+ const destinationToken = supportedTokens?.find((token) => token.contractAddress === toTokenAddress &&
1021
+ token.chainId === toChainId);
1022
+ const sourceTokenDecimals = originToken?.decimals ?? 18;
1023
+ const destinationTokenDecimals = destinationToken?.decimals ?? 18;
1024
+ const destinationTokenSymbol = destinationToken?.symbol ?? "";
1025
+ const options = {
1026
+ account: walletClient.account,
1027
+ originTokenAddress: fromTokenAddress,
1028
+ originChainId: fromChainId,
1029
+ originTokenAmount: originTokenAmount,
1030
+ destinationChainId: toChainId,
1031
+ recipient: toRecipient,
1032
+ destinationTokenAddress: toTokenAddress,
1033
+ destinationTokenAmount: toAmount.toString(),
1034
+ destinationTokenSymbol: destinationTokenSymbol,
1035
+ sequenceProjectAccessKey,
1036
+ client: walletClient,
1037
+ apiClient,
1038
+ originRelayer,
1039
+ destinationRelayer,
1040
+ sourceTokenPriceUsd,
1041
+ destinationTokenPriceUsd,
1042
+ sourceTokenDecimals,
1043
+ destinationTokenDecimals,
1044
+ fee: "0",
1045
+ dryMode: false,
1046
+ onTransactionStateChange: () => { },
1047
+ relayerConfig: {},
1048
+ };
1049
+ console.log("[trails-sdk] options", options);
1050
+ const { intentAddress, originSendAmount, send } = await prepareSend(options);
1051
+ console.log("[trails-sdk] Intent address:", intentAddress?.toString());
1052
+ const quote = {
1053
+ fromAmount: originSendAmount,
1054
+ };
1055
+ const swap = async () => {
1056
+ const { originUserTxReceipt, destinationMetaTxnReceipt } = await send();
1057
+ return {
1058
+ originTransaction: {
1059
+ transactionHash: originUserTxReceipt?.transactionHash,
1060
+ receipt: originUserTxReceipt,
1061
+ },
1062
+ destinationTransaction: {
1063
+ transactionHash: destinationMetaTxnReceipt?.txnHash,
1064
+ receipt: destinationMetaTxnReceipt,
1065
+ },
1066
+ };
1067
+ };
1068
+ return {
1069
+ quote,
1070
+ swap,
1071
+ };
1072
+ },
1073
+ });
1074
+ return {
1075
+ quote: data?.quote || null,
1076
+ swap: data?.swap || null,
1077
+ isLoadingQuote: isLoading,
1078
+ quoteError: error,
1079
+ };
1080
+ }