Skip to main content

MultisigClient

Struct MultisigClient 

Source
pub struct MultisigClient { /* private fields */ }
Expand description

Main client for interacting with multisig accounts.

This client manages a single multisig account connected to a GUARDIAN server, providing a high-level API for creating and managing multisig accounts, proposals, and transactions.

§Example

use miden_multisig_client::MultisigClient;
use miden_client::rpc::Endpoint;


let mut client = MultisigClient::builder()
    .miden_endpoint(Endpoint::new("http://localhost:57291"))
    .guardian_endpoint("http://localhost:50051")
    .data_dir("/tmp/multisig")
    .generate_key()
    .build()
    .await?;


let account = client.create_account(2, vec![signer1, signer2]).await?;

Implementations§

Source§

impl MultisigClient

Source

pub async fn create_account( &mut self, threshold: u32, signer_commitments: Vec<Word>, ) -> Result<&MultisigAccount>

Creates a new multisig account.

§Arguments
  • threshold - Minimum number of signatures required (default threshold)
  • signer_commitments - Public key commitments of all signers

For per-procedure thresholds, use create_account_with_proc_thresholds instead.

Source

pub async fn create_account_with_proc_thresholds( &mut self, threshold: u32, signer_commitments: Vec<Word>, proc_threshold_overrides: Vec<ProcedureThreshold>, ) -> Result<&MultisigAccount>

Creates a new multisig account with per-procedure threshold overrides.

§Arguments
  • threshold - Minimum number of signatures required (default threshold)
  • signer_commitments - Public key commitments of all signers
  • proc_threshold_overrides - Per-procedure threshold overrides using named procedures.
§Example
use miden_multisig_client::{ProcedureThreshold, ProcedureName};

let thresholds = vec![
    ProcedureThreshold::new(ProcedureName::ReceiveAsset, 1),
    ProcedureThreshold::new(ProcedureName::UpdateSigners, 3),
];

let account = client.create_account_with_proc_thresholds(
    2,  // default 2-of-3
    signer_commitments,
    thresholds,
).await?;
Source

pub async fn pull_account( &mut self, account_id: AccountId, ) -> Result<&MultisigAccount>

Pulls an account from GUARDIAN and loads it locally.

Use this when joining an existing multisig as a cosigner.

Source

pub async fn push_account(&mut self) -> Result<()>

Pushes the current account to GUARDIAN for initial registration.

Source

pub async fn sync(&mut self) -> Result<()>

Syncs state with the Miden network.

Source

pub async fn sync_network_only(&mut self) -> Result<()>

Syncs only with the Miden network and refreshes local cached account state.

Source

pub async fn sync_from_guardian(&mut self) -> Result<()>

Syncs account state from GUARDIAN into the local miden-client store.

Source

pub async fn verify_state_commitment(&self) -> Result<StateVerificationResult>

Explicitly verifies that local account state commitment matches on-chain commitment.

Source

pub async fn get_deltas(&mut self) -> Result<()>

Fetches deltas from GUARDIAN since the current local nonce and applies them to the local account.

Source

pub async fn register_on_guardian(&mut self) -> Result<()>

Registers the current account on the GUARDIAN server.

§Example
// After switching GUARDIAN endpoints
client.set_guardian_endpoint("http://new-guardian:50051");
client.register_on_guardian().await?;
Source

pub async fn set_guardian_endpoint( &mut self, new_endpoint: &str, register: bool, ) -> Result<()>

Changes the GUARDIAN endpoint and optionally registers the account on the new server.

§Arguments
  • new_endpoint - The new GUARDIAN server endpoint URL
  • register - If true, registers the current account on the new GUARDIAN server
§Example
// GUARDIAN server moved to new URL (same keys, no on-chain change needed)
client.set_guardian_endpoint("http://new-guardian:50051", true).await?;
Source§

impl MultisigClient

Source

pub async fn reset_miden_client(&mut self) -> Result<()>

Resets the miden-client by creating a new instance with a fresh database.

Source§

impl MultisigClient

Source

pub async fn export_proposal( &mut self, proposal_id: &str, path: &Path, ) -> Result<()>

Exports a proposal to a file for offline sharing.

This fetches the proposal from GUARDIAN, including all collected signatures, and writes it to the specified file path as JSON.

§Example
client.export_proposal(&proposal_id, "/tmp/proposal.json").await?;
Source

pub async fn export_proposal_to_string( &mut self, proposal_id: &str, ) -> Result<String>

Exports a proposal to a JSON string for programmatic use.

