@walletwright/core 0.2.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 +110 -0
- package/LICENSE +21 -0
- package/README.md +112 -0
- package/dist/cache-Bqz3Mchl.mjs +972 -0
- package/dist/cache-Bqz3Mchl.mjs.map +1 -0
- package/dist/chain.d.mts +24 -0
- package/dist/chain.mjs +25 -0
- package/dist/chain.mjs.map +1 -0
- package/dist/cli.d.mts +14 -0
- package/dist/cli.mjs +101 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +59 -0
- package/dist/index.mjs +201 -0
- package/dist/index.mjs.map +1 -0
- package/dist/mock-standard.d.mts +41 -0
- package/dist/mock-standard.mjs +125 -0
- package/dist/mock-standard.mjs.map +1 -0
- package/dist/mock.d.mts +30 -0
- package/dist/mock.mjs +66 -0
- package/dist/mock.mjs.map +1 -0
- package/dist/types-CWxz_dJe.d.mts +196 -0
- package/package.json +94 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# @walletwright/core
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 25a0f0b: Run wallet suites headless. `launchWallet` takes `{ headless }` and `createWalletFixtures` passes
|
|
8
|
+
Playwright's own `headless` option through, so `--headed` and `use: { headless }` now reach the
|
|
9
|
+
wallet's browser. Headless launches the `chromium` channel, because Playwright's default headless
|
|
10
|
+
build is the headless shell, which cannot load an extension at all.
|
|
11
|
+
|
|
12
|
+
Whether it then works is per wallet, and a wallet says so with the new
|
|
13
|
+
`WalletDefinition.headlessApprovals`: Phantom's and Rabby's approval windows surface as pages
|
|
14
|
+
headless, MetaMask's is created but never exposed, and Solflare rejects a headless connect outright.
|
|
15
|
+
`launchWallet` throws a named error for a wallet that has not declared it, rather than hanging at
|
|
16
|
+
the first approval.
|
|
17
|
+
|
|
18
|
+
Two smaller changes go with it. `WalletDefinition.approvalControls` lets a wallet say which controls
|
|
19
|
+
mean "a request is on screen", so a popup that renders the wallet's home screen is not mistaken for
|
|
20
|
+
an approval; MetaMask declares it. And an approval window is now pinned to 360x592 and moved on
|
|
21
|
+
screen over CDP before it is clicked, because a popup that opens partly off a small or virtual
|
|
22
|
+
display renders fine but cannot be clicked.
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- b84bd5a: Declare each wallet capability once. `AccountActions`, `NetworkActions` and `SettingsActions` are now
|
|
27
|
+
derived from the matching `AccountsApi`, `NetworkApi` and `SettingsApi` types on `Wallet`, so a
|
|
28
|
+
capability's name and argument list are written in a single place and the controller stops compiling
|
|
29
|
+
until a new one is bound. Published types are unchanged: the derived aliases resolve to exactly the
|
|
30
|
+
shapes they replaced.
|
|
31
|
+
- a7f7a51: Fix the `walletwright` CLI doing nothing when run from an installed package.
|
|
32
|
+
|
|
33
|
+
The entry guard compared `import.meta.url` against a raw `process.argv[1]`. Node resolves the
|
|
34
|
+
former through symlinks and leaves the latter alone, so every invocation through
|
|
35
|
+
`node_modules/.bin/walletwright` (a symlink under any pnpm install) compared unequal, skipped
|
|
36
|
+
`main()`, and exited 0 without output. The guard now resolves the entry path first.
|
|
37
|
+
|
|
38
|
+
With the CLI reachable again, `walletwright --help` and `walletwright -h` print the help text
|
|
39
|
+
instead of erroring with "unknown command": flags are now parsed from the whole argv rather than
|
|
40
|
+
only the tokens after a command, so a leading flag is seen.
|
|
41
|
+
|
|
42
|
+
- 0341a74: Drop the `prepare` script. It rebuilt the package after every `pnpm install`, outside turbo's cache
|
|
43
|
+
and graph, duplicating work `prepack` already does when publishing. Installing from a git reference
|
|
44
|
+
now needs an explicit build.
|
|
45
|
+
- 0341a74: Fail loudly when a wallet is not actually ready, instead of handing back a broken one.
|
|
46
|
+
|
|
47
|
+
- Phantom and Slush now tell "already unlocked" apart from "still locked", and throw when the
|
|
48
|
+
extension page rendered neither. Previously Phantom's `reachUnlockScreen` returned whatever it
|
|
49
|
+
found after six polls and its `unlock` returned early whenever no password field was visible, so a
|
|
50
|
+
broken wallet looked launched and failed later at the first approval.
|
|
51
|
+
- `buildCache` asserts that the wallet wrote state into the profile before reporting the cache, and
|
|
52
|
+
the MetaMask onboarding patch throws (rather than returning quietly) when the state it means to
|
|
53
|
+
patch is missing. Slush's import waits for the wallet home instead of falling through.
|
|
54
|
+
- Every poll loop shares one `waitUntil` helper, so the timeout a failure reports is the timeout it
|
|
55
|
+
actually waited.
|
|
56
|
+
- The `wallet` fixture reads from the same launch as `context` rather than a worker-level variable,
|
|
57
|
+
and no longer launches an extra Chromium per worker that no test drives.
|
|
58
|
+
|
|
59
|
+
- 25a0f0b: Fix the Slush cache build. Slush's own backend answers an automated browser with a Cloudflare 403
|
|
60
|
+
whose body is a marketing page, so its GraphQL client throws at boot and renders an error screen
|
|
61
|
+
instead of the wallet, which surfaced several screens later as a `Word 1` input timeout. Slush now
|
|
62
|
+
answers `*.slush.app` with an empty GraphQL body through `WalletDefinition.prepareContext`, a new
|
|
63
|
+
optional hook applied to both the cache-build and the test context before anything navigates.
|
|
64
|
+
Onboarding, unlock, connect, and sign need nothing from that API.
|
|
65
|
+
- 0341a74: Verify the pinned MetaMask download against a recorded sha256. The integrity option existed but no
|
|
66
|
+
caller passed it, so the pinned release archive was fetched and extracted unverified. The hash is now
|
|
67
|
+
required at every download site, recorded per MetaMask version in one place, and `undefined` only for
|
|
68
|
+
the Chrome Web Store fetches, whose endpoint always serves the current version and cannot be pinned.
|
|
69
|
+
|
|
70
|
+
## 0.1.0
|
|
71
|
+
|
|
72
|
+
Initial release.
|
|
73
|
+
|
|
74
|
+
### Wallets
|
|
75
|
+
|
|
76
|
+
Connect and sign are verified end to end against the real extension, headed, for every wallet below.
|
|
77
|
+
A wallet is only registered once it has been driven for real.
|
|
78
|
+
|
|
79
|
+
- **MetaMask** (EVM + Solana)
|
|
80
|
+
- **Phantom** (EVM + Solana)
|
|
81
|
+
- **Rabby** (EVM)
|
|
82
|
+
- **Solflare** (Solana)
|
|
83
|
+
- **Slush** (Sui)
|
|
84
|
+
|
|
85
|
+
### API
|
|
86
|
+
|
|
87
|
+
- `buildCache(setup)` onboards a wallet from a seed phrase into a cached profile on disk, once.
|
|
88
|
+
- `createWalletFixtures(setup)` returns a `@playwright/test` `test` with a `wallet` fixture, so there
|
|
89
|
+
is no framework lock-in.
|
|
90
|
+
- `launchWallet(setup)` for driving a wallet outside the fixture.
|
|
91
|
+
- `wallet.connectToDapp()`, `confirmSignature()`, `confirmTransaction()`, `approve()`, and the
|
|
92
|
+
matching `reject*()` methods.
|
|
93
|
+
- Optional per-wallet capabilities under `wallet.settings`, `wallet.network`, and `wallet.accounts`.
|
|
94
|
+
A wallet declares only what has been driven against the real extension; anything else throws
|
|
95
|
+
`[walletwright] <wallet> does not support <action>()`.
|
|
96
|
+
- `wallets` and `walletKindsByEcosystem(ecosystem)` for the registry.
|
|
97
|
+
- `walletwright cache` CLI for building profiles ahead of a test run.
|
|
98
|
+
|
|
99
|
+
### Subpath exports
|
|
100
|
+
|
|
101
|
+
- `@walletwright/core/chain` spins up a local anvil chain through `prool` for transaction tests.
|
|
102
|
+
- `@walletwright/core/mock` and `@walletwright/core/mock-standard` provide headless provider mocks
|
|
103
|
+
(EIP-1193 and the Solana Wallet Standard) for tests that do not need a real extension.
|
|
104
|
+
|
|
105
|
+
### Notes
|
|
106
|
+
|
|
107
|
+
- Approval popups only open in **headed** Chromium. On CI, use a virtual display such as `xvfb-run`.
|
|
108
|
+
- `prool` and `viem` are optional peer dependencies. `@walletwright/core/chain` needs both;
|
|
109
|
+
`@walletwright/core/mock` needs `viem`. The main entry and `@walletwright/core/mock-standard` need
|
|
110
|
+
neither.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pedro Filho
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# walletwright
|
|
2
|
+
|
|
3
|
+
Playwright wallet automation for **MetaMask (EVM + Solana)**, **Phantom (EVM + Solana)**,
|
|
4
|
+
**Rabby (EVM)**, **Solflare (Solana)**, and **Slush (Sui)**.
|
|
5
|
+
It connects and signs in the real browser extensions.
|
|
6
|
+
|
|
7
|
+
- Real extensions, no mocks: MetaMask, Phantom, Rabby, Solflare, and Slush on their current
|
|
8
|
+
versions.
|
|
9
|
+
- EVM, Solana, and Sui from one fixture: `window.ethereum`, `window.phantom.solana`, and the Sui
|
|
10
|
+
Wallet Standard.
|
|
11
|
+
- Onboard a wallet once into a cached profile, then unlock it and drive the popups in every test.
|
|
12
|
+
- Plain `@playwright/test` fixtures, so there is no framework lock-in.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
pnpm add -D @walletwright/core @playwright/test
|
|
18
|
+
pnpm exec playwright install chromium
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`@playwright/test` is a peer dependency.
|
|
22
|
+
|
|
23
|
+
## 1. Describe the wallet
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
// wallet-setup.ts
|
|
27
|
+
import type { WalletSetup } from "@walletwright/core";
|
|
28
|
+
|
|
29
|
+
export const metamask: WalletSetup = {
|
|
30
|
+
wallet: "metamask",
|
|
31
|
+
seedPhrase: "test test test test test test test test test test test junk",
|
|
32
|
+
password: "Tester@1234",
|
|
33
|
+
};
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> **Phantom and Slush** reject the famous public test seed (Phantom flags it as malicious and drops
|
|
37
|
+
> the connection). Use a fresh, unfunded mnemonic for those two.
|
|
38
|
+
|
|
39
|
+
## 2. Build the cache (once)
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
walletwright cache --setup ./wallet-setup.ts
|
|
43
|
+
# or: walletwright cache --wallet metamask --seed "YOUR_SEED_HERE" --password "YOUR_PASSWORD_HERE"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or call it from code, which works well as a Playwright global setup:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { buildCache } from "@walletwright/core";
|
|
50
|
+
import { metamask } from "./wallet-setup.ts";
|
|
51
|
+
|
|
52
|
+
await buildCache(metamask);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 3. Write a test
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createWalletFixtures } from "@walletwright/core";
|
|
59
|
+
import { metamask } from "./wallet-setup.ts";
|
|
60
|
+
|
|
61
|
+
const test = createWalletFixtures(metamask);
|
|
62
|
+
const { expect } = test;
|
|
63
|
+
|
|
64
|
+
test("connect and sign", async ({ page, wallet }) => {
|
|
65
|
+
await page.goto("/");
|
|
66
|
+
|
|
67
|
+
await page.getByRole("button", { name: "Connect" }).click();
|
|
68
|
+
await wallet.connectToDapp();
|
|
69
|
+
await expect(page.locator("#account")).toContainText("0x");
|
|
70
|
+
|
|
71
|
+
await page.getByRole("button", { name: "Sign" }).click();
|
|
72
|
+
await wallet.confirmSignature();
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The `wallet` fixture:
|
|
77
|
+
|
|
78
|
+
| Method | Description |
|
|
79
|
+
| ----------------------- | --------------------------------------------------------------------------------- |
|
|
80
|
+
| `connectToDapp()` | Approve a pending connection popup. Resolves quietly if the wallet auto-approved. |
|
|
81
|
+
| `confirmSignature()` | Approve a pending signature popup. |
|
|
82
|
+
| `approve({ optional })` | Approve any pending popup, whether connect, sign, or a transaction. |
|
|
83
|
+
| `extensionId` | The loaded extension id. |
|
|
84
|
+
|
|
85
|
+
The same two calls drive every chain. A Phantom test can connect and sign on
|
|
86
|
+
`window.phantom.ethereum` and then on `window.phantom.solana`; a Slush test does the same on Sui. See
|
|
87
|
+
`apps/demo` for a full example.
|
|
88
|
+
|
|
89
|
+
## Without fixtures
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { launchWallet } from "@walletwright/core";
|
|
93
|
+
|
|
94
|
+
const { context, wallet } = await launchWallet(metamask);
|
|
95
|
+
const page = await context.newPage();
|
|
96
|
+
// drive the page and the wallet here
|
|
97
|
+
await context.close();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Requirements and notes
|
|
101
|
+
|
|
102
|
+
- **Headless works for Phantom and Rabby**, whose approval windows surface as pages that way.
|
|
103
|
+
MetaMask, Solflare and Slush need a real window, so default those suites to headed and give CI a
|
|
104
|
+
virtual display: `xvfb-run --auto-servernum pnpm exec playwright test`.
|
|
105
|
+
- MetaMask is pinned to a known-good version (override it with `WalletSetup.version`). Phantom,
|
|
106
|
+
Rabby, Solflare, and Slush always use the current Web Store build.
|
|
107
|
+
- The cache lives in `.walletwright/` (override it with `WalletSetup.cacheDir`). Add that directory to
|
|
108
|
+
`.gitignore`.
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT
|