use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use crate::scope::OnchainRecord;
pub const FIXTURE_VERSION: u32 = 2;
fn default_version() -> u32 {
1 }
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "kind", rename_all = "lowercase")]
pub enum FixtureEntry {
Data {
address: String,
owner: String,
lamports: u64,
data_b64: String,
},
Program {
address: String,
elf_b64: String,
},
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Fixture {
#[serde(default = "default_version")]
pub version: u32,
pub signature: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub captured_slot: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub captured_block_time: Option<i64>,
pub tx_b64: String,
pub entries: Vec<FixtureEntry>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub idls: BTreeMap<String, serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub recorded: Option<OnchainRecord>,
}
impl Fixture {
pub fn to_json(&self) -> crate::error::Result<String> {
serde_json::to_string_pretty(self)
.map_err(|e| crate::error::Error::Fixture(format!("serialize: {e}")))
}
pub fn from_json(s: &str) -> crate::error::Result<Fixture> {
let fx: Fixture = serde_json::from_str(s)
.map_err(|e| crate::error::Error::Fixture(format!("parse: {e}")))?;
if fx.version > FIXTURE_VERSION {
return Err(crate::error::Error::Fixture(format!(
"unsupported fixture version {} (this build reads <= {FIXTURE_VERSION}) — \
update svmscope, or re-capture the fixture",
fx.version
)));
}
Ok(fx)
}
pub fn summary(&self) -> String {
let programs = self
.entries
.iter()
.filter(|e| matches!(e, FixtureEntry::Program { .. }))
.count();
let data = self.entries.len() - programs;
format!("{data} accounts, {programs} programs")
}
}