§Example
let json = client.export_proposal_to_string(&proposal_id).await?;
println!("{}", json);
Source

pub async fn import_proposal(&mut self, path: &Path) -> Result<ExportedProposal>

Imports a proposal from a file.

The proposal can then be signed with sign_imported_proposal or executed with execute_imported_proposal.

§Example
let proposal = client.import_proposal("/tmp/proposal.json").await?;
println!("Imported proposal: {}", proposal.id);
Source

pub async fn import_proposal_from_string( &mut self, json: &str, ) -> Result<ExportedProposal>

Imports a proposal from a JSON string.

§Example
let proposal = client.import_proposal_from_string(&json).await?;
Source§

impl MultisigClient

Source

pub async fn list_consumable_notes(&mut self) -> Result<Vec<ConsumableNote>>

Lists notes that can be consumed by the current account.

Returns a list of notes that are committed on-chain and can be consumed immediately by the multisig account.

Source

pub async fn list_notes_with_status( &mut self, ) -> Result<Vec<(ConsumableNote, Vec<(AccountId, String)>)>>

Returns a list of all notes with their consumption status

Source

pub async fn list_committed_notes(&mut self) -> Result<Vec<ConsumableNote>>

Returns a list of all committed notes (not just consumable).

Source

pub async fn list_consumable_notes_filtered( &mut self, filter: NoteFilter, ) -> Result<Vec<ConsumableNote>>

Lists consumable notes filtered by the given criteria.

This is a convenience method that combines list_consumable_notes with filtering. Use this to find notes from a specific faucet or above a minimum amount.

§Example
use miden_multisig_client::NoteFilter;

// Find notes from a specific faucet with at least 1000 tokens
let filter = NoteFilter {
    faucet_id: Some(my_faucet_id),
    min_amount: Some(1000),
};
let notes = client.list_consumable_notes_filtered(filter).await?;
Source§

impl MultisigClient

Source

pub async fn create_proposal_offline( &mut self, transaction_type: TransactionType, ) -> Result<ExportedProposal>

Creates a proposal offline without pushing to GUARDIAN.

Only SwitchGuardian transactions can be executed fully offline because all other transaction types require a GUARDIAN acknowledgment signature.

This returns an ExportedProposal that can be serialized to JSON and shared with cosigners.

The proposer’s signature is automatically included in the exported proposal.

§Example
use miden_multisig_client::TransactionType;

// Create proposal offline
let exported = client.create_proposal_offline(
    TransactionType::SwitchGuardian { new_endpoint, new_commitment }
).await?;

// Save to file for sharing
std::fs::write("proposal.json", exported.to_json()?)?;
Source

pub async fn sign_imported_proposal( &mut self, proposal: &mut ExportedProposal, ) -> Result<()>

Signs an imported proposal locally (without GUARDIAN).

The signature is added directly to the proposal. After signing, export the proposal again to share with other cosigners.

Only SwitchGuardian proposals are supported in this mode.

§Example
let mut proposal = client.import_proposal("/tmp/proposal.json").await?;
client.sign_imported_proposal(&mut proposal).await?;
let json = proposal.to_json()?;
std::fs::write("/tmp/proposal_signed.json", json)?;
Source

pub async fn execute_imported_proposal( &mut self, exported: &ExportedProposal, ) -> Result<()>

Executes an imported proposal (with all signatures already collected).

This builds and submits the transaction directly to the Miden network without contacting GUARDIAN.

Only SwitchGuardian transactions are supported in this mode.

§Example
let proposal = client.import_proposal("/tmp/proposal_final.json").await?;
client.execute_imported_proposal(&proposal).await?;
Source§

impl MultisigClient

Source

pub async fn list_proposals(&mut self) -> Result<Vec<Proposal>>

Lists pending proposals for the current account.

Proposals whose nonce is not above the committed account nonce are skipped: they have already been executed or superseded, but GUARDIAN may still report them pending until canonicalization prunes them.

§Errors

Returns an error if any proposal from GUARDIAN cannot be parsed. This ensures malformed GUARDIAN payloads are surfaced rather than silently dropped.

Source

pub async fn sign_proposal(&mut self, proposal_id: &str) -> Result<Proposal>

Signs a proposal with the user’s key.

Source

pub async fn execute_proposal(&mut self, proposal_id: &str) -> Result<()>

Executes a proposal when it has enough signatures.

