wasm_host_simulator/
mock_data.rs1#![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 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}