casperlabs_contract_utils/
data.rs1use alloc::{
2 string::{String, ToString},
3 vec::Vec,
4};
5use casper_contract::{
6 contract_api::{runtime, storage},
7 unwrap_or_revert::UnwrapOrRevert,
8};
9use casper_types::{
10 bytesrepr::{FromBytes, ToBytes},
11 ApiError, CLTyped, Key, RuntimeArgs, URef, U128, U256,
12};
13use casper_types_derive::{CLTyped, FromBytes, ToBytes};
14use core::convert::TryInto;
15
16#[derive(Clone, Copy, CLTyped, ToBytes, FromBytes, Default)]
17pub struct Dict {
18 uref: URef,
19}
20
21impl Dict {
22 pub fn instance(name: &str) -> Dict {
23 let key = runtime::get_key(name).unwrap_or_revert();
24 let uref = *key.as_uref().unwrap_or_revert();
25 Dict { uref }
26 }
27
28 pub fn init(name: &str) {
29 storage::new_dictionary(name).unwrap_or_revert();
30 }
31
32 pub fn at(uref: URef) -> Dict {
33 Dict { uref }
34 }
35
36 pub fn get<T: CLTyped + FromBytes>(&self, key: &str) -> Option<T> {
37 storage::dictionary_get(self.uref, key)
38 .unwrap_or_revert()
39 .unwrap_or_default()
40 }
41
42 pub fn get_by_key<T: CLTyped + FromBytes>(&self, key: &Key) -> Option<T> {
43 self.get(&key_to_str(key))
44 }
45
46 pub fn get_by_keys<T: CLTyped + FromBytes, U: CLTyped + ToBytes>(
47 &self,
48 keys: (&U, &Key),
49 ) -> Option<T> {
50 self.get(&keys_to_str(keys.0, keys.1))
51 }
52
53 pub fn set<T: CLTyped + ToBytes>(&self, key: &str, value: T) {
54 storage::dictionary_put(self.uref, key, Some(value));
55 }
56
57 pub fn set_by_key<T: CLTyped + ToBytes>(&self, key: &Key, value: T) {
58 self.set(&key_to_str(key), value);
59 }
60
61 pub fn set_by_keys<T: CLTyped + ToBytes, U: CLTyped + ToBytes>(
62 &self,
63 keys: (&U, &Key),
64 value: T,
65 ) {
66 self.set(&keys_to_str(keys.0, keys.1), value)
67 }
68 pub fn set_by_values<T: CLTyped + ToBytes, U: CLTyped + ToBytes, V: CLTyped + ToBytes>(
69 &self,
70 keys: (&T, &U),
71 value: V,
72 ) {
73 self.set(&values_to_str(keys.0, keys.1), value);
74 }
75
76 pub fn get_by_values<T: CLTyped + ToBytes, U: CLTyped + ToBytes, R: CLTyped + FromBytes>(
77 &self,
78 keys: (&T, &U),
79 ) -> Option<R> {
80 self.get(&values_to_str(keys.0, keys.1))
81 }
82
83 pub fn remove<T: CLTyped + ToBytes>(&self, key: &str) {
84 storage::dictionary_put(self.uref, key, Option::<T>::None);
85 }
86
87 pub fn remove_by_key<T: CLTyped + ToBytes>(&self, key: &Key) {
88 self.remove::<T>(&key_to_str(key));
89 }
90
91 pub fn remove_by_vec_of_keys<T: CLTyped + ToBytes>(&self, keys: (&Key, &Key)) {
92 self.remove::<T>(&keys_to_str(keys.0, keys.1))
93 }
94}
95
96pub fn key_to_str(key: &Key) -> String {
97 match key {
98 Key::Account(account) => account.to_string(),
99 Key::Hash(package) => hex::encode(package),
100 _ => runtime::revert(ApiError::UnexpectedKeyVariant),
101 }
102}
103
104pub fn keys_to_str<U: CLTyped + ToBytes, V: CLTyped + ToBytes>(key_a: &U, key_b: &V) -> String {
105 let mut bytes_a = key_a.to_bytes().unwrap_or_revert();
106 let mut bytes_b = key_b.to_bytes().unwrap_or_revert();
107 bytes_a.append(&mut bytes_b);
108 let bytes = runtime::blake2b(bytes_a);
109 hex::encode(bytes)
110}
111
112pub fn values_to_str<T: CLTyped + ToBytes, U: CLTyped + ToBytes>(
113 value_a: &T,
114 value_b: &U,
115) -> String {
116 let mut bytes_a = value_a.to_bytes().unwrap_or_revert();
117 let mut bytes_b = value_b.to_bytes().unwrap_or_revert();
118
119 bytes_a.append(&mut bytes_b);
120
121 let bytes = runtime::blake2b(bytes_a);
122 hex::encode(bytes)
123}
124
125pub fn key_and_value_to_str<T: CLTyped + ToBytes>(key: &Key, value: &T) -> String {
126 let mut bytes_a = key.to_bytes().unwrap_or_revert();
127 let mut bytes_b = value.to_bytes().unwrap_or_revert();
128
129 bytes_a.append(&mut bytes_b);
130
131 let bytes = runtime::blake2b(bytes_a);
132 hex::encode(bytes)
133}
134
135pub fn get_key<T: FromBytes + CLTyped>(name: &str) -> Option<T> {
136 match runtime::get_key(name) {
137 None => None,
138 Some(value) => {
139 let key = value.try_into().unwrap_or_revert();
140 let value = storage::read(key).unwrap_or_revert().unwrap_or_revert();
141 Some(value)
142 }
143 }
144}
145
146pub fn set_key<T: ToBytes + CLTyped>(name: &str, value: T) {
147 match runtime::get_key(name) {
148 Some(key) => {
149 let key_ref = key.try_into().unwrap_or_revert();
150 storage::write(key_ref, value);
151 }
152 None => {
153 let key = storage::new_uref(value).into();
154 runtime::put_key(name, key);
155 }
156 }
157}
158
159pub fn call_function(target: Key, function_name: String, function_args: RuntimeArgs) -> String {
160 if function_name == "get_gauge_weight"
161 || function_name == "gauge_relative_weight"
162 || function_name == "inflation_rate"
163 || function_name == "working_supply"
164 || function_name == "balance_of"
165 || function_name == "duration"
166 || function_name == "reward_rate"
167 || function_name == "balances"
168 || function_name == "total_supply"
169 || function_name == "get_balance"
170 || function_name == "earned"
171 || function_name == "allowance"
172 || function_name == "locked_end"
173 || function_name == "vested_of"
174 || function_name == "locked_of"
175 || function_name == "initial_locked"
176 || function_name == "start_time"
177 || function_name == "end_time"
178 || function_name == "total_claimed"
179 || function_name == "working_balances"
180 || function_name == "vested_supply"
181 || function_name == "user_reward_per_token_paid"
182 {
183 let ret: U256 = runtime::call_versioned_contract(
184 target.into_hash().unwrap_or_revert().into(),
185 None,
186 &function_name,
187 function_args,
188 );
189 let data: String = ret.to_string() + ":U256";
190 return data;
191 }
192 if function_name == "gauges" || function_name == "lp_token" {
193 let ret: Key = runtime::call_versioned_contract(
194 target.into_hash().unwrap_or_revert().into(),
195 None,
196 &function_name,
197 function_args,
198 );
199 let data: String = ret.to_string() + ":Key";
200 return data;
201 }
202 if function_name == "gauge_type_names" {
203 let ret: String = runtime::call_versioned_contract(
204 target.into_hash().unwrap_or_revert().into(),
205 None,
206 &function_name,
207 function_args,
208 );
209 let data: String = ret.to_string() + ":String";
210 return data;
211 }
212 if function_name == "gauge_types"
213 || function_name == "n_gauge_types"
214 || function_name == "n_gauges"
215 {
216 let ret: (bool, U128) = runtime::call_versioned_contract(
217 target.into_hash().unwrap_or_revert().into(),
218 None,
219 &function_name,
220 function_args,
221 );
222 let data: String =
223 "(".to_string() + &ret.0.to_string() + "," + &ret.1.to_string() + ")" + ":(bool,U128)";
224 return data;
225 }
226 "".to_string()
227}