This will:

  1. Sync with the Miden network to get latest chain state
  2. Get the proposal and verify it has enough signatures
  3. Push delta to GUARDIAN to get acknowledgment signature
  4. Build the transaction with all cosigner signatures + GUARDIAN ack
  5. Execute the transaction on-chain
  6. Sync and update local account state

A proposal whose nonce is not strictly above the committed account nonce is rejected: it has already been executed or superseded, and re-executing would double-apply the intent and corrupt the nonce/delta sequence GUARDIAN tracks for canonicalization.

SwitchGuardian carries no GUARDIAN ack in the transaction itself (the switch happens later in finalize_transaction), but its delta is still pushed to the pre-switch GUARDIAN so it canonicalizes like any other proposal. That push is best-effort: an unreachable GUARDIAN must not block the switch, so the ack and any error are discarded.

Source

pub async fn propose_custom_transaction( &mut self, transaction_request_bytes: &[u8], proposal_type: &str, ) -> Result<Proposal>

Creates a proposal from a producer-built transaction the SDK does not model (issue #266 producer API). transaction_request_bytes is a serialized TransactionRequest; proposal_type is a free-form, non-empty label that MUST NOT collide with a built-in type. The integration keeps its own recipe to execute later via prepare_custom_execution.

Source

pub async fn prepare_custom_execution( &mut self, proposal_id: &str, transaction_request_bytes: &[u8], ) -> Result<Vec<SignatureAdvice>>

Assembles the validated execution advice for a threshold-met custom proposal (issue #266 producer API): the cosigner signatures and the GUARDIAN acknowledgment, keyed for the transaction’s advice map. The integration injects this into its own rebuilt transaction request (request.advice_map_mut().extend(advice)) and submits it via its own Miden client.

transaction_request_bytes (the serialized transaction request) is used only to verify, before the acknowledgment is requested, that it reproduces the signed proposal commitment. On a not-ready proposal or a binding mismatch this fails before requesting the acknowledgment.

Source

pub async fn submit_transaction( &mut self, request: TransactionRequest, ) -> Result<()>

Submits an integration-built transaction on-chain (issue #266 producer API). The caller injects the advice from prepare_custom_execution into its own transaction request (request.advice_map_mut().extend(advice)) and passes it here to finalize.

Source

pub async fn propose_transaction( &mut self, transaction_type: TransactionType, ) -> Result<Proposal>

Creates a proposal for a transaction.

This is the primary API for creating multisig transaction proposals. It handles all transaction types through a unified interface.

§Example
use miden_multisig_client::TransactionType;

// Add a new cosigner
let proposal = client.propose_transaction(
    TransactionType::AddCosigner { new_commitment }
).await?;

// Remove a cosigner
let proposal = client.propose_transaction(
    TransactionType::RemoveCosigner { commitment }
).await?;
Source

pub async fn propose_with_fallback( &mut self, transaction_type: TransactionType, ) -> Result<ProposalResult>

Proposes a transaction with automatic fallback to offline mode.

First attempts to create the proposal via GUARDIAN. If GUARDIAN is unavailable (connection error), falls back to offline proposal creation only when the transaction supports GUARDIAN-less execution (SwitchGuardian).

This is useful when you want to attempt online coordination but have a graceful fallback path for offline sharing.

§Returns
  • ProposalResult::Online(Proposal) if GUARDIAN succeeded
  • ProposalResult::Offline(ExportedProposal) if GUARDIAN failed and transaction is SwitchGuardian
§Example
use miden_multisig_client::{TransactionType, ProposalResult};

let tx = TransactionType::switch_guardian("https://new-guardian.example.com", new_guardian_commitment);
let result = client.propose_with_fallback(
    tx
).await?;

match result {
    ProposalResult::Online(proposal) => {
        println!("Proposal {} created on GUARDIAN", proposal.id);
    }
    ProposalResult::Offline(exported) => {
        println!("GUARDIAN unavailable, share this file with cosigners:");
        std::fs::write("proposal.json", exported.to_json()?)?;
    }
}
Source§

impl MultisigClient

Source

pub fn builder() -> MultisigClientBuilder

Creates a new MultisigClientBuilder.

Source

pub fn guardian_endpoint(&self) -> &str

Returns the GUARDIAN endpoint.

Source

pub fn account(&self) -> Option<&MultisigAccount>

Returns the current account, if any.

Source

pub fn account_id(&self) -> Option<AccountId>

Returns the current account ID, if any.

Source

pub fn has_account(&self) -> bool

Returns true if an account is loaded.

Source

pub fn user_commitment(&self) -> Word

Returns the user’s public key commitment as a Word.

Source

pub fn user_commitment_hex(&self) -> String

Returns the user’s public key commitment as a hex string.

Source

pub fn key_manager(&self) -> &dyn KeyManager

Returns a reference to the key manager.

Source

pub async fn recover_by_key(&self) -> Result<Vec<RecoveredAccount>>

Recover the set of accounts the configured signer authorizes by querying GUARDIAN’s /state/lookup endpoint and fetching state for each match. Mirrors MultisigClient.recoverByKey in the TS SDK. Returns an empty list when no account on the configured GUARDIAN authorizes this commitment (distinct from “wrong key”, which fails authentication first).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<D> OwoColorize for D

Source§

fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>
where C: Color,

Set the foreground color generically Read more
Source§

fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>
where C: Color,

Set the background color generically. Read more
Source§

fn black(&self) -> FgColorDisplay<'_, Black, Self>

Change the foreground color to black
Source§

fn on_black(&self) -> BgColorDisplay<'_, Black, Self>

Change the background color to black
Source§

fn red(&self) -> FgColorDisplay<'_, Red, Self>

Change the foreground color to red
Source§

fn on_red(&self) -> BgColorDisplay<'_, Red, Self>

Change the background color to red
Source§

fn green(&self) -> FgColorDisplay<'_, Green, Self>

Change the foreground color to green
Source§

fn on_green(&self) -> BgColorDisplay<'_, Green, Self>

Change the background color to green
Source§

fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>

Change the foreground color to yellow
Source§

fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>

Change the background color to yellow
Source§

fn blue(&self) -> FgColorDisplay<'_, Blue, Self>

Change the foreground color to blue
Source§

fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>

Change the background color to blue
Source§

fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to magenta
Source§

fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to magenta
Source§

fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to purple
Source§

fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to purple
Source§

fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>

Change the foreground color to cyan
Source§

fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>

Change the background color to cyan
Source§

fn white(&self) -> FgColorDisplay<'_, White, Self>

Change the foreground color to white
Source§

fn on_white(&self) -> BgColorDisplay<'_, White, Self>

Change the background color to white
Source§

fn default_color(&self) -> FgColorDisplay<'_, Default, Self>

Change the foreground color to the terminal default
Source§

fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>

Change the background color to the terminal default
Source§

fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>

Change the foreground color to bright black
Source§

fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>

Change the background color to bright black
Source§

fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>

Change the foreground color to bright red
Source§

fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>

Change the background color to bright red
Source§

fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>

Change the foreground color to bright green
Source§

fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>

Change the background color to bright green
Source§

fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>

Change the foreground color to bright yellow
Source§

fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>

Change the background color to bright yellow
Source§

fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>

Change the foreground color to bright blue
Source§

fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>

Change the background color to bright blue
Source§

fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright magenta
Source§

fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright magenta
Source§

fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright purple
Source§

fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright purple
Source§

fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>

Change the foreground color to bright cyan
Source§

fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>

Change the background color to bright cyan
Source§

fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>

Change the foreground color to bright white
Source§

fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>

Change the background color to bright white
Source§

fn bold(&self) -> BoldDisplay<'_, Self>

Make the text bold
Source§

fn dimmed(&self) -> DimDisplay<'_, Self>

Make the text dim
Source§

fn italic(&self) -> ItalicDisplay<'_, Self>

Make the text italicized
Source§

fn underline(&self) -> UnderlineDisplay<'_, Self>

Make the text underlined
Make the text blink
Make the text blink (but fast!)
Source§

fn reversed(&self) -> ReversedDisplay<'_, Self>

Swap the foreground and background colors
Source§

fn hidden(&self) -> HiddenDisplay<'_, Self>

Hide the text
Source§

fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>

Cross out the text
Source§

fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the foreground color at runtime. Only use if you do not know which color will be used at compile-time. If the color is constant, use either OwoColorize::fg or a color-specific method, such as OwoColorize::green, Read more
Source§

fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the background color at runtime. Only use if you do not know what color to use at compile-time. If the color is constant, use either OwoColorize::bg or a color-specific method, such as OwoColorize::on_yellow, Read more
Source§

fn fg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the foreground color to a specific RGB value.
Source§

fn bg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the background color to a specific RGB value.
Source§

fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>

Sets the foreground color to an RGB value.
Source§

fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>

Sets the background color to an RGB value.
Source§

fn style(&self, style: Style) -> Styled<&Self>

Apply a runtime-determined style
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more