wasm_host_simulator/
mock_data.rs

1#![allow(dead_code)]
2
3use crate::data_provider::HostError;
4use crate::decoding::{AccountId, Decodable, SField_To_Name, decode};
5use crate::hashing::Hash256;
6use std::collections::HashMap;
7
8pub type Bytes = Vec<u8>;
9
10pub type Keylet = Hash256;
11
12pub enum DataSource {
13    Tx,
14    CurrentLedgerObj,
15    KeyletLedgerObj(Keylet),
16}
17
18#[derive(Debug)]
19pub struct MockData {
20    tx: serde_json::Value,
21    hosting_ledger_obj: serde_json::Value,
22    header: serde_json::Value,
23    ledger: HashMap<Keylet, serde_json::Value>,
24    nfts: HashMap<Hash256, (AccountId, serde_json::Value)>,
25}
26
27impl MockData {
28    pub fn new(
29        tx_str: &str,
30        hosting_ledger_obj_str: &str,
31        header_str: &str,
32        ledger_str: &str,
33        nfts_str: &str,
34    ) -> Self {
35        let tx = serde_json::from_str(tx_str).expect("Tx JSON bad formatted");
36        let hosting_ledger_obj = serde_json::from_str(hosting_ledger_obj_str)
37            .expect("Hosting ledger object JSON bad formatted");
38        let header = serde_json::from_str(header_str).expect("Ledger header JSON bad formatted");
39
40        let ledger = {
41            let parsed_data: Vec<HashMap<String, serde_json::Value>> =
42                serde_json::from_str(ledger_str).expect("Ledger JSON bad formatted");
43            let mut combined_hashmap: HashMap<Keylet, serde_json::Value> = HashMap::new();
44            for map_entry in parsed_data {
45                for (key, value) in map_entry {
46                    let keylet: Keylet =
47                        decode(&key, Decodable::UINT256).expect("ledger file, bad keylet");
48                    // println!("MockData keylet {:?}", keylet);
49                    combined_hashmap.insert(keylet, value);
50                }
51            }
52            combined_hashmap
53        };
54
55        let nfts = {
56            let mut nft_map = HashMap::new();
57            let parsed_json: serde_json::Value =
58                serde_json::from_str(nfts_str).expect("Failed to parse NFT JSON");
59            for item in parsed_json.as_array().expect("NFT JSON not an array") {
60                let nft_id = item["nft_id"].as_str();
61                let owner = item["owner"].as_str();
62                let uri = item.get("uri");
63
64                if let (Some(id), Some(owner), Some(uri)) = (nft_id, owner, uri) {
65                    nft_map.insert(
66                        decode(id, Decodable::UINT256).expect("NFT file, bad nft_id"),
67                        (
68                            decode(owner, Decodable::ACCOUNT).expect("NFT file, bad owner"),
69                            uri.clone(),
70                        ),
71                    );
72                } else {
73                    panic!("NFT missing field(s)");
74                }
75            }
76            nft_map
77        };
78
79        MockData {
80            tx,
81            hosting_ledger_obj,
82            header,
83            ledger,
84            nfts,
85        }
86    }
87
88    pub fn obj_exist(&self, keylet: &Keylet) -> bool {
89        self.ledger.contains_key(keylet)
90    }
91
92    #[inline]
93    fn get_field_name(&self, field_id: i32) -> Option<String> {
94        SField_To_Name.get(&field_id).cloned()
95    }
96
97    pub fn get_field_value(
98        &self,
99        source: DataSource,
100        idx_fields: Vec<i32>,
101    ) -> Result<(i32, &serde_json::Value), HostError> {
102        let mut curr = match source {
103            DataSource::Tx => &self.tx,
104            DataSource::CurrentLedgerObj => &self.hosting_ledger_obj,
105            DataSource::KeyletLedgerObj(obj_hash) => match self.ledger.get(&obj_hash) {
106                None => return Err(HostError::LedgerObjNotFound),
107                Some(obj) => obj,
108            },
109        };
110
111        let mut last_sfield = -1;
112        for idx_field in idx_fields {
113            if curr.is_array() {
114                curr = match curr.as_array().unwrap().get(idx_field as usize) {
115                    None => return Err(HostError::IndexOutOfBounds),
116                    Some(value) => value,
117                };
118            } else {
119                let field_name = match self.get_field_name(idx_field) {
120                    None => return Err(HostError::InvalidField),
121                    Some(name) => name,
122                };
123                curr = match curr.get(field_name) {
124                    None => return Err(HostError::FieldNotFound),
125                    Some(value) => value,
126                };
127                last_sfield = idx_field;
128            }
129        }
130        Ok((last_sfield, curr))
131    }
132
133    pub fn get_ledger_sqn(&self) -> Option<&serde_json::Value> {
134        self.header.get("ledger_index")
135    }
136
137    pub fn get_parent_ledger_time(&self) -> Option<&serde_json::Value> {
138        self.header.get("parent_close_time")
139    }
140
141    pub fn get_parent_ledger_hash(&self) -> Option<&serde_json::Value> {
142        self.header.get("parent_hash")
143    }
144
145    pub fn set_current_ledger_obj_data(&mut self, data: Vec<u8>) {
146        self.hosting_ledger_obj["data"] = serde_json::Value::from(data);
147    }
148
149    pub fn get_nft_uri(
150        &self,
151        nft_id: &Hash256,
152        account_id: &AccountId,
153    ) -> Option<&serde_json::Value> {
154        match self.nfts.get(nft_id) {
155            None => None,
156            Some((aid, uri)) => {
157                if account_id == aid {
158                    Some(uri)
159                } else {
160                    None
161                }
162            }
163        }
164    }
165}