@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.
- package/dist/blockchain/deployments.d.ts +40 -0
- package/dist/blockchain/deployments.d.ts.map +1 -0
- package/dist/blockchain/deployments.js +64 -0
- package/dist/debug/DebugConsole.d.ts +22 -0
- package/dist/debug/DebugConsole.d.ts.map +1 -0
- package/dist/debug/DebugConsole.js +79 -0
- package/dist/debug/Logger.d.ts +38 -0
- package/dist/debug/Logger.d.ts.map +1 -0
- package/dist/debug/Logger.js +94 -0
- package/dist/debug/index.d.ts +6 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +4 -0
- package/dist/debug/useLogger.d.ts +14 -0
- package/dist/debug/useLogger.d.ts.map +1 -0
- package/dist/debug/useLogger.js +23 -0
- package/dist/debug/utils.d.ts +10 -0
- package/dist/debug/utils.d.ts.map +1 -0
- package/dist/debug/utils.js +53 -0
- package/dist/e2e/assertions.d.ts +5 -0
- package/dist/e2e/assertions.d.ts.map +1 -0
- package/dist/e2e/assertions.js +18 -0
- package/dist/e2e/browser.d.ts +37 -0
- package/dist/e2e/browser.d.ts.map +1 -0
- package/dist/e2e/browser.js +97 -0
- package/dist/e2e/env.d.ts +18 -0
- package/dist/e2e/env.d.ts.map +1 -0
- package/dist/e2e/env.js +57 -0
- package/dist/e2e/index.d.ts +11 -0
- package/dist/e2e/index.d.ts.map +1 -0
- package/dist/e2e/index.js +8 -0
- package/dist/e2e/navigation.d.ts +4 -0
- package/dist/e2e/navigation.d.ts.map +1 -0
- package/dist/e2e/navigation.js +32 -0
- package/dist/e2e/siwe-mock.d.ts +11 -0
- package/dist/e2e/siwe-mock.d.ts.map +1 -0
- package/dist/e2e/siwe-mock.js +112 -0
- package/dist/e2e/siwe.d.ts +15 -0
- package/dist/e2e/siwe.d.ts.map +1 -0
- package/dist/e2e/siwe.js +85 -0
- package/dist/e2e/wallet-mock.d.ts +13 -0
- package/dist/e2e/wallet-mock.d.ts.map +1 -0
- package/dist/e2e/wallet-mock.js +91 -0
- package/dist/i18n/common-cli.d.ts +11 -0
- package/dist/i18n/common-cli.d.ts.map +1 -0
- package/dist/i18n/common-cli.js +22 -0
- package/dist/i18n/createTranslator.d.ts +28 -0
- package/dist/i18n/createTranslator.d.ts.map +1 -0
- package/dist/i18n/createTranslator.js +48 -0
- package/dist/i18n/index.d.ts +4 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/locales/cli.d.ts +3 -0
- package/dist/i18n/locales/cli.d.ts.map +1 -0
- package/dist/i18n/locales/cli.js +180 -0
- package/dist/i18n/types.d.ts +3 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +10 -0
- package/dist/m.d.ts +2 -0
- package/dist/m.d.ts.map +1 -0
- package/dist/m.js +334 -0
- package/dist/plugin.d.ts +10 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +7 -0
- package/dist/shadcn_components/cn.d.ts +13 -0
- package/dist/shadcn_components/cn.d.ts.map +1 -0
- package/dist/shadcn_components/cn.js +15 -0
- package/dist/shadcn_components/ui/accordion.d.ts +8 -0
- package/dist/shadcn_components/ui/accordion.d.ts.map +1 -0
- package/dist/shadcn_components/ui/accordion.js +14 -0
- package/dist/shadcn_components/ui/alert-dialog.d.ts +21 -0
- package/dist/shadcn_components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/shadcn_components/ui/alert-dialog.js +27 -0
- package/dist/shadcn_components/ui/alert.d.ts +9 -0
- package/dist/shadcn_components/ui/alert.d.ts.map +1 -0
- package/dist/shadcn_components/ui/alert.js +22 -0
- package/dist/shadcn_components/ui/avatar.d.ts +7 -0
- package/dist/shadcn_components/ui/avatar.d.ts.map +1 -0
- package/dist/shadcn_components/ui/avatar.js +12 -0
- package/dist/shadcn_components/ui/badge.d.ts +10 -0
- package/dist/shadcn_components/ui/badge.d.ts.map +1 -0
- package/dist/shadcn_components/ui/badge.js +22 -0
- package/dist/shadcn_components/ui/button.d.ts +11 -0
- package/dist/shadcn_components/ui/button.d.ts.map +1 -0
- package/dist/shadcn_components/ui/button.js +31 -0
- package/dist/shadcn_components/ui/card.d.ts +10 -0
- package/dist/shadcn_components/ui/card.d.ts.map +1 -0
- package/dist/shadcn_components/ui/card.js +24 -0
- package/dist/shadcn_components/ui/checkbox.d.ts +5 -0
- package/dist/shadcn_components/ui/checkbox.d.ts.map +1 -0
- package/dist/shadcn_components/ui/checkbox.js +9 -0
- package/dist/shadcn_components/ui/dialog.d.ts +20 -0
- package/dist/shadcn_components/ui/dialog.d.ts.map +1 -0
- package/dist/shadcn_components/ui/dialog.js +23 -0
- package/dist/shadcn_components/ui/dropdown-menu.d.ts +28 -0
- package/dist/shadcn_components/ui/dropdown-menu.d.ts.map +1 -0
- package/dist/shadcn_components/ui/dropdown-menu.js +36 -0
- package/dist/shadcn_components/ui/form.d.ts +24 -0
- package/dist/shadcn_components/ui/form.d.ts.map +1 -0
- package/dist/shadcn_components/ui/form.js +63 -0
- package/dist/shadcn_components/ui/input.d.ts +4 -0
- package/dist/shadcn_components/ui/input.d.ts.map +1 -0
- package/dist/shadcn_components/ui/input.js +6 -0
- package/dist/shadcn_components/ui/label.d.ts +6 -0
- package/dist/shadcn_components/ui/label.d.ts.map +1 -0
- package/dist/shadcn_components/ui/label.js +10 -0
- package/dist/shadcn_components/ui/menubar.d.ts +29 -0
- package/dist/shadcn_components/ui/menubar.d.ts.map +1 -0
- package/dist/shadcn_components/ui/menubar.js +46 -0
- package/dist/shadcn_components/ui/popover.d.ts +7 -0
- package/dist/shadcn_components/ui/popover.d.ts.map +1 -0
- package/dist/shadcn_components/ui/popover.js +10 -0
- package/dist/shadcn_components/ui/progress.d.ts +5 -0
- package/dist/shadcn_components/ui/progress.d.ts.map +1 -0
- package/dist/shadcn_components/ui/progress.js +8 -0
- package/dist/shadcn_components/ui/radio-group.d.ts +6 -0
- package/dist/shadcn_components/ui/radio-group.d.ts.map +1 -0
- package/dist/shadcn_components/ui/radio-group.js +15 -0
- package/dist/shadcn_components/ui/scroll-area.d.ts +6 -0
- package/dist/shadcn_components/ui/scroll-area.d.ts.map +1 -0
- package/dist/shadcn_components/ui/scroll-area.js +12 -0
- package/dist/shadcn_components/ui/select.d.ts +14 -0
- package/dist/shadcn_components/ui/select.d.ts.map +1 -0
- package/dist/shadcn_components/ui/select.js +27 -0
- package/dist/shadcn_components/ui/separator.d.ts +5 -0
- package/dist/shadcn_components/ui/separator.d.ts.map +1 -0
- package/dist/shadcn_components/ui/separator.js +8 -0
- package/dist/shadcn_components/ui/sheet.d.ts +26 -0
- package/dist/shadcn_components/ui/sheet.d.ts.map +1 -0
- package/dist/shadcn_components/ui/sheet.js +37 -0
- package/dist/shadcn_components/ui/skeleton.d.ts +3 -0
- package/dist/shadcn_components/ui/skeleton.d.ts.map +1 -0
- package/dist/shadcn_components/ui/skeleton.js +6 -0
- package/dist/shadcn_components/ui/slider.d.ts +5 -0
- package/dist/shadcn_components/ui/slider.d.ts.map +1 -0
- package/dist/shadcn_components/ui/slider.js +8 -0
- package/dist/shadcn_components/ui/switch.d.ts +5 -0
- package/dist/shadcn_components/ui/switch.d.ts.map +1 -0
- package/dist/shadcn_components/ui/switch.js +8 -0
- package/dist/shadcn_components/ui/table.d.ts +11 -0
- package/dist/shadcn_components/ui/table.d.ts.map +1 -0
- package/dist/shadcn_components/ui/table.js +20 -0
- package/dist/shadcn_components/ui/tabs.d.ts +8 -0
- package/dist/shadcn_components/ui/tabs.d.ts.map +1 -0
- package/dist/shadcn_components/ui/tabs.js +13 -0
- package/dist/shadcn_components/ui/textarea.d.ts +4 -0
- package/dist/shadcn_components/ui/textarea.d.ts.map +1 -0
- package/dist/shadcn_components/ui/textarea.js +8 -0
- package/dist/shadcn_components/ui/toast.d.ts +16 -0
- package/dist/shadcn_components/ui/toast.d.ts.map +1 -0
- package/dist/shadcn_components/ui/toast.js +34 -0
- package/dist/shadcn_components/ui/toaster.d.ts +2 -0
- package/dist/shadcn_components/ui/toaster.d.ts.map +1 -0
- package/dist/shadcn_components/ui/toaster.js +10 -0
- package/dist/shadcn_components/ui/tooltip.d.ts +8 -0
- package/dist/shadcn_components/ui/tooltip.d.ts.map +1 -0
- package/dist/shadcn_components/ui/tooltip.js +11 -0
- package/dist/shadcn_components/ui/use-toast.d.ts +45 -0
- package/dist/shadcn_components/ui/use-toast.d.ts.map +1 -0
- package/dist/shadcn_components/ui/use-toast.js +126 -0
- package/dist/tasks/context.d.ts +13 -0
- package/dist/tasks/context.d.ts.map +1 -0
- package/dist/tasks/context.js +310 -0
- package/dist/tasks/create.d.ts +2 -0
- package/dist/tasks/create.d.ts.map +1 -0
- package/dist/tasks/create.js +91 -0
- package/dist/tasks/db.d.ts +19 -0
- package/dist/tasks/db.d.ts.map +1 -0
- package/dist/tasks/db.js +791 -0
- package/dist/tasks/e2e.d.ts +2 -0
- package/dist/tasks/e2e.d.ts.map +1 -0
- package/dist/tasks/e2e.js +124 -0
- package/dist/tasks/edit.d.ts +7 -0
- package/dist/tasks/edit.d.ts.map +1 -0
- package/dist/tasks/edit.js +471 -0
- package/dist/tasks/engine.d.ts +2 -0
- package/dist/tasks/engine.d.ts.map +1 -0
- package/dist/tasks/engine.js +149 -0
- package/dist/tasks/env-diff.d.ts +2 -0
- package/dist/tasks/env-diff.d.ts.map +1 -0
- package/dist/tasks/env-diff.js +140 -0
- package/dist/tasks/fuzzy.d.ts +9 -0
- package/dist/tasks/fuzzy.d.ts.map +1 -0
- package/dist/tasks/fuzzy.js +153 -0
- package/dist/tasks/glob.d.ts +5 -0
- package/dist/tasks/glob.d.ts.map +1 -0
- package/dist/tasks/glob.js +57 -0
- package/dist/tasks/grep.d.ts +9 -0
- package/dist/tasks/grep.d.ts.map +1 -0
- package/dist/tasks/grep.js +93 -0
- package/dist/tasks/readfile.d.ts +2 -0
- package/dist/tasks/readfile.d.ts.map +1 -0
- package/dist/tasks/readfile.js +177 -0
- package/dist/tasks/update.d.ts +5 -0
- package/dist/tasks/update.d.ts.map +1 -0
- package/dist/tasks/update.js +200 -0
- package/dist/tasks/util.d.ts +12 -0
- package/dist/tasks/util.d.ts.map +1 -0
- package/dist/tasks/util.js +42 -0
- package/dist/tasks/wallet.d.ts +2 -0
- package/dist/tasks/wallet.d.ts.map +1 -0
- package/dist/tasks/wallet.js +697 -0
- package/dist/tasks/writefile.d.ts +2 -0
- package/dist/tasks/writefile.d.ts.map +1 -0
- package/dist/tasks/writefile.js +66 -0
- package/dist/templates/AGENTS.md.hbs +81 -0
- package/dist/templates/ARCHITECTURE.md.hbs +146 -0
- package/dist/templates/CONTRIBUTING.md.hbs +83 -0
- package/dist/templates/LICENCIA.md +21 -0
- package/dist/templates/LICENSE.md +15 -0
- package/dist/templates/Makefile +16 -0
- package/dist/templates/README.md.hbs +111 -0
- package/dist/templates/apps/.env.example.hbs +75 -0
- package/dist/templates/apps/hardhat/.prettierrc +16 -0
- package/dist/templates/apps/hardhat/MOCK_USDT_README.md +20 -0
- package/dist/templates/apps/hardhat/Makefile +13 -0
- package/dist/templates/apps/hardhat/README.md +129 -0
- package/dist/templates/apps/hardhat/bin/MusdtVerification +4 -0
- package/dist/templates/apps/hardhat/bin/approveDepositOwner +7 -0
- package/dist/templates/apps/hardhat/bin/contractVerification +9 -0
- package/dist/templates/apps/hardhat/bin/deployMockUSDT +7 -0
- package/dist/templates/apps/hardhat/bin/prepadJ.sh +14 -0
- package/dist/templates/apps/hardhat/bin/verifyMockUSDT +7 -0
- package/dist/templates/apps/hardhat/contracts/MockUSDT.sol +47 -0
- package/dist/templates/apps/hardhat/hardhat.config.ts +102 -0
- package/dist/templates/apps/hardhat/package.json +55 -0
- package/dist/templates/apps/hardhat/scripts/approveDepositOwner.ts +22 -0
- package/dist/templates/apps/hardhat/scripts/deployMockUSDT.ts +49 -0
- package/dist/templates/apps/hardhat/scripts/verifyDeployment.ts +93 -0
- package/dist/templates/apps/hardhat/scripts/verifyMockUSDT.ts +52 -0
- package/dist/templates/apps/hardhat/sync-abis.mjs +58 -0
- package/dist/templates/apps/hardhat/test/MockUSDT.test.ts +40 -0
- package/dist/templates/apps/hardhat/tsconfig.json +27 -0
- package/dist/templates/apps/nextjs/.config/kysely.config.ts +36 -0
- package/dist/templates/apps/nextjs/Makefile +24 -0
- package/dist/templates/apps/nextjs/README.md.hbs +76 -0
- package/dist/templates/apps/nextjs/abis/IERC20.json +74 -0
- package/dist/templates/apps/nextjs/abis/MockUSDT.json +242 -0
- package/dist/templates/apps/nextjs/abis/ReentrancyGuard.json +1 -0
- package/dist/templates/apps/nextjs/app/globals.css +3 -0
- package/dist/templates/apps/nextjs/app/layout.tsx.hbs +26 -0
- package/dist/templates/apps/nextjs/app/page.tsx.hbs +225 -0
- package/dist/templates/apps/nextjs/app/testui/page.tsx +371 -0
- package/dist/templates/apps/nextjs/bin/m +8 -0
- package/dist/templates/apps/nextjs/components.json +21 -0
- package/dist/templates/apps/nextjs/next-env.d.ts +5 -0
- package/dist/templates/apps/nextjs/next.config.ts +10 -0
- package/dist/templates/apps/nextjs/package.json.hbs +48 -0
- package/dist/templates/apps/nextjs/pnpm-workspace.yaml +13 -0
- package/dist/templates/apps/nextjs/postcss.config.mjs +6 -0
- package/dist/templates/apps/nextjs/tailwind.config.js +11 -0
- package/dist/templates/apps/nextjs/tests/helpers.ts +31 -0
- package/dist/templates/apps/nextjs/tests/index.test.ts +7 -0
- package/dist/templates/apps/nextjs/tests/setup-env.ts.hbs +8 -0
- package/dist/templates/apps/nextjs/tests/test-utils.example.test.ts +168 -0
- package/dist/templates/apps/nextjs/tsconfig.json +44 -0
- package/dist/templates/apps/nextjs/tsconfig.test.json +38 -0
- package/dist/templates/apps/nextjs/vitest.config.ts +13 -0
- package/dist/test-utils/fs-mocks.d.ts +32 -0
- package/dist/test-utils/fs-mocks.d.ts.map +1 -0
- package/dist/test-utils/fs-mocks.js +63 -0
- package/dist/test-utils/i18n-mock.d.ts +21 -0
- package/dist/test-utils/i18n-mock.d.ts.map +1 -0
- package/dist/test-utils/i18n-mock.js +29 -0
- package/dist/test-utils/index.d.ts +12 -0
- package/dist/test-utils/index.d.ts.map +1 -0
- package/dist/test-utils/index.js +11 -0
- package/dist/test-utils/kysely-mocks.d.ts +298 -0
- package/dist/test-utils/kysely-mocks.d.ts.map +1 -0
- package/dist/test-utils/kysely-mocks.js +173 -0
- package/dist/test-utils/radix-mocks.d.ts +134 -0
- package/dist/test-utils/radix-mocks.d.ts.map +1 -0
- package/dist/test-utils/radix-mocks.js +175 -0
- package/dist/test-utils/rainbowkit-mocks.d.ts +80 -0
- package/dist/test-utils/rainbowkit-mocks.d.ts.map +1 -0
- package/dist/test-utils/rainbowkit-mocks.js +247 -0
- package/dist/test-utils/viem-mocks.d.ts +86 -0
- package/dist/test-utils/viem-mocks.d.ts.map +1 -0
- package/dist/test-utils/viem-mocks.js +54 -0
- package/dist/util/cli-parser.d.ts +20 -0
- package/dist/util/cli-parser.d.ts.map +1 -0
- package/dist/util/cli-parser.js +38 -0
- package/dist/util/colors.d.ts +5 -0
- package/dist/util/colors.d.ts.map +1 -0
- package/dist/util/colors.js +5 -0
- package/dist/util/locale.d.ts +3 -0
- package/dist/util/locale.d.ts.map +1 -0
- package/dist/util/locale.js +10 -0
- package/dist/wba/client.d.ts +19 -0
- package/dist/wba/client.d.ts.map +1 -0
- package/dist/wba/client.js +31 -0
- package/dist/wba/index.d.ts +4 -0
- package/dist/wba/index.d.ts.map +1 -0
- package/dist/wba/index.js +2 -0
- package/dist/wba/routes/event.d.ts +32 -0
- package/dist/wba/routes/event.d.ts.map +1 -0
- package/dist/wba/routes/event.js +42 -0
- package/dist/wba/routes/index.d.ts +3 -0
- package/dist/wba/routes/index.d.ts.map +1 -0
- package/dist/wba/routes/index.js +2 -0
- package/dist/wba/routes/summary.d.ts +44 -0
- package/dist/wba/routes/summary.d.ts.map +1 -0
- package/dist/wba/routes/summary.js +146 -0
- package/dist/wba/server.d.ts +18 -0
- package/dist/wba/server.d.ts.map +1 -0
- package/dist/wba/server.js +29 -0
- package/dist/wba/types.d.ts +68 -0
- package/dist/wba/types.d.ts.map +1 -0
- package/dist/wba/types.js +6 -0
- package/package.json +223 -0
- package/src/blockchain/README.md +80 -0
- package/src/debug/README.md +94 -0
- package/src/e2e/README.md +105 -0
- package/src/i18n/README.md +143 -0
- package/src/shadcn_components/README.md +125 -0
- package/src/tasks/README.md +69 -0
- package/src/test-utils/README.md +638 -0
- package/src/util/README.md +18 -0
- 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"}
|
package/dist/e2e/env.js
ADDED
|
@@ -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"}
|
package/dist/e2e/siwe.js
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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"}
|