walletkit-web 0.21.3 → 0.22.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/README.md CHANGED
@@ -1,28 +1,116 @@
1
- # `@worldcoin/walletkit-web`
1
+ # `walletkit-web`
2
2
 
3
- Browser WebAssembly bindings for WalletKit.
3
+ WalletKit's browser client. The package always runs Rust/WASM, cryptography,
4
+ proof generation and SQLite in a dedicated Web Worker. Importing the package
5
+ is safe during SSR; call `initializeWalletKit` in a browser.
4
6
 
5
- > PROTOTYPE: this package is private while its generation and publication
6
- > workflow is being validated.
7
+ ```ts
8
+ import { initializeWalletKit } from "walletkit-web";
9
+
10
+ const wallet = await initializeWalletKit({
11
+ databaseKey, // Uint8Array containing the resolved 32-byte K_intermediate
12
+ storageId: "my-account", // stable namespace for this consumer/account
13
+ environment: "staging", // defaults to production
14
+ region: "eu",
15
+ });
16
+ const recovery = await wallet.recoveryDataFromSeed(seed);
17
+ // For an already registered account:
18
+ await wallet.initializeAuthenticator(seed);
19
+ const proofJson = await wallet.generateProof(requestJson);
20
+ await wallet.close();
21
+ ```
22
+
23
+ The host supplies the resolved `databaseKey`, for example after obtaining passkey
24
+ PRF output and deriving the database key. PRF acquisition/derivation happens before
25
+ initialization; WalletKit does not call WebAuthn or wrap this key in an envelope.
26
+ The worker constructs `StorageKeys.fromBytes(databaseKey)` and passes those keys to
27
+ `CredentialStore`. Both vault and cache use that key directly through sqlite3mc.
28
+
29
+ Supply the same key and storage ID when reopening. The authenticator seed and
30
+ database key are separate inputs. The package does not persist the database key;
31
+ initialization copies it and the caller owns clearing its own copy. Rust keeps the
32
+ resolved key in zeroizing memory until its last owner releases it.
33
+
34
+ Mobile hosts can instead resolve `openOrCreateStorageKeys(paths, keystore,
35
+ blobStore, now)` before constructing the same `CredentialStore(paths, keys)`.
36
+ The store retains no keystore or blob-store references. It releases its key
37
+ reference on destruction and requires a new instance to reopen. The host separately
38
+ calls `deleteStorageKeyEnvelope(paths, blobStore)` if it owns an envelope that should
39
+ be deleted. Existing envelope-backed databases still use their resolved intermediate
40
+ key; the old wrapping secret is not a replacement for that database key.
41
+
42
+ ## Browser API
43
+
44
+ All calls into the worker return Promises. The public client exposes
45
+ `recoveryDataFromSeed`, `register`, `pollRegistration`, `initializeAuthenticator`,
46
+ `prepareCredential`, `storeCredential`, and `generateProof`. Registration polling
47
+ returns plain status records, including failure details. `prepareCredential`
48
+ returns the subject and serialized blinding factor for an issuer flow;
49
+ `storeCredential` accepts credential bytes and that factor. Issuer HTTP calls and
50
+ relying-party request construction remain application code.
51
+
52
+ This replaces the prototype API that returned the generated UniFFI namespace.
53
+ Generated Rust objects are internal and never cross the worker boundary. Existing
54
+ consumers must migrate their calls to the browser client; it is not a transparent
55
+ proxy for every generated binding. See the Next.js demo for a complete registration,
56
+ issuance and proof flow.
7
57
 
8
- The package owns the compiled WalletKit module, generated TypeScript bindings,
9
- UniFFI player setup, and WASM asset resolution. Browser applications initialize
10
- it through one interface:
58
+ Operations run in order, including asynchronous work. `close()` drains queued
59
+ operations, destroys owned Rust objects and terminates the worker. `terminate()`
60
+ interrupts immediately and rejects pending requests. Worker failures also reject
61
+ pending requests. An optional `signal` cancels initialization only; after it
62
+ resolves, use `close()` or `terminate()`.
63
+
64
+ ## Assets and deployment
65
+
66
+ Default URLs are resolved by the application's bundler. Both worker JavaScript
67
+ and the roughly 40 MB WASM asset ship in `dist`. The worker is self-contained,
68
+ including the generated glue and its runtime dependencies.
69
+
70
+ Hosts with custom asset layouts can provide explicit URLs:
11
71
 
12
72
  ```ts
13
- const { initializeWalletKit } = await import("@worldcoin/walletkit-web");
14
- const walletKit = await initializeWalletKit();
73
+ const wallet = await initializeWalletKit({
74
+ databaseKey,
75
+ workerUrl: "/assets/walletkit.worker.js",
76
+ wasmUrl: "/assets/walletkit.wasm",
77
+ });
15
78
  ```
16
79
 
