Multi-signature account management on the Miden network. Multiple parties collectively control an account, requiring a configurable threshold of signatures to execute transactions.
This project is under active development. The APIs, data structures, and workflows are subject to change. Expect breaking changes as we iterate on the design and implementation.
The frontend communicates directly with the PSM (Private State Manager) SDK for proposal coordination and state synchronization. The coordinator server is available as an optional backend for deployments that need centralized API access or audit trails.
Frontend (Next.js + WASM)
├── WebClient (@miden-sdk/miden-sdk) ──────► Miden RPC Node
├── MultisigClient (@openzeppelin/miden-multisig-client) ──► PSM Endpoint
└── Para Wallet (@getpara/react-sdk-lite) ──► External ECDSA wallets
Coordinator Server (Rust/Axum) [optional]
├── MultisigEngine ──► Miden RPC Node
└── MultisigStore ──► PostgreSQL
- coordinator-frontend — Next.js web application. Runs a WASM-compiled Miden client in the browser, connects to PSM for proposal coordination, and supports multiple wallet types for signing.
- coordinator-server — Rust/Axum HTTP server that wraps the multisig engine. Provides a REST API for account creation, transaction proposals, and signature collection. See
bin/coordinator-server/README.mdfor the full API reference. - miden-multisig-client — Rust client library for multisig operations, used by the coordinator engine.
The frontend supports three wallet sources for signing:
| Source | Scheme | Description |
|---|---|---|
| Local keys | Falcon / ECDSA | Browser-generated keys stored in IndexedDB |
| Para | ECDSA | External EVM wallets (MetaMask, etc.) via Para SDK |
| Miden Wallet | Falcon / ECDSA | Miden Wallet browser extension |
.
├── bin/
│ ├── coordinator-frontend/ # Next.js web frontend (PSM SDK + WASM)
│ └── coordinator-server/ # Rust coordinator server (Axum + PostgreSQL)
├── crates/
│ ├── coordinator/
│ │ ├── domain/ # Core domain models and types
│ │ ├── engine/ # Business logic and multisig engine
│ │ ├── store/ # PostgreSQL persistence (Diesel ORM)
│ │ └── utils/ # Shared utilities
│ └── miden-multisig-client/ # Rust client library for multisig operations
├── Dockerfile.coordinator # Docker image for coordinator server
├── Dockerfile.coordinator-frontend # Docker image for frontend
└── docker-compose.yml # Full stack: frontend + server + PostgreSQL
Spin up the full stack (frontend, coordinator server, and PostgreSQL) locally:
make docker-run-coordinatorThis builds the Docker images and starts:
| Service | URL | Description |
|---|---|---|
| Frontend | http://localhost:3000 |
Web UI |
| Coordinator Server | http://localhost:59059 |
REST API (+ /health endpoint) |
| PostgreSQL | localhost:5432 |
Database |
To stop and remove all containers:
make docker-stop-coordinatorNote: The PostgreSQL database is ephemeral (no persistent volumes). All data is lost when containers stop.
The frontend is configured via NEXT_PUBLIC_* environment variables, set at build time. In Docker, these are defined in the frontend service in docker-compose.yml.
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_PSM_ENDPOINT |
PSM service URL for proposal coordination | https://psm-stg.openzeppelin.com |
NEXT_PUBLIC_MIDEN_RPC_URL |
Miden node RPC endpoint | https://rpc.devnet.miden.io |
NEXT_PUBLIC_PARA_API_KEY |
Para wallet API key (enables Para wallet support) | (empty — Para disabled) |
NEXT_PUBLIC_PARA_ENVIRONMENT |
Para environment (development or production) |
development |
NEXT_PUBLIC_COORDINATOR_API_URL |
Coordinator server URL (internal, for server-side requests) | — |
NEXT_PUBLIC_EXTERNAL_COORDINATOR_API_URL |
Coordinator server URL (external, for browser requests) | — |
VITE_PARA_API_KEYis also accepted as a compatibility alias forNEXT_PUBLIC_PARA_API_KEY.
The server reads bin/coordinator-server/src/base_config.ron as defaults and overrides values with environment variables prefixed MIDENMULTISIG_. Use __ for nested keys.
| Variable | Description | Default |
|---|---|---|
MIDENMULTISIG_APP__LISTEN |
Server bind address | localhost:59059 |
MIDENMULTISIG_APP__NETWORK_ID_HRP |
Bech32 human-readable prefix | mtst |
MIDENMULTISIG_APP__CORS_ALLOWED_ORIGINS |
JSON array of allowed origins | ["*"] |
MIDENMULTISIG_DB__DB_URL |
PostgreSQL connection string | postgres://multisig:multisig_password@localhost:5432/multisig |
MIDENMULTISIG_DB__MAX_CONN |
Connection pool size | 10 |
MIDENMULTISIG_MIDEN__NODE_URL |
Miden node RPC URL | https://rpc.testnet.miden.io:443 |
MIDENMULTISIG_MIDEN__STORE_PATH |
Local Miden client store path | ./store |
MIDENMULTISIG_MIDEN__KEYSTORE_PATH |
Keystore directory path | ./keystore |
MIDENMULTISIG_MIDEN__TIMEOUT |
Request timeout | 30s |
RUST_LOG |
Log level (debug, info, warn, error) |
info |
For full server configuration details, see bin/coordinator-server/README.md.
- Rust 1.90+ (see
rust-toolchain.toml) - Node.js 18+
- PostgreSQL 13+ (or use Docker)
- Docker (for containerized setup)
# Check which tools are installed
make check-tools
# Install all required dev tools (typos, nextest, taplo, machete)
make install-toolscd bin/coordinator-frontend
npm install
npm run dev
# → http://localhost:3000Create a .env.local file for local development:
NEXT_PUBLIC_PSM_ENDPOINT=https://psm-stg.openzeppelin.com
NEXT_PUBLIC_MIDEN_RPC_URL=https://rpc.devnet.miden.io
NEXT_PUBLIC_PARA_API_KEY=<your-para-api-key>
NEXT_PUBLIC_PARA_ENVIRONMENT=developmentSee the database migrations section for PostgreSQL setup, then:
cargo run --release --bin miden-multisig-coordinator-servermake build # Build all Rust crates (release)
make test # Run tests
make lint # Run all linters (clippy, fmt, taplo, typos, machete)
make check # Check all targets for errorsThis project is MIT licensed.