Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
34a30af
chore: update rust-sdk to 0.17.0-rc.1
WiktorStarczewski Sep 21, 2026
e26cf6e
ci: pin the test node to rust-sdk v0.17.0-rc.1
WiktorStarczewski Sep 21, 2026
14c38d8
test: give the integration harness the chain's fee faucet
WiktorStarczewski Sep 21, 2026
6f1b49e
feat(react): forward the chain's fee faucet through MidenProvider
WiktorStarczewski Sep 21, 2026
825f0ea
test: build every integration client through one helper
WiktorStarczewski Sep 21, 2026
08b4379
fix(repo): point the MASP strip tool at the VM version the client embeds
WiktorStarczewski Sep 21, 2026
e6b4234
docs(web): correct the vault-delta doc, classify feeFaucetId, note th…
WiktorStarczewski Sep 21, 2026
a7dfb1e
style: rustfmt the strip tool's test imports
WiktorStarczewski Sep 21, 2026
72ef117
docs: link the 0.17.0 changelog entries to their PR
WiktorStarczewski Sep 21, 2026
4a02395
fix(web): make the 0.17 auth and network-note paths work
WiktorStarczewski Sep 21, 2026
eb018b9
style(web): backtick AUTH_ARGS in the salt doc
WiktorStarczewski Sep 21, 2026
18bfed5
fix(web): give a multisig the three-word auth args its component reads
WiktorStarczewski Sep 21, 2026
3583806
test(web): deploy the network account by consuming a note
WiktorStarczewski Sep 21, 2026
7791cf0
test(web): pin feeFaucetId to the faucet the client was created with
WiktorStarczewski Sep 21, 2026
dfe4e5c
refactor(web): setup_client takes a ProtocolConfig, not an Option
WiktorStarczewski Sep 21, 2026
6c73ed8
test(web): build the sync-lock clients through the fixture helper
WiktorStarczewski Sep 21, 2026
fef78bf
feat(web): expose the multisig approval expiration, off by default
WiktorStarczewski Sep 21, 2026
e705104
docs: correct the fee-faucet and zero-fee claims across every surface
WiktorStarczewski Sep 21, 2026
ee60b38
test(web): give the browser fixture the fee faucet it builds clients …
WiktorStarczewski Sep 21, 2026
ba4d341
fix(web): no scriptless network-account deploy anywhere
WiktorStarczewski Sep 21, 2026
ebe675b
fix(web): read the multisig auth args off one block header
WiktorStarczewski Sep 21, 2026
4bc7886
feat(web): let a co-signer pin every value the approvers sign over
WiktorStarczewski Sep 21, 2026
5d85fac
docs(web): say what feeFaucetId reports, and what the builder now takes
WiktorStarczewski Sep 21, 2026
2137984
test(web): call the surface the multisig guards claim to guard
WiktorStarczewski Sep 21, 2026
89fb17d
fix(web): draw a salt only when the caller pinned none, publish fee_f…
WiktorStarczewski Sep 21, 2026
e607c85
fix(react): declare the target of a network note as a foreign account
WiktorStarczewski Sep 21, 2026
c92b356
test(web,react): close the sibling sites the same rules reach
WiktorStarczewski Sep 21, 2026
3eb1ecf
docs(web): state what was observed about network notes, and the 20-bl…
WiktorStarczewski Sep 21, 2026
8956cda
test: re-execute an expired network-note emit, and close two enumerat…
WiktorStarczewski Sep 21, 2026
8cd97dd
fix(web): price every note root the network auth component allowlists
WiktorStarczewski Sep 21, 2026
379c461
fix(web): draw the salt last, after everything that can fail
WiktorStarczewski Sep 21, 2026
a9b50d2
test(web): a fresh WASM handle per call, and the allowlist's real size
WiktorStarczewski Sep 21, 2026
339f25b
docs,build: resolve the fee faucet locally, and say the salt is consumed
WiktorStarczewski Sep 21, 2026
3a4cbfa
test(web): prove the network-note emit remotely, per call
WiktorStarczewski Sep 21, 2026
8bee169
test: assert positional contracts by length and index, not from the end
WiktorStarczewski Sep 21, 2026
0c59aff
fix,docs: validate through upstream, run the lookup once, say what is…
WiktorStarczewski Sep 21, 2026
e2fdde5
test(web): give the network-transaction builder a longer window, and …
WiktorStarczewski Sep 21, 2026
aa9811f
feat(web): declare the note scripts the node's NTX builder needs
WiktorStarczewski Sep 21, 2026
a46b8ad
fix(web): actually register the declared NTX scripts on submit
WiktorStarczewski Sep 21, 2026
72fe9eb
ci: dump the node logs when an integration shard fails
WiktorStarczewski Sep 21, 2026
bd237f7
ci: find the node logs instead of guessing their path
WiktorStarczewski Sep 21, 2026
accbe5f
revert(web): drop the NTX-script registration, built on a wrong diagn…
WiktorStarczewski Sep 21, 2026
66d2ff3
fix(web): a network account uses the chain's fee faucet
WiktorStarczewski Sep 21, 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
4 changes: 2 additions & 2 deletions .claude/skills/wasm-bridge/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -516,10 +516,10 @@ MidenClient._getWasmOrThrow = getWasmOrThrow;
There is **no** `safe-arrays.js` module. The wasm-bindgen array wrappers are
generated by the `declare_js_miden_arrays!` macro (defined in
`crates/web-client/src/miden_array.rs:41`, invoked in
`crates/web-client/src/models/mod.rs:134-148`), which produces **thirteen**
`crates/web-client/src/models/mod.rs:133-146`), which produces **twelve**
types, in this order: `AccountArray`, `AccountIdArray`, `ForeignAccountArray`,
`NoteRecipientArray`, `NoteArray`, `OutputNoteArray`, `StorageSlotArray`,
`TransactionScriptInputPairArray`, `FeltArray`, `AccountInputsArray`,
`TransactionScriptInputPairArray`, `FeltArray`,
`NoteAndArgsArray`, `NoteDetailsAndTagArray`, `NoteIdAndArgsArray`. Count them
from the macro invocation rather than from any list, including this one - the
set grows.
Expand Down
55 changes: 53 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ env:
# to in Cargo.lock: that ref's own Cargo.lock pins the node rev the client is
# built against. A commit sha (not the branch name) keeps cache keys stable.
# Re-pin whenever Cargo.lock moves, and to the release tag once one ships.
# v0.16.0
MIDEN_CLIENT_REF: 5478eeb3baf84a24d129b292fbc5ba558740bd46
# v0.17.0-rc.1
MIDEN_CLIENT_REF: 2fb20aca0869034dd26aa35473dbfb14fa017083