17
- Build it from the repository root with the pinned toolchain:
80
+ Relative overrides resolve against the page URL. These options change asset
81
+ locations; they do not enable main-thread execution. Serve the worker from a
82
+ permitted same-origin location and the WASM file as `application/wasm`.
83
+
84
+ ## Persistent storage
85
+
86
+ Initialization acquires the OPFS sync-access-handle pool asynchronously. SQLite
87
+ operations are synchronous afterward. The browser's direct-key path needs no envelope database. The encrypted credential
88
+ vault/cache retain their existing format and use rollback journals on WASM.
89
+
90
+ Closing a SQLite connection does not release the pool's OPFS handles: the pool
91
+ remains alive until worker termination. Currently one worker owns the WalletKit
92
+ pool per origin. A second tab/client receives an initialization error, even with
93
+ a different storage ID. After shutdown, browser handle release may be asynchronous;
94
+ a subsequent initializer may need to retry. There is no silent memory fallback.
95
+ Pool capacity is reserved at startup rather than expanded during synchronous SQL.
96
+
97
+ Browser storage requires a supported secure context (localhost is suitable for
98
+ development). The SAH pool does not require cross-origin-isolation headers.
99
+ Browser quota and eviction policy still apply.
100
+
101
+ ## Build and verify
18
102
 
19
103
  ```sh
20
- nix develop .#wasm --command npm --prefix web/walletkit install
21
- nix develop .#wasm --command npm --prefix web/walletkit run build
104
+ nix develop .#wasm --command bun install --cwd web/walletkit --frozen-lockfile
105
+ nix develop .#wasm --command bun run --cwd web/walletkit build
106
+ nix develop .#wasm --command bun run --cwd web/walletkit test:browser
22
107
  ```
23
108
 
24
- The release build uses `crates/walletkit` directly, disables its default
25
- features except for `embed-zkeys`, and optimizes the generated module with
26
- `wasm-opt -Oz --converge`. Embedding the proving artifacts currently makes the
27
- optimized WASM roughly 40 MB; lazy artifact delivery and worker placement are
28
- still future production work.
109
+ Browser tests use installed Google Chrome and a production Vite fixture. They
110
+ cover worker startup and lifecycle, URL overrides, exclusive pool ownership,
111
+ wrong-key rejection, and reopening storage with directly supplied keys.
112
+ `bun run bundle` reuses generated bindings for TypeScript-only development.
113
+
114
+ The example uses a new namespace and memory-only database keys on each load. Its encrypted
115
+ files persist, but it intentionally cannot unlock them after reload; a production
116
+ host must implement key recovery/unlock and stable account namespace selection.
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "walletkit-web",
3
- "version": "0.21.3",
4
- "description": "Browser WebAssembly bindings for WalletKit.",
3
+ "version": "0.22.0",
4
+ "description": "WalletKit enables users to hold credentials and prove their humanity with World ID .",
5
5
  "type": "module",
6
+ "packageManager": "bun@1.3.11",
6
7
  "files": [
7
8
  "dist/",
8
9
  "README.md"
@@ -15,20 +16,27 @@
15
16
  },
16
17
  "scripts": {
17
18
  "clean": "node scripts/clean.mjs",
19
+ "format": "prettier --write \"**/*.ts\"",
20
+ "format:check": "prettier --check \"**/*.ts\"",
18
21
  "patch:generator": "node scripts/patch-ubrn-wasm-bindgen.mjs",
19
- "generate": "npm run patch:generator && ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs",
20
- "build": "npm run clean && npm run generate && tsc -p tsconfig.build.json && esbuild src/index.ts --bundle --format=esm --platform=browser --target=es2022 --outfile=dist/index.js --external:@ubjs/core --external:@ubjs/wasm && node scripts/copy-wasm.mjs",
21
- "pack:check": "npm pack --dry-run"
22
+ "generate": "bun run patch:generator && ubrn build wasm2 --config ubrn.config.yaml --release && node scripts/optimize-wasm.mjs && node scripts/patch-generated-index.mjs",
23
+ "build": "bun run clean && bun run generate && bun run bundle",
24
+ "pack:check": "bun pm pack --dry-run",
25
+ "bundle": "tsc -p tsconfig.build.json && esbuild src/index.ts src/walletkit.worker.ts --bundle --format=esm --platform=browser --target=es2022 --outdir=dist --footer:js=\"export {};\" && node scripts/copy-wasm.mjs",
26
+ "test:serve": "vite preview --config tests/vite.config.ts --host 127.0.0.1 --port 4173 --strictPort",
27
+ "test:browser": "tsc -p tests/fixture/tsconfig.json && vite build --config tests/vite.config.ts && playwright test"
22
28
  },
23
29
  "dependencies": {
24
30
  "@ubjs/core": "0.31.0-5",
25
31
  "@ubjs/wasm": "0.31.0-5"
26
32
  },
27
33
  "devDependencies": {
34
+ "@playwright/test": "^1.63.0",
28
35
  "esbuild": "0.25.9",
29
36
  "prettier": "3.6.2",
30
37
  "typescript": "5.9.2",
31
- "uniffi-bindgen-react-native": "0.31.0-5"
38
+ "uniffi-bindgen-react-native": "0.31.0-5",
39
+ "vite": "^8.2.2"
32
40
  },
33
41
  "publishConfig": {
34
42
  "access": "public"
@@ -1,11 +0,0 @@
1
- export * from "./walletkit";
2
- export * from "./walletkit_core";
3
- import * as walletkit from "./walletkit";
4
- import * as walletkit_core from "./walletkit_core";
5
- import { type WasmSource } from "@ubjs/wasm";
6
- export declare function uniffiInitAsync(source: WasmSource): Promise<void>;
7
- declare const _default: {
8
- walletkit: typeof walletkit;
9
- walletkit_core: typeof walletkit_core;
10
- };
11
- export default _default;