Miden Multisig Client
High-level Rust SDK built on top of miden-client for private multisignature workflows on Miden. The crate wraps the on-chain multisig contracts plus Private State Manager (PSM) coordination so you can:
- create multisig accounts, register them with a PSM, and keep state off-chain,
- propose, sign, and execute transactions with threshold enforcement,
- fall back to fully offline flows when connectivity is limited,
- export/import proposals as files for sharing using side channels,
How Private Multisigs & PSM Work
Miden multisig accounts store their authentication logic on-chain, but their state (signers, metadata, proposals) is kept private. PSM acts as a coordination server:
- A proposer pushes a delta (transaction plan) to Private State Manager (PSM). PSM tracks who signed and emits an ack signature once the threshold is met.
- Cosigners fetch pending deltas, verify details locally, sign the transaction summary, and push signatures back to PSM.
- Once ready, any cosigner builds the final transaction using all cosigner signatures + the PSM ack, executes it on-chain.
Installation
Add the crate to your workspace (already available in this repo). From another project:
[]
= { = "https://github.com/OpenZeppelin/private-state-manager", = "miden-multisig-client" }
Quick Start
use Endpoint;
use ;
use ;
# async
Core Workflow Examples
Propose ➜ Sign ➜ Execute
use TransactionType;
use AccountId;
let recipient = from_hex?;
let faucet = from_hex?;
let tx = transfer;
// Proposer creates the delta on PSM
let proposal = client.propose_transaction.await?;
// Second cosigner lists available proposals and signs the matching one
let proposals = client.list_proposals.await?;
let to_sign = proposals
.iter
.find
.expect;
client.sign_proposal.await?;
// Once threshold is met, any cosigner can execute
client.execute_proposal.await?;
Fallback to Offline (if PSM unavailable)
If the PSM endpoint can’t be reached, the SDK automatically produces an offline proposal so you can continue via side-channel sharing:
use ;
let tx = consume_notes;
match client.propose_with_fallback.await?
Fully Offline Signing and Execution
use TransactionType;
let tx = switch_psm;
let mut exported = client.create_proposal_offline.await?;
// Cosigner signs locally
client.sign_imported_proposal?;
write?;
// Once enough signatures are collected offline:
client.execute_imported_proposal.await?;
Listing Notes
List all notes that are currently consumable by the loaded account:
let notes = client.list_consumable_notes.await?;
for note in notes
List notes from a specific faucet with a minimum amount filter:
use NoteFilter;
let faucet = from_hex?;
let filter = by_faucet_min_amount;
let spendable = client.list_consumable_notes_filtered.await?;
Demo CLI
Run the Terminal UI demo in examples/demo, which exercises the same APIs for account management, note listing, proposal signing, and offline export/import.
Contributions and bug reports are welcome!