@deeeed/metamask-harness 0.5.0 → 0.6.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/CHANGELOG.md +51 -20
- package/adapters/core/inject.sh +1 -0
- package/adapters/extension/cleanup.mjs +1 -1
- package/adapters/extension/inject.mjs +4 -1
- package/adapters/extension/launch-browser.cjs +18 -4
- package/adapters/extension/live.sh +14 -2
- package/adapters/extension/refresh-build.sh +2 -2
- package/adapters/extension/sidepanel-toggle.sh +33 -12
- package/adapters/extension/start-watch.sh +2 -2
- package/adapters/extension/wallet-fixture-state.cjs +38 -24
- package/adapters/manifest.json +32 -3
- package/adapters/mobile/inject.sh +1 -0
- package/adapters/mobile/start-metro.sh +1 -1
- package/adapters/mobile/stop-metro.sh +20 -0
- package/adapters/mobile/verify.sh +1 -1
- package/adapters/shared/activate-repo-node.sh +1 -1
- package/adapters/shared/cli-ux.sh +44 -25
- package/adapters/shared/ensure-runner-deps.sh +30 -0
- package/adapters/shared/log-tui.mjs +4 -4
- package/adapters/shared/open-debug.mjs +1 -1
- package/adapters/shared/reap-checkout-metros.sh +53 -0
- package/adapters/shared/recipe-harness-root.mjs +23 -0
- package/adapters/shared/resolve-farmslot-ports-core.mjs +205 -0
- package/adapters/shared/resolve-farmslot-ports.mjs +20 -0
- package/adapters/shared/resolve-farmslot-ports.sh +19 -126
- package/bin/mm-harness +45 -4
- package/dist/adapters/extension/runtime.js +3 -1
- package/dist/adapters/mobile/provision.js +34 -1
- package/dist/adapters/mobile/runtime-decision.js +3 -1
- package/dist/adapters/resolve-farmslot-ports.js +22 -0
- package/dist/adapters/slot-ports.js +18 -29
- package/dist/cli.js +32 -1463
- package/dist/commands/call.js +183 -0
- package/dist/commands/completion-candidates.js +58 -0
- package/dist/commands/doctor.js +101 -0
- package/dist/commands/ensure-ready.js +24 -0
- package/dist/commands/flows.js +62 -0
- package/dist/commands/launch/extension.js +40 -0
- package/dist/commands/{launch.js → launch/index.js} +15 -47
- package/dist/commands/launch/mobile.js +10 -0
- package/dist/commands/manifest.js +72 -0
- package/dist/commands/parse-args.js +189 -0
- package/dist/commands/provision.js +136 -0
- package/dist/commands/resolve-extension.js +23 -0
- package/dist/commands/run-engine.js +341 -0
- package/dist/commands/run.js +217 -0
- package/dist/commands/runtime-decision.js +58 -0
- package/dist/commands/runtime-health.js +25 -0
- package/dist/commands/runtime-launch.js +139 -0
- package/dist/commands/self-test.js +52 -0
- package/dist/commands/stop.js +52 -0
- package/dist/harness.js +8 -48
- package/dist/mm-harness-cli.js +13 -8
- package/docs/CLI-SPEC.md +1 -1
- package/docs/CODE-MAP.md +62 -0
- package/library/README.md +14 -0
- package/library/actions/core/perps/_controller.mjs +1 -1
- package/library/actions/extension/platform/cdp.mjs +2 -2
- package/library/actions/extension/wallet/ensure_unlocked.mjs +7 -1
- package/library/actions/harness-exports.mjs +27 -0
- package/library/actions/mobile/wallet/ensure_unlocked.mjs +14 -2
- package/library/actions/mobile/wallet/setup.mjs +1 -1
- package/package.json +6 -7
- package/src/adapters/core/surface.ts +0 -71
- package/src/adapters/extension/ensure-ready.ts +0 -185
- package/src/adapters/extension/extension-id.ts +0 -107
- package/src/adapters/extension/runtime-decision.ts +0 -445
- package/src/adapters/extension/runtime.ts +0 -407
- package/src/adapters/extension/surface.ts +0 -88
- package/src/adapters/mobile/deps-markers.ts +0 -21
- package/src/adapters/mobile/prepare.ts +0 -246
- package/src/adapters/mobile/provision.ts +0 -594
- package/src/adapters/mobile/runtime-decision.ts +0 -459
- package/src/adapters/mobile/surface.ts +0 -71
- package/src/adapters/slot-ports.ts +0 -165
- package/src/adapters/surface.ts +0 -117
- package/src/adapters.ts +0 -601
- package/src/cli-color.ts +0 -92
- package/src/cli-commands.ts +0 -250
- package/src/cli-version.ts +0 -141
- package/src/cli.ts +0 -2091
- package/src/commands/debug.ts +0 -65
- package/src/commands/fixtures.ts +0 -198
- package/src/commands/launch.ts +0 -470
- package/src/commands/logs.ts +0 -99
- package/src/commands/shared.ts +0 -235
- package/src/commands/update.ts +0 -316
- package/src/completions-cache.ts +0 -86
- package/src/doctor.ts +0 -215
- package/src/harness.ts +0 -797
- package/src/heal-bounds.ts +0 -198
- package/src/index.ts +0 -15
- package/src/leaf-invoke.ts +0 -28
- package/src/live-adapter-contract.ts +0 -274
- package/src/manifest.ts +0 -47
- package/src/mm-harness-cli.ts +0 -655
- package/src/paths.ts +0 -198
- package/src/progress.ts +0 -117
- package/src/recording-target.ts +0 -147
- package/src/run-recording.ts +0 -329
- package/src/runner.ts +0 -108
- package/src/types.ts +0 -57
package/src/commands/debug.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// debug — open the debug console by composing open-debug.mjs directly:
|
|
2
|
-
// extension `debug` (--worker → service-worker target); mobile `debug`
|
|
3
|
-
// (--dev-menu → developer menu). Cross-platform flag misuse teaches (exit 2).
|
|
4
|
-
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
|
|
7
|
-
import { runnerDir } from '../paths.ts';
|
|
8
|
-
import { getAdapterSurface } from '../adapters/surface.ts';
|
|
9
|
-
import { ADAPTER_DETECT_NEXT, EXIT, flag, parseFlags, resolveAdapter, spawnScript, targetOf, usageOut } from './shared.ts';
|
|
10
|
-
|
|
11
|
-
const DEBUG_BOOLEANS = new Set(['worker', 'devMenu', 'json']);
|
|
12
|
-
|
|
13
|
-
export async function handleDebug(argv: string[]): Promise<number> {
|
|
14
|
-
const { options } = parseFlags(argv, DEBUG_BOOLEANS);
|
|
15
|
-
const json = flag(options, 'json');
|
|
16
|
-
const target = targetOf(options);
|
|
17
|
-
const adapter = resolveAdapter(options, target);
|
|
18
|
-
|
|
19
|
-
if (!adapter) return usageOut(json, 'debug', `could not detect the MetaMask repo type for ${target}`, ADAPTER_DETECT_NEXT);
|
|
20
|
-
const surface = getAdapterSurface(adapter);
|
|
21
|
-
if (surface.headless) return usageOut(json, 'debug', 'core is headless; there is no debug console.', surface.hints.relaunch);
|
|
22
|
-
|
|
23
|
-
const worker = flag(options, 'worker');
|
|
24
|
-
const devMenu = flag(options, 'devMenu');
|
|
25
|
-
if (adapter === 'mobile' && worker) {
|
|
26
|
-
return usageOut(
|
|
27
|
-
json,
|
|
28
|
-
'debug',
|
|
29
|
-
'--worker is extension-only (service-worker DevTools). Use --dev-menu on mobile.',
|
|
30
|
-
'mm-harness debug --dev-menu',
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
if (adapter === 'extension' && devMenu) {
|
|
34
|
-
return usageOut(
|
|
35
|
-
json,
|
|
36
|
-
'debug',
|
|
37
|
-
'--dev-menu is mobile-only (RN developer menu). Use --worker on the extension.',
|
|
38
|
-
'mm-harness debug --worker',
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const openDebug = path.join(runnerDir, 'adapters/shared/open-debug.mjs');
|
|
43
|
-
const debugArgs: string[] = ['--adapter', adapter];
|
|
44
|
-
|
|
45
|
-
if (adapter === 'extension') {
|
|
46
|
-
if (process.env.CDP_PORT) debugArgs.push('--cdp-port', process.env.CDP_PORT);
|
|
47
|
-
debugArgs.push('--target', worker ? 'worker' : 'page');
|
|
48
|
-
} else {
|
|
49
|
-
if (process.env.WATCHER_PORT) debugArgs.push('--port', process.env.WATCHER_PORT);
|
|
50
|
-
debugArgs.push('--action', devMenu ? 'dev-menu' : 'debug');
|
|
51
|
-
}
|
|
52
|
-
if (json) debugArgs.push('--json');
|
|
53
|
-
|
|
54
|
-
const result = spawnScript(process.execPath, [openDebug, ...debugArgs], target, json);
|
|
55
|
-
if (json) {
|
|
56
|
-
console.log(
|
|
57
|
-
JSON.stringify(
|
|
58
|
-
{ schemaVersion: 1, command: 'debug', adapter, mode: worker ? 'worker' : devMenu ? 'dev-menu' : 'default', exitCode: result.status === 0 ? EXIT.ok : EXIT.runtime },
|
|
59
|
-
null,
|
|
60
|
-
2,
|
|
61
|
-
),
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
return result.status === 0 ? EXIT.ok : EXIT.runtime;
|
|
65
|
-
}
|
package/src/commands/fixtures.ts
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
// fixtures <sync|set> — manage wallet DATA (never overlay/runtime state). `sync`
|
|
2
|
-
// re-renders the wallet fixture files; `set` applies THE canonical fixture (SRP/
|
|
3
|
-
// password read FROM the fixture, never typed) and always teaches the edit path.
|
|
4
|
-
|
|
5
|
-
import fs from 'node:fs';
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
|
|
8
|
-
import { runnerDir, walletFixturePath } from '../paths.ts';
|
|
9
|
-
import { getAdapterSurface } from '../adapters/surface.ts';
|
|
10
|
-
import type { MetaMaskRecipeAdapter } from '../types.ts';
|
|
11
|
-
import { ADAPTER_DETECT_NEXT, EXIT, flag, parseFlags, resolveAdapter, spawnScript, str, targetOf, usageOut } from './shared.ts';
|
|
12
|
-
|
|
13
|
-
// One node injected from cli.ts so `fixtures set` can reuse the real engine path
|
|
14
|
-
// (`call`'s one-node machinery) without a circular import.
|
|
15
|
-
export interface CommandDeps {
|
|
16
|
-
runOneNode: (
|
|
17
|
-
adapter: MetaMaskRecipeAdapter,
|
|
18
|
-
action: string,
|
|
19
|
-
args: Record<string, string>,
|
|
20
|
-
target: string,
|
|
21
|
-
actionManifest: string | undefined,
|
|
22
|
-
) => Promise<{ status: 'pass' | 'fail' }>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const FIXTURES_BOOLEANS = new Set(['json']);
|
|
26
|
-
|
|
27
|
-
// Patterns indicating setup-wallet failed due to a Metro/bridge issue (not a bad
|
|
28
|
-
// fixture). A clean Metro restart + relaunch is likely to resolve these.
|
|
29
|
-
// Mirrors baseline mm-recipe:820-824 setup_wallet_failure_recoverable patterns.
|
|
30
|
-
const RECOVERABLE_SETUP_WALLET_PATTERNS = [
|
|
31
|
-
'CDP not reachable',
|
|
32
|
-
'CDP bridge',
|
|
33
|
-
'is not installed',
|
|
34
|
-
'Engine.context.KeyringController not available',
|
|
35
|
-
'Engine does not exist',
|
|
36
|
-
"Cannot read property 'transactions'",
|
|
37
|
-
'bridge-not-ready',
|
|
38
|
-
'debug-target-missing',
|
|
39
|
-
'CDP eval failed',
|
|
40
|
-
'CDP eval-async failed',
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
function isRecoverableSetupWalletFailure(output: string): boolean {
|
|
44
|
-
return RECOVERABLE_SETUP_WALLET_PATTERNS.some((p) => output.includes(p));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function handleFixtures(argv: string[], deps: CommandDeps): Promise<number> {
|
|
48
|
-
const { positional, options } = parseFlags(argv, FIXTURES_BOOLEANS);
|
|
49
|
-
const json = flag(options, 'json');
|
|
50
|
-
const sub = positional[0];
|
|
51
|
-
if (sub !== 'sync' && sub !== 'set') {
|
|
52
|
-
return usageOut(json, 'fixtures', 'fixtures requires a subcommand: mm-harness fixtures <sync|set>', 'mm-harness fixtures sync or mm-harness fixtures set');
|
|
53
|
-
}
|
|
54
|
-
const target = targetOf(options);
|
|
55
|
-
const adapter = resolveAdapter(options, target);
|
|
56
|
-
if (!adapter) {
|
|
57
|
-
return usageOut(json, 'fixtures', `could not detect the MetaMask repo type for ${target}`, ADAPTER_DETECT_NEXT);
|
|
58
|
-
}
|
|
59
|
-
const surface = getAdapterSurface(adapter);
|
|
60
|
-
if (surface.headless) return usageOut(json, 'fixtures', 'core is headless; it has no wallet fixture.', surface.hints.launch);
|
|
61
|
-
|
|
62
|
-
const canonicalFixture = walletFixturePath(target);
|
|
63
|
-
// Platform-phrased retry hint on a setup-wallet failure: the surface owns the
|
|
64
|
-
// (re)build/relaunch command; this command never spells out another platform's.
|
|
65
|
-
const retryHint = `${surface.hints.relaunch} # relaunch, then retry: mm-harness fixtures set`;
|
|
66
|
-
|
|
67
|
-
if (sub === 'sync') {
|
|
68
|
-
const exitCode = fixturesSync(adapter, target, json);
|
|
69
|
-
if (json) {
|
|
70
|
-
console.log(
|
|
71
|
-
JSON.stringify(
|
|
72
|
-
{ schemaVersion: 1, command: 'fixtures', action: 'sync', adapter, fixture: canonicalFixture, exitCode },
|
|
73
|
-
null,
|
|
74
|
-
2,
|
|
75
|
-
),
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
return exitCode;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// set — apply THE canonical wallet fixture (password read FROM the fixture).
|
|
82
|
-
// Env-gap resolution (docs/CLI-SPEC.md Part 4): flag > env RECIPE_WALLET_FIXTURE
|
|
83
|
-
// > the slot's canonical fixture.
|
|
84
|
-
const fixturePath = path.resolve(str(options, 'fixture') ?? process.env.RECIPE_WALLET_FIXTURE ?? canonicalFixture);
|
|
85
|
-
let status: 'pass' | 'fail';
|
|
86
|
-
if (adapter === 'mobile') {
|
|
87
|
-
// Compose setup-wallet.sh directly (requires bridge to be live).
|
|
88
|
-
const setupWalletSh = path.join(runnerDir, 'adapters/mobile/bridge-runtime/setup-wallet.sh');
|
|
89
|
-
const previousAppRoot = process.env.APP_ROOT;
|
|
90
|
-
process.env.APP_ROOT = target;
|
|
91
|
-
try {
|
|
92
|
-
let result = spawnScript(setupWalletSh, ['--fixture', fixturePath], target, json);
|
|
93
|
-
// One clean-Metro auto-retry on recoverable failures (CDP unreachable, bridge
|
|
94
|
-
// not installed). RECIPE_SETUP_WALLET_RETRIED guards against infinite loops.
|
|
95
|
-
if (result.status !== 0 && isRecoverableSetupWalletFailure(result.output) && !process.env['RECIPE_SETUP_WALLET_RETRIED']) {
|
|
96
|
-
process.env['RECIPE_SETUP_WALLET_RETRIED'] = '1';
|
|
97
|
-
if (!json) process.stderr.write(' setup-wallet: recoverable failure — restarting Metro and retrying\n Next: wait for relaunch, then wallet setup will retry automatically\n');
|
|
98
|
-
const { prepareMobile } = await import('../adapters/mobile/prepare.ts');
|
|
99
|
-
const platform = str(options, 'platform') ?? process.env['MOBILE_PLATFORM'] ?? 'ios';
|
|
100
|
-
const relaunchResult = await prepareMobile(target, { platform, json, preflightMode: 'auto', clearMetro: true });
|
|
101
|
-
if (relaunchResult.status === 0) {
|
|
102
|
-
result = spawnScript(setupWalletSh, ['--fixture', fixturePath], target, json);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
status = result.status === 0 ? 'pass' : 'fail';
|
|
106
|
-
} finally {
|
|
107
|
-
delete process.env['RECIPE_SETUP_WALLET_RETRIED'];
|
|
108
|
-
if (previousAppRoot === undefined) delete process.env.APP_ROOT;
|
|
109
|
-
else process.env.APP_ROOT = previousAppRoot;
|
|
110
|
-
}
|
|
111
|
-
if (!json && status === 'fail') {
|
|
112
|
-
console.error(` Next: ${retryHint}`);
|
|
113
|
-
}
|
|
114
|
-
} else {
|
|
115
|
-
// Extension has no standalone set arm — reuse call's one-node machinery via
|
|
116
|
-
// the real engine path (metamask.wallet.setup in the manifest).
|
|
117
|
-
if (!fs.existsSync(fixturePath)) {
|
|
118
|
-
return usageOut(
|
|
119
|
-
json,
|
|
120
|
-
'fixtures',
|
|
121
|
-
`no wallet fixture at ${fixturePath}.`,
|
|
122
|
-
'create it (or pass --fixture <path>), then re-run: mm-harness fixtures set',
|
|
123
|
-
);
|
|
124
|
-
}
|
|
125
|
-
const previousFixtureEnv = process.env.RECIPE_WALLET_FIXTURE;
|
|
126
|
-
process.env.RECIPE_WALLET_FIXTURE = fixturePath;
|
|
127
|
-
try {
|
|
128
|
-
const result = await deps.runOneNode('extension', 'metamask.wallet.setup', {}, target, str(options, 'actionManifest'));
|
|
129
|
-
status = result.status;
|
|
130
|
-
} finally {
|
|
131
|
-
if (previousFixtureEnv === undefined) delete process.env.RECIPE_WALLET_FIXTURE;
|
|
132
|
-
else process.env.RECIPE_WALLET_FIXTURE = previousFixtureEnv;
|
|
133
|
-
}
|
|
134
|
-
if (!json && status === 'fail') {
|
|
135
|
-
console.error(` Next: ${retryHint}`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Always teach where to customize the wallet.
|
|
140
|
-
const teaching = `Wallet fixture applied. Want different accounts? Edit: ${canonicalFixture}`;
|
|
141
|
-
if (json) {
|
|
142
|
-
console.log(
|
|
143
|
-
JSON.stringify(
|
|
144
|
-
{
|
|
145
|
-
schemaVersion: 1,
|
|
146
|
-
command: 'fixtures',
|
|
147
|
-
action: 'set',
|
|
148
|
-
adapter,
|
|
149
|
-
fixture: fixturePath,
|
|
150
|
-
canonicalFixture,
|
|
151
|
-
status,
|
|
152
|
-
exitCode: status === 'pass' ? EXIT.ok : EXIT.runtime,
|
|
153
|
-
message: teaching,
|
|
154
|
-
error: status === 'fail' ? {
|
|
155
|
-
code: 'SETUP_WALLET_FAILED',
|
|
156
|
-
message: 'wallet fixture setup failed',
|
|
157
|
-
userAction: retryHint,
|
|
158
|
-
} : null,
|
|
159
|
-
},
|
|
160
|
-
null,
|
|
161
|
-
2,
|
|
162
|
-
),
|
|
163
|
-
);
|
|
164
|
-
} else {
|
|
165
|
-
console.error(teaching);
|
|
166
|
-
}
|
|
167
|
-
return status === 'pass' ? EXIT.ok : EXIT.runtime;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Sync the overlay installation + wallet fixture for the checkout.
|
|
171
|
-
// Re-runs the adapter inject to refresh patched files, then copies the wallet
|
|
172
|
-
// fixture to the canonical runtime location via sync-wallet-fixture.sh. Reached
|
|
173
|
-
// only for device adapters (headless core returns earlier); the adapter is
|
|
174
|
-
// forwarded verbatim to `install`.
|
|
175
|
-
function fixturesSync(adapter: MetaMaskRecipeAdapter, target: string, json: boolean): number {
|
|
176
|
-
const mmHarnessBin = path.join(runnerDir, 'bin/mm-harness');
|
|
177
|
-
const installResult = spawnScript(
|
|
178
|
-
mmHarnessBin,
|
|
179
|
-
['install', '--adapter', adapter, '--target', target],
|
|
180
|
-
target,
|
|
181
|
-
json,
|
|
182
|
-
);
|
|
183
|
-
if (installResult.status !== 0) {
|
|
184
|
-
if (!json) {
|
|
185
|
-
console.error(`✗ mm-harness fixtures sync: overlay reinstall failed.\n Next: mm-harness install --target ${target} # diagnose the install failure`);
|
|
186
|
-
}
|
|
187
|
-
return EXIT.runtime;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const syncFixtureSh = path.join(runnerDir, 'adapters/shared/sync-wallet-fixture.sh');
|
|
191
|
-
const syncArgs = ['--target', target];
|
|
192
|
-
if (process.env.CDP_PORT) syncArgs.push('--cdp-port', process.env.CDP_PORT);
|
|
193
|
-
if (process.env.RECIPE_SLOT_ID) syncArgs.push('--slot-id', process.env.RECIPE_SLOT_ID);
|
|
194
|
-
spawnScript(syncFixtureSh, syncArgs, target, json);
|
|
195
|
-
// Non-zero from sync-wallet-fixture.sh is informational (no fixture source);
|
|
196
|
-
// the install succeeded so the overlay is fresh.
|
|
197
|
-
return EXIT.ok;
|
|
198
|
-
}
|