@pasosdejesus/m 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/dist/blockchain/deployments.d.ts +40 -0
  2. package/dist/blockchain/deployments.d.ts.map +1 -0
  3. package/dist/blockchain/deployments.js +64 -0
  4. package/dist/debug/DebugConsole.d.ts +22 -0
  5. package/dist/debug/DebugConsole.d.ts.map +1 -0
  6. package/dist/debug/DebugConsole.js +79 -0
  7. package/dist/debug/Logger.d.ts +38 -0
  8. package/dist/debug/Logger.d.ts.map +1 -0
  9. package/dist/debug/Logger.js +94 -0
  10. package/dist/debug/index.d.ts +6 -0
  11. package/dist/debug/index.d.ts.map +1 -0
  12. package/dist/debug/index.js +4 -0
  13. package/dist/debug/useLogger.d.ts +14 -0
  14. package/dist/debug/useLogger.d.ts.map +1 -0
  15. package/dist/debug/useLogger.js +23 -0
  16. package/dist/debug/utils.d.ts +10 -0
  17. package/dist/debug/utils.d.ts.map +1 -0
  18. package/dist/debug/utils.js +53 -0
  19. package/dist/e2e/assertions.d.ts +5 -0
  20. package/dist/e2e/assertions.d.ts.map +1 -0
  21. package/dist/e2e/assertions.js +18 -0
  22. package/dist/e2e/browser.d.ts +37 -0
  23. package/dist/e2e/browser.d.ts.map +1 -0
  24. package/dist/e2e/browser.js +97 -0
  25. package/dist/e2e/env.d.ts +18 -0
  26. package/dist/e2e/env.d.ts.map +1 -0
  27. package/dist/e2e/env.js +57 -0
  28. package/dist/e2e/index.d.ts +11 -0
  29. package/dist/e2e/index.d.ts.map +1 -0
  30. package/dist/e2e/index.js +8 -0
  31. package/dist/e2e/navigation.d.ts +4 -0
  32. package/dist/e2e/navigation.d.ts.map +1 -0
  33. package/dist/e2e/navigation.js +32 -0
  34. package/dist/e2e/siwe-mock.d.ts +11 -0
  35. package/dist/e2e/siwe-mock.d.ts.map +1 -0
  36. package/dist/e2e/siwe-mock.js +112 -0
  37. package/dist/e2e/siwe.d.ts +15 -0
  38. package/dist/e2e/siwe.d.ts.map +1 -0
  39. package/dist/e2e/siwe.js +85 -0
  40. package/dist/e2e/wallet-mock.d.ts +13 -0
  41. package/dist/e2e/wallet-mock.d.ts.map +1 -0
  42. package/dist/e2e/wallet-mock.js +91 -0
  43. package/dist/i18n/common-cli.d.ts +11 -0
  44. package/dist/i18n/common-cli.d.ts.map +1 -0
  45. package/dist/i18n/common-cli.js +22 -0
  46. package/dist/i18n/createTranslator.d.ts +28 -0
  47. package/dist/i18n/createTranslator.d.ts.map +1 -0
  48. package/dist/i18n/createTranslator.js +48 -0
  49. package/dist/i18n/index.d.ts +4 -0
  50. package/dist/i18n/index.d.ts.map +1 -0
  51. package/dist/i18n/index.js +2 -0
  52. package/dist/i18n/locales/cli.d.ts +3 -0
  53. package/dist/i18n/locales/cli.d.ts.map +1 -0
  54. package/dist/i18n/locales/cli.js +180 -0
  55. package/dist/i18n/types.d.ts +3 -0
  56. package/dist/i18n/types.d.ts.map +1 -0
  57. package/dist/i18n/types.js +1 -0
  58. package/dist/index.d.ts +2 -0
  59. package/dist/index.d.ts.map +1 -0
  60. package/dist/index.js +15 -0
  61. package/dist/index.test.d.ts +2 -0
  62. package/dist/index.test.d.ts.map +1 -0
  63. package/dist/index.test.js +10 -0
  64. package/dist/m.d.ts +2 -0
  65. package/dist/m.d.ts.map +1 -0
  66. package/dist/m.js +334 -0
  67. package/dist/plugin.d.ts +10 -0
  68. package/dist/plugin.d.ts.map +1 -0
  69. package/dist/plugin.js +7 -0
  70. package/dist/shadcn_components/cn.d.ts +13 -0
  71. package/dist/shadcn_components/cn.d.ts.map +1 -0
  72. package/dist/shadcn_components/cn.js +15 -0
  73. package/dist/shadcn_components/ui/accordion.d.ts +8 -0
  74. package/dist/shadcn_components/ui/accordion.d.ts.map +1 -0
  75. package/dist/shadcn_components/ui/accordion.js +14 -0
  76. package/dist/shadcn_components/ui/alert-dialog.d.ts +21 -0
  77. package/dist/shadcn_components/ui/alert-dialog.d.ts.map +1 -0
  78. package/dist/shadcn_components/ui/alert-dialog.js +27 -0
  79. package/dist/shadcn_components/ui/alert.d.ts +9 -0
  80. package/dist/shadcn_components/ui/alert.d.ts.map +1 -0
  81. package/dist/shadcn_components/ui/alert.js +22 -0
  82. package/dist/shadcn_components/ui/avatar.d.ts +7 -0
  83. package/dist/shadcn_components/ui/avatar.d.ts.map +1 -0
  84. package/dist/shadcn_components/ui/avatar.js +12 -0
  85. package/dist/shadcn_components/ui/badge.d.ts +10 -0
  86. package/dist/shadcn_components/ui/badge.d.ts.map +1 -0
  87. package/dist/shadcn_components/ui/badge.js +22 -0
  88. package/dist/shadcn_components/ui/button.d.ts +11 -0
  89. package/dist/shadcn_components/ui/button.d.ts.map +1 -0
  90. package/dist/shadcn_components/ui/button.js +31 -0
  91. package/dist/shadcn_components/ui/card.d.ts +10 -0
  92. package/dist/shadcn_components/ui/card.d.ts.map +1 -0
  93. package/dist/shadcn_components/ui/card.js +24 -0
  94. package/dist/shadcn_components/ui/checkbox.d.ts +5 -0
  95. package/dist/shadcn_components/ui/checkbox.d.ts.map +1 -0
  96. package/dist/shadcn_components/ui/checkbox.js +9 -0
  97. package/dist/shadcn_components/ui/dialog.d.ts +20 -0
  98. package/dist/shadcn_components/ui/dialog.d.ts.map +1 -0
  99. package/dist/shadcn_components/ui/dialog.js +23 -0
  100. package/dist/shadcn_components/ui/dropdown-menu.d.ts +28 -0
  101. package/dist/shadcn_components/ui/dropdown-menu.d.ts.map +1 -0
  102. package/dist/shadcn_components/ui/dropdown-menu.js +36 -0
  103. package/dist/shadcn_components/ui/form.d.ts +24 -0
  104. package/dist/shadcn_components/ui/form.d.ts.map +1 -0
  105. package/dist/shadcn_components/ui/form.js +63 -0
  106. package/dist/shadcn_components/ui/input.d.ts +4 -0
  107. package/dist/shadcn_components/ui/input.d.ts.map +1 -0
  108. package/dist/shadcn_components/ui/input.js +6 -0
  109. package/dist/shadcn_components/ui/label.d.ts +6 -0
  110. package/dist/shadcn_components/ui/label.d.ts.map +1 -0
  111. package/dist/shadcn_components/ui/label.js +10 -0
  112. package/dist/shadcn_components/ui/menubar.d.ts +29 -0
  113. package/dist/shadcn_components/ui/menubar.d.ts.map +1 -0
  114. package/dist/shadcn_components/ui/menubar.js +46 -0
  115. package/dist/shadcn_components/ui/popover.d.ts +7 -0
  116. package/dist/shadcn_components/ui/popover.d.ts.map +1 -0
  117. package/dist/shadcn_components/ui/popover.js +10 -0
  118. package/dist/shadcn_components/ui/progress.d.ts +5 -0
  119. package/dist/shadcn_components/ui/progress.d.ts.map +1 -0
  120. package/dist/shadcn_components/ui/progress.js +8 -0
  121. package/dist/shadcn_components/ui/radio-group.d.ts +6 -0
  122. package/dist/shadcn_components/ui/radio-group.d.ts.map +1 -0
  123. package/dist/shadcn_components/ui/radio-group.js +15 -0
  124. package/dist/shadcn_components/ui/scroll-area.d.ts +6 -0
  125. package/dist/shadcn_components/ui/scroll-area.d.ts.map +1 -0
  126. package/dist/shadcn_components/ui/scroll-area.js +12 -0
  127. package/dist/shadcn_components/ui/select.d.ts +14 -0
  128. package/dist/shadcn_components/ui/select.d.ts.map +1 -0
  129. package/dist/shadcn_components/ui/select.js +27 -0
  130. package/dist/shadcn_components/ui/separator.d.ts +5 -0
  131. package/dist/shadcn_components/ui/separator.d.ts.map +1 -0
  132. package/dist/shadcn_components/ui/separator.js +8 -0
  133. package/dist/shadcn_components/ui/sheet.d.ts +26 -0
  134. package/dist/shadcn_components/ui/sheet.d.ts.map +1 -0
  135. package/dist/shadcn_components/ui/sheet.js +37 -0
  136. package/dist/shadcn_components/ui/skeleton.d.ts +3 -0
  137. package/dist/shadcn_components/ui/skeleton.d.ts.map +1 -0
  138. package/dist/shadcn_components/ui/skeleton.js +6 -0
  139. package/dist/shadcn_components/ui/slider.d.ts +5 -0
  140. package/dist/shadcn_components/ui/slider.d.ts.map +1 -0
  141. package/dist/shadcn_components/ui/slider.js +8 -0
  142. package/dist/shadcn_components/ui/switch.d.ts +5 -0
  143. package/dist/shadcn_components/ui/switch.d.ts.map +1 -0
  144. package/dist/shadcn_components/ui/switch.js +8 -0
  145. package/dist/shadcn_components/ui/table.d.ts +11 -0
  146. package/dist/shadcn_components/ui/table.d.ts.map +1 -0
  147. package/dist/shadcn_components/ui/table.js +20 -0
  148. package/dist/shadcn_components/ui/tabs.d.ts +8 -0
  149. package/dist/shadcn_components/ui/tabs.d.ts.map +1 -0
  150. package/dist/shadcn_components/ui/tabs.js +13 -0
  151. package/dist/shadcn_components/ui/textarea.d.ts +4 -0
  152. package/dist/shadcn_components/ui/textarea.d.ts.map +1 -0
  153. package/dist/shadcn_components/ui/textarea.js +8 -0
  154. package/dist/shadcn_components/ui/toast.d.ts +16 -0
  155. package/dist/shadcn_components/ui/toast.d.ts.map +1 -0
  156. package/dist/shadcn_components/ui/toast.js +34 -0
  157. package/dist/shadcn_components/ui/toaster.d.ts +2 -0
  158. package/dist/shadcn_components/ui/toaster.d.ts.map +1 -0
  159. package/dist/shadcn_components/ui/toaster.js +10 -0
  160. package/dist/shadcn_components/ui/tooltip.d.ts +8 -0
  161. package/dist/shadcn_components/ui/tooltip.d.ts.map +1 -0
  162. package/dist/shadcn_components/ui/tooltip.js +11 -0
  163. package/dist/shadcn_components/ui/use-toast.d.ts +45 -0
  164. package/dist/shadcn_components/ui/use-toast.d.ts.map +1 -0
  165. package/dist/shadcn_components/ui/use-toast.js +126 -0
  166. package/dist/tasks/context.d.ts +13 -0
  167. package/dist/tasks/context.d.ts.map +1 -0
  168. package/dist/tasks/context.js +310 -0
  169. package/dist/tasks/create.d.ts +2 -0
  170. package/dist/tasks/create.d.ts.map +1 -0
  171. package/dist/tasks/create.js +91 -0
  172. package/dist/tasks/db.d.ts +19 -0
  173. package/dist/tasks/db.d.ts.map +1 -0
  174. package/dist/tasks/db.js +791 -0
  175. package/dist/tasks/e2e.d.ts +2 -0
  176. package/dist/tasks/e2e.d.ts.map +1 -0
  177. package/dist/tasks/e2e.js +124 -0
  178. package/dist/tasks/edit.d.ts +7 -0
  179. package/dist/tasks/edit.d.ts.map +1 -0
  180. package/dist/tasks/edit.js +471 -0
  181. package/dist/tasks/engine.d.ts +2 -0
  182. package/dist/tasks/engine.d.ts.map +1 -0
  183. package/dist/tasks/engine.js +149 -0
  184. package/dist/tasks/env-diff.d.ts +2 -0
  185. package/dist/tasks/env-diff.d.ts.map +1 -0
  186. package/dist/tasks/env-diff.js +140 -0
  187. package/dist/tasks/fuzzy.d.ts +9 -0
  188. package/dist/tasks/fuzzy.d.ts.map +1 -0
  189. package/dist/tasks/fuzzy.js +153 -0
  190. package/dist/tasks/glob.d.ts +5 -0
  191. package/dist/tasks/glob.d.ts.map +1 -0
  192. package/dist/tasks/glob.js +57 -0
  193. package/dist/tasks/grep.d.ts +9 -0
  194. package/dist/tasks/grep.d.ts.map +1 -0
  195. package/dist/tasks/grep.js +93 -0
  196. package/dist/tasks/readfile.d.ts +2 -0
  197. package/dist/tasks/readfile.d.ts.map +1 -0
  198. package/dist/tasks/readfile.js +177 -0
  199. package/dist/tasks/update.d.ts +5 -0
  200. package/dist/tasks/update.d.ts.map +1 -0
  201. package/dist/tasks/update.js +200 -0
  202. package/dist/tasks/util.d.ts +12 -0
  203. package/dist/tasks/util.d.ts.map +1 -0
  204. package/dist/tasks/util.js +42 -0
  205. package/dist/tasks/wallet.d.ts +2 -0
  206. package/dist/tasks/wallet.d.ts.map +1 -0
  207. package/dist/tasks/wallet.js +697 -0
  208. package/dist/tasks/writefile.d.ts +2 -0
  209. package/dist/tasks/writefile.d.ts.map +1 -0
  210. package/dist/tasks/writefile.js +66 -0
  211. package/dist/templates/AGENTS.md.hbs +81 -0
  212. package/dist/templates/ARCHITECTURE.md.hbs +146 -0
  213. package/dist/templates/CONTRIBUTING.md.hbs +83 -0
  214. package/dist/templates/LICENCIA.md +21 -0
  215. package/dist/templates/LICENSE.md +15 -0
  216. package/dist/templates/Makefile +16 -0
  217. package/dist/templates/README.md.hbs +111 -0
  218. package/dist/templates/apps/.env.example.hbs +75 -0
  219. package/dist/templates/apps/hardhat/.prettierrc +16 -0
  220. package/dist/templates/apps/hardhat/MOCK_USDT_README.md +20 -0
  221. package/dist/templates/apps/hardhat/Makefile +13 -0
  222. package/dist/templates/apps/hardhat/README.md +129 -0
  223. package/dist/templates/apps/hardhat/bin/MusdtVerification +4 -0
  224. package/dist/templates/apps/hardhat/bin/approveDepositOwner +7 -0
  225. package/dist/templates/apps/hardhat/bin/contractVerification +9 -0
  226. package/dist/templates/apps/hardhat/bin/deployMockUSDT +7 -0
  227. package/dist/templates/apps/hardhat/bin/prepadJ.sh +14 -0
  228. package/dist/templates/apps/hardhat/bin/verifyMockUSDT +7 -0
  229. package/dist/templates/apps/hardhat/contracts/MockUSDT.sol +47 -0
  230. package/dist/templates/apps/hardhat/hardhat.config.ts +102 -0
  231. package/dist/templates/apps/hardhat/package.json +55 -0
  232. package/dist/templates/apps/hardhat/scripts/approveDepositOwner.ts +22 -0
  233. package/dist/templates/apps/hardhat/scripts/deployMockUSDT.ts +49 -0
  234. package/dist/templates/apps/hardhat/scripts/verifyDeployment.ts +93 -0
  235. package/dist/templates/apps/hardhat/scripts/verifyMockUSDT.ts +52 -0
  236. package/dist/templates/apps/hardhat/sync-abis.mjs +58 -0
  237. package/dist/templates/apps/hardhat/test/MockUSDT.test.ts +40 -0
  238. package/dist/templates/apps/hardhat/tsconfig.json +27 -0
  239. package/dist/templates/apps/nextjs/.config/kysely.config.ts +36 -0
  240. package/dist/templates/apps/nextjs/Makefile +24 -0
  241. package/dist/templates/apps/nextjs/README.md.hbs +76 -0
  242. package/dist/templates/apps/nextjs/abis/IERC20.json +74 -0
  243. package/dist/templates/apps/nextjs/abis/MockUSDT.json +242 -0
  244. package/dist/templates/apps/nextjs/abis/ReentrancyGuard.json +1 -0
  245. package/dist/templates/apps/nextjs/app/globals.css +3 -0
  246. package/dist/templates/apps/nextjs/app/layout.tsx.hbs +26 -0
  247. package/dist/templates/apps/nextjs/app/page.tsx.hbs +225 -0
  248. package/dist/templates/apps/nextjs/app/testui/page.tsx +371 -0
  249. package/dist/templates/apps/nextjs/bin/m +8 -0
  250. package/dist/templates/apps/nextjs/components.json +21 -0
  251. package/dist/templates/apps/nextjs/next-env.d.ts +5 -0
  252. package/dist/templates/apps/nextjs/next.config.ts +10 -0
  253. package/dist/templates/apps/nextjs/package.json.hbs +48 -0
  254. package/dist/templates/apps/nextjs/pnpm-workspace.yaml +13 -0
  255. package/dist/templates/apps/nextjs/postcss.config.mjs +6 -0
  256. package/dist/templates/apps/nextjs/tailwind.config.js +11 -0
  257. package/dist/templates/apps/nextjs/tests/helpers.ts +31 -0
  258. package/dist/templates/apps/nextjs/tests/index.test.ts +7 -0
  259. package/dist/templates/apps/nextjs/tests/setup-env.ts.hbs +8 -0
  260. package/dist/templates/apps/nextjs/tests/test-utils.example.test.ts +168 -0
  261. package/dist/templates/apps/nextjs/tsconfig.json +44 -0
  262. package/dist/templates/apps/nextjs/tsconfig.test.json +38 -0
  263. package/dist/templates/apps/nextjs/vitest.config.ts +13 -0
  264. package/dist/test-utils/fs-mocks.d.ts +32 -0
  265. package/dist/test-utils/fs-mocks.d.ts.map +1 -0
  266. package/dist/test-utils/fs-mocks.js +63 -0
  267. package/dist/test-utils/i18n-mock.d.ts +21 -0
  268. package/dist/test-utils/i18n-mock.d.ts.map +1 -0
  269. package/dist/test-utils/i18n-mock.js +29 -0
  270. package/dist/test-utils/index.d.ts +12 -0
  271. package/dist/test-utils/index.d.ts.map +1 -0
  272. package/dist/test-utils/index.js +11 -0
  273. package/dist/test-utils/kysely-mocks.d.ts +298 -0
  274. package/dist/test-utils/kysely-mocks.d.ts.map +1 -0
  275. package/dist/test-utils/kysely-mocks.js +173 -0
  276. package/dist/test-utils/radix-mocks.d.ts +134 -0
  277. package/dist/test-utils/radix-mocks.d.ts.map +1 -0
  278. package/dist/test-utils/radix-mocks.js +175 -0
  279. package/dist/test-utils/rainbowkit-mocks.d.ts +80 -0
  280. package/dist/test-utils/rainbowkit-mocks.d.ts.map +1 -0
  281. package/dist/test-utils/rainbowkit-mocks.js +247 -0
  282. package/dist/test-utils/viem-mocks.d.ts +86 -0
  283. package/dist/test-utils/viem-mocks.d.ts.map +1 -0
  284. package/dist/test-utils/viem-mocks.js +54 -0
  285. package/dist/util/cli-parser.d.ts +20 -0
  286. package/dist/util/cli-parser.d.ts.map +1 -0
  287. package/dist/util/cli-parser.js +38 -0
  288. package/dist/util/colors.d.ts +5 -0
  289. package/dist/util/colors.d.ts.map +1 -0
  290. package/dist/util/colors.js +5 -0
  291. package/dist/util/locale.d.ts +3 -0
  292. package/dist/util/locale.d.ts.map +1 -0
  293. package/dist/util/locale.js +10 -0
  294. package/dist/wba/client.d.ts +19 -0
  295. package/dist/wba/client.d.ts.map +1 -0
  296. package/dist/wba/client.js +31 -0
  297. package/dist/wba/index.d.ts +4 -0
  298. package/dist/wba/index.d.ts.map +1 -0
  299. package/dist/wba/index.js +2 -0
  300. package/dist/wba/routes/event.d.ts +32 -0
  301. package/dist/wba/routes/event.d.ts.map +1 -0
  302. package/dist/wba/routes/event.js +42 -0
  303. package/dist/wba/routes/index.d.ts +3 -0
  304. package/dist/wba/routes/index.d.ts.map +1 -0
  305. package/dist/wba/routes/index.js +2 -0
  306. package/dist/wba/routes/summary.d.ts +44 -0
  307. package/dist/wba/routes/summary.d.ts.map +1 -0
  308. package/dist/wba/routes/summary.js +146 -0
  309. package/dist/wba/server.d.ts +18 -0
  310. package/dist/wba/server.d.ts.map +1 -0
  311. package/dist/wba/server.js +29 -0
  312. package/dist/wba/types.d.ts +68 -0
  313. package/dist/wba/types.d.ts.map +1 -0
  314. package/dist/wba/types.js +6 -0
  315. package/package.json +223 -0
  316. package/src/blockchain/README.md +80 -0
  317. package/src/debug/README.md +94 -0
  318. package/src/e2e/README.md +105 -0
  319. package/src/i18n/README.md +143 -0
  320. package/src/shadcn_components/README.md +125 -0
  321. package/src/tasks/README.md +69 -0
  322. package/src/test-utils/README.md +638 -0
  323. package/src/util/README.md +18 -0
  324. package/src/wba/README.md +175 -0
