use crate::nns::governance::{NnsGovernanceError, NnsGovernanceSourceProvenance};
#[cfg(feature = "nns-host")]
use crate::{
HostCacheError, nns::governance::NnsGovernanceAttemptReadError, runtime::RuntimeError,
};
#[cfg(feature = "nns-host")]
use std::path::PathBuf;
use thiserror::Error as ThisError;
#[derive(Debug, ThisError)]
pub enum NnsProposalError {
#[error(transparent)]
Governance(#[from] NnsGovernanceError),
#[error("invalid NNS proposal page limit {limit}; expected 1..={maximum}")]
InvalidLimit { limit: u32, maximum: u32 },
#[error("NNS proposal page returned {actual} rows; requested at most {requested}")]
PageTooLarge { actual: usize, requested: u32 },
#[error("NNS proposal list page returned a row without a proposal id")]
MissingProposalIdInPage,
#[error("NNS proposal list page returned proposal id zero")]
InvalidProposalIdInPage,
#[error("NNS proposal page returned duplicate proposal id {proposal_id}")]
DuplicateProposalId { proposal_id: u64 },
#[error(
"NNS proposal page returned id {proposal_id}; expected every id below {before_proposal_id}"
)]
ProposalCursorMismatch {
proposal_id: u64,
before_proposal_id: u64,
},
#[error("NNS proposal {proposal_id} was not found")]
ProposalNotFound { proposal_id: u64 },
#[error("NNS proposal detail returned id {actual:?}; expected {expected}")]
ProposalIdMismatch { expected: u64, actual: Option<u64> },
#[error("invalid NNS proposal collection page limit 0; expected at least one page")]
InvalidCollectionMaxPages,
#[error("invalid NNS proposal collection state: {reason}")]
InvalidCollectionState {
reason: String,
},
#[error(
"NNS proposal collection request changed {field}: received {actual}, expected {expected}"
)]
CollectionRequestMismatch {
field: &'static str,
expected: String,
actual: String,
},
#[error("NNS proposal collection is already complete after {pages_fetched} pages")]
CollectionComplete {
pages_fetched: u32,
},
#[error(
"NNS proposal collection reached its {max_pages}-page limit after {pages_fetched} pages"
)]
CollectionPageLimitReached {
pages_fetched: u32,
max_pages: u32,
},
#[error("NNS proposal collection source changed: received {actual:?}, expected {expected:?}")]
CollectionSourceChanged {
expected: NnsGovernanceSourceProvenance,
actual: NnsGovernanceSourceProvenance,
},
#[error("NNS proposal collection accounting overflow")]
CollectionAccountingOverflow,
}
#[cfg(feature = "nns-host")]
#[derive(Debug, ThisError)]
pub enum NnsProposalHostError {
#[error(transparent)]
Proposal(#[from] NnsProposalError),
#[error(transparent)]
Cache(#[from] HostCacheError),
#[error(
"cached NNS proposal snapshot identity mismatch at {}: {field} is {actual}, expected {expected}",
path.display()
)]
CacheIdentityMismatch {
path: PathBuf,
field: &'static str,
expected: String,
actual: String,
},
#[error(
"NNS proposal refresh did not publish a complete snapshot after {pages_fetched} pages and {rows_fetched} rows: {reason}"
)]
IncompleteRefresh {
pages_fetched: u32,
rows_fetched: usize,
reason: String,
},
#[error("invalid NNS proposal refresh page size {page_size}; expected 1..={max_page_size}")]
InvalidRefreshPageSize { page_size: u32, max_page_size: u32 },
#[error("NNS proposals cache is missing at {}\n\nRun `icq nns proposal refresh` to fetch a complete snapshot.", path.display())]
MissingProposalCache { path: PathBuf },
#[error("invalid NNS proposal refresh attempt at {}: {reason}", path.display())]
InvalidRefreshAttempt { path: PathBuf, reason: String },
#[error("invalid NNS proposal cache at {}: {reason}", path.display())]
InvalidCache { path: PathBuf, reason: String },
#[error("failed to create Tokio runtime for NNS proposal query: {0}")]
Runtime(#[from] RuntimeError),
}
#[cfg(feature = "nns-host")]
impl From<NnsGovernanceAttemptReadError> for NnsProposalHostError {
fn from(error: NnsGovernanceAttemptReadError) -> Self {
match error {
NnsGovernanceAttemptReadError::Cache(error) => Self::Cache(error),
NnsGovernanceAttemptReadError::Invalid { path, reason } => {
Self::InvalidRefreshAttempt { path, reason }
}
}
}
}