@valve-tech/wallet-adapter 0.11.2 → 0.13.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 CHANGED
@@ -6,6 +6,36 @@ this file.
6
6
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
7
7
  and this project adheres to [Semantic Versioning](https://semver.org/).
8
8
 
9
+ ## [0.13.0] — 2026-05-12
10
+
11
+ ### Notes
12
+
13
+ - Synchronized release — no changes to this package. Republished at
14
+ 0.13.0 alongside the rest of the toolkit; the substantive change
15
+ is in `@valve-tech/tx-tracker` (new `TrackOptions.probeMined`
16
+ consumer-supplied mined-detection probe). See
17
+ `@valve-tech/tx-tracker`'s CHANGELOG for details.
18
+
19
+ ## [0.12.0] — 2026-05-11
20
+
21
+ ### Added
22
+
23
+ - Three more `examples/` covering wallet-plumbing classes the
24
+ original five didn't reach (now 8 total):
25
+
26
+ | Example | Covers | Helper |
27
+ |---|---|---|
28
+ | `06-ethers-adapter.ts` | ethers v6 `Signer` (`BrowserProvider.getSigner()` or `Wallet`). For dapps still on ethers or mid-migration to viem. | `walletAdapterFromEthersSigner(...)` |
29
+ | `07-privy-embedded.ts` | Privy embedded wallets via `@privy-io/react-auth`'s `useWallets()`. Handles CAIP-2 chain encoding (`eip155:<id>`) and lazy provider fetching across wallet swaps. | `walletAdapterFromPrivyWallet(...)` |
30
+ | `08-safe-multisig.ts` | Safe (Gnosis Safe) multisig via `@safe-global/protocol-kit` + `@safe-global/api-kit`. **Returns a safeTxHash, not an on-chain tx hash** — UIs have to fork to await the executed hash separately. File header documents the consumer-visible implications. | `walletAdapterFromSafe(...)` |
31
+
32
+ Each follows the existing example shape (inline SDK type-stubs +
33
+ no-network sanity check) so the files typecheck and run without
34
+ any wallet libraries installed.
35
+
36
+ - README "Bridging a real wallet to `WalletAdapter`" table extended
37
+ from 5 to 8 rows.
38
+
9
39
  ## [0.11.2] — 2026-05-11
10
40
 
11
41
  ### Notes
package/README.md CHANGED
@@ -218,6 +218,9 @@ thing:
218
218
  | [`03-server-relayer.ts`](./examples/03-server-relayer.ts) | Backend code: relayer signing from a private key (env var / KMS). No provider, no chain-switching, hard-fail on cross-chain. Right for sponsored-tx services, indexer write paths, integration tests. | `walletAdapterFromRelayer(...)` |
219
219
  | [`04-erc4337-smart-account.ts`](./examples/04-erc4337-smart-account.ts) | ERC-4337 smart accounts via permissionless.js or similar. `adapter.address` is the smart-account address (not the EOA signer). | `walletAdapterFromSmartAccount(...)` |
220
220
  | [`05-hardware-wallet-direct.ts`](./examples/05-hardware-wallet-direct.ts) | Hardware wallets attached **directly** via USB/HID (no wallet app in between) — `@ledgerhq/hw-app-eth` for Ledger; the same shape works for Trezor via `@trezor/connect`. For backend code, kiosk apps, dev tooling. | `walletAdapterFromLedger(...)` |
221
+ | [`06-ethers-adapter.ts`](./examples/06-ethers-adapter.ts) | Dapps still on ethers v6 (or in mid-migration), bridging an `ethers.Signer` (`BrowserProvider.getSigner()` or `Wallet`) without re-wiring to viem. | `walletAdapterFromEthersSigner(...)` |
222
+ | [`07-privy-embedded.ts`](./examples/07-privy-embedded.ts) | Privy embedded wallets via `@privy-io/react-auth`'s `useWallets()`. Handles CAIP-2 chain encoding and lazy provider fetching across wallet swaps. | `walletAdapterFromPrivyWallet(...)` |
223
+ | [`08-safe-multisig.ts`](./examples/08-safe-multisig.ts) | Safe (Gnosis Safe) multisig via `@safe-global/protocol-kit` + `@safe-global/api-kit`. **Returns a safeTxHash, not an on-chain tx hash** — UIs need to fork to await the executed hash separately. | `walletAdapterFromSafe(...)` |
221
224
 
222
225
  Each example includes a no-network sanity check at the bottom so you
223
226
  can run it (`yarn tsx examples/0X-...ts`) without installing any of
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Anvil's deterministic 10-account list — re-exported here as plain
3
+ * data so browser-mode test files can import it without pulling in
4
+ * the Node-only `createAnvilFixture` (which uses `node:child_process`
5
+ * and crashes the browser bundler).
6
+ *
7
+ * These are well-known throwaway keys baked into anvil's default
8
+ * mnemonic. Every account has 10_000 ETH on a fresh anvil instance.
9
+ * NEVER use these on any real chain.
10
+ */
11
+ export declare const ANVIL_ACCOUNTS: {
12
+ readonly relayer: {
13
+ readonly address: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266";
14
+ readonly privateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
15
+ };
16
+ readonly recipient: {
17
+ readonly address: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";
18
+ readonly privateKey: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d";
19
+ };
20
+ readonly cosigner: {
21
+ readonly address: "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC";
22
+ readonly privateKey: "0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a";
23
+ };
24
+ };
25
+ //# sourceMappingURL=anvil-accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anvil-accounts.d.ts","sourceRoot":"","sources":["../src/anvil-accounts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;CAgBjB,CAAA"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Anvil's deterministic 10-account list — re-exported here as plain
3
+ * data so browser-mode test files can import it without pulling in
4
+ * the Node-only `createAnvilFixture` (which uses `node:child_process`
5
+ * and crashes the browser bundler).
6
+ *
7
+ * These are well-known throwaway keys baked into anvil's default
8
+ * mnemonic. Every account has 10_000 ETH on a fresh anvil instance.
9
+ * NEVER use these on any real chain.
10
+ */
11
+ export const ANVIL_ACCOUNTS = {
12
+ relayer: {
13
+ address: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
14
+ privateKey: '0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
15
+ },
16
+ recipient: {
17
+ address: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8',
18
+ privateKey: '0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d',
19
+ },
20
+ cosigner: {
21
+ address: '0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC',
22
+ privateKey: '0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a',
23
+ },
24
+ };
25
+ //# sourceMappingURL=anvil-accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anvil-accounts.js","sourceRoot":"","sources":["../src/anvil-accounts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,OAAO,EAAE;QACP,OAAO,EAAE,4CAAqD;QAC9D,UAAU,EACR,oEAA6E;KAChF;IACD,SAAS,EAAE;QACT,OAAO,EAAE,4CAAqD;QAC9D,UAAU,EACR,oEAA6E;KAChF;IACD,QAAQ,EAAE;QACR,OAAO,EAAE,4CAAqD;QAC9D,UAAU,EACR,oEAA6E;KAChF;CACO,CAAA"}
@@ -0,0 +1,16 @@
1
+ export { ANVIL_ACCOUNTS } from './anvil-accounts.js';
2
+ export interface AnvilFixture {
3
+ url: string;
4
+ start: () => Promise<void>;
5
+ stop: () => Promise<void>;
6
+ }
7
+ /**
8
+ * Build an anvil fixture bound to a port. Tests should call
9
+ * `start()` in beforeAll and `stop()` in afterAll.
10
+ *
11
+ * Polls `eth_chainId` until anvil responds (anvil prints a banner
12
+ * but parsing stdout is racy across versions). Default poll window
13
+ * is 10 seconds — anvil typically starts in under 500ms locally.
14
+ */
15
+ export declare const createAnvilFixture: (port?: number) => AnvilFixture;
16
+ //# sourceMappingURL=anvil-fixture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anvil-fixture.d.ts","sourceRoot":"","sources":["../src/anvil-fixture.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB,GAAI,aAAW,KAAG,YAuDhD,CAAA"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Shared anvil fixture for the wallet-adapter integration tests.
3
+ *
4
+ * Spawns a local anvil instance via child_process, polls its RPC
5
+ * until ready, exposes its URL and deterministic test-account list,
6
+ * and tears down on test exit. The fixture is Node-only — anvil is
7
+ * a native binary launched from outside the test process.
8
+ *
9
+ * Anvil's deterministic 10-account setup is what we lean on: every
10
+ * account has 10_000 ETH and a known private key. We use the first
11
+ * three slots:
12
+ * - account 0: relayer / signer
13
+ * - account 1: recipient
14
+ * - account 2: spare (Safe co-signer, etc.)
15
+ *
16
+ * Each test file pins its own port to avoid races when multiple
17
+ * integration files run in parallel (the integration config uses
18
+ * `singleFork: true` to serialize anyway, but per-file ports are
19
+ * extra defense).
20
+ */
21
+ import { spawn } from 'node:child_process';
22
+ // Re-export account fixtures so Node-side test files only need one
23
+ // import. Browser-side files should import from `./anvil-accounts.js`
24
+ // directly to avoid pulling in this file's Node-only machinery.
25
+ export { ANVIL_ACCOUNTS } from './anvil-accounts.js';
26
+ /**
27
+ * Build an anvil fixture bound to a port. Tests should call
28
+ * `start()` in beforeAll and `stop()` in afterAll.
29
+ *
30
+ * Polls `eth_chainId` until anvil responds (anvil prints a banner
31
+ * but parsing stdout is racy across versions). Default poll window
32
+ * is 10 seconds — anvil typically starts in under 500ms locally.
33
+ */
34
+ export const createAnvilFixture = (port = 8645) => {
35
+ const url = `http://127.0.0.1:${port}`;
36
+ let proc = null;
37
+ const waitForReady = async (deadlineMs) => {
38
+ const start = Date.now();
39
+ while (Date.now() - start < deadlineMs) {
40
+ try {
41
+ const res = await fetch(url, {
42
+ method: 'POST',
43
+ headers: { 'content-type': 'application/json' },
44
+ body: JSON.stringify({
45
+ jsonrpc: '2.0',
46
+ id: 1,
47
+ method: 'eth_chainId',
48
+ params: [],
49
+ }),
50
+ });
51
+ if (res.ok) {
52
+ const json = (await res.json());
53
+ if (typeof json.result === 'string')
54
+ return;
55
+ }
56
+ }
57
+ catch {
58
+ // anvil not listening yet — keep polling.
59
+ }
60
+ await new Promise((r) => setTimeout(r, 100));
61
+ }
62
+ throw new Error(`anvil did not respond on ${url} within ${deadlineMs}ms`);
63
+ };
64
+ return {
65
+ url,
66
+ start: async () => {
67
+ if (proc !== null)
68
+ return;
69
+ proc = spawn('anvil', ['--port', String(port), '--silent'], {
70
+ stdio: 'ignore',
71
+ });
72
+ proc.on('error', (err) => {
73
+ console.error(`anvil spawn failed: ${err.message}`);
74
+ });
75
+ await waitForReady(10000);
76
+ },
77
+ stop: async () => {
78
+ if (proc === null)
79
+ return;
80
+ const exited = new Promise((resolve) => {
81
+ proc?.once('exit', () => resolve());
82
+ });
83
+ proc.kill('SIGTERM');
84
+ await Promise.race([
85
+ exited,
86
+ new Promise((r) => setTimeout(r, 2000)),
87
+ ]);
88
+ proc = null;
89
+ },
90
+ };
91
+ };
92
+ //# sourceMappingURL=anvil-fixture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anvil-fixture.js","sourceRoot":"","sources":["../src/anvil-fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAA;AAE7D,mEAAmE;AACnE,sEAAsE;AACtE,gEAAgE;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAQpD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAI,GAAG,IAAI,EAAgB,EAAE;IAC9D,MAAM,GAAG,GAAG,oBAAoB,IAAI,EAAE,CAAA;IACtC,IAAI,IAAI,GAAwB,IAAI,CAAA;IAEpC,MAAM,YAAY,GAAG,KAAK,EAAE,UAAkB,EAAiB,EAAE;QAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACxB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,UAAU,EAAE,CAAC;YACvC,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;oBAC3B,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;oBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;wBACnB,OAAO,EAAE,KAAK;wBACd,EAAE,EAAE,CAAC;wBACL,MAAM,EAAE,aAAa;wBACrB,MAAM,EAAE,EAAE;qBACX,CAAC;iBACH,CAAC,CAAA;gBACF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;oBACX,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAwB,CAAA;oBACtD,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ;wBAAE,OAAM;gBAC7C,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,0CAA0C;YAC5C,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,WAAW,UAAU,IAAI,CAAC,CAAA;IAC3E,CAAC,CAAA;IAED,OAAO;QACL,GAAG;QACH,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAM;YACzB,IAAI,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,EAAE;gBAC1D,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAA;YACF,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;gBACvB,OAAO,CAAC,KAAK,CAAC,uBAAuB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAA;YACrD,CAAC,CAAC,CAAA;YACF,MAAM,YAAY,CAAC,KAAM,CAAC,CAAA;QAC5B,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,EAAE;YACf,IAAI,IAAI,KAAK,IAAI;gBAAE,OAAM;YACzB,MAAM,MAAM,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAC3C,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAA;YACrC,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACpB,MAAM,OAAO,CAAC,IAAI,CAAC;gBACjB,MAAM;gBACN,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAK,CAAC,CAAC;aACzC,CAAC,CAAA;YACF,IAAI,GAAG,IAAI,CAAA;QACb,CAAC;KACF,CAAA;AACH,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@valve-tech/wallet-adapter",
3
- "version": "0.11.2",
3
+ "version": "0.13.0",
4
4
  "description": "Framework-agnostic vocabulary + runtime helpers for EVM dapp wallet integration. WalletAdapter interface (sign + send), WriteHookParams full lifecycle with rich TxContext payloads (chainId + original request) on every event so consumers don't side-channel; six named hooks (onAwaitingSignature, onTransactionHash, onConfirmed, onFailed, onDropped, onReplaced) plus complementary onPhase(event) discriminated-union shape derived from the WritePhaseSteps phase-map; sendTransactionWithHooks + awaitReceiptWithHooks helpers that fire the hooks at real boundaries (with awaitReceiptWithHooks fetching the containing block once on behalf of all downstream consumers); typed WalletRejectedError + ContractRevertedError for instanceof-discriminated catch; plus TX_STATUS / TX_FLOW / TrackedTx for tx-state UI. Lets SDKs and dapps share one contract instead of each redefining it. Part of the valve-tech/evm-toolkit synchronized release line.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/valve-tech/evm-toolkit/tree/main/packages/wallet-adapter#readme",
@@ -45,11 +45,13 @@
45
45
  "typecheck:examples": "tsc -p examples",
46
46
  "lint": "eslint src",
47
47
  "test": "vitest run",
48
+ "test:browser": "vitest run --config vitest.browser.config.ts",
49
+ "test:integration": "vitest run --config vitest.integration.config.ts",
48
50
  "test:coverage": "vitest run --coverage",
49
51
  "prepare": "yarn build"
50
52
  },
51
53
  "dependencies": {
52
- "@valve-tech/viem-errors": "^0.11.2"
54
+ "@valve-tech/viem-errors": "^0.13.0"
53
55
  },
54
56
  "peerDependencies": {
55
57
  "viem": "^2.0.0"