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,199 @@
1
+ import { TokenImage } from "./TokenImage.js"
2
+ import { ChevronDown } from "lucide-react"
3
+ import type React from "react"
4
+ import { useEffect, useMemo, useRef, useState } from "react"
5
+ import { useQueryParams } from "../../queryParams.js"
6
+ import type { ActiveTheme } from "../../theme.js"
7
+
8
+ // Simulated fee amounts and prices
9
+ const FEE_AMOUNTS = {
10
+ ETH: "0.00001",
11
+ USDC: "0.1",
12
+ }
13
+
14
+ const TOKEN_PRICES = {
15
+ ETH: 3500, // Simulated ETH price in USD
16
+ USDC: 1, // USDC is pegged to USD
17
+ }
18
+
19
+ interface FeeToken {
20
+ name: string
21
+ symbol: string
22
+ imageUrl: string
23
+ decimals: number
24
+ }
25
+
26
+ interface FeeOptionsProps {
27
+ options: FeeToken[]
28
+ selectedOption?: FeeToken
29
+ onSelect: (option: FeeToken) => void
30
+ theme?: ActiveTheme
31
+ }
32
+
33
+ export const FeeOptions: React.FC<FeeOptionsProps> = ({
34
+ options,
35
+ selectedOption,
36
+ onSelect,
37
+ theme = "light",
38
+ }) => {
39
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false)
40
+ const dropdownRef = useRef<HTMLDivElement>(null)
41
+ const { hasParam } = useQueryParams()
42
+
43
+ // Show fee display if feeOptions=true is in URL params
44
+ const shouldShowFeeDisplay = hasParam("feeOptions", "true")
45
+
46
+ // Calculate USD value of fee
47
+ const feeUsdValue = useMemo(() => {
48
+ if (!selectedOption) return "0.00"
49
+ const feeAmount = parseFloat(
50
+ FEE_AMOUNTS[selectedOption.symbol as keyof typeof FEE_AMOUNTS] || "0",
51
+ )
52
+ const tokenPrice =
53
+ TOKEN_PRICES[selectedOption.symbol as keyof typeof TOKEN_PRICES] || 0
54
+ const usdValue = feeAmount * tokenPrice
55
+ return usdValue.toFixed(2)
56
+ }, [selectedOption])
57
+
58
+ // Set first option as default if none selected
59
+ useEffect(() => {
60
+ if (!selectedOption && options.length > 0) {
61
+ onSelect(options[0]!)
62
+ }
63
+ }, [selectedOption, options, onSelect])
64
+
65
+ // Handle clicking outside to close dropdown
66
+ useEffect(() => {
67
+ const handleClickOutside = (event: MouseEvent) => {
68
+ if (
69
+ dropdownRef.current &&
70
+ !dropdownRef.current.contains(event.target as Node)
71
+ ) {
72
+ setIsDropdownOpen(false)
73
+ }
74
+ }
75
+
76
+ document.addEventListener("mousedown", handleClickOutside)
77
+ return () => document.removeEventListener("mousedown", handleClickOutside)
78
+ }, [])
79
+
80
+ if (!shouldShowFeeDisplay) {
81
+ return null
82
+ }
83
+
84
+ return (
85
+ <div className="space-y-1" ref={dropdownRef}>
86
+ <div className="flex items-center justify-between">
87
+ <label
88
+ className={`block text-xs font-medium ${
89
+ theme === "dark" ? "text-gray-300" : "text-gray-700"
90
+ }`}
91
+ >
92
+ Pay fee with
93
+ </label>
94
+ {selectedOption && (
95
+ <div
96
+ className={`text-xs ${theme === "dark" ? "text-gray-400" : "text-gray-500"}`}
97
+ >
98
+ Fee {FEE_AMOUNTS[selectedOption.symbol as keyof typeof FEE_AMOUNTS]}{" "}
99
+ {selectedOption.symbol}
100
+ <span
101
+ className={`ml-1 text-xs ${theme === "dark" ? "text-gray-400" : "text-gray-500"}`}
102
+ >
103
+ ≈ ${feeUsdValue}
104
+ </span>
105
+ </div>
106
+ )}
107
+ </div>
108
+ <div className="relative flex justify-start">
109
+ <button
110
+ type="button"
111
+ onClick={() => setIsDropdownOpen(!isDropdownOpen)}
112
+ className={`w-32 flex items-center px-3 py-2 border rounded-[16px] hover:border-gray-400 cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 text-sm ${
113
+ theme === "dark"
114
+ ? "bg-gray-800 border-gray-700 text-white"
115
+ : "bg-white border-gray-300 text-gray-900"
116
+ }`}
117
+ >
118
+ {selectedOption ? (
119
+ <>
120
+ <TokenImage
121
+ symbol={selectedOption.symbol}
122
+ imageUrl={selectedOption.imageUrl}
123
+ size={16}
124
+ />
125
+ <span className="ml-1.5 flex-1 text-left">
126
+ {selectedOption.symbol}
127
+ </span>
128
+ </>
129
+ ) : (
130
+ <span className="flex-1 text-left text-gray-400">
131
+ Select Fee Token
132
+ </span>
133
+ )}
134
+ <ChevronDown
135
+ className={`h-4 w-4 ${
136
+ theme === "dark" ? "text-gray-400" : "text-gray-400"
137
+ } transition-transform ${
138
+ isDropdownOpen ? "transform rotate-180" : ""
139
+ }`}
140
+ />
141
+ </button>
142
+
143
+ {isDropdownOpen && (
144
+ <div
145
+ className={`absolute z-10 mt-1 border rounded-[16px] shadow-lg w-32 ${
146
+ theme === "dark"
147
+ ? "bg-gray-800 border-gray-700"
148
+ : "bg-white border-gray-200"
149
+ }`}
150
+ >
151
+ {options.map((option) => (
152
+ <button
153
+ key={option.symbol}
154
+ type="button"
155
+ onClick={() => {
156
+ onSelect(option)
157
+ setIsDropdownOpen(false)
158
+ }}
159
+ className={`w-full flex items-center px-3 py-2 cursor-pointer text-sm ${
160
+ theme === "dark"
161
+ ? selectedOption?.symbol === option.symbol
162
+ ? "bg-gray-700 text-white"
163
+ : "text-white hover:bg-gray-700"
164
+ : selectedOption?.symbol === option.symbol
165
+ ? "bg-gray-100 text-gray-900"
166
+ : "text-gray-900 hover:bg-gray-50"
167
+ }`}
168
+ >
169
+ <div
170
+ className={`w-4 h-4 rounded-full flex items-center justify-center ${
171
+ theme === "dark" ? "bg-gray-700" : "bg-gray-100"
172
+ }`}
173
+ >
174
+ <TokenImage
175
+ symbol={option.symbol}
176
+ imageUrl={option.imageUrl}
177
+ size={16}
178
+ />
179
+ </div>
180
+ <span className="ml-1.5">{option.symbol}</span>
181
+ {selectedOption?.symbol === option.symbol && (
182
+ <span
183
+ className={`ml-auto ${
184
+ theme === "dark" ? "text-white" : "text-gray-900"
185
+ }`}
186
+ >
187
+
188
+ </span>
189
+ )}
190
+ </button>
191
+ ))}
192
+ </div>
193
+ )}
194
+ </div>
195
+ </div>
196
+ )
197
+ }
198
+
199
+ export default FeeOptions
@@ -0,0 +1,51 @@
1
+ import { motion } from "motion/react"
2
+ import type React from "react"
3
+ import type { ActiveTheme } from "../../theme.js"
4
+ import TrailsLogoBlack from "../assets/Trails-logo-black.svg"
5
+ import TrailsLogoWhite from "../assets/Trails-logo-white.svg"
6
+ import { SITE_URL } from "../config.js"
7
+ import DebugScreensDropdown from "./DebugScreensDropdown.js"
8
+
9
+ interface FooterProps {
10
+ theme: ActiveTheme
11
+ onDebugScreenSelect: (screen: string) => void
12
+ }
13
+
14
+ export const Footer: React.FC<FooterProps> = ({
15
+ theme,
16
+ onDebugScreenSelect,
17
+ }) => {
18
+ const TrailsLogo = theme === "dark" ? TrailsLogoWhite : TrailsLogoBlack
19
+
20
+ return (
21
+ <motion.div
22
+ initial={{ opacity: 0, y: 10 }}
23
+ animate={{ opacity: 1, y: 0 }}
24
+ transition={{ duration: 0.15 }}
25
+ className={`mt-auto pt-4 text-center text-sm relative flex items-center justify-center ${theme === "dark" ? "text-gray-400" : "text-gray-500"}`}
26
+ layout
27
+ >
28
+ <div className="absolute right-0 flex items-center h-full">
29
+ <DebugScreensDropdown
30
+ onScreenSelect={onDebugScreenSelect}
31
+ theme={theme}
32
+ />
33
+ </div>
34
+ Powered by&nbsp;
35
+ <a
36
+ href={SITE_URL}
37
+ target="_blank"
38
+ rel="noopener noreferrer"
39
+ className={`font-medium transition-colors hover:opacity-80 leading-none ${
40
+ theme === "dark"
41
+ ? "text-gray-400 hover:text-white"
42
+ : "text-gray-500 hover:text-black"
43
+ }`}
44
+ >
45
+ <img src={TrailsLogo} alt="Trails" className="h-4 inline-block" />
46
+ </a>
47
+ </motion.div>
48
+ )
49
+ }
50
+
51
+ export default Footer
@@ -0,0 +1,119 @@
1
+ import { type CSSProperties, useEffect, useState } from "react"
2
+
3
+ export function GreenCheckAnimation() {
4
+ const [animate, setAnimate] = useState(false)
5
+
6
+ useEffect(() => {
7
+ const timer = setTimeout(() => {
8
+ setAnimate(true)
9
+ }, 100)
10
+
11
+ return () => clearTimeout(timer)
12
+ }, [])
13
+
14
+ const styles: Record<string, CSSProperties> = {
15
+ container: {
16
+ width: "80px",
17
+ height: "80px",
18
+ position: "relative" as const,
19
+ },
20
+ circleContainer: {
21
+ position: "relative" as const,
22
+ width: "100%",
23
+ height: "100%",
24
+ },
25
+ circleFill: {
26
+ position: "absolute" as const,
27
+ top: 0,
28
+ left: 0,
29
+ width: "100%",
30
+ height: "100%",
31
+ borderRadius: "50%",
32
+ backgroundColor: "#22c55e",
33
+ transform: animate ? "scale(1)" : "scale(0)",
34
+ opacity: animate ? 1 : 0,
35
+ transition: "transform 0.15s ease-out 0.3s, opacity 0.15s ease-out 0.3s",
36
+ },
37
+ progressRing: {
38
+ position: "absolute" as const,
39
+ top: 0,
40
+ left: 0,
41
+ width: "100%",
42
+ height: "100%",
43
+ transform: "rotate(-90deg)",
44
+ },
45
+ circle: {
46
+ fill: "none",
47
+ stroke: "url(#gradient)",
48
+ strokeWidth: 4,
49
+ strokeLinecap: "round" as const,
50
+ strokeDasharray: 226,
51
+ strokeDashoffset: animate ? 0 : 226,
52
+ transition: "stroke-dashoffset 0.3s ease-out",
53
+ },
54
+ checkmarkContainer: {
55
+ position: "absolute" as const,
56
+ top: "50%",
57
+ left: "50%",
58
+ transform: animate
59
+ ? "translate(-50%, -50%) scale(1)"
60
+ : "translate(-50%, -50%) scale(0)",
61
+ opacity: animate ? 1 : 0,
62
+ zIndex: 10,
63
+ transition: "transform 0.1s ease-out 0.4s, opacity 0.1s ease-out 0.4s",
64
+ },
65
+ checkmarkPath: {
66
+ fill: "none",
67
+ stroke: "white",
68
+ strokeWidth: 4,
69
+ strokeLinecap: "round" as const,
70
+ strokeLinejoin: "round" as const,
71
+ strokeDasharray: 18,
72
+ strokeDashoffset: animate ? 0 : 18,
73
+ transition: "stroke-dashoffset 0.15s ease-out 0.45s",
74
+ },
75
+ }
76
+
77
+ return (
78
+ <div style={styles.container}>
79
+ <div style={styles.circleContainer}>
80
+ {/* Circle fill */}
81
+ <div style={styles.circleFill} />
82
+
83
+ {/* Progress ring */}
84
+ <svg style={styles.progressRing}>
85
+ <defs>
86
+ <radialGradient
87
+ id="gradient"
88
+ cx="50%"
89
+ cy="50%"
90
+ r="50%"
91
+ gradientUnits="objectBoundingBox"
92
+ >
93
+ <stop
94
+ offset="0%"
95
+ style={{ stopColor: "#22c55e", stopOpacity: 0 }}
96
+ />
97
+ <stop
98
+ offset="70%"
99
+ style={{ stopColor: "#22c55e", stopOpacity: 0.3 }}
100
+ />
101
+ <stop
102
+ offset="100%"
103
+ style={{ stopColor: "#22c55e", stopOpacity: 1 }}
104
+ />
105
+ </radialGradient>
106
+ </defs>
107
+ <circle cx="40" cy="40" r="36" style={styles.circle} />
108
+ </svg>
109
+
110
+ {/* Checkmark */}
111
+ <div style={styles.checkmarkContainer}>
112
+ <svg width="48" height="48" viewBox="0 0 24 24">
113
+ <path d="M6 14l4 4L18 8" style={styles.checkmarkPath} />
114
+ </svg>
115
+ </div>
116
+ </div>
117
+ </div>
118
+ )
119
+ }
@@ -0,0 +1,97 @@
1
+ import { X } from "lucide-react"
2
+ import { AnimatePresence, motion } from "motion/react"
3
+ import type React from "react"
4
+ import { useEffect, useRef } from "react"
5
+ import type { ActiveTheme } from "../../theme.js"
6
+
7
+ interface ModalProps {
8
+ isOpen: boolean
9
+ onClose: () => void
10
+ children: React.ReactNode
11
+ theme?: ActiveTheme
12
+ }
13
+
14
+ const Modal: React.FC<ModalProps> = ({
15
+ isOpen,
16
+ onClose,
17
+ children,
18
+ theme = "light",
19
+ }) => {
20
+ const modalRef = useRef<HTMLDivElement>(null)
21
+
22
+ // Handle escape key
23
+ useEffect(() => {
24
+ const handleEscape = (e: KeyboardEvent) => {
25
+ if (e.key === "Escape") {
26
+ onClose()
27
+ }
28
+ }
29
+
30
+ if (isOpen) {
31
+ document.addEventListener("keydown", handleEscape)
32
+ }
33
+
34
+ return () => {
35
+ document.removeEventListener("keydown", handleEscape)
36
+ }
37
+ }, [isOpen, onClose])
38
+
39
+ // Handle click outside
40
+ const handleClickOutside = (e: React.MouseEvent<HTMLDivElement>) => {
41
+ if (modalRef.current && !modalRef.current.contains(e.target as Node)) {
42
+ onClose()
43
+ }
44
+ }
45
+
46
+ return (
47
+ <AnimatePresence>
48
+ {isOpen && (
49
+ <>
50
+ <motion.div
51
+ initial={{ opacity: 0 }}
52
+ animate={{ opacity: 1 }}
53
+ exit={{ opacity: 0 }}
54
+ transition={{ duration: 0.2 }}
55
+ className="fixed inset-0 bg-black/50 backdrop-blur-sm z-50"
56
+ onClick={onClose}
57
+ />
58
+ <div
59
+ className={`fixed inset-0 flex items-center justify-center z-50 p-2 sm:p-4 ${theme === "dark" ? "text-white" : "text-gray-900"}`}
60
+ onClick={handleClickOutside}
61
+ >
62
+ <motion.div
63
+ ref={modalRef}
64
+ initial={{ opacity: 0, scale: 0.95, y: 10 }}
65
+ animate={{ opacity: 1, scale: 1, y: 0 }}
66
+ exit={{ opacity: 0, scale: 0.95, y: 10 }}
67
+ transition={{
68
+ type: "spring",
69
+ stiffness: 400,
70
+ damping: 25,
71
+ mass: 0.8,
72
+ }}
73
+ className="pointer-events-auto relative"
74
+ layoutId="modal-content"
75
+ layout="preserve-aspect"
76
+ >
77
+ <button
78
+ type="button"
79
+ onClick={onClose}
80
+ className={`absolute right-2 top-2 p-2 rounded-full transition-colors cursor-pointer z-10 ${
81
+ theme === "dark"
82
+ ? "hover:bg-gray-800 text-gray-400"
83
+ : "hover:bg-gray-100 text-gray-600"
84
+ }`}
85
+ >
86
+ <X className="h-6 w-6" />
87
+ </button>
88
+ {children}
89
+ </motion.div>
90
+ </div>
91
+ </>
92
+ )}
93
+ </AnimatePresence>
94
+ )
95
+ }
96
+
97
+ export default Modal
@@ -0,0 +1,237 @@
1
+ // biome-ignore lint/style/useImportType: False positive
2
+ import React, { useEffect, useState } from "react"
3
+ import type { TransactionState } from "../../prepareSend.js"
4
+ import type { ActiveTheme } from "../../theme.js"
5
+ import { GreenCheckAnimation } from "./GreenCheckAnimation.js"
6
+
7
+ interface ReceiptProps {
8
+ onSendAnother: () => void
9
+ onClose: () => void
10
+ theme?: ActiveTheme
11
+ renderInline?: boolean
12
+ transactionStates?: TransactionState[]
13
+ }
14
+
15
+ export const Receipt: React.FC<ReceiptProps> = ({
16
+ onClose,
17
+ theme = "light",
18
+ renderInline = false,
19
+ transactionStates = [],
20
+ }) => {
21
+ const [showDetails, setShowDetails] = useState(false)
22
+ const [showContent, setShowContent] = useState(false)
23
+
24
+ useEffect(() => {
25
+ const timer = setTimeout(() => {
26
+ setShowContent(true)
27
+ }, 400)
28
+
29
+ return () => clearTimeout(timer)
30
+ }, [])
31
+
32
+ const finalExplorerUrl =
33
+ transactionStates?.[transactionStates.length - 1]?.explorerUrl
34
+
35
+ if (!finalExplorerUrl) {
36
+ return null
37
+ }
38
+
39
+ return (
40
+ <div className="flex flex-col justify-center min-h-full space-y-6 pt-8">
41
+ <div className="text-center">
42
+ <div className={`mx-auto flex items-center justify-center`}>
43
+ <GreenCheckAnimation />
44
+ </div>
45
+
46
+ <div
47
+ className={`transition-all duration-500 ease-out ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
48
+ >
49
+ <h2
50
+ className={`mt-4 text-2xl font-bold ${theme === "dark" ? "text-white" : "text-gray-900"}`}
51
+ >
52
+ Transaction Confirmed
53
+ </h2>
54
+ </div>
55
+ </div>
56
+
57
+ <div
58
+ className={`text-center transition-all duration-500 ease-out delay-100 ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
59
+ >
60
+ <a
61
+ href={finalExplorerUrl}
62
+ target="_blank"
63
+ rel="noopener noreferrer"
64
+ className={`inline-flex items-center gap-1 px-3 py-1.5 rounded-md font-medium transition-colors border text-sm
65
+ ${
66
+ theme === "dark"
67
+ ? "bg-gray-900 border-gray-700 text-blue-300 hover:bg-gray-800 hover:text-blue-200"
68
+ : "bg-white border-gray-200 text-black hover:bg-gray-50 hover:text-gray-900"
69
+ }
70
+ `}
71
+ >
72
+ View on Explorer
73
+ <svg
74
+ className="w-4 h-4 ml-1"
75
+ fill="none"
76
+ viewBox="0 0 24 24"
77
+ stroke={theme === "dark" ? "currentColor" : "black"}
78
+ >
79
+ <path
80
+ strokeLinecap="round"
81
+ strokeLinejoin="round"
82
+ strokeWidth={2}
83
+ d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
84
+ />
85
+ </svg>
86
+ </a>
87
+ </div>
88
+
89
+ <div
90
+ className={`space-y-3 transition-all duration-500 ease-out delay-200 ${showContent ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"}`}
91
+ >
92
+ {!renderInline && (
93
+ <button
94
+ onClick={onClose}
95
+ className={`w-full cursor-pointer font-semibold py-3 px-4 rounded-[24px] transition-colors ${
96
+ theme === "dark"
97
+ ? "bg-gray-800 hover:bg-gray-700 text-gray-300 hover:text-white"
98
+ : "bg-gray-100 hover:bg-gray-200 text-gray-600 hover:text-gray-900"
99
+ }`}
100
+ >
101
+ Close
102
+ </button>
103
+ )}
104
+ <button
105
+ onClick={() => setShowDetails(!showDetails)}
106
+ className={`w-full flex items-center justify-center gap-2 py-2 px-4 rounded-[24px] transition-colors cursor-pointer text-sm ${
107
+ theme === "dark"
108
+ ? "text-gray-400 hover:text-gray-300"
109
+ : "text-gray-500 hover:text-gray-700"
110
+ }`}
111
+ >
112
+ <span>More Details</span>
113
+ <svg
114
+ className={`w-4 h-4 transition-transform ${showDetails ? "rotate-180" : ""}`}
115
+ fill="none"
116
+ viewBox="0 0 24 24"
117
+ stroke="currentColor"
118
+ >
119
+ <path
120
+ strokeLinecap="round"
121
+ strokeLinejoin="round"
122
+ strokeWidth={2}
123
+ d="M19 9l-7 7-7-7"
124
+ />
125
+ </svg>
126
+ </button>
127
+ {showDetails && (
128
+ <div
129
+ className={`p-4 rounded-lg text-sm space-y-4 ${
130
+ theme === "dark" ? "bg-gray-800" : "bg-gray-50"
131
+ }`}
132
+ >
133
+ {transactionStates.length > 0 && (
134
+ <div className="space-y-2">
135
+ <div
136
+ className={`font-medium ${
137
+ theme === "dark" ? "text-gray-300" : "text-gray-700"
138
+ }`}
139
+ >
140
+ Transactions:
141
+ </div>
142
+ <div className="space-y-2">
143
+ {transactionStates.map((state) => (
144
+ <div
145
+ key={state.transactionHash}
146
+ className={`p-2 rounded ${
147
+ theme === "dark" ? "bg-gray-700/50" : "bg-gray-100"
148
+ }`}
149
+ >
150
+ <div className="flex justify-between items-center">
151
+ <span
152
+ className={
153
+ theme === "dark" ? "text-gray-400" : "text-gray-600"
154
+ }
155
+ >
156
+ {state.label}:
157
+ </span>
158
+ <span
159
+ className={`px-2 py-0.5 rounded-full text-xs ${
160
+ state.state === "confirmed"
161
+ ? theme === "dark"
162
+ ? "bg-green-900/50 text-green-400"
163
+ : "bg-green-100 text-green-700"
164
+ : theme === "dark"
165
+ ? "bg-yellow-900/50 text-yellow-400"
166
+ : "bg-yellow-100 text-yellow-700"
167
+ }`}
168
+ >
169
+ {state.state}
170
+ </span>
171
+ </div>
172
+ <div className="mt-1 flex justify-between items-center">
173
+ <span
174
+ className={
175
+ theme === "dark" ? "text-gray-400" : "text-gray-600"
176
+ }
177
+ >
178
+ Chain ID:
179
+ </span>
180
+ <span
181
+ className={
182
+ theme === "dark" ? "text-white" : "text-gray-900"
183
+ }
184
+ >
185
+ {state.chainId}
186
+ </span>
187
+ </div>
188
+ <div className="mt-1 flex justify-between items-center">
189
+ <span
190
+ className={
191
+ theme === "dark" ? "text-gray-400" : "text-gray-600"
192
+ }
193
+ >
194
+ Hash:
195
+ </span>
196
+ <a
197
+ href={state.explorerUrl}
198
+ target="_blank"
199
+ rel="noopener noreferrer"
200
+ className={`flex items-center gap-1 hover:underline ${
201
+ theme === "dark"
202
+ ? "text-blue-400 hover:text-blue-300"
203
+ : "text-blue-600 hover:text-blue-700"
204
+ }`}
205
+ >
206
+ <span>
207
+ {state.transactionHash.slice(0, 6)}...
208
+ {state.transactionHash.slice(-4)}
209
+ </span>
210
+ <svg
211
+ className="w-3 h-3"
212
+ fill="none"
213
+ viewBox="0 0 24 24"
214
+ stroke="currentColor"
215
+ >
216
+ <path
217
+ strokeLinecap="round"
218
+ strokeLinejoin="round"
219
+ strokeWidth={2}
220
+ d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
221
+ />
222
+ </svg>
223
+ </a>
224
+ </div>
225
+ </div>
226
+ ))}
227
+ </div>
228
+ </div>
229
+ )}
230
+ </div>
231
+ )}
232
+ </div>
233
+ </div>
234
+ )
235
+ }
236
+
237
+ export default Receipt