jobs:
# Pre-flight: detect whether any non-docs files changed. See build.yml's
Expand Down Expand Up @@ -991,6 +991,18 @@ jobs:
# tests draw fee balances from the genesis funder wallets.
MIDEN_VERIFICATION_BASE_FEE: "0"
run: ./scripts/start-test-node.sh --background
# Since 0.17 the fee asset lives in the protocol configuration rather than
# the block header, so a client is told which faucet issues it instead of
# reading it off a block. Each genesis mints a fresh one, so it is read
# from the bootstrap log rather than pinned.
- name: Export the node's native fee faucet
working-directory: miden-client
run: |
ID=$(sed -n 's/^Native faucet account id: //p' \
target/test-node/data/logs/bootstrap.log | tail -1)
[ -n "$ID" ] || { echo "::error::native faucet id not found in bootstrap.log"; exit 1; }
echo "TEST_MIDEN_FEE_FAUCET_ID=$ID" >> "$GITHUB_ENV"
echo "native fee faucet: $ID"
- name: Build napi binary
run: cargo build -p miden-client-web --no-default-features --features nodejs,testing --release
- name: Stage napi binary as `miden_client_web.node`
Expand Down Expand Up @@ -1092,6 +1104,18 @@ jobs:
# tests draw fee balances from the genesis funder wallets.
MIDEN_VERIFICATION_BASE_FEE: "0"
run: ./scripts/start-test-node.sh --background
# Since 0.17 the fee asset lives in the protocol configuration rather than
# the block header, so a client is told which faucet issues it instead of
# reading it off a block. Each genesis mints a fresh one, so it is read
# from the bootstrap log rather than pinned.
- name: Export the node's native fee faucet
working-directory: miden-client
run: |
ID=$(sed -n 's/^Native faucet account id: //p' \
target/test-node/data/logs/bootstrap.log | tail -1)
[ -n "$ID" ] || { echo "::error::native faucet id not found in bootstrap.log"; exit 1; }
echo "TEST_MIDEN_FEE_FAUCET_ID=$ID" >> "$GITHUB_ENV"
echo "native fee faucet: $ID"
# Install Playwright separately from the test run. Inlining the install
# into the test:ci script (yarn-style chained `&&`) breaks pnpm arg
# forwarding: pnpm appends `-- --project=X` to the LAST command, but
Expand All @@ -1101,6 +1125,21 @@ jobs:
run: pnpm --filter @miden-sdk/miden-sdk run test:install:ci
- name: Run web client tests
run: pnpm --filter @miden-sdk/miden-sdk run test:ci --project=${{ matrix.project }}
# A network transaction that the builder declines is not an error anywhere the test can
# see: the note simply stays unconsumed. Its own log is the only place that says why.
- name: Dump node logs on failure
if: failure()
run: |
# Locate the logs rather than assuming a path: a previous attempt
# guessed one and reported three missing files, which says nothing.
echo "::group::log files found"
find . -path ./node_modules -prune -o -name '*.log' -path '*test-node*' -print 2>/dev/null | head -40
echo "::endgroup::"
find . -path ./node_modules -prune -o -name '*.log' -path '*test-node*' -print 2>/dev/null | while read -r f; do
echo "::group::$f (last 200 lines)"
tail -n 200 "$f"
echo "::endgroup::"
done
- name: Upload Playwright JSON report
if: always()
uses: actions/upload-artifact@v4
Expand Down Expand Up @@ -1179,6 +1218,18 @@ jobs:
# tests draw fee balances from the genesis funder wallets.
MIDEN_VERIFICATION_BASE_FEE: "0"
run: ./scripts/start-test-node.sh --background
# Since 0.17 the fee asset lives in the protocol configuration rather than
# the block header, so a client is told which faucet issues it instead of
# reading it off a block. Each genesis mints a fresh one, so it is read
# from the bootstrap log rather than pinned.
- name: Export the node's native fee faucet
working-directory: miden-client
run: |
ID=$(sed -n 's/^Native faucet account id: //p' \
target/test-node/data/logs/bootstrap.log | tail -1)
[ -n "$ID" ] || { echo "::error::native faucet id not found in bootstrap.log"; exit 1; }
echo "TEST_MIDEN_FEE_FAUCET_ID=$ID" >> "$GITHUB_ENV"
echo "native fee faucet: $ID"
# See integration-tests-web-client for rationale on splitting the
# Playwright install from the test invocation.
- name: Install Playwright browsers
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@

