use super::balance_table::BalanceTable;
use anyhow::anyhow;
use cid::Cid;
use fil_actor_verifreg_state::v9::AllocationID;
use fil_actors_shared::v9::{make_empty_map, ActorError, Array, AsActorError as _, SetMultimap};
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::tuple::*;
use fvm_shared::clock::{ChainEpoch, EPOCH_UNDEFINED};
use fvm_shared::deal::DealID;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::HAMT_BIT_WIDTH;
use super::types::*;
#[derive(Clone, Default, Serialize_tuple, Deserialize_tuple, Debug)]
pub struct State {
pub proposals: Cid,
pub states: Cid,
pub pending_proposals: Cid,
pub escrow_table: Cid,
pub locked_table: Cid,
pub next_id: DealID,
pub deal_ops_by_epoch: Cid,
pub last_cron: ChainEpoch,
pub total_client_locked_collateral: TokenAmount,
pub total_provider_locked_collateral: TokenAmount,
pub total_client_storage_fee: TokenAmount,
pub pending_deal_allocation_ids: Cid, }
impl State {
pub fn new<BS: Blockstore>(store: &BS) -> anyhow::Result<Self> {
let empty_proposals_array =
Array::<(), BS>::new_with_bit_width(store, PROPOSALS_AMT_BITWIDTH)
.flush()
.map_err(|e| anyhow!("Failed to create empty proposals array: {}", e))?;
let empty_states_array = Array::<(), BS>::new_with_bit_width(store, STATES_AMT_BITWIDTH)
.flush()
.map_err(|e| anyhow!("Failed to create empty states array: {}", e))?;
let empty_pending_proposals_map = make_empty_map::<_, ()>(store, HAMT_BIT_WIDTH)
.flush()
.map_err(|e| anyhow!("Failed to create empty pending proposals map state: {}", e))?;
let empty_balance_table = BalanceTable::new(store)
.root()
.map_err(|e| anyhow!("Failed to create empty balance table map: {}", e))?;
let empty_deal_ops_hamt = SetMultimap::new(store)
.root()
.map_err(|e| anyhow!("Failed to create empty multiset: {}", e))?;
let empty_pending_deal_allocation_map =
make_empty_map::<_, AllocationID>(store, HAMT_BIT_WIDTH)
.flush()
.map_err(|e| {
anyhow!("Failed to create empty pending deal allocation map: {}", e)
})?;
Ok(Self {
proposals: empty_proposals_array,
states: empty_states_array,
pending_proposals: empty_pending_proposals_map,
escrow_table: empty_balance_table,
locked_table: empty_balance_table,
next_id: 0,
deal_ops_by_epoch: empty_deal_ops_hamt,
last_cron: EPOCH_UNDEFINED,
total_client_locked_collateral: TokenAmount::default(),
total_provider_locked_collateral: TokenAmount::default(),
total_client_storage_fee: TokenAmount::default(),
pending_deal_allocation_ids: empty_pending_deal_allocation_map,
})
}
pub fn total_locked(&self) -> TokenAmount {
&self.total_client_locked_collateral
+ &self.total_provider_locked_collateral
+ &self.total_client_storage_fee
}
pub fn escrow_table<'a, BS: Blockstore>(
&self,
store: &'a BS,
) -> Result<BalanceTable<'a, BS>, ActorError> {
BalanceTable::from_root(store, &self.escrow_table)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load escrow table")
}
pub fn locked_table<'a, BS: Blockstore>(
&self,
store: &'a BS,
) -> Result<BalanceTable<'a, BS>, ActorError> {
BalanceTable::from_root(store, &self.locked_table)
.context_code(ExitCode::USR_ILLEGAL_STATE, "failed to load locked table")
}
}