use cid::Cid;
use fvm_ipld_encoding::RawBytes;
use fvm_shared::{
address::Address, econ::TokenAmount, error::ExitCode, message::Message as FvmMessage,
version::NetworkVersion,
};
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use recall_fendermint_vm_encoding::IsHumanReadable;
#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)]
pub enum FvmQueryHeight {
#[default]
Committed,
Pending,
Height(u64),
}
impl From<u64> for FvmQueryHeight {
fn from(value: u64) -> Self {
match value {
0 => FvmQueryHeight::Committed,
n if n >= i64::MAX as u64 => FvmQueryHeight::Pending,
n => FvmQueryHeight::Height(n),
}
}
}
impl From<FvmQueryHeight> for u64 {
fn from(value: FvmQueryHeight) -> Self {
match value {
FvmQueryHeight::Committed => 0,
FvmQueryHeight::Pending => i64::MAX as u64,
FvmQueryHeight::Height(n) => n,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum FvmQuery {
Ipld(Cid),
ActorState(Address),
Call(Box<FvmMessage>),
EstimateGas(Box<FvmMessage>),
StateParams,
BuiltinActors,
}
#[serde_as]
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct ActorState {
#[serde_as(as = "IsHumanReadable")]
pub code: Cid,
#[serde_as(as = "IsHumanReadable")]
pub state: Cid,
pub sequence: u64,
#[serde_as(as = "IsHumanReadable")]
pub balance: TokenAmount,
#[serde_as(as = "Option<IsHumanReadable>")]
pub delegated_address: Option<Address>,
}
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct GasEstimate {
pub exit_code: ExitCode,
pub info: String,
pub return_data: RawBytes,
pub gas_limit: u64,
}
#[serde_as]
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct StateParams {
#[serde_as(as = "IsHumanReadable")]
pub base_fee: TokenAmount,
#[serde_as(as = "IsHumanReadable")]
pub circ_supply: TokenAmount,
pub chain_id: u64,
pub network_version: NetworkVersion,
}
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct BuiltinActors {
pub registry: Vec<(String, Cid)>,
}
#[cfg(feature = "arb")]
mod arb {
use recall_fendermint_testing::arb::{ArbAddress, ArbCid, ArbTokenAmount};
use crate::signed::SignedMessage;
use super::{ActorState, FvmQuery};
impl quickcheck::Arbitrary for FvmQuery {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
match u8::arbitrary(g) % 5 {
0 => FvmQuery::Ipld(ArbCid::arbitrary(g).0),
1 => FvmQuery::ActorState(ArbAddress::arbitrary(g).0),
2 => FvmQuery::Call(Box::new(SignedMessage::arbitrary(g).into_message())),
3 => FvmQuery::EstimateGas(Box::new(SignedMessage::arbitrary(g).into_message())),
_ => FvmQuery::StateParams,
}
}
}
impl quickcheck::Arbitrary for ActorState {
fn arbitrary(g: &mut quickcheck::Gen) -> Self {
Self {
code: ArbCid::arbitrary(g).0,
state: ArbCid::arbitrary(g).0,
sequence: u64::arbitrary(g),
balance: ArbTokenAmount::arbitrary(g).0,
delegated_address: Option::<ArbAddress>::arbitrary(g).map(|a| a.0),
}
}
}
}