@@ -0,0 +1,18 @@
1
+ export interface E2EEnv {
2
+ port: string;
3
+ host: string;
4
+ domainPort: string;
5
+ base: string;
6
+ timeout: number;
7
+ headless: boolean;
8
+ account: {
9
+ address: string;
10
+ signMessage: (opts: {
11
+ message: string;
12
+ }) => Promise<string>;
13
+ };
14
+ chainId: number;
15
+ }
16
+ export declare function initTestEnv(): Promise<E2EEnv>;
17
+ export declare function short(addr: string): string;
18
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/e2e/env.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,CAAC,IAAI,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,CAAA;IACzF,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CA0BnD;AAED,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1C"}
@@ -0,0 +1,57 @@
1
+ // Environment helper for E2E tests β€” parses env vars, resolves account
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ // Try to load PRIVATE_KEY and NEXT_PUBLIC_ADDRESS from apps/.env
5
+ function loadEnvFile() {
6
+ try {
7
+ const envPath = path.join(process.cwd(), '..', '..', '.env');
8
+ if (fs.existsSync(envPath)) {
9
+ const content = fs.readFileSync(envPath, 'utf8');
10
+ const pk = content.match(/PRIVATE_KEY="([^"]+)"/)?.[1];
11
+ const addr = content.match(/NEXT_PUBLIC_ADDRESS="([^"]+)"/)?.[1];
12
+ if (pk && addr)
13
+ return { pk, addr, source: 'apps/.env' };
14
+ }
15
+ }
16
+ catch { /* fallback */ }
17
+ // Also try .env from working directory
18
+ try {
19
+ const envPath = path.join(process.cwd(), '.env');
20
+ if (fs.existsSync(envPath)) {
21
+ const content = fs.readFileSync(envPath, 'utf8');
22
+ const pk = content.match(/PRIVATE_KEY="([^"]+)"/)?.[1];
23
+ const addr = content.match(/NEXT_PUBLIC_ADDRESS="([^"]+)"/)?.[1];
24
+ if (pk && addr)
25
+ return { pk, addr, source: '.env' };
26
+ }
27
+ }
28
+ catch { /* fallback */ }
29
+ return null;
30
+ }
31
+ const _envFile = loadEnvFile();
32
+ export async function initTestEnv() {
33
+ const port = process.env.PUERTOPRU || '443';
34
+ const host = process.env.IPDES || 'learn.tg';
35
+ const domainPort = port === '443' || port === '80' ? '' : `:${port}`;
36
+ const base = `https://${host}${domainPort}`;
37
+ const timeout = 60000;
38
+ const headless = process.env.CONCABEZA ? false : true;
39
+ // Priority: TEST_PRIVATE_KEY > apps/.env > Hardhat test key
40
+ const pk = process.env.TEST_PRIVATE_KEY ||
41
+ _envFile?.pk ||
42
+ '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80';
43
+ // Lazy import viem to avoid requiring it for smoke tests
44
+ const { privateKeyToAccount } = await import('viem/accounts');
45
+ const account = privateKeyToAccount(pk);
46
+ if (_envFile) {
47
+ console.log(` πŸ”‘ Using ${_envFile.source} wallet: ${account.address}`);
48
+ }
49
+ else {
50
+ console.log(` πŸ”‘ Using Hardhat test key: ${account.address}`);
51
+ }
52
+ const chainId = parseInt(process.env.CHAIN_ID || '42220', 10);
53
+ return { port, host, domainPort, base, timeout, headless, account, chainId };
54
+ }
55
+ export function short(addr) {
56
+ return addr.slice(0, 10) + '...';
57
+ }
@@ -0,0 +1,11 @@
1
+ export { ok, fail, resetFailures, summary } from './assertions.js';
2
+ export { initTestEnv, short } from './env.js';
3
+ export type { E2EEnv } from './env.js';
4
+ export { findChrome, launchBrowser, newPage, newIncognitoContext, newIncognitoPage, clearBrowserCache } from './browser.js';
5
+ export type { E2EPage, E2EBrowser, E2EBrowserContext } from './browser.js';
6
+ export { safeNavigate, waitForText } from './navigation.js';
7
+ export { simulateSIWE, checkSessionFull, checkPartialLogin } from './siwe.js';
8
+ export { setupSIWEMock } from './siwe-mock.js';
9
+ export { ethereumMockCode, eip6963MockCode, injectEIP6963 } from './wallet-mock.js';
10
+ export type { EthereumMockOpts } from './wallet-mock.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/e2e/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAClE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,UAAU,CAAA;AAC7C,YAAY,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC3H,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAC1E,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC9C,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AACnF,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,8 @@
1
+ // Barrel export for @pasosdejesus/m/e2e
2
+ export { ok, fail, resetFailures, summary } from './assertions.js';
3
+ export { initTestEnv, short } from './env.js';
4
+ export { findChrome, launchBrowser, newPage, newIncognitoContext, newIncognitoPage, clearBrowserCache } from './browser.js';
5
+ export { safeNavigate, waitForText } from './navigation.js';
6
+ export { simulateSIWE, checkSessionFull, checkPartialLogin } from './siwe.js';
7
+ export { setupSIWEMock } from './siwe-mock.js';
8
+ export { ethereumMockCode, eip6963MockCode, injectEIP6963 } from './wallet-mock.js';
@@ -0,0 +1,4 @@
1
+ import type { E2EPage } from './browser.js';
2
+ export declare function safeNavigate(page: E2EPage, link: any, hrefFallback: string | null): Promise<void>;
3
+ export declare function waitForText(page: E2EPage, text: string, maxSeconds?: number): Promise<boolean>;
4
+ //# sourceMappingURL=navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/e2e/navigation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C,wBAAsB,YAAY,CAChC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,GAAG,EACT,YAAY,EAAE,MAAM,GAAG,IAAI,GAC1B,OAAO,CAAC,IAAI,CAAC,CAWf;AAID,wBAAsB,WAAW,CAC/B,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAW,GACtB,OAAO,CAAC,OAAO,CAAC,CAclB"}
@@ -0,0 +1,32 @@
1
+ export async function safeNavigate(page, link, hrefFallback) {
2
+ try {
3
+ await Promise.all([
4
+ page.waitForNavigation({ waitUntil: 'domcontentloaded', timeout: 30000 }),
5
+ link.click(),
6
+ ]);
7
+ }
8
+ catch {
9
+ if (hrefFallback) {
10
+ await page.goto(hrefFallback, { waitUntil: 'domcontentloaded', timeout: 30000 });
11
+ }
12
+ }
13
+ }
14
+ // Wait up to maxSeconds for text to appear in the DOM (TreeWalker).
15
+ // Returns true if found, false if timed out.
16
+ export async function waitForText(page, text, maxSeconds = 12) {
17
+ for (let i = 0; i < maxSeconds; i++) {
18
+ await new Promise(r => setTimeout(r, 1000));
19
+ const found = await page.evaluate((t) => {
20
+ const w = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
21
+ let n;
22
+ while ((n = w.nextNode())) {
23
+ if (n.textContent?.includes(t))
24
+ return true;
25
+ }
26
+ return false;
27
+ }, text);
28
+ if (found)
29
+ return true;
30
+ }
31
+ return false;
32
+ }
@@ -0,0 +1,11 @@
1
+ import type { E2EPage } from './browser.js';
2
+ export interface SIWEMockOptions {
3
+ /** Balance to return for eth_call (balanceOf). Default: 1000 * 10^18 */
4
+ fakeBalance?: string;
5
+ /** Native balance for eth_getBalance (CELO). Default: 1 CELO */
6
+ fakeCelo?: string;
7
+ /** Tx hash for eth_sendTransaction. Default: 0xcd...cd (repeated 32 times) */
8
+ fakeTxHash?: string;
9
+ }
10
+ export declare function setupSIWEMock(page: E2EPage, address: string, privateKey: string, chainId?: number, opts?: SIWEMockOptions): Promise<void>;
11
+ //# sourceMappingURL=siwe-mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siwe-mock.d.ts","sourceRoot":"","sources":["../../src/e2e/siwe-mock.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAe3C,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,OAAO,EACb,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,MAAc,EACvB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CA0Ef"}
@@ -0,0 +1,112 @@
1
+ // SIWE-capable wallet mock for Puppeteer E2E tests.
2
+ //
3
+ // Injects via evaluateOnNewDocument so it survives page reloads.
4
+ // Uses page.exposeFunction to bridge browser β†’ Node.js for real ECDSA signing.
5
+ //
6
+ // Unlike simulateSIWE() (which calls the NextAuth backend directly via fetch),
7
+ // this mock lets the frontend complete the full SIWE flow:
8
+ // user clicks "Connect Wallet" β†’ window.ethereum injected β†’ personal_sign β†’
9
+ // POST /api/auth/callback/credentials β†’ session cookie set β†’ page reloads
10
+ //
11
+ // Handles the full window.ethereum API:
12
+ // - eth_chainId, eth_accounts, eth_requestAccounts β†’ identity
13
+ // - personal_sign β†’ real ECDSA via exposeFunction bridge
14
+ // - eth_call β†’ fake balances (1000 tokens, 6 or 18 decimals)
15
+ // - eth_getBalance β†’ 1 CELO for gas
16
+ // - eth_sendTransaction β†’ fake tx hash
17
+ // - eth_blockNumber, eth_gasPrice, eth_estimateGas β†’ realistic defaults
18
+ //
19
+ // Usage:
20
+ // import { setupSIWEMock } from '@pasosdejesus/m/e2e'
21
+ // const page = await browser.newPage()
22
+ // await setupSIWEMock(page, address, privateKey, chainId)
23
+ // await page.goto(url) // mock is ready before any page script runs
24
+ // Fake balance: 1000 * 10^18 wei (for native CELO / 18-decimal tokens)
25
+ const FAKE_BALANCE_18 = '0x00000000000000000000000000000000000000000000003635C9ADC5DEA00000';
26
+ // Fake balance: 1000 * 10^6 (for USDT / 6-decimal tokens)
27
+ const FAKE_BALANCE_6 = '0x000000000000000000000000000000000000000000000000000000003B9ACA00';
28
+ // Fake CELO balance: 1 CELO = 1e18 wei
29
+ const FAKE_CELO = '0x0DE0B6B3A7640000';
30
+ // Fake gas price: 5 gwei
31
+ const FAKE_GAS_PRICE = '0x12A05F200';
32
+ // Fake block number
33
+ const FAKE_BLOCK = '0x1312D00';
34
+ // Fake gas estimate: 500000
35
+ const FAKE_GAS_ESTIMATE = '0x7A120';
36
+ export async function setupSIWEMock(page, address, privateKey, chainId = 42220, opts = {}) {
37
+ const hexChainId = '0x' + chainId.toString(16);
38
+ const fakeBalance = opts.fakeBalance || FAKE_BALANCE_18;
39
+ const fakeCelo = opts.fakeCelo || FAKE_CELO;
40
+ const fakeTxHash = opts.fakeTxHash || ('0x' + 'cd'.repeat(32));
41
+ // Set up signing bridge BEFORE page loads
42
+ await page.exposeFunction('__signSiwe', async (message) => {
43
+ const { privateKeyToAccount } = await import('viem/accounts');
44
+ const account = privateKeyToAccount(privateKey);
45
+ const sig = await account.signMessage({ message });
46
+ return typeof sig === 'string' ? sig : sig.signature || sig;
47
+ });
48
+ // Inject full wallet mock BEFORE any page script runs
49
+ // This survives page reloads (evaluateOnNewDocument)
50
+ await page.evaluateOnNewDocument((addr, cid, bal, celo, txHash) => {
51
+ ;
52
+ window.ethereum = {
53
+ isMetaMask: true,
54
+ chainId: cid,
55
+ selectedAddress: addr,
56
+ request: async ({ method, params }) => {
57
+ if (method === 'eth_chainId')
58
+ return cid;
59
+ if (method === 'eth_accounts')
60
+ return [addr];
61
+ if (method === 'eth_requestAccounts')
62
+ return [addr];
63
+ if (method === 'personal_sign')
64
+ return window.__signSiwe(params[0]);
65
+ if (method === 'wallet_switchEthereumChain')
66
+ return null;
67
+ if (method === 'eth_getBalance')
68
+ return celo;
69
+ if (method === 'eth_blockNumber')
70
+ return '0x1312D00';
71
+ if (method === 'eth_gasPrice')
72
+ return '0x12A05F200';
73
+ if (method === 'eth_estimateGas')
74
+ return '0x7A120';
75
+ if (method === 'eth_call') {
76
+ // Return fake balance for balanceOf/allowance calls
77
+ // Check if the call data looks like balanceOf (0x70a08231...)
78
+ const data = params[0]?.data || '';
79
+ if (typeof data === 'string' && data.startsWith('0x70a08231')) {
80
+ return bal;
81
+ }
82
+ // Return 0 for other calls (allowance, etc.)
83
+ return '0x0000000000000000000000000000000000000000000000000000000000000000';
84
+ }
85
+ if (method === 'eth_sendTransaction')
86
+ return txHash;
87
+ if (method === 'eth_getTransactionReceipt') {
88
+ // Return a successful receipt for our fake tx hash
89
+ return {
90
+ blockHash: '0x' + 'ab'.repeat(32),
91
+ blockNumber: '0x1312D01',
92
+ contractAddress: null,
93
+ cumulativeGasUsed: '0x7A120',
94
+ effectiveGasPrice: '0x12A05F200',
95
+ from: addr,
96
+ gasUsed: '0x7A120',
97
+ logs: [],
98
+ logsBloom: '0x' + '00'.repeat(256),
99
+ status: '0x1',
100
+ to: params[0] || addr,
101
+ transactionHash: txHash,
102
+ transactionIndex: '0x0',
103
+ type: '0x2',
104
+ };
105
+ }
106
+ return null;
107
+ },
108
+ on: (_event, _listener) => { },
109
+ removeListener: (_event, _listener) => { },
110
+ };
111
+ }, address, hexChainId, fakeBalance, fakeCelo, fakeTxHash);
112
+ }
@@ -0,0 +1,15 @@
1
+ import type { E2EPage } from './browser.js';
2
+ import type { E2EEnv } from './env.js';
3
+ interface SiweParams {
4
+ account: E2EEnv['account'];
5
+ host: string;
6
+ domainPort: string;
7
+ base: string;
8
+ chainId: number;
9
+ statement?: string;
10
+ }
11
+ export declare function checkSessionFull(page: E2EPage): Promise<boolean>;
12
+ export declare function simulateSIWE(page: E2EPage, params: SiweParams): Promise<boolean>;
13
+ export declare function checkPartialLogin(page: E2EPage): Promise<boolean>;
14
+ export {};
15
+ //# sourceMappingURL=siwe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"siwe.d.ts","sourceRoot":"","sources":["../../src/e2e/siwe.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AAEtC,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAA;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAcD,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAItE;AAMD,wBAAsB,YAAY,CAChC,IAAI,EAAE,OAAO,EACb,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,OAAO,CAAC,CA6DlB;AAGD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CASvE"}
@@ -0,0 +1,85 @@
1
+ // SIWE simulation for E2E tests β€” authenticate without a real wallet
2
+ // Uses siwe + viem (already devDependencies of m).
3
+ import { SiweMessage } from 'siwe';
4
+ // Check if NextAuth session cookie is present
5
+ function checkSessionCookie(cookies) {
6
+ return cookies.some(c => c.name.includes('next-auth.session-token'));
7
+ }
8
+ // Check if session token exists in localStorage (fallback for httpOnly cookies)
9
+ async function checkSessionLocal(page) {
10
+ const token = await page.evaluate(() => localStorage.getItem('nextauth.message'));
11
+ return token !== null;
12
+ }
13
+ export async function checkSessionFull(page) {
14
+ const cookies = await page.cookies();
15
+ if (checkSessionCookie(cookies))
16
+ return true;
17
+ return await checkSessionLocal(page);
18
+ }
19
+ // Simulate full SIWE authentication flow:
20
+ // 1. Fetch CSRF token (nonce)
21
+ // 2. Build and sign SIWE message
22
+ // 3. POST to NextAuth callback
23
+ export async function simulateSIWE(page, params) {
24
+ const { account, host, domainPort, base, chainId, statement } = params;
25
+ // Step 1: Get CSRF token
26
+ const nonce = await page.evaluate(async () => {
27
+ const r = await fetch('/api/auth/csrf');
28
+ return (await r.json()).csrfToken;
29
+ });
30
+ if (!nonce)
31
+ throw new Error('Could not get CSRF token (nonce)');
32
+ // Step 2: Build and sign SIWE message
33
+ const domain = `${host}${domainPort}`;
34
+ const msg = new SiweMessage({
35
+ domain,
36
+ address: account.address,
37
+ statement: statement || 'Sign in to Learn through games.',
38
+ uri: base,
39
+ version: '1',
40
+ chainId,
41
+ nonce,
42
+ });
43
+ const msgStr = msg.prepareMessage();
44
+ const sig = await account.signMessage({ message: msgStr });
45
+ // Step 3: POST to NextAuth callback
46
+ const cb = await page.evaluate(async ({ msg, sig, n }) => {
47
+ const body = new URLSearchParams({
48
+ csrfToken: n,
49
+ message: msg,
50
+ signature: sig,
51
+ redirect: 'false',
52
+ json: 'true',
53
+ });
54
+ const r = await fetch('/api/auth/callback/credentials', {
55
+ method: 'POST',
56
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
57
+ body: body.toString(),
58
+ });
59
+ const text = await r.text();
60
+ return { ok: r.ok, status: r.status, body: text.slice(0, 200) };
61
+ }, { msg: msgStr, sig, n: nonce });
62
+ console.log(` SIWE: ${cb.status} β€” ${cb.body.slice(0, 80)}`);
63
+ // Store auth token + session address in localStorage.
64
+ // ConnectWalletButton does this after SIWE; simulateSIWE must match
65
+ // so that profile/crossword/UBI API calls can authenticate.
66
+ if (cb.ok) {
67
+ await page.evaluate(({ token, addr }) => {
68
+ localStorage.setItem('learn.tg.authToken', token);
69
+ localStorage.setItem('learn.tg.sessionAddress', addr);
70
+ }, { token: nonce, addr: account.address.toLowerCase() });
71
+ }
72
+ return cb.ok;
73
+ }
74
+ // Detect "Partial login" text anywhere in the page DOM
75
+ export async function checkPartialLogin(page) {
76
+ return page.evaluate(() => {
77
+ const w = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
78
+ let n;
79
+ while ((n = w.nextNode())) {
80
+ if (n.textContent?.includes('Partial login'))
81
+ return true;
82
+ }
83
+ return false;
84
+ });
85
+ }
@@ -0,0 +1,13 @@
1
+ import type { E2EPage } from './browser.js';
2
+ export interface EthereumMockOpts {
3
+ address: string;
4
+ chainId?: number;
5
+ }
6
+ export declare function ethereumMockCode(opts: EthereumMockOpts): string;
7
+ export declare function eip6963MockCode(opts: EthereumMockOpts & {
8
+ walletName?: string;
9
+ }): string;
10
+ export declare function injectEIP6963(page: E2EPage, opts: EthereumMockOpts & {
11
+ walletName?: string;
12
+ }): Promise<void>;
13
+ //# sourceMappingURL=wallet-mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet-mock.d.ts","sourceRoot":"","sources":["../../src/e2e/wallet-mock.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAsB/D;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,gBAAgB,GAAG;IACvD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,MAAM,CAuCT;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,gBAAgB,GAAG;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,OAAO,CAAC,IAAI,CAAC,CAmBf"}
@@ -0,0 +1,91 @@
1
+ // Wallet mock for E2E tests β€” injects a minimal window.ethereum shim
2
+ // into the browser page. Not detected by wagmi (EIP-6963), but prevents
3
+ // console errors and enables basic dApp interaction.
4
+ //
5
+ // For wagmi/RainbowKit compatibility, use eip6963MockCode() or injectEIP6963().
6
+ export function ethereumMockCode(opts) {
7
+ const addr = opts.address;
8
+ const cid = opts.chainId || 42220;
9
+ const hexChainId = '0x' + cid.toString(16);
10
+ return `
11
+ window.ethereum = {
12
+ isMetaMask: true,
13
+ chainId: '${hexChainId}',
14
+ selectedAddress: '${addr}',
15
+ request: async ({ method, params }) => {
16
+ if (method === 'eth_chainId') return '${hexChainId}'
17
+ if (method === 'eth_accounts') return ['${addr}']
18
+ if (method === 'eth_requestAccounts') return ['${addr}']
19
+ if (method === 'personal_sign') return '0x' + 'ab'.repeat(65)
20
+ if (method === 'wallet_switchEthereumChain') return null
21
+ if (method === 'eth_sendTransaction') return '0x' + 'cd'.repeat(32)
22
+ return null
23
+ },
24
+ on: () => {},
25
+ removeListener: () => {},
26
+ }
27
+ `;
28
+ }
29
+ // Full EIP-6963 mock β€” detected by wagmi/RainbowKit as a connected wallet.
30
+ // Use this when tests need useAccount(), useWalletClient(), or usePublicClient().
31
+ export function eip6963MockCode(opts) {
32
+ const addr = opts.address;
33
+ const cid = opts.chainId || 42220;
34
+ const hexChainId = '0x' + cid.toString(16);
35
+ const walletName = opts.walletName || 'MockWallet';
36
+ return `
37
+ const __provider = {
38
+ isMetaMask: true,
39
+ chainId: '${hexChainId}',
40
+ selectedAddress: '${addr}',
41
+ request: async ({ method, params }) => {
42
+ if (method === 'eth_chainId') return '${hexChainId}'
43
+ if (method === 'eth_accounts') return ['${addr}']
44
+ if (method === 'eth_requestAccounts') return ['${addr}']
45
+ if (method === 'personal_sign') return '0x' + 'ab'.repeat(65)
46
+ if (method === 'wallet_switchEthereumChain') return null
47
+ if (method === 'eth_sendTransaction') return '0x' + 'cd'.repeat(32)
48
+ return null
49
+ },
50
+ on: (event, listener) => {
51
+ if (event === 'accountsChanged') {
52
+ window.__eip6963Listeners = window.__eip6963Listeners || {}
53
+ window.__eip6963Listeners[event] = listener
54
+ }
55
+ },
56
+ removeListener: () => {},
57
+ }
58
+ window.ethereum = __provider
59
+
60
+ const __info = {
61
+ uuid: crypto.randomUUID ? crypto.randomUUID() : 'mock-uuid-0001',
62
+ name: '${walletName}',
63
+ icon: 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>',
64
+ rdns: 'com.mock.wallet',
65
+ }
66
+ window.dispatchEvent(new CustomEvent('eip6963:announceProvider', {
67
+ detail: { info: __info, provider: __provider }
68
+ }))
69
+ `;
70
+ }
71
+ export async function injectEIP6963(page, opts) {
72
+ // Inject provider via evaluateOnNewDocument (runs before page scripts)
73
+ await page.evaluateOnNewDocument(eip6963MockCode(opts));
74
+ // Re-dispatch EIP-6963 event after page loads so wagmi catches it
75
+ page.on('load', async () => {
76
+ await page.evaluate(() => {
77
+ const provider = window.ethereum;
78
+ if (!provider)
79
+ return;
80
+ const info = {
81
+ uuid: crypto.randomUUID ? crypto.randomUUID() : 'mock-uuid-0002',
82
+ name: 'MockWallet',
83
+ icon: 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>',
84
+ rdns: 'com.mock.wallet',
85
+ };
86
+ window.dispatchEvent(new CustomEvent('eip6963:announceProvider', {
87
+ detail: { info, provider }
88
+ }));
89
+ });
90
+ });
91
+ }
@@ -0,0 +1,11 @@
1
+ import type { TranslationSet } from './types.js';
2
+ /**
3
+ * Common CLI translations shared across commands.
4
+ *
5
+ * Fallback: createTranslator uses translations['en'] when the requested
6
+ * locale has no match, so common strings only need 'en' entries.
7
+ * Spanish translations provided when the Spanish string differs.
8
+ */
9
+ declare const commonCli: TranslationSet;
10
+ export default commonCli;
11
+ //# sourceMappingURL=common-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"common-cli.d.ts","sourceRoot":"","sources":["../../src/i18n/common-cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD;;;;;;GAMG;AACH,QAAA,MAAM,SAAS,EAAE,cAahB,CAAA;AAED,eAAe,SAAS,CAAA"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Common CLI translations shared across commands.
3
+ *
4
+ * Fallback: createTranslator uses translations['en'] when the requested
5
+ * locale has no match, so common strings only need 'en' entries.
6
+ * Spanish translations provided when the Spanish string differs.
7
+ */
8
+ const commonCli = {
9
+ en: {
10
+ 'error.generic': 'Error: {{0}}',
11
+ 'success.generic': 'Success: {{0}}',
12
+ 'file.written': 'File written: {{0}}',
13
+ 'clipboard.copied': 'πŸ“‹ Copied to clipboard ({{0}}KB)',
14
+ },
15
+ es: {
16
+ 'error.generic': 'Error: {{0}}',
17
+ 'success.generic': 'Γ‰xito: {{0}}',
18
+ 'file.written': 'Archivo escrito: {{0}}',
19
+ 'clipboard.copied': 'πŸ“‹ Copiado al portapapeles ({{0}}KB)',
20
+ },
21
+ };
22
+ export default commonCli;
@@ -0,0 +1,28 @@
1
+ import type { TranslationSet } from './types.js';
2
+ /**
3
+ * Creates a pure translator function (no hooks, no framework dependencies).
4
+ *
5
+ * Falls back in this order:
6
+ * 1. translations[lang]
7
+ * 2. translations['en']
8
+ * 3. common?.[lang] (if common is provided)
9
+ * 4. common?.['en'] (if common is provided)
10
+ * 5. The raw key as last resort
11
+ *
12
+ * Supports {{0}}, {{1}}, etc. placeholder replacement for interpolation.
13
+ *
14
+ * @param locale Requested locale ('es', 'en', etc. β€” non-es falls to 'en')
15
+ * @param translations Local translations object ({ en: {...}, es: {...} })
16
+ * @param common Optional global/shared translations (same shape)
17
+ * @returns A function t(key, ...args) that returns the translated string
18
+ *
19
+ * @example
20
+ * const t = createTranslator('es', { en: { hello: 'Hello' }, es: { hello: 'Hola' } })
21
+ * t('hello') // β†’ 'Hola'
22
+ *
23
+ * @example
24
+ * const t = createTranslator('es', localT, commonT)
25
+ * t('greeting', 'Mundo') // β†’ 'Hola Mundo' (with {{0}} interpolation)
26
+ */
27
+ export declare function createTranslator(locale: string, translations: TranslationSet, common?: TranslationSet): (key: string, ...args: string[]) => string;
28
+ //# sourceMappingURL=createTranslator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTranslator.d.ts","sourceRoot":"","sources":["../../src/i18n/createTranslator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,YAAY,CAAA;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,cAAc,EAC5B,MAAM,CAAC,EAAE,cAAc,GACtB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,MAAM,CA0B5C"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Creates a pure translator function (no hooks, no framework dependencies).
3
+ *
4
+ * Falls back in this order:
5
+ * 1. translations[lang]
6
+ * 2. translations['en']
7
+ * 3. common?.[lang] (if common is provided)
8
+ * 4. common?.['en'] (if common is provided)
9
+ * 5. The raw key as last resort
10
+ *
11
+ * Supports {{0}}, {{1}}, etc. placeholder replacement for interpolation.
12
+ *
13
+ * @param locale Requested locale ('es', 'en', etc. β€” non-es falls to 'en')
14
+ * @param translations Local translations object ({ en: {...}, es: {...} })
15
+ * @param common Optional global/shared translations (same shape)
16
+ * @returns A function t(key, ...args) that returns the translated string
17
+ *
18
+ * @example
19
+ * const t = createTranslator('es', { en: { hello: 'Hello' }, es: { hello: 'Hola' } })
20
+ * t('hello') // β†’ 'Hola'
21
+ *
22
+ * @example
23
+ * const t = createTranslator('es', localT, commonT)
24
+ * t('greeting', 'Mundo') // β†’ 'Hola Mundo' (with {{0}} interpolation)
25
+ */
26
+ export function createTranslator(locale, translations, common) {
27
+ const lang = locale === 'es' ? 'es' : 'en';
28
+ const resolve = (key) => {
29
+ const dicts = [
30
+ translations[lang],
31
+ translations['en'],
32
+ common?.[lang],
33
+ common?.['en'],
34
+ ];
35
+ for (const d of dicts) {
36
+ const v = d?.[key];
37
+ if (v !== undefined)
38
+ return v;
39
+ }
40
+ return undefined;
41
+ };
42
+ return (key, ...args) => {
43
+ let template = resolve(key);
44
+ if (template === undefined)
45
+ return key;
46
+ return args.reduce((acc, arg, i) => acc.replace(new RegExp(`\\{\\{${i}\\}\\}`, 'g'), arg), template);
47
+ };
48
+ }
@@ -0,0 +1,4 @@
1
+ export type { TranslationSet, LocaleStrings } from './types.js';
2
+ export { createTranslator } from './createTranslator.js';
3
+ export { default as commonCli } from './common-cli.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,2 @@
1
+ export { createTranslator } from './createTranslator.js';
2
+ export { default as commonCli } from './common-cli.js';
@@ -0,0 +1,3 @@
1
+ import type { TranslationSet } from '../types.js';
2
+ export declare const cliTranslations: TranslationSet;
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../../src/i18n/locales/cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,eAAO,MAAM,eAAe,EAAE,cAmL7B,CAAC"}