@deeeed/metamask-harness 0.30.0 → 0.32.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 +12 -0
- package/adapters/extension/verify.sh +16 -4
- package/dist/commands/self-test.js +1 -1
- package/dist/recipe-security.js +1 -0
- package/docs/RECIPES.md +5 -2
- package/library/actions/extension/deeplink/open.mjs +26 -0
- package/library/actions/mobile/deeplink/open.mjs +16 -0
- package/library/actions/mobile/platform/bridge.mjs +80 -0
- package/library/actions/shared/deeplink/url.mjs +37 -0
- package/library/manifests/extension.action-manifest.json +33 -0
- package/library/manifests/mobile.action-manifest.json +33 -0
- package/package.json +2 -2
- /package/library/recipes/{perps/clean-market-testnet.core.recipe.json → core/perps/clean-market-testnet.recipe.json} +0 -0
- /package/library/recipes/{perps/order-lifecycle.core.recipe.json → core/perps/order-lifecycle.recipe.json} +0 -0
- /package/library/recipes/{perps/read-markets.core.recipe.json → core/perps/read-markets.recipe.json} +0 -0
- /package/library/recipes/{perps/smoke.core.recipe.json → core/perps/smoke.recipe.json} +0 -0
- /package/library/recipes/{perps/trading-lifecycle.core.recipe.json → core/perps/trading-lifecycle.recipe.json} +0 -0
- /package/library/recipes/{runner/smoke.core.recipe.json → core/runner/smoke.recipe.json} +0 -0
- /package/library/recipes/{perps/smoke.extension.recipe.json → extension/perps/smoke.recipe.json} +0 -0
- /package/library/recipes/{runner/action-validation.extension.recipe.json → extension/runner/action-validation.recipe.json} +0 -0
- /package/library/recipes/{runner/smoke.extension.recipe.json → extension/runner/smoke.recipe.json} +0 -0
- /package/library/recipes/{wallet/smoke.extension.recipe.json → extension/wallet/smoke.recipe.json} +0 -0
- /package/library/recipes/{app/lifecycle.android-smoke.mobile.recipe.json → mobile/app/lifecycle.android-smoke.recipe.json} +0 -0
- /package/library/recipes/{perps/performance.background-resume.mobile.recipe.json → mobile/perps/performance.background-resume.recipe.json} +0 -0
- /package/library/recipes/{perps/performance.cold-start.mobile.recipe.json → mobile/perps/performance.cold-start.recipe.json} +0 -0
- /package/library/recipes/{perps/performance.mobile.recipe.json → mobile/perps/performance.recipe.json} +0 -0
- /package/library/recipes/{perps/performance.warm-start.mobile.recipe.json → mobile/perps/performance.warm-start.recipe.json} +0 -0
- /package/library/recipes/{perps/smoke.mobile.recipe.json → mobile/perps/smoke.recipe.json} +0 -0
- /package/library/recipes/{runner/action-validation.mobile.recipe.json → mobile/runner/action-validation.recipe.json} +0 -0
- /package/library/recipes/{runner/smoke.mobile.recipe.json → mobile/runner/smoke.recipe.json} +0 -0
- /package/library/recipes/{wallet/smoke.mobile.recipe.json → mobile/wallet/smoke.recipe.json} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.32.0 - 2026-08-02
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Organize bundled platform recipe variants under `library/recipes/<adapter>/` while retaining temporary compatibility with legacy filename suffixes.
|
|
10
|
+
|
|
11
|
+
## 0.31.0 - 2026-08-02
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Add one cross-platform `metamask.deeplink.open` capability that exercises real Chrome or device URL ingress for external deeplink proofs.
|
|
16
|
+
|
|
5
17
|
## 0.30.0 - 2026-08-02
|
|
6
18
|
|
|
7
19
|
### Changed
|
|
@@ -88,7 +88,7 @@ RUNNER_BIN="$HARNESS_DIR/runner/bin/mm-harness"
|
|
|
88
88
|
# --out (optional): a task-local recipes dir. Resolve it safely within the target
|
|
89
89
|
# (resolve_harness_out rejects absolute/.. escapes) and prefer its smoke recipe so
|
|
90
90
|
# `live --out <dir>` does not silently fall back to the installed default.
|
|
91
|
-
SMOKE_RECIPE="$HARNESS_DIR/runner/recipes/runner/smoke.
|
|
91
|
+
SMOKE_RECIPE="$HARNESS_DIR/runner/recipes/extension/runner/smoke.recipe.json"
|
|
92
92
|
if [ -n "$OUT" ]; then
|
|
93
93
|
# Fail fast on a task-local --out that does not contain the requested recipe.
|
|
94
94
|
# Silently falling back to the installed default would validate a different
|
|
@@ -98,11 +98,23 @@ if [ -n "$OUT" ]; then
|
|
|
98
98
|
echo "extension verify: --out '$OUT' did not resolve to a safe path under the target." >&2
|
|
99
99
|
exit 2
|
|
100
100
|
fi
|
|
101
|
-
|
|
102
|
-
|
|
101
|
+
CANONICAL_SMOKE_RECIPE="$OUT_ABS/extension/runner/smoke.recipe.json"
|
|
102
|
+
LEGACY_SMOKE_RECIPE="$OUT_ABS/runner/smoke.extension.recipe.json"
|
|
103
|
+
if [ -f "$CANONICAL_SMOKE_RECIPE" ] && [ -f "$LEGACY_SMOKE_RECIPE" ]; then
|
|
104
|
+
echo "extension verify: --out '$OUT' declares runner.smoke for extension in both canonical and legacy paths." >&2
|
|
105
|
+
echo "Next: Remove $LEGACY_SMOKE_RECIPE and rerun verification." >&2
|
|
103
106
|
exit 2
|
|
104
107
|
fi
|
|
105
|
-
|
|
108
|
+
if [ -f "$CANONICAL_SMOKE_RECIPE" ]; then
|
|
109
|
+
SMOKE_RECIPE="$CANONICAL_SMOKE_RECIPE"
|
|
110
|
+
elif [ -f "$LEGACY_SMOKE_RECIPE" ]; then
|
|
111
|
+
SMOKE_RECIPE="$LEGACY_SMOKE_RECIPE"
|
|
112
|
+
else
|
|
113
|
+
echo "extension verify: --out '$OUT' has no extension runner.smoke recipe." >&2
|
|
114
|
+
echo "Next: Add extension/runner/smoke.recipe.json under $OUT_ABS or omit --out." >&2
|
|
115
|
+
exit 2
|
|
116
|
+
fi
|
|
117
|
+
unset CANONICAL_SMOKE_RECIPE LEGACY_SMOKE_RECIPE
|
|
106
118
|
fi
|
|
107
119
|
ARTIFACTS="${ARTIFACTS:-$HARNESS_DIR/verify/$(date -u +%Y%m%dT%H%M%SZ)}"
|
|
108
120
|
mkdir -p "$ARTIFACTS/logs"
|
|
@@ -26,7 +26,7 @@ async function runSelfTest(options) {
|
|
|
26
26
|
const manifest = loadActionManifest(adapter);
|
|
27
27
|
const manifestValidation = await validateManifest(manifest);
|
|
28
28
|
const smokeRecipe = recipePath(
|
|
29
|
-
adapter === "mobile" ? "runner/smoke.
|
|
29
|
+
adapter === "mobile" ? "mobile/runner/smoke.recipe.json" : "extension/runner/smoke.recipe.json"
|
|
30
30
|
);
|
|
31
31
|
const artifactsDir = path.join(root, adapter);
|
|
32
32
|
const result = await runRecipe(adapter, smokeRecipe, artifactsDir, runnerDir, void 0, {
|
package/dist/recipe-security.js
CHANGED
|
@@ -20,6 +20,7 @@ const APP_MUTATION_CUSTOM_ACTIONS = /* @__PURE__ */ new Set([
|
|
|
20
20
|
"metamask.wallet.setup",
|
|
21
21
|
"metamask.wallet.ensure_unlocked",
|
|
22
22
|
"metamask.wallet.select_account",
|
|
23
|
+
"metamask.deeplink.open",
|
|
23
24
|
"metamask.perps.close_positions",
|
|
24
25
|
"metamask.perps.close_orders",
|
|
25
26
|
"metamask.perps.place_order",
|
package/docs/RECIPES.md
CHANGED
|
@@ -116,7 +116,7 @@ The protocol is authoritative:
|
|
|
116
116
|
team-recipes/
|
|
117
117
|
manifests/extension.action-manifest.json
|
|
118
118
|
actions/extension/wallet/ensure_ready.mjs
|
|
119
|
-
recipes/onboarding/smoke.
|
|
119
|
+
recipes/extension/onboarding/smoke.recipe.json
|
|
120
120
|
```
|
|
121
121
|
|
|
122
122
|
```bash
|
|
@@ -129,7 +129,10 @@ mm-harness run onboarding.smoke --plan
|
|
|
129
129
|
Use `--library wallet=/path/to/library` for one command. The alias is the
|
|
130
130
|
source name; without one, the directory name is used. Resolution follows the
|
|
131
131
|
explicit library order, then bundled MetaMask. Adapter-specific variants are
|
|
132
|
-
selected deterministically
|
|
132
|
+
selected deterministically from `recipes/<adapter>/<domain>/`. Legacy
|
|
133
|
+
`*.<adapter>.recipe.json` paths remain readable during migration, but new and
|
|
134
|
+
migrated libraries use the adapter-first layout. A file cannot declare its
|
|
135
|
+
adapter through both forms. Every run records the root recipe, exact resolved
|
|
133
136
|
dependency documents, their digests, call edges, selected sources, and shadows.
|
|
134
137
|
|
|
135
138
|
## Direct product access
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { pathToFileURL } from 'node:url';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
externalDeeplinkTimeout,
|
|
5
|
+
externalDeeplinkUrl,
|
|
6
|
+
} from '../../shared/deeplink/url.mjs';
|
|
7
|
+
import { runAdapter, withExtensionPage } from '../platform/cdp.mjs';
|
|
8
|
+
|
|
9
|
+
export async function openExtensionDeeplink(input) {
|
|
10
|
+
return withExtensionPage(input, (page) => navigateExtensionDeeplink(page, input));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function navigateExtensionDeeplink(page, input) {
|
|
14
|
+
const url = externalDeeplinkUrl(input.node);
|
|
15
|
+
const timeoutMs = externalDeeplinkTimeout(input.node);
|
|
16
|
+
return {
|
|
17
|
+
action: input.action,
|
|
18
|
+
url,
|
|
19
|
+
navigation: await page.navigate(url, timeoutMs),
|
|
20
|
+
proofPath: 'external-deeplink',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
25
|
+
runAdapter(openExtensionDeeplink);
|
|
26
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
externalDeeplinkTimeout,
|
|
3
|
+
externalDeeplinkUrl,
|
|
4
|
+
} from '../../shared/deeplink/url.mjs';
|
|
5
|
+
import { openExternalDeeplink, runAdapter } from '../platform/bridge.mjs';
|
|
6
|
+
|
|
7
|
+
runAdapter(async (input) => {
|
|
8
|
+
const url = externalDeeplinkUrl(input.node);
|
|
9
|
+
const timeoutMs = externalDeeplinkTimeout(input.node);
|
|
10
|
+
return {
|
|
11
|
+
action: input.action,
|
|
12
|
+
url,
|
|
13
|
+
...(await openExternalDeeplink(input, url, timeoutMs)),
|
|
14
|
+
proofPath: 'external-deeplink',
|
|
15
|
+
};
|
|
16
|
+
});
|
|
@@ -160,6 +160,86 @@ function resolveMobileTarget(input) {
|
|
|
160
160
|
return { watcherPort, iosSimulator, androidDevice, androidTargetDeviceName, adbSerial };
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
export async function openExternalDeeplink(input, url, timeout = 15000) {
|
|
164
|
+
const target = resolveMobileTarget(input);
|
|
165
|
+
const requestedPlatform = String(
|
|
166
|
+
input.context?.env?.PLATFORM ?? process.env.PLATFORM ?? '',
|
|
167
|
+
).toLowerCase();
|
|
168
|
+
const serial = String(
|
|
169
|
+
input.context?.env?.ADB_SERIAL ??
|
|
170
|
+
input.context?.env?.ANDROID_SERIAL ??
|
|
171
|
+
process.env.ADB_SERIAL ??
|
|
172
|
+
process.env.ANDROID_SERIAL ??
|
|
173
|
+
'',
|
|
174
|
+
).trim();
|
|
175
|
+
const android =
|
|
176
|
+
requestedPlatform === 'android' || (requestedPlatform !== 'ios' && Boolean(serial));
|
|
177
|
+
if (android) {
|
|
178
|
+
if (!serial) {
|
|
179
|
+
throw new Error(
|
|
180
|
+
'Android deeplink ingress requires an adb serial.\n' +
|
|
181
|
+
' Next: mm-harness devices --adapter mobile --json',
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
const adb = resolveMobileToolPath('adb', { required: true });
|
|
185
|
+
const { stdout } = await runDeeplinkCommand(
|
|
186
|
+
adb,
|
|
187
|
+
[
|
|
188
|
+
'-s',
|
|
189
|
+
serial,
|
|
190
|
+
'shell',
|
|
191
|
+
'am',
|
|
192
|
+
'start',
|
|
193
|
+
'-W',
|
|
194
|
+
'-a',
|
|
195
|
+
'android.intent.action.VIEW',
|
|
196
|
+
'-d',
|
|
197
|
+
quoteRemoteShellArgument(url),
|
|
198
|
+
],
|
|
199
|
+
timeout,
|
|
200
|
+
`Android device ${serial}`,
|
|
201
|
+
);
|
|
202
|
+
if (!/^Status:\s*ok\s*$/imu.test(stdout)) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`Android device ${serial} did not report a successful deeplink launch.\n` +
|
|
205
|
+
' Next: mm-harness doctor --adapter mobile --json',
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return { platform: 'android', selectedDevice: serial, method: 'adb-am-start-view' };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const simulator = String(target.iosSimulator ?? '').trim();
|
|
212
|
+
if (!simulator) {
|
|
213
|
+
throw new Error(
|
|
214
|
+
'iOS deeplink ingress requires an iOS simulator.\n' +
|
|
215
|
+
' Next: mm-harness devices --adapter mobile --json',
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
await runDeeplinkCommand(
|
|
219
|
+
'xcrun',
|
|
220
|
+
['simctl', 'openurl', simulator, url],
|
|
221
|
+
timeout,
|
|
222
|
+
`iOS simulator ${simulator}`,
|
|
223
|
+
);
|
|
224
|
+
return { platform: 'ios', selectedDevice: simulator, method: 'simctl-openurl' };
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function quoteRemoteShellArgument(value) {
|
|
228
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async function runDeeplinkCommand(command, args, timeout, target) {
|
|
232
|
+
try {
|
|
233
|
+
return await execFileAsync(command, args, { timeout, encoding: 'utf8' });
|
|
234
|
+
} catch (error) {
|
|
235
|
+
const detail = String(error?.stderr ?? error?.message ?? error).trim();
|
|
236
|
+
throw new Error(
|
|
237
|
+
`Could not open the deeplink on ${target}${detail ? `: ${detail}` : '.'}\n` +
|
|
238
|
+
' Next: mm-harness doctor --adapter mobile --json',
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
163
243
|
function androidDeviceNameMatches(deviceName, targetName) {
|
|
164
244
|
if (!targetName) return false;
|
|
165
245
|
return deviceName === targetName || deviceName.startsWith(`${targetName} -`);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export function externalDeeplinkUrl(node) {
|
|
2
|
+
const raw = node?.url;
|
|
3
|
+
if (typeof raw !== 'string' || raw.trim().length === 0) {
|
|
4
|
+
throw new Error(
|
|
5
|
+
'metamask.deeplink.open requires url.\n' +
|
|
6
|
+
' Next: mm-harness call metamask.deeplink.open url=https://link.metamask.io/home',
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let url;
|
|
11
|
+
try {
|
|
12
|
+
url = new URL(raw);
|
|
13
|
+
} catch {
|
|
14
|
+
throw new Error(
|
|
15
|
+
'metamask.deeplink.open requires an absolute HTTPS url.\n' +
|
|
16
|
+
' Next: mm-harness call metamask.deeplink.open url=https://link.metamask.io/home',
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
if (url.protocol !== 'https:') {
|
|
20
|
+
throw new Error(
|
|
21
|
+
'metamask.deeplink.open accepts only HTTPS urls.\n' +
|
|
22
|
+
' Next: mm-harness call metamask.deeplink.open url=https://link.metamask.io/home',
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
return url.toString();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function externalDeeplinkTimeout(node) {
|
|
29
|
+
const timeout = Number(node?.timeout_ms ?? 15000);
|
|
30
|
+
if (!Number.isFinite(timeout) || timeout <= 0 || timeout > 120000) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
'metamask.deeplink.open timeout_ms must be between 1 and 120000.\n' +
|
|
33
|
+
' Next: mm-harness call metamask.deeplink.open url=https://link.metamask.io/home timeout_ms=15000',
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
return timeout;
|
|
37
|
+
}
|
|
@@ -2779,6 +2779,37 @@
|
|
|
2779
2779
|
"external-mutation"
|
|
2780
2780
|
]
|
|
2781
2781
|
},
|
|
2782
|
+
"metamask.deeplink.open": {
|
|
2783
|
+
"description": "Open an HTTPS deeplink through real browser ingress so the Extension owns parsing, verification, and destination navigation.",
|
|
2784
|
+
"execution_capabilities": [
|
|
2785
|
+
"app-mutation"
|
|
2786
|
+
],
|
|
2787
|
+
"examples": [
|
|
2788
|
+
{
|
|
2789
|
+
"action": "metamask.deeplink.open",
|
|
2790
|
+
"url": "https://link.metamask.io/home",
|
|
2791
|
+
"intent": "Open the deeplink through external browser navigation",
|
|
2792
|
+
"next": "done"
|
|
2793
|
+
}
|
|
2794
|
+
],
|
|
2795
|
+
"schema": {
|
|
2796
|
+
"type": "object",
|
|
2797
|
+
"properties": {
|
|
2798
|
+
"url": {
|
|
2799
|
+
"type": "string",
|
|
2800
|
+
"description": "Absolute HTTPS deeplink URL."
|
|
2801
|
+
},
|
|
2802
|
+
"timeout_ms": {
|
|
2803
|
+
"type": "number",
|
|
2804
|
+
"description": "Maximum time for the external navigation. Default 15000."
|
|
2805
|
+
}
|
|
2806
|
+
},
|
|
2807
|
+
"required": [
|
|
2808
|
+
"url"
|
|
2809
|
+
],
|
|
2810
|
+
"additionalProperties": false
|
|
2811
|
+
}
|
|
2812
|
+
},
|
|
2782
2813
|
"metamask.analytics.start_capture": {
|
|
2783
2814
|
"description": "extension Start capturing MetaMetrics events at the Segment transport and return a cursor to bracket later reads.",
|
|
2784
2815
|
"execution_capabilities": [
|
|
@@ -2945,6 +2976,7 @@
|
|
|
2945
2976
|
{
|
|
2946
2977
|
"ref": "ui.screen",
|
|
2947
2978
|
"default_for": [
|
|
2979
|
+
"metamask.deeplink.open",
|
|
2948
2980
|
"ui.navigate",
|
|
2949
2981
|
"ui.press",
|
|
2950
2982
|
"ui.key_press",
|
|
@@ -2957,6 +2989,7 @@
|
|
|
2957
2989
|
{
|
|
2958
2990
|
"ref": "ui.visible",
|
|
2959
2991
|
"default_for": [
|
|
2992
|
+
"metamask.deeplink.open",
|
|
2960
2993
|
"ui.navigate",
|
|
2961
2994
|
"ui.press",
|
|
2962
2995
|
"ui.key_press",
|
|
@@ -2901,6 +2901,37 @@
|
|
|
2901
2901
|
"external-mutation"
|
|
2902
2902
|
]
|
|
2903
2903
|
},
|
|
2904
|
+
"metamask.deeplink.open": {
|
|
2905
|
+
"description": "Open an HTTPS deeplink through the selected Android device or iOS simulator so Mobile owns parsing and destination navigation.",
|
|
2906
|
+
"execution_capabilities": [
|
|
2907
|
+
"app-mutation"
|
|
2908
|
+
],
|
|
2909
|
+
"examples": [
|
|
2910
|
+
{
|
|
2911
|
+
"action": "metamask.deeplink.open",
|
|
2912
|
+
"url": "https://link.metamask.io/home",
|
|
2913
|
+
"intent": "Open the deeplink through external device navigation",
|
|
2914
|
+
"next": "done"
|
|
2915
|
+
}
|
|
2916
|
+
],
|
|
2917
|
+
"schema": {
|
|
2918
|
+
"type": "object",
|
|
2919
|
+
"properties": {
|
|
2920
|
+
"url": {
|
|
2921
|
+
"type": "string",
|
|
2922
|
+
"description": "Absolute HTTPS deeplink URL."
|
|
2923
|
+
},
|
|
2924
|
+
"timeout_ms": {
|
|
2925
|
+
"type": "number",
|
|
2926
|
+
"description": "Maximum time for the external navigation. Default 15000."
|
|
2927
|
+
}
|
|
2928
|
+
},
|
|
2929
|
+
"required": [
|
|
2930
|
+
"url"
|
|
2931
|
+
],
|
|
2932
|
+
"additionalProperties": false
|
|
2933
|
+
}
|
|
2934
|
+
},
|
|
2904
2935
|
"metamask.analytics.start_capture": {
|
|
2905
2936
|
"description": "mobile Start capturing MetaMetrics events at the Segment transport and return a cursor to bracket later reads.",
|
|
2906
2937
|
"execution_capabilities": [
|
|
@@ -3067,6 +3098,7 @@
|
|
|
3067
3098
|
{
|
|
3068
3099
|
"ref": "ui.screen",
|
|
3069
3100
|
"default_for": [
|
|
3101
|
+
"metamask.deeplink.open",
|
|
3070
3102
|
"ui.navigate",
|
|
3071
3103
|
"ui.press",
|
|
3072
3104
|
"ui.screenshot",
|
|
@@ -3078,6 +3110,7 @@
|
|
|
3078
3110
|
{
|
|
3079
3111
|
"ref": "ui.visible",
|
|
3080
3112
|
"default_for": [
|
|
3113
|
+
"metamask.deeplink.open",
|
|
3081
3114
|
"ui.navigate",
|
|
3082
3115
|
"ui.press",
|
|
3083
3116
|
"ui.screenshot",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deeeed/metamask-harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mm-harness": "bin/mm-harness"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"@farmslot/agent-runtime": "0.5.1",
|
|
24
24
|
"@farmslot/handoff": "^0.3.1",
|
|
25
25
|
"@farmslot/protocol": "0.16.0",
|
|
26
|
-
"@farmslot/recipe-harness": "0.
|
|
26
|
+
"@farmslot/recipe-harness": "0.13.0",
|
|
27
27
|
"commander": "^12.0.0",
|
|
28
28
|
"es-module-lexer": "2.3.1",
|
|
29
29
|
"esbuild": "0.28.1",
|
|
File without changes
|
|
File without changes
|
/package/library/recipes/{perps/read-markets.core.recipe.json → core/perps/read-markets.recipe.json}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/library/recipes/{perps/smoke.extension.recipe.json → extension/perps/smoke.recipe.json}
RENAMED
|
File without changes
|
|
File without changes
|
/package/library/recipes/{runner/smoke.extension.recipe.json → extension/runner/smoke.recipe.json}
RENAMED
|
File without changes
|
/package/library/recipes/{wallet/smoke.extension.recipe.json → extension/wallet/smoke.recipe.json}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/library/recipes/{runner/smoke.mobile.recipe.json → mobile/runner/smoke.recipe.json}
RENAMED
|
File without changes
|
/package/library/recipes/{wallet/smoke.mobile.recipe.json → mobile/wallet/smoke.recipe.json}
RENAMED
|
File without changes
|