Skip to content

feat(all): migrate wallet to the Miden 0.15 protocol line - #277

Merged
WiktorStarczewski merged 12 commits into
mainfrom
wiktor/bump-miden-sdk-0.15
Jun 12, 2026
Merged

feat(all): migrate wallet to the Miden 0.15 protocol line#277
WiktorStarczewski merged 12 commits into
mainfrom
wiktor/bump-miden-sdk-0.15

Conversation

@WiktorStarczewski

@WiktorStarczewski WiktorStarczewski commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

What

Migrates the wallet to the Miden 0.15 protocol line: @miden-sdk/miden-sdk + @miden-sdk/react → published 0.15.0-alpha.7, native provers (Android .so + iOS xcframework) rebuilt against the 0.15 client, E2E infrastructure on the 0.15 CLI surface. Devnet runs node 0.15.0; testnet is still 0.14 (expected-red under the e2e at-least-one-network gate until it upgrades).

All web-sdk dependencies are released: @miden-sdk/miden-sdk + @miden-sdk/react pinned to published 0.15.0-alpha.7 (carries web-sdk#182 — the explicit-prover fix the offscreen path needs — and web-sdk#184 — the direct-path call serialization that unblocks mobile).

Changes

TS migration (per the 0.15 migration guide, 0xMiden/docs#312 — which gained three sections from breaks this PR discovered):

  • account.isNetwork() dropped; AccountType.RegularAccountImmutableCode builder step removed
  • notes.import resolves a hex string (details-commitment for the wallet's details-only dApp noteBytes path — ImportPrivateNoteResponse.noteId semantics change, changelogged)
  • Partial (metadata-less) notes: id() and nullifier() are now undefined until sync completes them — filtered from consumable/claimable listings (interface, dapp, sync-manager, claimable-notes)
  • storeIdentifier() went async; WasmWebClient.proveTransactionWithProverproveTransaction (offscreen prover doc)
  • Pre-0.15 faucets aren't introspectable via BasicFungibleFaucetComponent.fromAccount → degrade to "Unknown" metadata instead of session-blacklisting
  • Fee/native-asset discovery via BlockHeader.feeFaucetId(); discovery cache keyed v2

Boot reliability: SdkMidenProvider mounts only after ensureSdkWasmReady() — the /lazy entries do no import-time WASM init, and the SDK provider constructs WASM objects during setup (SDK-side fix: web-sdk#179; this gate is the wallet-side guarantee either way).

Local proving: offscreen multi-threaded proving stays on (MIDEN_USE_OFFSCREEN_PROVING defaults 'true'). The "0.15 prover hang" decomposed into three stacked defects (full analysis: web-sdk#180 comment): the offscreen doc constructed the SDK's worker-shim wrapper (WasmWebClient) believing it was the raw class, the wrapper's implicit worker INIT fails on 0.15 (eager genesis fetch against the default endpoint → version-rejected by 0.14 testnet), and the SDK dropped the INIT error leaving ready pending — a silent forever-hang. The offscreen doc now proves on the raw prover-only WebClient (its own rayon pool, no implicit network), which needs web-sdk#182 (≥ 0.15.0-alpha.6): the explicit-prover proveTransaction fix. On older 0.15 builds the prove fails loudly with Client not initialized instead of hanging.

Native provers: Android JNI bridge + iOS xcframework rebuilt from miden-client rev 733720a7 / web-sdk crates/mobile-prover at the alpha.5 rev — the exact rev the SDK WASM pins, so the TransactionInputs/ProvenTransaction wire format matches byte-for-byte.

E2E/CI: miden-client-cli installs from a pinned git rev (midenClientCliGit; 0.15 CLI unreleased on crates.io); 0.15 faucet surface (--account-type public + -p basic-fungible-faucet, typed [fungible-faucet-metadata]); the helper retries the transient new nonce N is less than old nonce M sync failure (miden-client#2243); send specs pin tokenSymbol: 'TST' (fee-asset discovery now works, so the native MIDEN row renders above the funded token).

Store migration for existing users

0.14 stores don't round-trip; the SDK's IndexedDB store self-detects the version bump and re-creates itself — accounts re-register from the wallet seed and balances resync. Saved 0.14 store files can't be imported into a 0.15 build. Changelogged.

Verification

  • yarn ts 0 errors against published alpha.5 ✅
  • yarn lint ✅ · yarn test 1907/1907 ✅ · coverage 95.04% branches ≥ 95% gate ✅ · yarn test:smoke
  • Devnet blockchain e2e (Chrome): 8/8 ✅ on published alpha.7 (mint+balance, multi-account, multi-claim, private send via transport, public send, public send with forced local proving, wallet lifecycle ×2) against devnet node 0.15.0 — with offscreen MT proving on, built against the web-sdk#182 fix via the linked-PR mechanism; the forced-local-prove spec records tx_completed prove_ms=5653 (the prove that previously hung indefinitely), and the speculative pre-prove path works (via_speculation=true)
  • Devnet mobile e2e (iOS, two simulators): 7/7 ✅ on published alpha.7 — first fully green mobile run on the 0.15 line (mint+claim+balance, multi-account, multi-claim, private send via transport, public send, lifecycle ×2). Two blockers root-caused on the way: the SDK's lost direct-path call serialization (web-sdk#184; wallet-creation RefCell panic) and the e2e fixture's file-level sandbox wipe being defeated by cfprefsd/WebKit daemon caches (fixed: per-test uninstall+install).
  • Manual extension boot verified (chromium, fullpage onboarding renders, zero console errors)
  • Remaining manual item: store-upgrade test (0.14.11 build → this build, accounts/balances resync after the SDK store re-creates)

…-alpha)

Phase A of the 0.15 migration — everything that compiles against
@miden-sdk/miden-sdk@0.15.0-alpha.4. Four call sites still reference
APIs that exist on web-sdk main but not yet in a published 0.15 alpha
(useWorker, newCallbackProver, MidenClient.ready, BlockHeader.feeFaucetId);
they are restored by the web-sdk main→next unification PR and the wallet
build goes fully green against that branch (alpha.5).

- deps: miden-sdk + react + resolutions → 0.15.0-alpha.4 (vite-plugin
  stays 0.14.11 — verified SDK-version-agnostic: name-based dedup +
  COOP/COEP headers + gRPC proxy only)
- vault: drop account.isNetwork() (gone — networkness is now a
  component property) and the removed AccountType.RegularAccountImmutableCode
  builder step (faucet/regular moved off the account ID; storageMode()
  is the remaining visibility setter)
- notes.import resolves a hex string (details-commitment for the
  wallet's details-only path) — dropped .toString() round-trips and
  documented the dApp-facing semantics change
- InputNoteRecord.id() is now NoteId | undefined for partial
  (metadata-less) notes — consumable/claimable listings filter them
  until sync completes them (interface, dapp, sync-manager,
  claimable-notes)
- storeIdentifier() became async — exportDb/importDb await it
- metadata: faucets minted by pre-0.15 SDKs are not introspectable via
  BasicFungibleFaucetComponent.fromAccount — degrade to default
  metadata instead of session-blacklisting via NotFoundTokenMetadata
- native-asset: nativeAssetId() → feeFaucetId() (protocol rename);
  discovery cache keys bumped to v2 (0.14 account IDs don't round-trip)
- native-prover (Android rust-bridge): miden-client via git rev
  733720a7 (the same rev the SDK WASM pins; 0.15 is unreleased on
  crates.io), concurrent now cascades from miden-client itself —
  direct miden-tx/miden-protocol deps dropped
- e2e: miden-client-cli installable from a pinned git rev
  (midenClientCliGit in package.json, helpers/miden-cli.ts, and the 4
  e2e-blockchain.yml install blocks); faucet creation uses the 0.15
  CLI surface (--account-type public + -p basic-fungible-faucet,
  typed [fungible-faucet-metadata] init block, --storage-mode removed)
- tests: mocks updated to the 0.15 surface (string import results,
  toHex, no isNetwork) + new coverage for every added guard branch;
  1907 tests green, coverage 95.03% branches (gate: 95%)
… 0.15 (rev 733720a7)

arm64-v8a + x86_64 .so binaries built via scripts/build-android.sh with
the git-pinned miden-client (same rev the @miden-sdk/miden-sdk 0.15 WASM
pins), so the TransactionInputs/ProvenTransaction wire format matches
the SDK byte-for-byte. The iOS xcframework rebuild comes from web-sdk's
crates/mobile-prover once the main→next unification PR lands.
First alpha cut from the unified web-sdk branch (web-sdk#177 + #178) —
the four APIs the wallet was waiting on (useWorker, newCallbackProver,
MidenClient.ready, BlockHeader.feeFaucetId) plus lastAuthError are in
the published package, so the wallet now typechecks with zero errors
against npm instead of a linked-PR build.

alpha.5 also refines InputNoteRecord.nullifier() to string | undefined
(a 0.15 nullifier folds in metadata, so a partial record cannot have
one) — folded into the existing partial-note guards: a record without
a nullifier is skipped from consumable/claimable listings alongside
the id()-less case.
… prover, e2e green on devnet

Runtime issues found and fixed after the alpha.5 flip (full blockchain
e2e suite now 8/8 against devnet 0.15.0):

- front: gate SdkMidenProvider on ensureSdkWasmReady() — the /lazy
  entries do no import-time WASM init, and mounting the SDK provider
  before the module is up crashed the whole popup tree ('Something went
  wrong while booting a wallet'). Root-caused to the SDK's MidenProvider
  resolving its prover via WASM constructors at first render; SDK-side
  fix in web-sdk#179, this gate is the wallet-side guarantee
- offscreen: WasmWebClient.proveTransactionWithProver →
  proveTransaction (0.15 raw-surface rename; documented in the 0.15
  migration guide, 0xMiden/docs#312)
- build: MIDEN_USE_OFFSCREEN_PROVING defaults to false on the 0.15
  line — the 0.15 prover hangs under the MT WASM build (pool bring-up,
  rayon dispatch, and the SW<->offscreen protocol all verified healthy
  in isolation; single-threaded prove of the same tx completes).
  Tracked in web-sdk#180; local proving runs single-threaded until then
- native-prover: iOS MidenMobileProver.xcframework rebuilt from
  web-sdk crates/mobile-prover at the alpha.5 rev (both slices;
  module.modulemap preserved; miden_prove_transaction symbol verified)
- e2e: the CLI helper retries 'new nonce N is less than old nonce M'
  sync failures (transient while a deploy/mint is in flight —
  miden-client#2243; matched wrap-tolerantly, miette folds the message);
  send specs pin tokenSymbol 'TST' (fee-asset discovery now works on
  0.15, so the native MIDEN row renders above the funded token and
  first-row clicks pick the wrong asset)
- tests: provider tests await the readiness gate; partial-note mocks
  carry nullifier() (alpha.5 types it string | undefined)
…ving on by default

The offscreen doc constructed the SDK's worker-shim wrapper (exported as
WasmWebClient) instead of the raw wasm-bindgen class (exported as
WebClient). Consequences: the prove ran in the wrapper's method worker —
a WASM instance whose rayon pool this document never initialized — and
the wrapper's implicit worker INIT (createClient with an undefined
rpcUrl) performs an eager genesis fetch against the default endpoint,
whose failure leaves the wrapper's ready promise pending and every
method call hanging forever. That was the wallet leg of
0xMiden/web-sdk#180.

The raw class proves in this document's own WASM instance, on the pool
init() brings up, with no implicit network round-trip. Proving on a bare
client with an explicit prover requires the 0xMiden/web-sdk#182 fix
(>= 0.15.0-alpha.6); older 0.15 builds fail the prove loudly with
'Client not initialized' instead of hanging.

MIDEN_USE_OFFSCREEN_PROVING defaults to 'true' again on both configs.
…ile wipe

The file-level wipe (rm Library/Documents/tmp in the app data container)
never actually cleared the wallet's persisted state: UserDefaults is
served through cfprefsd's cache and WebKit localStorage/IndexedDB
through the per-device WebKit storage daemons, so a relaunched app read
its old vault straight back from the daemons and booted to the unlock
screen instead of onboarding. Every iOS test after the first failed at
createNewWallet, deterministically. simctl uninstall purges app state
through the OS and is the only reset that verifiably works.
@WiktorStarczewski
WiktorStarczewski merged commit 5ec3069 into main Jun 12, 2026
14 checks passed
@WiktorStarczewski
WiktorStarczewski deleted the wiktor/bump-miden-sdk-0.15 branch June 12, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant