w3wallets 0.0.1 → 0.0.3

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 ADDED
@@ -0,0 +1,39 @@
1
+ # w3wallets
2
+
3
+ Web3 wallets for Playwright.
4
+
5
+ > [!IMPORTANT]
6
+ > This is Alpha!
7
+
8
+ This library provides methods for interacting with Web3 wallets using Playwright.
9
+
10
+ ```sh
11
+ npm install -D w3wallets
12
+ ```
13
+
14
+ ## Getting Started
15
+
16
+ Only the `Backpack` wallet is supported at this point.
17
+
18
+ #### 1. Download wallets
19
+
20
+ ```sh
21
+ npx w3wallets
22
+ ```
23
+
24
+ #### 2. Wrap your fixture `withWallets`
25
+
26
+ ```ts
27
+ import { test as base } from "@playwright/test";
28
+ import { withWallets } from "../src/withWallets";
29
+
30
+ const test = withWallets(base, { backpack: true });
31
+
32
+ test("has title", async ({ page, backpack }) => {
33
+ await page.goto("https://playwright.dev/");
34
+
35
+ await backpack.onboard(
36
+ "4wDJd9Ds5ueTdS95ReAZGSBVkjMcNKbgZk47xcmqzpUJjCt7VoB2Cs7hqwXWRnopzXqE4mCP6BEDHCYrFttEcBw2",
37
+ );
38
+ });
39
+ ```
package/dist/index.d.mts CHANGED
@@ -1,11 +1,19 @@
1
1
  import * as playwright_test from 'playwright/test';
2
- import { test, BrowserContext } from '@playwright/test';
2
+ import { Page, test, BrowserContext } from '@playwright/test';
3
+
4
+ declare class Backpack {
5
+ private page;
6
+ constructor(page: Page);
7
+ onboard(privateKey: string): Promise<void>;
8
+ }
3
9
 
4
10
  type Config = {
5
11
  backpack: boolean;
6
12
  };
7
- declare function withExtensions(test: typeof test, config: Config): playwright_test.TestType<playwright_test.PlaywrightTestArgs & playwright_test.PlaywrightTestOptions & {
13
+ declare function withWallets(test: typeof test, config: Config): playwright_test.TestType<playwright_test.PlaywrightTestArgs & playwright_test.PlaywrightTestOptions & {
8
14
  context: BrowserContext;
15
+ backpack: Backpack;
16
+ extensionId: string;
9
17
  }, playwright_test.PlaywrightWorkerArgs & playwright_test.PlaywrightWorkerOptions>;
10
18
 
11
- export { withExtensions };
19
+ export { withWallets as withExtensions };
package/dist/index.d.ts CHANGED
@@ -1,11 +1,19 @@
1
1
  import * as playwright_test from 'playwright/test';
2
- import { test, BrowserContext } from '@playwright/test';
2
+ import { Page, test, BrowserContext } from '@playwright/test';
3
+
4
+ declare class Backpack {
5
+ private page;
6
+ constructor(page: Page);
7
+ onboard(privateKey: string): Promise<void>;
8
+ }
3
9
 
4
10
  type Config = {
5
11
  backpack: boolean;
6
12
  };
7
- declare function withExtensions(test: typeof test, config: Config): playwright_test.TestType<playwright_test.PlaywrightTestArgs & playwright_test.PlaywrightTestOptions & {
13
+ declare function withWallets(test: typeof test, config: Config): playwright_test.TestType<playwright_test.PlaywrightTestArgs & playwright_test.PlaywrightTestOptions & {
8
14
  context: BrowserContext;
15
+ backpack: Backpack;
16
+ extensionId: string;
9
17
  }, playwright_test.PlaywrightWorkerArgs & playwright_test.PlaywrightWorkerOptions>;
10
18
 
11
- export { withExtensions };
19
+ export { withWallets as withExtensions };
package/dist/index.js CHANGED
@@ -30,19 +30,54 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- withExtensions: () => withExtensions
33
+ withExtensions: () => withWallets
34
34
  });
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
37
- // src/withExtension.ts
37
+ // src/withWallets.ts
38
38
  var import_path = __toESM(require("path"));
39
+ var import_fs = __toESM(require("fs"));
39
40
  var import_test = require("@playwright/test");
40
41
  var import_test2 = require("@playwright/test");
