use miden_protocol::account::AccountId;
use miden_protocol::note::NoteId;
use thiserror::Error;
pub type Result<T> = std::result::Result<T, MultisigError>;
#[derive(Debug, Error)]
pub enum MultisigError {
#[error("account not found: {0}")]
AccountNotFound(AccountId),
#[error("proposal not found: {0}")]
ProposalNotFound(String),
#[error("GUARDIAN connection error: {0}")]
GuardianConnection(String),
#[error("GUARDIAN server error: {0}")]
GuardianServer(String),
#[error("miden client error: {0}")]
MidenClient(String),
#[error("sync panicked (corrupted local state): {0}")]
SyncPanicked(String),
#[error("transaction execution failed: {0}")]
TransactionExecution(String),
#[error("invalid configuration: {0}")]
InvalidConfig(String),
#[error("signature error: {0}")]
Signature(String),
#[error("serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("not a cosigner for this account")]
NotCosigner,
#[error("already signed this proposal")]
AlreadySigned,
#[error("proposal not ready: need {required} signatures, have {collected}")]
ProposalNotReady { required: usize, collected: usize },
#[error("signer not configured")]
NoSigner,
#[error("missing required configuration: {0}")]
MissingConfig(String),
#[error("hex decode error: {0}")]
HexDecode(String),
#[error("account storage error: {0}")]
AccountStorage(String),
#[error("transaction executed successfully when failure was expected")]
UnexpectedSuccess,
#[error("unknown transaction type: {0}")]
UnknownTransactionType(String),
#[error("unsupported transaction type for this operation: {0}")]
UnsupportedTransactionType(String),
#[error("invalid filter: {0}")]
InvalidFilter(String),
#[error("offline mode only supports SwitchGuardian transactions, got: {0}")]
OfflineUnsupportedTransaction(String),
#[error("consume_notes metadata note binding mismatch: {0}")]
NoteBindingMismatch(String),
#[error("unsupported consume_notes metadata version: {found:?}")]
UnsupportedMetadataVersion { found: Option<u32> },
#[error(
"consume_notes metadata exceeds size limit: limit={limit} bytes, actual={actual} bytes"
)]
ConsumeNotesMetadataOversize { limit: usize, actual: usize },
#[error("consume_notes legacy verification: note not found in local store: {note_id}")]
LegacyConsumeNotesNoteMissing { note_id: NoteId },
}
impl MultisigError {
pub fn code(&self) -> Option<&'static str> {
match self {
Self::NoteBindingMismatch(_) => Some("consume_notes_note_binding_mismatch"),
Self::UnsupportedMetadataVersion { .. } => {
Some("consume_notes_unsupported_metadata_version")
}
Self::ConsumeNotesMetadataOversize { .. } => Some("consume_notes_metadata_oversize"),
Self::LegacyConsumeNotesNoteMissing { .. } => Some("consume_notes_legacy_note_missing"),
Self::UnsupportedTransactionType(_) => Some("unsupported_transaction_type"),
_ => None,
}
}
}
impl From<guardian_client::ClientError> for MultisigError {
fn from(err: guardian_client::ClientError) -> Self {
MultisigError::GuardianServer(err.to_string())
}
}
pub(crate) fn error_chain(err: &dyn std::error::Error) -> String {
let mut message = err.to_string();
let mut source = err.source();
while let Some(cause) = source {
message.push_str(": ");
message.push_str(&cause.to_string());
source = cause.source();
}
message
}
impl From<miden_client::ClientError> for MultisigError {
fn from(err: miden_client::ClientError) -> Self {
MultisigError::MidenClient(error_chain(&err))
}
}
impl From<miden_client::transaction::TransactionRequestError> for MultisigError {
fn from(err: miden_client::transaction::TransactionRequestError) -> Self {
MultisigError::TransactionExecution(err.to_string())
}
}
impl From<miden_client::transaction::TransactionExecutorError> for MultisigError {
fn from(err: miden_client::transaction::TransactionExecutorError) -> Self {
MultisigError::TransactionExecution(err.to_string())
}
}