soroban_simulation/
testutils.rs

1use anyhow::{bail, Result};
2use soroban_env_host::{
3    e2e_testutils::ledger_entry,
4    storage::{EntryWithLiveUntil, SnapshotSource},
5    xdr::{
6        ContractDataDurability, ContractDataEntry, ContractId, ExtensionPoint, Hash, LedgerEntry,
7        LedgerEntryData, LedgerKey, LedgerKeyAccount, LedgerKeyConfigSetting,
8        LedgerKeyContractCode, LedgerKeyContractData, LedgerKeyTrustLine, ScAddress, ScBytes,
9        ScVal,
10    },
11    HostError,
12};
13use std::collections::BTreeMap;
14use std::rc::Rc;
15
16pub struct MockSnapshotSource {
17    map: BTreeMap<Rc<LedgerKey>, EntryWithLiveUntil>,
18}
19
20impl MockSnapshotSource {
21    pub fn from_entries(entries: Vec<(LedgerEntry, Option<u32>)>) -> Result<Self> {
22        let mut map = BTreeMap::<Rc<LedgerKey>, (Rc<LedgerEntry>, Option<u32>)>::new();
23        for (e, maybe_ttl) in entries {
24            let key = Rc::new(ledger_entry_to_ledger_key(&e)?);
25            map.insert(key, (Rc::new(e), maybe_ttl));
26        }
27        Ok(Self { map })
28    }
29}
30
31pub fn ledger_entry_to_ledger_key(entry: &LedgerEntry) -> Result<LedgerKey> {
32    match &entry.data {
33        LedgerEntryData::Account(a) => Ok(LedgerKey::Account(LedgerKeyAccount {
34            account_id: a.account_id.clone(),
35        })),
36        LedgerEntryData::Trustline(tl) => Ok(LedgerKey::Trustline(LedgerKeyTrustLine {
37            account_id: tl.account_id.clone(),
38            asset: tl.asset.clone(),
39        })),
40        LedgerEntryData::ContractData(cd) => Ok(LedgerKey::ContractData(LedgerKeyContractData {
41            contract: cd.contract.clone(),
42            key: cd.key.clone(),
43            durability: cd.durability,
44        })),
45        LedgerEntryData::ContractCode(code) => Ok(LedgerKey::ContractCode(LedgerKeyContractCode {
46            hash: code.hash.clone(),
47        })),
48        LedgerEntryData::ConfigSetting(cs) => {
49            Ok(LedgerKey::ConfigSetting(LedgerKeyConfigSetting {
50                config_setting_id: cs.discriminant(),
51            }))
52        }
53        _ => bail!("ledger entry type is not supported: {entry:#?}"),
54    }
55}
56
57impl SnapshotSource for MockSnapshotSource {
58    fn get(
59        &self,
60        key: &Rc<LedgerKey>,
61    ) -> std::result::Result<Option<EntryWithLiveUntil>, HostError> {
62        if let Some((entry, live_until)) = self.map.get(key) {
63            Ok(Some((entry.clone(), *live_until)))
64        } else {
65            Ok(None)
66        }
67    }
68}
69
70pub fn temp_entry(key: &[u8]) -> LedgerEntry {
71    ledger_entry(LedgerEntryData::ContractData(ContractDataEntry {
72        ext: ExtensionPoint::V0,
73        contract: ScAddress::Contract(ContractId(Hash([0; 32]))),
74        key: ScVal::Bytes(ScBytes(key.try_into().unwrap())),
75        durability: ContractDataDurability::Temporary,
76        val: ScVal::Void,
77    }))
78}