41
- function withExtensions(test, config) {
42
+
43
+ // src/backpack/index.ts
44
+ var Backpack = class {
45
+ constructor(page) {
46
+ this.page = page;
47
+ }
48
+ async onboard(privateKey) {
49
+ await this.page.getByRole("button", { name: "I already have a wallet" }).click();
50
+ await this.page.getByRole("button", { name: "Show advanced options" }).click();
51
+ await this.page.getByRole("button", { name: "Import with private key" }).click();
52
+ await this.page.getByPlaceholder("Enter private key").fill(privateKey);
53
+ await this.page.getByRole("button", { name: "Import" }).click();
54
+ await this.page.getByPlaceholder("Password", { exact: true }).fill("11111111");
55
+ await this.page.getByPlaceholder("Confirm Password").fill("11111111");
56
+ await this.page.getByRole("checkbox").click();
57
+ await this.page.getByRole("button", { name: "Next" }).click();
58
+ }
59
+ };
60
+
61
+ // src/withWallets.ts
62
+ function withWallets(test, config) {
42
63
  const backpack = import_path.default.join(process.cwd(), "extensions", "backpack");
43
64
  return test.extend({
65
+ backpack: async ({ context, extensionId }, use) => {
66
+ const page = context.pages()[0];
67
+ if (!page) throw Error("No pages in context");
68
+ const backpack2 = new Backpack(page);
69
+ await page.goto(
70
+ `chrome-extension://${extensionId}/options.html?onboarding=true`
71
+ );
72
+ await use(backpack2);
73
+ },
44
74
  context: async ({}, use) => {
45
75
  const userDataDir = import_path.default.join(process.cwd(), ".tmp-user-data");
76
+ const backpackDownloaded = import_fs.default.existsSync(
77
+ import_path.default.join(backpack, "manifest.json")
78
+ );
79
+ if (!backpackDownloaded)
80
+ throw Error("Cannot find Backpack. download it `npx w3wallets`");
46
81
  const context = await import_test2.chromium.launchPersistentContext(userDataDir, {
47
82
  headless: false,
48
83
  args: [
@@ -52,6 +87,13 @@ function withExtensions(test, config) {
52
87
  });
53
88
  await use(context);
54
89
  await context.close();
90
+ },
91
+ extensionId: async ({ context }, use) => {
92
+ let [background] = context.serviceWorkers();
93
+ if (!background) background = await context.waitForEvent("serviceworker");
94
+ const extensionId = background.url().split("/")[2];
95
+ if (!extensionId) throw Error("No extension id");
96
+ await use(extensionId);
55
97
  }
56
98
  });
57
99
  }
package/dist/index.mjs CHANGED
@@ -1,12 +1,47 @@
1
- // src/withExtension.ts
1
+ // src/withWallets.ts
2
2
  import path from "path";
3
+ import fs from "fs";
3
4
  import "@playwright/test";
4
5
  import { chromium } from "@playwright/test";
5
- function withExtensions(test, config) {
6
+
7
+ // src/backpack/index.ts
8
+ var Backpack = class {
9
+ constructor(page) {
10
+ this.page = page;
11
+ }
12
+ async onboard(privateKey) {
13
+ await this.page.getByRole("button", { name: "I already have a wallet" }).click();
14
+ await this.page.getByRole("button", { name: "Show advanced options" }).click();
15
+ await this.page.getByRole("button", { name: "Import with private key" }).click();
16
+ await this.page.getByPlaceholder("Enter private key").fill(privateKey);
17
+ await this.page.getByRole("button", { name: "Import" }).click();
18
+ await this.page.getByPlaceholder("Password", { exact: true }).fill("11111111");
19
+ await this.page.getByPlaceholder("Confirm Password").fill("11111111");
20
+ await this.page.getByRole("checkbox").click();
21
+ await this.page.getByRole("button", { name: "Next" }).click();
22
+ }
23
+ };
24
+
25
+ // src/withWallets.ts
26
+ function withWallets(test, config) {
6
27
  const backpack = path.join(process.cwd(), "extensions", "backpack");
7
28
  return test.extend({
29
+ backpack: async ({ context, extensionId }, use) => {
30
+ const page = context.pages()[0];
31
+ if (!page) throw Error("No pages in context");
32
+ const backpack2 = new Backpack(page);
33
+ await page.goto(
34
+ `chrome-extension://${extensionId}/options.html?onboarding=true`
35
+ );
36
+ await use(backpack2);
37
+ },
8
38
  context: async ({}, use) => {
9
39
  const userDataDir = path.join(process.cwd(), ".tmp-user-data");
40
+ const backpackDownloaded = fs.existsSync(
41
+ path.join(backpack, "manifest.json")
42
+ );
43
+ if (!backpackDownloaded)
44
+ throw Error("Cannot find Backpack. download it `npx w3wallets`");
10
45
  const context = await chromium.launchPersistentContext(userDataDir, {
11
46
  headless: false,
12
47
  args: [
@@ -16,9 +51,16 @@ function withExtensions(test, config) {
16
51
  });
17
52
  await use(context);
18
53
  await context.close();
54
+ },
55
+ extensionId: async ({ context }, use) => {
56
+ let [background] = context.serviceWorkers();
57
+ if (!background) background = await context.waitForEvent("serviceworker");
58
+ const extensionId = background.url().split("/")[2];
59
+ if (!extensionId) throw Error("No extension id");
60
+ await use(extensionId);
19
61
  }
20
62
  });
21
63
  }
22
64
  export {
23
- withExtensions
65
+ withWallets as withExtensions
24
66
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "w3wallets",
3
3
  "description": "browser wallets for playwright",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "author": "Max Andreev <maxick20@gmail.com>",
@@ -12,6 +12,9 @@
12
12
  "files": [
13
13
  "dist"
14
14
  ],
15
+ "bin": {
16
+ "w3wallets": "./src/scripts/download.js"
17
+ },
15
18
  "devDependencies": {
16
19
  "@arethetypeswrong/cli": "^0.17.2",
17
20
  "@changesets/cli": "^2.27.11",
@@ -30,8 +33,14 @@
30
33
  "clean": "rm -rf dist",
31
34
  "check-format": "prettier --check .",
32
35
  "check-exports": "attw --pack .",
36
+ "format": "prettier --write .",
33
37
  "lint": "tsc",
34
38
  "ci": "yarn lint && yarn clean && yarn build && yarn check-format && yarn check-exports",
39
+ "changeset": "npx changeset",
35
40
  "local-release": "changeset version && changeset publish"
41
+ },
42
+ "dependencies": {
43
+ "adm-zip": "^0.5.16",
44
+ "follow-redirects": "^1.15.9"
36
45
  }
37
- }
46
+ }
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { https } = require("follow-redirects");
6
+ const AdmZip = require("adm-zip");
7
+
8
+ const args = process.argv.slice(2);
9
+
10
+ // Default configurations
11
+ const DEFAULT_WALLET = "backpack";
12
+ const DEFAULT_DOWNLOAD_LINK =
13
+ "https://github.com/coral-xyz/backpack/releases/download/0.10.1-latest-4/build-beta-4.zip";
14
+
15
+ // Parse arguments
16
+ const walletArg = args.find((arg) => arg.startsWith("--wallet="));
17
+ const downloadArg = args.find((arg) => arg.startsWith("--version="));
18
+
19
+ const wallet = walletArg ? walletArg.split("=")[1] : DEFAULT_WALLET;
20
+ const downloadLink = downloadArg
21
+ ? downloadArg.split("=")[1]
22
+ : DEFAULT_DOWNLOAD_LINK;
23
+ const outputDir = path.resolve(`extensions/${wallet}`);
24
+ const zipPath = path.resolve(outputDir, `${wallet}.zip`);
25
+
26
+ console.log(`Fetching ${wallet}...`);
27
+
28
+ // Ensure the output directory exists
29
+ fs.mkdirSync(outputDir, { recursive: true });
30
+
31
+ // Download the zip file
32
+ https
33
+ .get(downloadLink, (response) => {
34
+ if (response.statusCode !== 200) {
35
+ console.error(
36
+ `Failed to download file. Status Code: ${response.statusCode}`,
37
+ );
38
+ return;
39
+ }
40
+
41
+ const fileStream = fs.createWriteStream(zipPath);
42
+ response.pipe(fileStream);
43
+
44
+ fileStream.on("finish", () => {
45
+ fileStream.close();
46
+ console.log(`Downloaded to ${zipPath}`);
47
+
48
+ // Unzip the file
49
+ console.log("Unzipping...");
50
+ const zip = new AdmZip(zipPath);
51
+ zip.extractAllTo(outputDir, true);
52
+ console.log(`Extracted to ${outputDir}`);
53
+
54
+ fs.unlinkSync(zipPath);
55
+
56
+ // Check if the result is a single directory with manifest.json inside
57
+ const files = fs.readdirSync(outputDir);
58
+ if (files.length === 1) {
59
+ const singleDirPath = path.join(outputDir, files[0]);
60
+ if (
61
+ fs.lstatSync(singleDirPath).isDirectory() &&
62
+ fs.existsSync(path.join(singleDirPath, "manifest.json"))
63
+ ) {
64
+ // Move all files from the directory to the outputDir
65
+ const nestedFiles = fs.readdirSync(singleDirPath);
66
+ nestedFiles.forEach((file) => {
67
+ const srcPath = path.join(singleDirPath, file);
68
+ const destPath = path.join(outputDir, file);
69
+ fs.renameSync(srcPath, destPath);
70
+ });
71
+ } else {
72
+ throw Error("Cannot find the manifest.json file");
73
+ }
74
+ }
75
+ });
76
+ })
77
+ .on("error", (err) => {
78
+ console.error(`Error downloading the file: ${err.message}`);
79
+ });