### Changes

* [CHANGE][web] Upgraded `miden-client` to 0.17.0-rc.1 (from 0.16.1), which adopts protocol 0.17.0-rc.5 and VM 0.33. Requires a node on the matching protocol - a 0.16 node rejects a 0.17 client at the accept header, before any request is served - and a new client database. The entries below are the parts of that upgrade a JS consumer has to act on ([client 0.17.0-rc.1](https://github.com/0xMiden/rust-sdk/releases/tag/v0.17.0-rc.1)) ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [BREAKING][web] A client now needs a protocol configuration, and `ClientOptions.feeFaucetId` is how it gets one. 0.17 moved the fee asset out of the block header into the protocol configuration, which execution and note screening both resolve by the commitment in the transaction's reference block; a client holding none cannot execute at all. The node does not serve the configuration over RPC yet, so the SDK builds it from the chain's fee faucet: pass `feeFaucetId` (a bech32 address or a hex account ID) for any network the SDK knows no fee faucet for, and creating the client fails with a message naming the option rather than a store error on the first transaction. A mock client is unaffected - its configuration comes from the mock chain itself ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [BREAKING][web] `BlockHeader.feeFaucetId()` is removed, replaced by `client.feeFaucetId()`. The header no longer carries the fee asset, so the fee faucet can no longer be discovered by reading any block: the client reports the one its registered protocol configuration names, which is the `feeFaucetId` it was created with. `BlockHeader.verificationBaseFee()` is unchanged - the base fee is still a header field ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [BREAKING][web] `BlockHeader.txKernelCommitment()` is removed, replaced by `BlockHeader.protocolConfigCommitment()`. The header committed to the transaction kernel individually before 0.17; it now commits to the protocol configuration, which carries the transaction, batch and block kernels along with the fee asset ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [BREAKING][web] `ForeignAccount.prefetched()`, the `AccountInputs` and `AccountInputsArray` types, `client.transactions.foreignAccountInputs()` and `WebClient.getForeignAccountInputs()` are removed, following the client dropping `ForeignAccount::Prefetched` and making `AccountInputs` private. 0.17 resolves a foreign account's vault and storage-map entries during execution, as per-asset and per-key witnesses against the reference block, instead of requiring the whole state up front - which is what prefetching existed to avoid. Declare the account with `ForeignAccount.public(...)` or `ForeignAccount.private(...)` and execute against a recent reference block; a transaction pinned to a block the node no longer serves account state for can no longer be made to execute by prefetching ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [BREAKING][web] `AccountVaultDelta.fungible()` and the `FungibleAssetDelta` and `FungibleAssetDeltaItem` types are removed, following the upstream type. A vault delta is now a set of whole assets added or removed rather than a map of signed per-faucet balance changes, so there is no aggregate to hand out. `addedFungibleAssets()` and `removedFungibleAssets()` are unchanged and remain the way to read it; `numAssets()` is new and reports how many assets the delta changes, added and removed together ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [FIX][web] A request for a multisig account carries that component's own auth args, at any base fee. 0.17's multisig auth procedure reads three words - the block its summary binds with the approval expiration, the salt, and the fee conversion info - and resolves them unconditionally, skipping only the fee note itself when the base fee is zero. `miden-client` commits the two-word fee pair a fixed-salt component reads, so a multisig was handed a preimage one word short and aborted piping it (`advice stack read failed`); on a fee-free chain it was handed no auth args at all. The SDK now builds the three-word shape and sets it as the request's auth argument, which `miden-client` leaves alone. Every summary-producing path was affected, including `executeForSummary` and chain-anchored co-signing ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [FEATURE][web] `client.feeAwareTransactionRequestBuilder(account, options?)` takes the three multisig values the approvers sign over. `approvalExpirationDelta` stops the signatures authorizing the transaction that many blocks after the block the summary binds, so a proposal that is never executed cannot be executed much later instead. `feeConversionSalt` and `boundBlockNum` are what a co-signer needs to *reproduce* a proposal rather than receive one: left out, the salt is drawn per build and the block is the local sync height, so two parties who disagree on either can never derive the same summary. A co-signer holding the proposer's serialized request needs neither, since it carries the auth argument and its advice-map preimage. Every field is optional, defaulted, and ignored for an account that is not a multisig. Do not call `withFeeConversionSalt` or `withAuthArg` on the returned builder for a multisig: the two setters clear each other, so either discards the auth args it already carries ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] A network account can no longer be deployed by an empty transaction. 0.17's network auth component asserts the transaction had an effect before it pays the fee - an input note consumed, an output note created, or the account state changed - so the scriptless nonce bump that used to commit the account on-chain now aborts with `network account transactions must have an effect before fee payment`. Deploy by consuming a note whose script the account allowlists ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] `client.transactions.createNetworkNote` declares the target network account as a foreign account, and so does `useCreateNetworkNote`. Since 0.17 the kernel prices a note carrying a `NetworkAccountTarget` attachment by calling `estimate_note_fee` on the target, so the emitting transaction reads foreign state: declaring it pins that state at the reference block rather than leaving the client to resolve the account lazily, which it can only do for a public account it can reach. `buildNetworkNote` only builds the note, so a caller submitting it themselves owns the declaration; its documentation now says so ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] Every network account built from `AccountComponent.createNetworkAuthComponents` now allowlists the P2ID note script, and the factory prices it at zero along with the other roots `AuthNetworkAccount` adds by default. 0.17 added P2ID to that default list as a stopgap for deployment - upstream marks it "replace by the DEPLOY note script" - so such an account auto-consumes P2ID notes whether or not the caller named that root. The factory derives the zero-priced set from upstream rather than restating it, because an allowlisted root with no fee entry aborts fee estimation: before this, a caller who did not name P2ID got an account that would auto-consume those notes and then fail to price them ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] `feeAwareTransactionRequestBuilder`'s `feeConversionSalt` consumes the `Word` passed to it, as every by-value handle across the WASM boundary does. Build a fresh one per call: a spent handle is not rejected, it arrives as if no salt were given and one is drawn, which is exactly the divergence pinning the salt prevents ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] Emitting a note that carries a `NetworkAccountTarget` caps the transaction at 20 blocks. Pricing it calls `estimate_note_fee` on the target, and that procedure applies the standards' default expiration delta - about a minute at a three-second block interval - to bound how stale the foreign state it read may be. A transaction expiration can only be lowered, never raised, so the emitter cannot widen it: the transaction has to be included within 20 blocks of its reference block or it is rejected as expired, and a slow prover is enough to miss that on a busy chain. Re-execute against a fresh reference block and submit again ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] The fee faucet passed to `AccountComponent.createNetworkAuthComponents` must be the chain's own, read with `client.feeFaucetId()`. A 0.17 node's network-transaction builder compares a network account's fee asset with the chain's protocol configuration and refuses to execute for any account where they differ. Nothing reaches the client: the notes sent to such an account are simply never consumed, and only the node's log says why (`network account fee asset does not match the protocol configuration`). The fee asset is fixed when the account is built, so an account built with another faucet has to be rebuilt ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][react] `MidenConfig.feeFaucetId` hands the chain's fee faucet to the client `MidenProvider` builds, for the same reason: without it the provider's client can neither execute nor screen notes on a network the SDK knows no fee faucet for ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][repo] `tools/strip-masp-debug`, which removes the embedded MAST packages' debug info from the published WASM, now names the VM version the client embeds (0.33). It requested `0.29`, which resolved a second, older copy of the package format: against a 0.17 artifact it recognised no packages, exited non-zero, and the build skipped `wasm-opt` altogether - leaving an ST artifact of 118.5 MiB against the 25 MiB the size gate allows. Workspace membership does not pin the tool to what the binary contains; the version requirement does, so it moves with `miden-client` ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [CHANGE][web] `BlockHeader.version()` reports the protocol's `u8` rather than a widened `u32`. Both reach JS as a `number`, so only a Rust caller of the crate sees a difference ([#406](https://github.com/0xMiden/web-sdk/pull/406)).
* [BREAKING][web] `ForeignAccount.account_id()` and `ForeignAccount.storage_slot_requirements()` are now `accountId()` and `storageSlotRequirements()` on the WASM build. They had no `js_name`, so the WASM build exposed them in snake_case while napi camelCased them by default, leaving the same two accessors with different names depending on which build a consumer loaded. The camelCase spelling matches what Node already exposed and the rest of the JS surface, so only WASM callers change.
* [CHANGE][adapter] `@miden-sdk/miden-wallet-adapter-{base,miden,reactui}` now declare a `files` array and ship only what a consumer resolves. All three had neither `files` nor `.npmignore`, so npm packed the whole directory: TypeScript sources, `__tests__`, `tsconfig.json`, `vitest.config.ts`, the compiled tests and vitest config under `dist/`, and the generated typedoc `docs/` tree. `base` went from 131 files / 273 KB to 24 / 56 KB, `miden` from 35 / 230 KB to 11 / 44 KB, `reactui` from 77 / 218 KB to 46 / 73 KB. Every documented entry point still resolves, including both `@miden-sdk/miden-wallet-adapter-reactui/styles.css` and `.../reactui/dist/styles.css`. None of the three declares an `exports` map, so a deep import into their sources was legal and now stops resolving; import from the package root, or from `dist/` for the stylesheet ([#394](https://github.com/0xMiden/web-sdk/pull/394)).

Expand Down
Loading
Loading