TypeScript Multisig SDK
The @openzeppelin/miden-multisig-client package provides a high-level TypeScript SDK for private multisig workflows on Miden. It supports multiple signer types including external wallets.
Package: @openzeppelin/miden-multisig-client
Source: packages/miden-multisig-client
Installation
npm install @openzeppelin/miden-multisig-client @miden-sdk/miden-sdk
Setup
import { MultisigClient, FalconSigner } from '@openzeppelin/miden-multisig-client';
import { WebClient, AuthSecretKey } from '@miden-sdk/miden-sdk';
// Initialize the Miden WebClient
const webClient = await WebClient.createClient('https://rpc.testnet.miden.io:443');
// Create a Falcon signer
const secretKey = AuthSecretKey.rpoFalconWithRNG(undefined);
const signer = new FalconSigner(secretKey);
// Create the multisig client and fetch Guardian info
const client = new MultisigClient(webClient, {
psmEndpoint: 'http://localhost:3000',
});
const { psmCommitment } = await client.initialize();
Creating a multisig account
const config = {
threshold: 2,
signerCommitments: [signer.commitment, otherSignerCommitment],
psmCommitment,
signatureScheme: 'falcon',
};
const multisig = await client.create(config, signer);
console.log('Account ID:', multisig.accountId);
// Register on Guardian
await multisig.registerOnPsm();
Loading an existing account
// Configuration is auto-detected from on-chain storage
const multisig = await client.load(accountId, signer);
Syncing state
Fetch proposals, state, notes, and config in a single call:
const { proposals, state, notes, config } = await multisig.syncAll();
Creating and executing proposals
// Send payment
const { proposal } = await multisig.createSendProposal(recipientId, faucetId, amount);
// Sign a proposal
await multisig.signTransactionProposal(proposal.commitment);
// Execute when ready
if (proposal.status.type === 'ready') {
await multisig.executeTransactionProposal(proposal.commitment);
}
Other proposal types:
await multisig.createConsumeNotesProposal(noteIds);
await multisig.createAddSignerProposal(newCommitment, { newThreshold: 3 });
await multisig.createRemoveSignerProposal(signerToRemove);
await multisig.createChangeThresholdProposal(3);
await multisig.createSwitchPsmProposal(newEndpoint, newPubkey);
External wallet integration
For browser wallets where the signing key is external:
// Sign the commitment with an external wallet
const signature = await wallet.sign(proposal.commitment);
// Submit the external signature
await multisig.signTransactionProposalExternal({
commitment: proposal.commitment,
signature,
publicKey: wallet.publicKey,
scheme: 'ecdsa',
});
Wallet signers
import { ParaSigner, MidenWalletSigner } from '@openzeppelin/miden-multisig-client';
// Para wallet integration
const signer = new ParaSigner(paraContext, walletId, commitment, publicKey);
// Miden wallet integration
const signer = new MidenWalletSigner(walletContext, commitment, 'ecdsa');
Offline workflows
Export and import proposals for side-channel signing:
// Export a proposal as JSON
const json = multisig.exportTransactionProposalToJson(proposal.commitment);
// Sign offline
const signedJson = multisig.signTransactionProposalOffline(proposal.commitment);
// Import on another device
const { proposal: imported } = multisig.importTransactionProposal(json);
Full reference
See the packages/miden-multisig-client/README.md for the complete API reference.