use candid::Principal;
use canic_contracts::ids::{
CanisterRole, ComponentBinding, ComponentInstanceId, FleetRegistryAuthority,
FleetSubnetRootReleaseSet,
};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum FundingQuoteStage {
Observation,
Recovery,
}
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingQuoteSourceRecord {
pub review_sha256: String,
pub stage: FundingQuoteStage,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingObservationAuthorityRecord {
pub registry: FleetRegistryAuthority,
pub revision: u64,
pub content_hash: [u8; 32],
pub components: BTreeMap<ComponentInstanceId, FundingComponentHeadRecord>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingComponentHeadRecord {
pub revision: u64,
pub content_hash: [u8; 32],
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingObservationRequestRecord {
pub component: ComponentBinding,
pub release_set: FleetSubnetRootReleaseSet,
pub parent: Principal,
#[serde(deserialize_with = "super::serialization::required_option")]
pub parent_role: Option<CanisterRole>,
pub child: Principal,
pub role: CanisterRole,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingObservationReviewBodyRecord {
pub configuration_source: String,
pub operation_id: String,
pub plan_sha256: String,
pub root: String,
pub authority: FundingObservationAuthorityRecord,
pub requests: Vec<FundingObservationRequestRecord>,
#[serde(with = "super::u128_text")]
pub per_attempt_cycles: u128,
#[serde(with = "super::u128_text")]
pub maximum_cycles: u128,
#[serde(with = "super::u128_text")]
pub recovery_floor_cycles: u128,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingObservationReviewRecord {
#[serde(with = "super::option_u128_text")]
pub final_root_cycles: Option<u128>,
pub body: FundingObservationReviewBodyRecord,
pub review_sha256: String,
pub approved: bool,
pub attempts: Vec<FundingObservationAttemptRecord>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingObservationAttemptRecord {
pub request_index: usize,
#[serde(deserialize_with = "super::serialization::required_option")]
pub outcome: Option<FundingObservationOutcomeRecord>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum FundingObservationOutcomeRecord {
Observed(FundingChildAccountingRecord),
ObservationFailed,
Interrupted,
AuthorityChanged,
RecoveryRequired,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct FundingChildAccountingRecord {
#[serde(with = "super::u128_text")]
pub native_cycles: u128,
pub parent: Principal,
pub child: Principal,
pub observed_at_ns: u64,
#[serde(with = "super::u128_text")]
pub accounted_cycles: u128,
pub last_accounted_at_secs: u64,
pub pending_operations: u32,
#[serde(with = "super::option_u128_text")]
pub reserved_cycles: Option<u128>,
}
#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum FundingObservationError {
#[error("funding observation authority or retained record differs")]
AuthorityMismatch,
#[error("funding observation approval digest differs")]
ApprovalMismatch,
#[error("funding observation requires an in-progress operation")]
OperationNotInProgress,
#[error("funding observation is unavailable or has invalid bounds")]
Unavailable,
#[error("funding observation requires native recovery before another attempt")]
Underfunded,
#[error("funding observation accounting overflowed")]
ArithmeticOverflow,
}