Skip to content
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7cabdbf
feat(web-client): add WebAuthn PRF-based key encryption module
WiktorStarczewski Feb 26, 2026
5c9ef7e
feat(web-client): integrate passkeyEncryption into MidenClient.create()
WiktorStarczewski Feb 26, 2026
ed25d53
feat(react-sdk): add passkeyEncryption support to MidenProvider
WiktorStarczewski Feb 26, 2026
9dd3614
docs: add passkey encryption documentation
WiktorStarczewski Feb 26, 2026
36dcb45
feat: add vite-plugin, fix StrictMode init, enable passkey in wallet …
WiktorStarczewski Feb 27, 2026
9238445
chore: update yarn lockfiles
WiktorStarczewski Feb 27, 2026
94b77e4
chore: remove debug logs from MidenProvider
WiktorStarczewski Feb 27, 2026
5f187ea
docs: add changelog entry for passkey encryption feature
WiktorStarczewski Feb 27, 2026
1712425
fix: review fixes — migration round-trip verification, passkey fallba…
WiktorStarczewski Feb 27, 2026
606320c
fix: add passkey fallback to MidenClient.create() for unsupported bro…
WiktorStarczewski Feb 27, 2026
2313910
fix: review round 2 — verify migration bytes, fix storeName mismatch,…
WiktorStarczewski Feb 27, 2026
70c5a4d
fix: pass storeName to fallback createClient path in MidenProvider
WiktorStarczewski Feb 27, 2026
7b26e27
docs: fill changelog PR number (#1836)
WiktorStarczewski Feb 27, 2026
62e83b8
fix(ci): run prettier, regenerate typedoc, remove version sync script
WiktorStarczewski Feb 27, 2026
46690f6
fix(ci): ignore vite-plugin in root eslint config
WiktorStarczewski Feb 27, 2026
34ca09c
fix(web-client): add passkey-keystore as standalone rollup entry point
WiktorStarczewski Feb 27, 2026
74ff593
fix(web-client): use native IndexedDB API instead of Dexie in passkey…
WiktorStarczewski Feb 27, 2026
8fe769f
fix(web-client): address PR review feedback
WiktorStarczewski Mar 4, 2026
53f7b63
fix(rust-client): merge use statements to satisfy nightly fmt
WiktorStarczewski Mar 4, 2026
5d53187
docs(wallet-example): add key recovery warning for passkey encryption
WiktorStarczewski Mar 6, 2026
9b40a90
fix(web-client): fix accountAuth table name in migration and add migr…
WiktorStarczewski Mar 6, 2026
95193d3
fix(web-client): format passkey-keystore test with prettier
WiktorStarczewski Mar 6, 2026
f926e8b
docs(web-client): mention seed phrase recovery in credential loss sec…
WiktorStarczewski Mar 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Check React SDK version sync
run: node scripts/check-react-sdk-sync.js
- name: Install dependencies
run: ./scripts/retry-yarn-install.sh packages/react-sdk
- name: Run lint
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ miden-client.toml
!packages/react-sdk/
!packages/react-sdk/**
packages/react-sdk/dist/
!packages/vite-plugin/
!packages/vite-plugin/**
packages/vite-plugin/dist/
keystore/

# Ignore files that spawn using `cargo run`
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* [FEATURE][web] New `MidenClient` class with resource-based API (`client.accounts`, `client.transactions`, `client.notes`, `client.tags`, `client.settings`). Provides high-level transaction helpers (`send`, `mint`, `consume`, `swap`, `consumeAll`), transaction dry-runs via `preview()`, confirmation polling via `waitFor()`, and flexible account/note references that accept hex strings, bech32 strings, or WASM objects interchangeably (`AccountRef`, `NoteInput` types). Factory methods: `MidenClient.create()`, `MidenClient.createTestnet()`, `MidenClient.createMock()`. ([#1762](https://github.com/0xMiden/miden-client/pull/1762))
* [FEATURE][web] Added `TransactionId.fromHex()` static constructor for creating transaction IDs from hex strings. ([#1762](https://github.com/0xMiden/miden-client/pull/1762))
* [FEATURE][web] Added standalone tree-shakeable note utilities (`createP2IDNote`, `createP2IDENote`, `buildSwapTag`) usable without a client instance. ([#1762](https://github.com/0xMiden/miden-client/pull/1762))
* [FEATURE][web] Opt-in passkey-based encryption for secret keys at rest using WebAuthn PRF (Touch ID / Face ID / Windows Hello). Keys are encrypted with AES-256-GCM using a wrapping key derived from the authenticator's PRF output via HKDF-SHA256. Enable via `MidenClient.create({ passkeyEncryption: true })` or `MidenProvider config={{ passkeyEncryption: true }}`. Includes `isPasskeyPrfSupported()` for feature detection, transparent migration from plaintext keys, and a separate `MidenKeystore_*` IndexedDB for encrypted storage. Requires Chrome 116+, Safari 18+, or Edge 116+. ([#1836](https://github.com/0xMiden/miden-client/pull/1836))

## 0.13.1 (TBD)

Expand Down
3 changes: 1 addition & 2 deletions crates/rust-client/src/rpc/domain/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,7 @@ impl From<AccountStorageRequirements> for Vec<account_detail_request::StorageMap
fn from(
value: AccountStorageRequirements,
) -> Vec<account_detail_request::StorageMapDetailRequest> {
use account_detail_request;
use account_detail_request::storage_map_detail_request;
use account_detail_request::{self, storage_map_detail_request};
let request_map = value.0;
let mut requests = Vec::with_capacity(request_map.len());
for (slot_name, _map_keys) in request_map {
Expand Down
30 changes: 30 additions & 0 deletions crates/web-client/js/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,36 @@ export class MidenClient {

const seed = options?.seed ? await hashSeed(options.seed) : undefined;

// Resolve passkey encryption → keystore callbacks (before the keystore branch)
if (options?.passkeyEncryption && options?.keystore) {
console.warn(
"Both passkeyEncryption and keystore provided; keystore takes precedence."
);
}
if (options?.passkeyEncryption && !options?.keystore) {
const { createPasskeyKeystore, isPasskeyPrfSupported } =
await import("./passkey-keystore.js");
if (await isPasskeyPrfSupported()) {
const passkeyOpts =
typeof options.passkeyEncryption === "object"
? options.passkeyEncryption
: {};
const storeName = options?.storeName || "default";
const result = await createPasskeyKeystore(storeName, passkeyOpts);
options = {
...options,
storeName,
keystore: { getKey: result.getKey, insertKey: result.insertKey },
};
}
// Unsupported browser — fall through to standard keystore
else {
console.warn(
"passkeyEncryption was requested but WebAuthn PRF is not supported in this browser. Falling back to standard keystore."
);
}
}

let inner;
if (options?.keystore) {
inner = await WebClientClass.createClientWithExternalKeystore(
Expand Down
4 changes: 4 additions & 0 deletions crates/web-client/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export const AuthScheme = Object.freeze({

export { MidenClient };
export { createP2IDNote, createP2IDENote, buildSwapTag };
export {
isPasskeyPrfSupported,
createPasskeyKeystore,
} from "./passkey-keystore.js";

// Internal exports — used by integration tests that need direct access to the low-level WebClient proxy.
export { WebClient as WasmWebClient, MockWebClient as MockWasmWebClient };
Expand Down
Loading