w3wallets 0.10.2 → 1.0.0-beta.10
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/README.md +128 -21
- package/dist/index.d.mts +172 -54
- package/dist/index.d.ts +172 -54
- package/dist/index.js +679 -301
- package/dist/index.mjs +676 -300
- package/dist/scripts/cache.js +317 -0
- package/package.json +17 -12
- package/src/scripts/download.js +426 -65
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/cache/buildCache.ts
|
|
27
|
+
var import_path2 = __toESM(require("path"));
|
|
28
|
+
var import_fs2 = __toESM(require("fs"));
|
|
29
|
+
var import_crypto2 = __toESM(require("crypto"));
|
|
30
|
+
var import_test = require("@playwright/test");
|
|
31
|
+
|
|
32
|
+
// src/cache/constants.ts
|
|
33
|
+
var CACHE_DIR = ".w3wallets/cache";
|
|
34
|
+
|
|
35
|
+
// src/cache/types.ts
|
|
36
|
+
function isCachedConfig(config) {
|
|
37
|
+
return "__cached" in config && config.__cached === true;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/core/utils.ts
|
|
41
|
+
var import_path = __toESM(require("path"));
|
|
42
|
+
var import_fs = __toESM(require("fs"));
|
|
43
|
+
var import_crypto = __toESM(require("crypto"));
|
|
44
|
+
function sleep(ms) {
|
|
45
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
46
|
+
}
|
|
47
|
+
function getExtensionId(extensionPath) {
|
|
48
|
+
const absolutePath = import_path.default.resolve(extensionPath);
|
|
49
|
+
const manifestPath = import_path.default.join(absolutePath, "manifest.json");
|
|
50
|
+
const manifest = JSON.parse(import_fs.default.readFileSync(manifestPath, "utf-8"));
|
|
51
|
+
let dataToHash;
|
|
52
|
+
if (manifest.key) {
|
|
53
|
+
dataToHash = Buffer.from(manifest.key, "base64");
|
|
54
|
+
} else {
|
|
55
|
+
dataToHash = Buffer.from(absolutePath);
|
|
56
|
+
}
|
|
57
|
+
const hash = import_crypto.default.createHash("sha256").update(dataToHash).digest();
|
|
58
|
+
const ALPHABET = "abcdefghijklmnop";
|
|
59
|
+
let extensionId = "";
|
|
60
|
+
for (let i = 0; i < 16; i++) {
|
|
61
|
+
const byte = hash[i];
|
|
62
|
+
extensionId += ALPHABET[byte >> 4 & 15];
|
|
63
|
+
extensionId += ALPHABET[byte & 15];
|
|
64
|
+
}
|
|
65
|
+
return extensionId;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/timeouts.ts
|
|
69
|
+
var SERVICE_WORKER_TIMEOUT = 3e4;
|
|
70
|
+
var SERVICE_WORKER_POLL_INTERVAL = 500;
|
|
71
|
+
var STORAGE_STABILIZE_TIMEOUT = 12e4;
|
|
72
|
+
var STORAGE_POLL_INTERVAL = 5e3;
|
|
73
|
+
var STORAGE_STABLE_CHECKS = 6;
|
|
74
|
+
var HELPER_PAGE_TIMEOUT = 1e4;
|
|
75
|
+
var LEVELDB_FLUSH_DELAY = 5e3;
|
|
76
|
+
|
|
77
|
+
// src/debug.ts
|
|
78
|
+
var isDebug = () => process.env.W3WALLETS_DEBUG === "true";
|
|
79
|
+
function debug(message) {
|
|
80
|
+
if (!isDebug()) return;
|
|
81
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
82
|
+
console.log(`[w3wallets ${ts}] ${message}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/cache/buildCache.ts
|
|
86
|
+
var W3WALLETS_DIR = ".w3wallets";
|
|
87
|
+
async function waitForStorageStable(helperPage, helperUrl) {
|
|
88
|
+
const TIMEOUT = STORAGE_STABILIZE_TIMEOUT;
|
|
89
|
+
const POLL_INTERVAL = STORAGE_POLL_INTERVAL;
|
|
90
|
+
const STABLE_CHECKS_REQUIRED = STORAGE_STABLE_CHECKS;
|
|
91
|
+
const start = Date.now();
|
|
92
|
+
let lastKeyCount = -1;
|
|
93
|
+
let stableCount = 0;
|
|
94
|
+
while (Date.now() - start < TIMEOUT) {
|
|
95
|
+
await sleep(POLL_INTERVAL);
|
|
96
|
+
await helperPage.goto(helperUrl);
|
|
97
|
+
await helperPage.waitForFunction(
|
|
98
|
+
() => document.title.startsWith("done:"),
|
|
99
|
+
null,
|
|
100
|
+
{ timeout: HELPER_PAGE_TIMEOUT }
|
|
101
|
+
);
|
|
102
|
+
const title = await helperPage.title();
|
|
103
|
+
const keyCount = parseInt(title.split(":")[1], 10);
|
|
104
|
+
if (keyCount === 0) continue;
|
|
105
|
+
if (keyCount === lastKeyCount) {
|
|
106
|
+
stableCount++;
|
|
107
|
+
} else {
|
|
108
|
+
stableCount = 1;
|
|
109
|
+
lastKeyCount = keyCount;
|
|
110
|
+
}
|
|
111
|
+
debug(
|
|
112
|
+
`Storage poll: ${keyCount} keys (stable ${stableCount}/${STABLE_CHECKS_REQUIRED})`
|
|
113
|
+
);
|
|
114
|
+
if (stableCount >= STABLE_CHECKS_REQUIRED) {
|
|
115
|
+
console.log(` Storage stabilized at ${keyCount} keys`);
|
|
116
|
+
return keyCount;
|
|
117
|
+
}
|
|
118
|
+
console.log(
|
|
119
|
+
` Waiting for storage to stabilize: ${keyCount} keys (${stableCount}/${STABLE_CHECKS_REQUIRED})`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
console.log(` Storage stabilization timed out after ${TIMEOUT / 1e3}s`);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function hashFilePath(filePath) {
|
|
126
|
+
const hash = import_crypto2.default.createHash("sha256").update(filePath).digest("hex");
|
|
127
|
+
return hash.slice(0, 20);
|
|
128
|
+
}
|
|
129
|
+
async function buildCacheForSetup(compiledFilePath, originalFilePath, options2 = {}) {
|
|
130
|
+
const hash = hashFilePath(import_path2.default.resolve(originalFilePath));
|
|
131
|
+
const cacheDir = import_path2.default.join(process.cwd(), CACHE_DIR, hash);
|
|
132
|
+
if (!options2.force && import_fs2.default.existsSync(cacheDir)) {
|
|
133
|
+
console.log(` Cache exists: ${cacheDir} (use --force to rebuild)`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const compiled = require(import_path2.default.resolve(compiledFilePath));
|
|
137
|
+
const config = compiled.default ?? compiled;
|
|
138
|
+
if (!isCachedConfig(config)) {
|
|
139
|
+
throw new Error(
|
|
140
|
+
`Setup file must export a CachedWalletConfig (use prepareWallet()): ${originalFilePath}`
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
const extPath = import_path2.default.join(process.cwd(), W3WALLETS_DIR, config.extensionDir);
|
|
144
|
+
if (!import_fs2.default.existsSync(import_path2.default.join(extPath, "manifest.json"))) {
|
|
145
|
+
throw new Error(
|
|
146
|
+
`Extension not found at ${extPath}. Run 'npx w3wallets ${config.name}' first.`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
console.log(` Building cache for "${config.name}"...`);
|
|
150
|
+
if (import_fs2.default.existsSync(cacheDir)) {
|
|
151
|
+
import_fs2.default.rmSync(cacheDir, { recursive: true });
|
|
152
|
+
}
|
|
153
|
+
const context = await import_test.chromium.launchPersistentContext(cacheDir, {
|
|
154
|
+
headless: !options2.headed,
|
|
155
|
+
channel: "chromium",
|
|
156
|
+
args: [
|
|
157
|
+
`--disable-extensions-except=${extPath}`,
|
|
158
|
+
`--load-extension=${extPath}`
|
|
159
|
+
]
|
|
160
|
+
});
|
|
161
|
+
const extensionId = getExtensionId(extPath);
|
|
162
|
+
if (context.serviceWorkers().length < 1) {
|
|
163
|
+
await Promise.race([
|
|
164
|
+
context.waitForEvent("serviceworker", {
|
|
165
|
+
timeout: SERVICE_WORKER_TIMEOUT
|
|
166
|
+
}),
|
|
167
|
+
(async () => {
|
|
168
|
+
while (context.serviceWorkers().length < 1) {
|
|
169
|
+
await sleep(SERVICE_WORKER_POLL_INTERVAL);
|
|
170
|
+
}
|
|
171
|
+
})()
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
const page = await context.newPage();
|
|
175
|
+
const wallet = new config.WalletClass(page, extensionId);
|
|
176
|
+
await config.setupFn(wallet, page);
|
|
177
|
+
await page.goto(`chrome-extension://${extensionId}/home.html`);
|
|
178
|
+
await page.waitForLoadState("networkidle");
|
|
179
|
+
await page.goto(`chrome-extension://${extensionId}/home.html`);
|
|
180
|
+
await page.waitForLoadState("networkidle");
|
|
181
|
+
try {
|
|
182
|
+
const extDir = import_path2.default.join(process.cwd(), W3WALLETS_DIR, config.extensionDir);
|
|
183
|
+
const helperJs = import_path2.default.join(extDir, "_w3wallets_helper.js");
|
|
184
|
+
const helperHtml = import_path2.default.join(extDir, "_w3wallets_helper.html");
|
|
185
|
+
import_fs2.default.writeFileSync(
|
|
186
|
+
helperJs,
|
|
187
|
+
`chrome.storage.local.get(null, (data) => {
|
|
188
|
+
document.title = "done:" + Object.keys(data).length;
|
|
189
|
+
});`
|
|
190
|
+
);
|
|
191
|
+
import_fs2.default.writeFileSync(
|
|
192
|
+
helperHtml,
|
|
193
|
+
`<!DOCTYPE html><html><head><script src="_w3wallets_helper.js"></script></head><body></body></html>`
|
|
194
|
+
);
|
|
195
|
+
const helperPage = await context.newPage();
|
|
196
|
+
const helperUrl = `chrome-extension://${extensionId}/_w3wallets_helper.html`;
|
|
197
|
+
await waitForStorageStable(helperPage, helperUrl);
|
|
198
|
+
await helperPage.close();
|
|
199
|
+
import_fs2.default.unlinkSync(helperJs);
|
|
200
|
+
import_fs2.default.unlinkSync(helperHtml);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
console.log(` Note: could not verify persistence: ${err}`);
|
|
203
|
+
}
|
|
204
|
+
await sleep(LEVELDB_FLUSH_DELAY);
|
|
205
|
+
await context.close();
|
|
206
|
+
import_fs2.default.writeFileSync(
|
|
207
|
+
import_path2.default.join(cacheDir, ".meta.json"),
|
|
208
|
+
JSON.stringify({ name: config.name })
|
|
209
|
+
);
|
|
210
|
+
console.log(` Cached: ${cacheDir}`);
|
|
211
|
+
}
|
|
212
|
+
async function buildAllCaches(directory, options2 = {}) {
|
|
213
|
+
const absoluteDir = import_path2.default.resolve(directory);
|
|
214
|
+
if (!import_fs2.default.existsSync(absoluteDir)) {
|
|
215
|
+
throw new Error(`Setup directory not found: ${absoluteDir}`);
|
|
216
|
+
}
|
|
217
|
+
const files = import_fs2.default.readdirSync(absoluteDir).filter((f) => {
|
|
218
|
+
return /\.cache\.(ts|js)$/.test(f);
|
|
219
|
+
});
|
|
220
|
+
if (files.length === 0) {
|
|
221
|
+
console.log(`No *.cache.{ts,js} files found in ${absoluteDir}`);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
console.log(`Found ${files.length} setup file(s) in ${absoluteDir}`);
|
|
225
|
+
const distDir = import_path2.default.join(process.cwd(), CACHE_DIR, ".dist");
|
|
226
|
+
const entryPoints = files.map((f) => import_path2.default.join(absoluteDir, f));
|
|
227
|
+
console.log("Compiling setup files...");
|
|
228
|
+
const { build } = await import("tsup");
|
|
229
|
+
await build({
|
|
230
|
+
entry: entryPoints,
|
|
231
|
+
outDir: distDir,
|
|
232
|
+
format: ["cjs"],
|
|
233
|
+
clean: true,
|
|
234
|
+
silent: true,
|
|
235
|
+
external: ["@playwright/test"]
|
|
236
|
+
});
|
|
237
|
+
let built = 0;
|
|
238
|
+
let skipped = 0;
|
|
239
|
+
for (const file of files) {
|
|
240
|
+
const baseName = file.replace(/\.ts$/, ".js");
|
|
241
|
+
const compiledPath = import_path2.default.join(distDir, baseName);
|
|
242
|
+
const originalPath = import_path2.default.join(absoluteDir, file);
|
|
243
|
+
console.log(`
|
|
244
|
+
[${file}]`);
|
|
245
|
+
if (!import_fs2.default.existsSync(compiledPath)) {
|
|
246
|
+
console.log(` Compiled file not found: ${compiledPath}`);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
const hash = hashFilePath(import_path2.default.resolve(originalPath));
|
|
250
|
+
const cacheExists = import_fs2.default.existsSync(
|
|
251
|
+
import_path2.default.join(process.cwd(), CACHE_DIR, hash)
|
|
252
|
+
);
|
|
253
|
+
if (!options2.force && cacheExists) {
|
|
254
|
+
console.log(` Cache exists (use --force to rebuild)`);
|
|
255
|
+
skipped++;
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
await buildCacheForSetup(compiledPath, originalPath, {
|
|
259
|
+
...options2,
|
|
260
|
+
force: true
|
|
261
|
+
});
|
|
262
|
+
built++;
|
|
263
|
+
}
|
|
264
|
+
console.log(`
|
|
265
|
+
Done: ${built} built, ${skipped} skipped`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/scripts/cache.ts
|
|
269
|
+
function parseArgs(args) {
|
|
270
|
+
const options2 = {
|
|
271
|
+
force: false,
|
|
272
|
+
headed: false,
|
|
273
|
+
directory: "./wallets-cache/"
|
|
274
|
+
};
|
|
275
|
+
for (const arg of args) {
|
|
276
|
+
if (arg === "-f" || arg === "--force") {
|
|
277
|
+
options2.force = true;
|
|
278
|
+
} else if (arg === "--headed") {
|
|
279
|
+
options2.headed = true;
|
|
280
|
+
} else if (arg === "-h" || arg === "--help") {
|
|
281
|
+
console.log(`
|
|
282
|
+
w3wallets cache - Build wallet caches from setup files
|
|
283
|
+
|
|
284
|
+
USAGE:
|
|
285
|
+
npx w3wallets cache [OPTIONS] [directory]
|
|
286
|
+
|
|
287
|
+
ARGUMENTS:
|
|
288
|
+
directory Directory containing *.cache.{ts,js} files (default: ./wallets-cache/)
|
|
289
|
+
|
|
290
|
+
OPTIONS:
|
|
291
|
+
-f, --force Force rebuild even if cache exists
|
|
292
|
+
--headed Run browser in headed mode
|
|
293
|
+
-h, --help Show this help message
|
|
294
|
+
|
|
295
|
+
EXAMPLES:
|
|
296
|
+
npx w3wallets cache # Build caches from ./wallets-cache/
|
|
297
|
+
npx w3wallets cache ./tests/setups/ # Custom directory
|
|
298
|
+
npx w3wallets cache --force # Force rebuild
|
|
299
|
+
`);
|
|
300
|
+
process.exit(0);
|
|
301
|
+
} else if (!arg.startsWith("-")) {
|
|
302
|
+
options2.directory = arg;
|
|
303
|
+
} else {
|
|
304
|
+
console.error(`Error: Unknown option "${arg}"`);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return options2;
|
|
309
|
+
}
|
|
310
|
+
var options = parseArgs(process.argv.slice(2));
|
|
311
|
+
buildAllCaches(options.directory, {
|
|
312
|
+
force: options.force,
|
|
313
|
+
headed: options.headed
|
|
314
|
+
}).catch((err) => {
|
|
315
|
+
console.error(`Cache build failed: ${err.message}`);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w3wallets",
|
|
3
3
|
"description": "browser wallets for playwright",
|
|
4
|
-
"version": "0.10
|
|
4
|
+
"version": "1.0.0-beta.10",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"homepage": "https://github.com/Maksandre/w3wallets",
|
|
@@ -16,12 +16,10 @@
|
|
|
16
16
|
"keywords": [
|
|
17
17
|
"e2e",
|
|
18
18
|
"playwright",
|
|
19
|
-
"backpack",
|
|
20
19
|
"metamask",
|
|
21
20
|
"testing",
|
|
22
21
|
"ethereum",
|
|
23
|
-
"polkadot"
|
|
24
|
-
"eclipse"
|
|
22
|
+
"polkadot"
|
|
25
23
|
],
|
|
26
24
|
"license": "MIT",
|
|
27
25
|
"publishConfig": {
|
|
@@ -32,32 +30,39 @@
|
|
|
32
30
|
],
|
|
33
31
|
"bin": "./src/scripts/download.js",
|
|
34
32
|
"scripts": {
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"test": "npx playwright test --project=local
|
|
33
|
+
"download-wallets": "npx w3wallets pjs mm",
|
|
34
|
+
"cache-wallets": "npx w3wallets cache --force ./tests/wallets-cache/",
|
|
35
|
+
"test": "npx playwright test --project=local",
|
|
38
36
|
"test:ci": "npx playwright test --project=ci",
|
|
39
37
|
"build": "tsup",
|
|
40
38
|
"clean": "rm -rf dist",
|
|
41
39
|
"check-format": "prettier --check .",
|
|
42
40
|
"check-exports": "attw --pack .",
|
|
43
41
|
"format": "prettier --write .",
|
|
44
|
-
"lint": "tsc",
|
|
45
|
-
"
|
|
42
|
+
"lint": "tsc && eslint .",
|
|
43
|
+
"test:unit": "vitest run",
|
|
44
|
+
"test:unit:watch": "vitest",
|
|
45
|
+
"ci": "yarn test:unit && yarn lint && yarn clean && yarn build && yarn check-format && yarn check-exports",
|
|
46
46
|
"changeset": "npx changeset",
|
|
47
47
|
"local-release": "changeset version && changeset publish"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@arethetypeswrong/cli": "^0.17.2",
|
|
51
51
|
"@changesets/cli": "^2.27.11",
|
|
52
|
-
"@
|
|
52
|
+
"@eslint/js": "^10.0.1",
|
|
53
|
+
"@playwright/test": "1.58.1",
|
|
53
54
|
"@types/node": "^22.10.5",
|
|
54
55
|
"dotenv": "^16.4.7",
|
|
56
|
+
"eslint": "^10.0.2",
|
|
57
|
+
"eslint-config-prettier": "^10.1.8",
|
|
55
58
|
"prettier": "^3.4.2",
|
|
56
59
|
"standard-version": "^9.5.0",
|
|
57
60
|
"tsup": "^8.3.5",
|
|
58
|
-
"typescript": "^5.7.2"
|
|
61
|
+
"typescript": "^5.7.2",
|
|
62
|
+
"typescript-eslint": "^8.56.1",
|
|
63
|
+
"vitest": "^3.0.0"
|
|
59
64
|
},
|
|
60
65
|
"peerDependencies": {
|
|
61
|
-
"@playwright/test": "^1.
|
|
66
|
+
"@playwright/test": "^1.57.0"
|
|
62
67
|
}
|
|
63
68
|
}
|