w3wallets

star 120

Interact with browser wallets (MetaMask, Polkadot.js) in Playwright e2e tests. Use when the user needs to set up wallet extensions, create wallet fixtures, approve/deny transactions, manage wallet caching, or any Web3 wallet interaction in tests.

Maksandre By Maksandre schedule Updated 3/7/2026

name: w3wallets description: Interact with browser wallets (MetaMask, Polkadot.js) in Playwright e2e tests. Use when the user needs to set up wallet extensions, create wallet fixtures, approve/deny transactions, manage wallet caching, or any Web3 wallet interaction in tests. metadata: author: Maksandre version: "1.0" license: MIT

w3wallets

A Playwright library for browser wallet interactions (MetaMask, Polkadot.js) in e2e tests.

Quick Start

# 1. Install the library
npm install -D w3wallets

# 2. Download the wallet extension
npx w3wallets metamask

# 3. Create a fixture and write a test
// fixtures.ts
import { test as base } from "@playwright/test";
import { withWallets, metamask } from "w3wallets";

export const test = withWallets(base, metamask);

// my-test.spec.ts
import { test } from "./fixtures";

test("connect wallet", async ({ page, metamask }) => {
  await metamask.onboard("your twelve word mnemonic phrase here ...");
  await page.goto("http://localhost:3000");
  await page.getByRole("button", { name: "Connect Wallet" }).click();
  await metamask.approve();
});

Setup

Download wallet extensions with the CLI:

npx w3wallets metamask      # downloads MetaMask
npx w3wallets polkadotjs    # downloads Polkadot.js
npx w3wallets <extension-id> # downloads any Chrome extension by ID

Extensions are stored in .w3wallets/ at the project root. Add .w3wallets/ to .gitignore.

withWallets Fixture

withWallets(base, ...walletConfigs) extends Playwright's test with wallet fixtures. Each wallet config adds a typed fixture by its name.

import { test as base } from "@playwright/test";
import { withWallets, metamask, polkadotJS } from "w3wallets";

// Single wallet
const test = withWallets(base, metamask);
// test("...", async ({ metamask }) => { ... });

// Multiple wallets
const test = withWallets(base, metamask, polkadotJS);
// test("...", async ({ metamask, polkadotJS }) => { ... });

Each fixture provides a wallet instance with its own extension page. The context fixture is a persistent Chromium context with extensions loaded.

Wallet API Overview

MetaMask

Method Description
onboard(mnemonic, password?) Import wallet with recovery phrase
approve() Confirm the pending transaction/connection
deny() Reject the pending transaction/connection
lock() Lock the wallet
unlock(password?) Unlock the wallet (handles post-unlock screens)
switchNetwork(name, category?) Switch to a network ("Popular" or "Custom")
switchAccount(name) Switch to an account by name
addNetwork(settings) Add a custom network via settings page
addCustomNetwork(settings) Add a custom network via the networks modal
enableTestNetworks() Toggle test networks visibility
importAccount(privateKey) Import an account by private key
accountNameIs(name) Assert the active account name

NetworkSettings: { name: string, rpc: string, chainId: number, currencySymbol: string }

Polkadot.js

Method Description
onboard(seed, password?, name?) Import account from seed phrase
approve() Approve connection or sign transaction
deny() Reject connection or cancel signing
selectAllAccounts() Select all accounts for connection
selectAccount(accountId) Select a specific account by ID
enterPassword(password?) Enter password for signing

Full API details: MetaMask reference | Polkadot.js reference

Common Patterns

The Two-Page Dance

Wallet interactions involve two pages: your dApp page and the wallet extension page. The library handles navigation to the extension automatically.

// 1. Trigger action on dApp page
await page.getByRole("button", { name: "Connect Wallet" }).click();

// 2. Approve in wallet (library navigates to extension page internally)
await metamask.approve();

// 3. Continue on dApp page
await page.bringToFront(); // bring dApp page back to focus if needed

Connect, Sign, Approve, Deny

// Connect
await page.getByRole("button", { name: "Connect" }).click();
await metamask.approve();

// Sign a message
await page.getByRole("button", { name: "Sign" }).click();
await metamask.approve();

// Deny a transaction
await page.getByRole("button", { name: "Send" }).click();
await metamask.deny();

Switch Network

await metamask.switchNetwork("Sepolia");
await metamask.switchNetwork("My Custom Network", "Custom");

Caching

Wallet onboarding (seed import, password setup) takes 15-30 seconds. Caching reduces this to ~2 seconds by restoring a pre-onboarded browser profile.

Quick setup:

// wallets-cache/default.cache.ts
import { prepareWallet, metamask } from "w3wallets";

export default prepareWallet(metamask, async (wallet) => {
  await wallet.onboard("your twelve word mnemonic ...", "MyPassword123!");
});
npx w3wallets cache wallets-cache          # build cache
npx w3wallets cache wallets-cache --force  # rebuild
// fixtures.ts — use cached wallet
import { test as base } from "@playwright/test";
import { withWallets } from "w3wallets";
import cachedMetamask from "./wallets-cache/default.cache";

const test = withWallets(base, cachedMetamask);

// Fixture: unlock instead of onboard
test.extend({
  metamask: async ({ metamask }, use) => {
    await metamask.unlock(); // ~2s instead of ~20s
    await use(metamask);
  },
});

Full caching guide: references/caching.md

Configuration

Environment variables:

Variable Description Default
W3WALLETS_ACTION_TIMEOUT Timeout for actions (click, fill, goto) in ms 30000
W3WALLETS_EXPECT_TIMEOUT Timeout for expect assertions in ms Playwright default (5000)
W3WALLETS_DEBUG Enable debug logging ("true") disabled
W3WALLETS_DEBUG=true npx playwright test

Waiting Best Practices

  • Prefer waiting for UI effects: await expect(element).toBeVisible()
  • Use page.waitForResponse / page.waitForRequest for API calls when no reliable UI indicator exists
  • Avoid page.waitForTimeout — only use during debugging or as a last resort

Custom Wallets

You can add support for any Chrome extension wallet by extending the Wallet base class. See references/custom-wallets.md.

References

Install via CLI
npx skills add https://github.com/Maksandre/w3wallets --skill w3wallets
Repository Details
star Stars 120
call_split Forks 17
navigation Branch main
article Path SKILL.md
More from Creator