@deeeed/metamask-harness 0.46.0 → 0.47.1
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 +28 -0
- package/README.md +1 -1
- package/adapters/manifest.json +12 -4
- package/adapters/mobile/wait-for-bridge.cjs +550 -0
- package/adapters/mobile/wait-for-bridge.sh +11 -148
- package/bin/mm-harness +7 -2
- package/dist/adapters/mobile/prepare.js +26 -18
- package/dist/adapters/mobile/runtime-decision.js +1 -0
- package/dist/cli-commands.js +2 -0
- package/dist/command-contract.js +7 -0
- package/dist/commands/checklist.js +1 -0
- package/dist/commands/help.js +76 -0
- package/dist/commands/parse-args.js +2 -1
- package/dist/commands/recipe-quality.js +1 -1
- package/dist/commands/tutorial.js +46 -0
- package/dist/mm-harness-cli.js +45 -6
- package/docs/CONTRIBUTING.md +2 -0
- package/docs/QA.md +2 -2
- package/library/actions/mobile/perps/perps.mjs +1 -1
- package/package.json +2 -2
- package/scripts/site-contrast.mjs +6 -2
- package/site/assets/help-recipes.json +113 -0
- package/site/architecture.html +0 -497
- package/site/assets/metamask-fox.svg +0 -24
- package/site/assets/progress.mjs +0 -323
- package/site/assets/style.css +0 -1066
- package/site/cheatsheet.html +0 -307
- package/site/ecosystem.html +0 -162
- package/site/how-it-works.html +0 -692
- package/site/index.html +0 -184
- package/site/perps-advanced-orders-qa.html +0 -96
- package/site/perps.html +0 -265
- package/site/recipes.html +0 -423
- package/site/reviewers.html +0 -375
- package/site/tutorials/index.html +0 -181
- package/site/tutorials/v1.html +0 -212
- package/site/tutorials/v2.html +0 -207
- package/site/tutorials/v3.html +0 -258
- package/site/tutorials/v4.html +0 -196
- package/site/tutorials/v5.html +0 -164
- package/site/tutorials/v6.html +0 -166
- package/site/tutorials/v7.html +0 -185
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
<svg width="35" height="34" viewBox="0 0 35 34" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
-
<path d="M32.7077 32.7522L25.1688 30.5174L19.4833 33.9008L15.5167 33.8991L9.82793 30.5174L2.29225 32.7522L0 25.0489L2.29225 16.4993L0 9.27094L2.29225 0.312256L14.0674 7.31554H20.9326L32.7077 0.312256L35 9.27094L32.7077 16.4993L35 25.0489L32.7077 32.7522Z" fill="#FF5C16"/>
|
|
3
|
-
<path d="M2.29395 0.312256L14.0691 7.32047L13.6008 12.1301L2.29395 0.312256Z" fill="#FF5C16"/>
|
|
4
|
-
<path d="M9.82959 25.0522L15.0106 28.9811L9.82959 30.5175V25.0522Z" fill="#FF5C16"/>
|
|
5
|
-
<path d="M14.5966 18.5565L13.6009 12.1333L7.22692 16.5009L7.22363 16.4993V16.5025L7.24335 20.9983L9.82809 18.5565H9.82974H14.5966Z" fill="#FF5C16"/>
|
|
6
|
-
<path d="M32.7077 0.312256L20.9326 7.32047L21.3993 12.1301L32.7077 0.312256Z" fill="#FF5C16"/>
|
|
7
|
-
<path d="M25.1722 25.0522L19.9912 28.9811L25.1722 30.5175V25.0522Z" fill="#FF5C16"/>
|
|
8
|
-
<path d="M27.7766 16.5025H27.7783H27.7766V16.4993L27.775 16.5009L21.401 12.1333L20.4053 18.5565H25.1722L27.7586 20.9983L27.7766 16.5025Z" fill="#FF5C16"/>
|
|
9
|
-
<path d="M9.82793 30.5175L2.29225 32.7522L0 25.0522H9.82793V30.5175Z" fill="#E34807"/>
|
|
10
|
-
<path d="M14.5947 18.5549L16.0341 27.8406L14.0393 22.6777L7.23975 20.9984L9.82613 18.5549H14.593H14.5947Z" fill="#E34807"/>
|
|
11
|
-
<path d="M25.1721 30.5175L32.7078 32.7522L35.0001 25.0522H25.1721V30.5175Z" fill="#E34807"/>
|
|
12
|
-
<path d="M20.4053 18.5549L18.9658 27.8406L20.9607 22.6777L27.7602 20.9984L25.1722 18.5549H20.4053Z" fill="#E34807"/>
|
|
13
|
-
<path d="M0 25.0488L2.29225 16.4993H7.22183L7.23991 20.9967L14.0394 22.676L16.0343 27.8389L15.0089 28.976L9.82793 25.0472H0V25.0488Z" fill="#FF8D5D"/>
|
|
14
|
-
<path d="M35.0001 25.0488L32.7078 16.4993H27.7783L27.7602 20.9967L20.9607 22.676L18.9658 27.8389L19.9912 28.976L25.1722 25.0472H35.0001V25.0488Z" fill="#FF8D5D"/>
|
|
15
|
-
<path d="M20.9325 7.31543H17.4999H14.0673L13.6006 12.1251L16.0342 27.834H18.9656L21.4008 12.1251L20.9325 7.31543Z" fill="#FF8D5D"/>
|
|
16
|
-
<path d="M2.29225 0.312256L0 9.27094L2.29225 16.4993H7.22183L13.5991 12.1301L2.29225 0.312256Z" fill="#661800"/>
|
|
17
|
-
<path d="M13.17 20.4199H10.9369L9.72095 21.6062L14.0409 22.6727L13.17 20.4182V20.4199Z" fill="#661800"/>
|
|
18
|
-
<path d="M32.7077 0.312256L34.9999 9.27094L32.7077 16.4993H27.7781L21.4009 12.1301L32.7077 0.312256Z" fill="#661800"/>
|
|
19
|
-
<path d="M21.833 20.4199H24.0694L25.2853 21.6079L20.9604 22.676L21.833 20.4182V20.4199Z" fill="#661800"/>
|
|
20
|
-
<path d="M19.4817 30.8362L19.9911 28.9794L18.9658 27.8423H16.0327L15.0073 28.9794L15.5167 30.8362" fill="#661800"/>
|
|
21
|
-
<path d="M19.4816 30.8359V33.9021H15.5166V30.8359H19.4816Z" fill="#C0C4CD"/>
|
|
22
|
-
<path d="M9.82959 30.5142L15.52 33.9008V30.8346L15.0106 28.9778L9.82959 30.5142Z" fill="#E7EBF6"/>
|
|
23
|
-
<path d="M25.1721 30.5142L19.4817 33.9008V30.8346L19.9911 28.9778L25.1721 30.5142Z" fill="#E7EBF6"/>
|
|
24
|
-
</svg>
|
package/site/assets/progress.mjs
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Shared behaviour for the getting-started site: checklist progress, copy
|
|
3
|
-
* buttons, platform filters, tabs, and the layer diagram. No dependencies, no
|
|
4
|
-
* network, no tracking. Progress lives in localStorage under
|
|
5
|
-
* `mmh.progress.<page>`, where <page> comes from body[data-progress-page].
|
|
6
|
-
* Pages that share a namespace share their state (the How it works walkthrough and the V1
|
|
7
|
-
* tutorial are deliberately the same checklist).
|
|
8
|
-
*/
|
|
9
|
-
(function () {
|
|
10
|
-
'use strict';
|
|
11
|
-
|
|
12
|
-
var KEY_PREFIX = 'mmh.progress.';
|
|
13
|
-
|
|
14
|
-
/* ---------- storage (degrades to in-memory if localStorage is blocked) ---------- */
|
|
15
|
-
|
|
16
|
-
var memory = {};
|
|
17
|
-
|
|
18
|
-
function read(key) {
|
|
19
|
-
try {
|
|
20
|
-
var raw = window.localStorage.getItem(key);
|
|
21
|
-
return raw ? JSON.parse(raw) : [];
|
|
22
|
-
} catch (_err) {
|
|
23
|
-
return memory[key] || [];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function write(key, ids) {
|
|
28
|
-
memory[key] = ids;
|
|
29
|
-
try {
|
|
30
|
-
window.localStorage.setItem(key, JSON.stringify(ids));
|
|
31
|
-
} catch (_err) {
|
|
32
|
-
/* Private mode or blocked storage: the page still works, just forgets. */
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/* ---------- checklist ---------- */
|
|
37
|
-
|
|
38
|
-
function initChecklist() {
|
|
39
|
-
var page = document.body.getAttribute('data-progress-page');
|
|
40
|
-
var steps = [].slice.call(document.querySelectorAll('.step[data-step]'));
|
|
41
|
-
if (!page || !steps.length) return;
|
|
42
|
-
|
|
43
|
-
var key = KEY_PREFIX + page;
|
|
44
|
-
var fill = document.querySelector('.progress-fill');
|
|
45
|
-
var label = document.querySelector('.progress-label');
|
|
46
|
-
var reset = document.querySelector('.progress-reset');
|
|
47
|
-
|
|
48
|
-
function done() {
|
|
49
|
-
return steps.filter(function (s) { return s.getAttribute('data-done') === '1'; });
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function render() {
|
|
53
|
-
var n = done().length;
|
|
54
|
-
var pct = steps.length ? Math.round((n / steps.length) * 100) : 0;
|
|
55
|
-
if (fill) {
|
|
56
|
-
fill.style.width = pct + '%';
|
|
57
|
-
fill.parentNode.setAttribute('aria-valuenow', String(pct));
|
|
58
|
-
}
|
|
59
|
-
if (label) {
|
|
60
|
-
label.textContent = n === steps.length
|
|
61
|
-
? n + '/' + steps.length + ' — done'
|
|
62
|
-
: n + '/' + steps.length + ' steps';
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function apply(ids) {
|
|
67
|
-
steps.forEach(function (step) {
|
|
68
|
-
var on = ids.indexOf(step.getAttribute('data-step')) !== -1;
|
|
69
|
-
step.setAttribute('data-done', on ? '1' : '0');
|
|
70
|
-
var box = step.querySelector('.step-check');
|
|
71
|
-
if (box) box.checked = on;
|
|
72
|
-
});
|
|
73
|
-
render();
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
steps.forEach(function (step) {
|
|
77
|
-
var box = step.querySelector('.step-check');
|
|
78
|
-
if (!box) return;
|
|
79
|
-
box.addEventListener('change', function () {
|
|
80
|
-
var ids = read(key);
|
|
81
|
-
var id = step.getAttribute('data-step');
|
|
82
|
-
var at = ids.indexOf(id);
|
|
83
|
-
if (box.checked && at === -1) ids.push(id);
|
|
84
|
-
if (!box.checked && at !== -1) ids.splice(at, 1);
|
|
85
|
-
write(key, ids);
|
|
86
|
-
apply(ids);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
if (reset) {
|
|
91
|
-
reset.addEventListener('click', function () {
|
|
92
|
-
write(key, []);
|
|
93
|
-
apply([]);
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/* Reflect edits made in another tab on the same namespace. */
|
|
98
|
-
window.addEventListener('storage', function (e) {
|
|
99
|
-
if (e.key === key) apply(read(key));
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
apply(read(key));
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/* ---------- copy buttons ---------- */
|
|
106
|
-
|
|
107
|
-
function textOf(block) {
|
|
108
|
-
var pre = block.querySelector('pre');
|
|
109
|
-
if (!pre) return '';
|
|
110
|
-
var clone = pre.cloneNode(true);
|
|
111
|
-
/* Shell prompt markers are decoration, never part of the command. */
|
|
112
|
-
[].slice.call(clone.querySelectorAll('.p')).forEach(function (n) {
|
|
113
|
-
n.parentNode.removeChild(n);
|
|
114
|
-
});
|
|
115
|
-
return clone.textContent.replace(/[ \t]+$/gm, '').trim();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function legacyCopy(text) {
|
|
119
|
-
return new Promise(function (resolve, reject) {
|
|
120
|
-
var ta = document.createElement('textarea');
|
|
121
|
-
ta.value = text;
|
|
122
|
-
ta.setAttribute('readonly', '');
|
|
123
|
-
ta.style.position = 'fixed';
|
|
124
|
-
ta.style.opacity = '0';
|
|
125
|
-
document.body.appendChild(ta);
|
|
126
|
-
ta.select();
|
|
127
|
-
var ok = false;
|
|
128
|
-
try { ok = document.execCommand('copy'); } catch (_err) { ok = false; }
|
|
129
|
-
document.body.removeChild(ta);
|
|
130
|
-
ok ? resolve() : reject(new Error('copy unavailable'));
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/*
|
|
135
|
-
* The async clipboard needs a secure context AND permission; it rejects when
|
|
136
|
-
* the document lacks focus. Fall through to the legacy path rather than
|
|
137
|
-
* telling the reader to give up.
|
|
138
|
-
*/
|
|
139
|
-
function copy(text) {
|
|
140
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
141
|
-
return navigator.clipboard.writeText(text).catch(function () {
|
|
142
|
-
return legacyCopy(text);
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
return legacyCopy(text);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function initCopy() {
|
|
149
|
-
[].slice.call(document.querySelectorAll('.cmd')).forEach(function (block) {
|
|
150
|
-
if (block.querySelector('.copy')) return;
|
|
151
|
-
var btn = document.createElement('button');
|
|
152
|
-
btn.type = 'button';
|
|
153
|
-
btn.className = 'copy';
|
|
154
|
-
btn.textContent = 'Copy';
|
|
155
|
-
btn.setAttribute('aria-label', 'Copy to clipboard');
|
|
156
|
-
btn.addEventListener('click', function () {
|
|
157
|
-
copy(textOf(block)).then(function () {
|
|
158
|
-
btn.textContent = 'Copied';
|
|
159
|
-
btn.setAttribute('data-copied', '1');
|
|
160
|
-
}, function () {
|
|
161
|
-
btn.textContent = 'Press ⌘C';
|
|
162
|
-
});
|
|
163
|
-
setTimeout(function () {
|
|
164
|
-
btn.textContent = 'Copy';
|
|
165
|
-
btn.removeAttribute('data-copied');
|
|
166
|
-
}, 1600);
|
|
167
|
-
});
|
|
168
|
-
block.appendChild(btn);
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/* ---------- click-to-copy table cells ---------- */
|
|
173
|
-
|
|
174
|
-
/*
|
|
175
|
-
* Reference tables put one command per cell, where a hovering copy button
|
|
176
|
-
* would crowd the row. The cell itself is the button instead.
|
|
177
|
-
*/
|
|
178
|
-
function initCellCopy() {
|
|
179
|
-
var cells = [].slice.call(document.querySelectorAll('[data-copy-cells] td code'));
|
|
180
|
-
cells.forEach(function (cell) {
|
|
181
|
-
var original = cell.textContent;
|
|
182
|
-
cell.tabIndex = 0;
|
|
183
|
-
cell.setAttribute('role', 'button');
|
|
184
|
-
cell.setAttribute('title', 'Click to copy');
|
|
185
|
-
cell.classList.add('copyable');
|
|
186
|
-
|
|
187
|
-
function run() {
|
|
188
|
-
copy(original).then(function () {
|
|
189
|
-
cell.textContent = 'Copied';
|
|
190
|
-
cell.classList.add('copied');
|
|
191
|
-
}, function () {
|
|
192
|
-
cell.textContent = 'Press ⌘C';
|
|
193
|
-
});
|
|
194
|
-
setTimeout(function () {
|
|
195
|
-
cell.textContent = original;
|
|
196
|
-
cell.classList.remove('copied');
|
|
197
|
-
}, 1200);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
cell.addEventListener('click', run);
|
|
201
|
-
cell.addEventListener('keydown', function (e) {
|
|
202
|
-
if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); run(); }
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/* ---------- platform filter ---------- */
|
|
208
|
-
|
|
209
|
-
function initFilters() {
|
|
210
|
-
var chips = [].slice.call(document.querySelectorAll('.chip[data-platform]'));
|
|
211
|
-
if (!chips.length) return;
|
|
212
|
-
var rows = [].slice.call(document.querySelectorAll('[data-platforms]'));
|
|
213
|
-
|
|
214
|
-
function select(want) {
|
|
215
|
-
chips.forEach(function (c) {
|
|
216
|
-
c.setAttribute('aria-pressed', String(c.getAttribute('data-platform') === want));
|
|
217
|
-
});
|
|
218
|
-
rows.forEach(function (row) {
|
|
219
|
-
var list = row.getAttribute('data-platforms').split(/\s+/);
|
|
220
|
-
var show = want === 'all' || list.indexOf('all') !== -1 || list.indexOf(want) !== -1;
|
|
221
|
-
row.hidden = !show;
|
|
222
|
-
});
|
|
223
|
-
/* A section whose rows are all hidden says so instead of looking broken. */
|
|
224
|
-
[].slice.call(document.querySelectorAll('[data-filter-section]')).forEach(function (sec) {
|
|
225
|
-
var visible = [].slice.call(sec.querySelectorAll('[data-platforms]')).some(function (r) {
|
|
226
|
-
return !r.hidden;
|
|
227
|
-
});
|
|
228
|
-
sec.classList.toggle('filter-hidden', !visible);
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
chips.forEach(function (c) {
|
|
233
|
-
c.addEventListener('click', function () { select(c.getAttribute('data-platform')); });
|
|
234
|
-
});
|
|
235
|
-
select('all');
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
/* ---------- tabs ---------- */
|
|
239
|
-
|
|
240
|
-
/*
|
|
241
|
-
* One tablist per group, roving tabindex: only the selected tab is in the
|
|
242
|
-
* tab order, arrows move between them. Panels stay in the DOM so their
|
|
243
|
-
* commands remain copyable the moment a tab is shown.
|
|
244
|
-
*
|
|
245
|
-
* The markup ships every panel visible and the tablist hidden; hiding is
|
|
246
|
-
* this function's first act. Without it — stale cache, blocked module,
|
|
247
|
-
* file:// — the reader gets all three prompts stacked instead of controls
|
|
248
|
-
* that do nothing.
|
|
249
|
-
*/
|
|
250
|
-
function initTabs() {
|
|
251
|
-
[].slice.call(document.querySelectorAll('[role="tablist"]')).forEach(function (list) {
|
|
252
|
-
var tabs = [].slice.call(list.querySelectorAll('[role="tab"]'));
|
|
253
|
-
if (!tabs.length) return;
|
|
254
|
-
list.hidden = false;
|
|
255
|
-
|
|
256
|
-
function select(tab, focus) {
|
|
257
|
-
tabs.forEach(function (other) {
|
|
258
|
-
var on = other === tab;
|
|
259
|
-
other.setAttribute('aria-selected', String(on));
|
|
260
|
-
other.tabIndex = on ? 0 : -1;
|
|
261
|
-
var panel = document.getElementById(other.getAttribute('aria-controls'));
|
|
262
|
-
if (panel) panel.hidden = !on;
|
|
263
|
-
});
|
|
264
|
-
if (focus) tab.focus();
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
tabs.forEach(function (tab, i) {
|
|
268
|
-
tab.addEventListener('click', function () { select(tab, false); });
|
|
269
|
-
tab.addEventListener('keydown', function (e) {
|
|
270
|
-
var next = null;
|
|
271
|
-
if (e.key === 'ArrowRight') next = tabs[(i + 1) % tabs.length];
|
|
272
|
-
if (e.key === 'ArrowLeft') next = tabs[(i - 1 + tabs.length) % tabs.length];
|
|
273
|
-
if (e.key === 'Home') next = tabs[0];
|
|
274
|
-
if (e.key === 'End') next = tabs[tabs.length - 1];
|
|
275
|
-
if (!next) return;
|
|
276
|
-
e.preventDefault();
|
|
277
|
-
select(next, true);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
var current = tabs.filter(function (t) {
|
|
282
|
-
return t.getAttribute('aria-selected') === 'true';
|
|
283
|
-
})[0];
|
|
284
|
-
select(current || tabs[0], false);
|
|
285
|
-
});
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/* ---------- layer diagram ---------- */
|
|
289
|
-
|
|
290
|
-
function initLayers() {
|
|
291
|
-
var layers = [].slice.call(document.querySelectorAll('.layer[aria-controls]'));
|
|
292
|
-
layers.forEach(function (layer) {
|
|
293
|
-
layer.addEventListener('click', function () {
|
|
294
|
-
var open = layer.getAttribute('aria-expanded') === 'true';
|
|
295
|
-
layers.forEach(function (other) {
|
|
296
|
-
other.setAttribute('aria-expanded', 'false');
|
|
297
|
-
var d = document.getElementById(other.getAttribute('aria-controls'));
|
|
298
|
-
if (d) d.hidden = true;
|
|
299
|
-
});
|
|
300
|
-
if (!open) {
|
|
301
|
-
layer.setAttribute('aria-expanded', 'true');
|
|
302
|
-
var detail = document.getElementById(layer.getAttribute('aria-controls'));
|
|
303
|
-
if (detail) detail.hidden = false;
|
|
304
|
-
}
|
|
305
|
-
});
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function init() {
|
|
310
|
-
initChecklist();
|
|
311
|
-
initCopy();
|
|
312
|
-
initCellCopy();
|
|
313
|
-
initFilters();
|
|
314
|
-
initTabs();
|
|
315
|
-
initLayers();
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
if (document.readyState === 'loading') {
|
|
319
|
-
document.addEventListener('DOMContentLoaded', init);
|
|
320
|
-
} else {
|
|
321
|
-
init();
|
|
322
|
-
}
|
|
323
|
-
})();
|