@layerzerolabs/common-utils-macros-stellar-contracts 0.2.122
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +21 -0
- package/LICENSE +23 -0
- package/clippy.toml +7 -0
- package/package.json +37 -0
- package/rust-toolchain.toml +4 -0
- package/rustfmt.toml +15 -0
- package/src/auth.rs +95 -0
- package/src/contract_ttl.rs +92 -0
- package/src/error.rs +43 -0
- package/src/lib.rs +585 -0
- package/src/lz_contract.rs +105 -0
- package/src/rbac.rs +90 -0
- package/src/storage.rs +522 -0
- package/src/tests/auth.rs +230 -0
- package/src/tests/contract_ttl.rs +695 -0
- package/src/tests/error.rs +156 -0
- package/src/tests/lz_contract.rs +87 -0
- package/src/tests/mod.rs +11 -0
- package/src/tests/rbac.rs +523 -0
- package/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +31 -0
- package/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +39 -0
- package/src/tests/snapshots/common_macros__tests__auth__snapshot_only_auth_preserves_function_signature.snap +19 -0
- package/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap +77 -0
- package/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contracttrait_code.snap +46 -0
- package/src/tests/snapshots/common_macros__tests__error__snapshot_generated_contract_error_code.snap +20 -0
- package/src/tests/snapshots/common_macros__tests__lz_contract__snapshot_generated_lz_contract_code.snap +51 -0
- package/src/tests/snapshots/common_macros__tests__rbac__snapshot_authorizer_role.snap +21 -0
- package/src/tests/snapshots/common_macros__tests__rbac__snapshot_preserve_function_signature.snap +21 -0
- package/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +10 -0
- package/src/tests/snapshots/common_macros__tests__ttl_extendable__snapshot_generated_ttl_extendable_code.snap +8 -0
- package/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +28 -0
- package/src/tests/storage/extract_fields.rs +87 -0
- package/src/tests/storage/gen_accessor_methods.rs +223 -0
- package/src/tests/storage/gen_args.rs +65 -0
- package/src/tests/storage/gen_enum_variant.rs +78 -0
- package/src/tests/storage/gen_key.rs +108 -0
- package/src/tests/storage/gen_params.rs +105 -0
- package/src/tests/storage/generate_storage.rs +410 -0
- package/src/tests/storage/is_primitive_type.rs +48 -0
- package/src/tests/storage/mod.rs +16 -0
- package/src/tests/storage/parse_default.rs +164 -0
- package/src/tests/storage/parse_name.rs +158 -0
- package/src/tests/storage/parse_no_ttl_extension.rs +124 -0
- package/src/tests/storage/parse_storage_type.rs +174 -0
- package/src/tests/storage/snapshots/common_macros__tests__storage__generate_storage__snapshot_generated_storage_code.snap +412 -0
- package/src/tests/storage/storage_kind.rs +39 -0
- package/src/tests/storage/test_setup.rs +25 -0
- package/src/tests/storage/validate_attrs.rs +138 -0
- package/src/tests/storage/variant_config.rs +226 -0
- package/src/tests/test_helpers.rs +87 -0
- package/src/tests/ttl_configurable.rs +34 -0
- package/src/tests/ttl_extendable.rs +32 -0
- package/src/tests/upgradeable.rs +169 -0
- package/src/tests/utils.rs +267 -0
- package/src/ttl_configurable.rs +24 -0
- package/src/ttl_extendable.rs +28 -0
- package/src/upgradeable.rs +136 -0
- package/src/utils.rs +56 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
---
|
|
2
|
+
source: contracts/common-macros/src/tests/storage/generate_storage.rs
|
|
3
|
+
assertion_line: 409
|
|
4
|
+
expression: formatted
|
|
5
|
+
---
|
|
6
|
+
#[soroban_sdk::contracttype]
|
|
7
|
+
pub enum StorageKeys {
|
|
8
|
+
Counter,
|
|
9
|
+
Message(Address),
|
|
10
|
+
Flag(String),
|
|
11
|
+
Owner,
|
|
12
|
+
OptionalData(BytesN<32>),
|
|
13
|
+
TempData,
|
|
14
|
+
PrimitiveKey(u32),
|
|
15
|
+
NonPrimitiveKey(String),
|
|
16
|
+
NamedVariant(u32, String, Address),
|
|
17
|
+
CachedValue(Address),
|
|
18
|
+
}
|
|
19
|
+
impl StorageKeys {
|
|
20
|
+
pub fn counter(env: &soroban_sdk::Env) -> u32 {
|
|
21
|
+
let key = StorageKeys::Counter;
|
|
22
|
+
let value = env.storage().instance().get::<_, u32>(&key);
|
|
23
|
+
value.unwrap_or_else(|| 0)
|
|
24
|
+
}
|
|
25
|
+
pub fn set_counter(env: &soroban_sdk::Env, value: &u32) {
|
|
26
|
+
let key = StorageKeys::Counter;
|
|
27
|
+
env.storage().instance().set(&key, value);
|
|
28
|
+
}
|
|
29
|
+
pub fn remove_counter(env: &soroban_sdk::Env) {
|
|
30
|
+
let key = StorageKeys::Counter;
|
|
31
|
+
env.storage().instance().remove(&key);
|
|
32
|
+
}
|
|
33
|
+
pub fn set_or_remove_counter(env: &soroban_sdk::Env, value: &Option<u32>) {
|
|
34
|
+
match value.as_ref() {
|
|
35
|
+
Some(v) => Self::set_counter(env, v),
|
|
36
|
+
None => Self::remove_counter(env),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
pub fn has_counter(env: &soroban_sdk::Env) -> bool {
|
|
40
|
+
let key = StorageKeys::Counter;
|
|
41
|
+
env.storage().instance().has(&key)
|
|
42
|
+
}
|
|
43
|
+
pub fn message(env: &soroban_sdk::Env, sender: &Address) -> String {
|
|
44
|
+
let key = StorageKeys::Message(sender.clone());
|
|
45
|
+
let value = env.storage().persistent().get::<_, String>(&key);
|
|
46
|
+
if value.is_some() {
|
|
47
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
48
|
+
}
|
|
49
|
+
value.unwrap_or_else(|| String::from_str(env, "hello"))
|
|
50
|
+
}
|
|
51
|
+
pub fn set_message(env: &soroban_sdk::Env, sender: &Address, value: &String) {
|
|
52
|
+
let key = StorageKeys::Message(sender.clone());
|
|
53
|
+
env.storage().persistent().set(&key, value);
|
|
54
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
55
|
+
}
|
|
56
|
+
pub fn remove_message(env: &soroban_sdk::Env, sender: &Address) {
|
|
57
|
+
let key = StorageKeys::Message(sender.clone());
|
|
58
|
+
env.storage().persistent().remove(&key);
|
|
59
|
+
}
|
|
60
|
+
pub fn set_or_remove_message(
|
|
61
|
+
env: &soroban_sdk::Env,
|
|
62
|
+
sender: &Address,
|
|
63
|
+
value: &Option<String>,
|
|
64
|
+
) {
|
|
65
|
+
match value.as_ref() {
|
|
66
|
+
Some(v) => Self::set_message(env, sender, v),
|
|
67
|
+
None => Self::remove_message(env, sender),
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
pub fn has_message(env: &soroban_sdk::Env, sender: &Address) -> bool {
|
|
71
|
+
let key = StorageKeys::Message(sender.clone());
|
|
72
|
+
let exists = env.storage().persistent().has(&key);
|
|
73
|
+
if exists {
|
|
74
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
75
|
+
}
|
|
76
|
+
exists
|
|
77
|
+
}
|
|
78
|
+
pub fn extend_message_ttl(
|
|
79
|
+
env: &soroban_sdk::Env,
|
|
80
|
+
sender: &Address,
|
|
81
|
+
threshold: u32,
|
|
82
|
+
extend_to: u32,
|
|
83
|
+
) {
|
|
84
|
+
let key = StorageKeys::Message(sender.clone());
|
|
85
|
+
env.storage().persistent().extend_ttl(&key, threshold, extend_to);
|
|
86
|
+
}
|
|
87
|
+
pub fn flag(env: &soroban_sdk::Env, key: &String) -> Option<bool> {
|
|
88
|
+
let key = StorageKeys::Flag(key.clone());
|
|
89
|
+
let value = env.storage().temporary().get::<_, bool>(&key);
|
|
90
|
+
value
|
|
91
|
+
}
|
|
92
|
+
pub fn set_flag(env: &soroban_sdk::Env, key: &String, value: &bool) {
|
|
93
|
+
let key = StorageKeys::Flag(key.clone());
|
|
94
|
+
env.storage().temporary().set(&key, value);
|
|
95
|
+
}
|
|
96
|
+
pub fn remove_flag(env: &soroban_sdk::Env, key: &String) {
|
|
97
|
+
let key = StorageKeys::Flag(key.clone());
|
|
98
|
+
env.storage().temporary().remove(&key);
|
|
99
|
+
}
|
|
100
|
+
pub fn set_or_remove_flag(
|
|
101
|
+
env: &soroban_sdk::Env,
|
|
102
|
+
key: &String,
|
|
103
|
+
value: &Option<bool>,
|
|
104
|
+
) {
|
|
105
|
+
match value.as_ref() {
|
|
106
|
+
Some(v) => Self::set_flag(env, key, v),
|
|
107
|
+
None => Self::remove_flag(env, key),
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
pub fn has_flag(env: &soroban_sdk::Env, key: &String) -> bool {
|
|
111
|
+
let key = StorageKeys::Flag(key.clone());
|
|
112
|
+
env.storage().temporary().has(&key)
|
|
113
|
+
}
|
|
114
|
+
pub fn extend_flag_ttl(
|
|
115
|
+
env: &soroban_sdk::Env,
|
|
116
|
+
key: &String,
|
|
117
|
+
threshold: u32,
|
|
118
|
+
extend_to: u32,
|
|
119
|
+
) {
|
|
120
|
+
let key = StorageKeys::Flag(key.clone());
|
|
121
|
+
env.storage().temporary().extend_ttl(&key, threshold, extend_to);
|
|
122
|
+
}
|
|
123
|
+
pub fn owner(env: &soroban_sdk::Env) -> Option<Address> {
|
|
124
|
+
let key = StorageKeys::Owner;
|
|
125
|
+
let value = env.storage().persistent().get::<_, Address>(&key);
|
|
126
|
+
if value.is_some() {
|
|
127
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
128
|
+
}
|
|
129
|
+
value
|
|
130
|
+
}
|
|
131
|
+
pub fn set_owner(env: &soroban_sdk::Env, value: &Address) {
|
|
132
|
+
let key = StorageKeys::Owner;
|
|
133
|
+
env.storage().persistent().set(&key, value);
|
|
134
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
135
|
+
}
|
|
136
|
+
pub fn remove_owner(env: &soroban_sdk::Env) {
|
|
137
|
+
let key = StorageKeys::Owner;
|
|
138
|
+
env.storage().persistent().remove(&key);
|
|
139
|
+
}
|
|
140
|
+
pub fn set_or_remove_owner(env: &soroban_sdk::Env, value: &Option<Address>) {
|
|
141
|
+
match value.as_ref() {
|
|
142
|
+
Some(v) => Self::set_owner(env, v),
|
|
143
|
+
None => Self::remove_owner(env),
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
pub fn has_owner(env: &soroban_sdk::Env) -> bool {
|
|
147
|
+
let key = StorageKeys::Owner;
|
|
148
|
+
let exists = env.storage().persistent().has(&key);
|
|
149
|
+
if exists {
|
|
150
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
151
|
+
}
|
|
152
|
+
exists
|
|
153
|
+
}
|
|
154
|
+
pub fn extend_owner_ttl(env: &soroban_sdk::Env, threshold: u32, extend_to: u32) {
|
|
155
|
+
let key = StorageKeys::Owner;
|
|
156
|
+
env.storage().persistent().extend_ttl(&key, threshold, extend_to);
|
|
157
|
+
}
|
|
158
|
+
pub fn custom_key_name(
|
|
159
|
+
env: &soroban_sdk::Env,
|
|
160
|
+
key: &BytesN<32>,
|
|
161
|
+
) -> Option<Option<Address>> {
|
|
162
|
+
let key = StorageKeys::OptionalData(key.clone());
|
|
163
|
+
let value = env.storage().persistent().get::<_, Option<Address>>(&key);
|
|
164
|
+
if value.is_some() {
|
|
165
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
166
|
+
}
|
|
167
|
+
value
|
|
168
|
+
}
|
|
169
|
+
pub fn set_custom_key_name(
|
|
170
|
+
env: &soroban_sdk::Env,
|
|
171
|
+
key: &BytesN<32>,
|
|
172
|
+
value: &Option<Address>,
|
|
173
|
+
) {
|
|
174
|
+
let key = StorageKeys::OptionalData(key.clone());
|
|
175
|
+
env.storage().persistent().set(&key, value);
|
|
176
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
177
|
+
}
|
|
178
|
+
pub fn remove_custom_key_name(env: &soroban_sdk::Env, key: &BytesN<32>) {
|
|
179
|
+
let key = StorageKeys::OptionalData(key.clone());
|
|
180
|
+
env.storage().persistent().remove(&key);
|
|
181
|
+
}
|
|
182
|
+
pub fn set_or_remove_custom_key_name(
|
|
183
|
+
env: &soroban_sdk::Env,
|
|
184
|
+
key: &BytesN<32>,
|
|
185
|
+
value: &Option<Option<Address>>,
|
|
186
|
+
) {
|
|
187
|
+
match value.as_ref() {
|
|
188
|
+
Some(v) => Self::set_custom_key_name(env, key, v),
|
|
189
|
+
None => Self::remove_custom_key_name(env, key),
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
pub fn has_custom_key_name(env: &soroban_sdk::Env, key: &BytesN<32>) -> bool {
|
|
193
|
+
let key = StorageKeys::OptionalData(key.clone());
|
|
194
|
+
let exists = env.storage().persistent().has(&key);
|
|
195
|
+
if exists {
|
|
196
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
197
|
+
}
|
|
198
|
+
exists
|
|
199
|
+
}
|
|
200
|
+
pub fn extend_custom_key_name_ttl(
|
|
201
|
+
env: &soroban_sdk::Env,
|
|
202
|
+
key: &BytesN<32>,
|
|
203
|
+
threshold: u32,
|
|
204
|
+
extend_to: u32,
|
|
205
|
+
) {
|
|
206
|
+
let key = StorageKeys::OptionalData(key.clone());
|
|
207
|
+
env.storage().persistent().extend_ttl(&key, threshold, extend_to);
|
|
208
|
+
}
|
|
209
|
+
pub fn temp_data(env: &soroban_sdk::Env) -> Option<u64> {
|
|
210
|
+
let key = StorageKeys::TempData;
|
|
211
|
+
let value = env.storage().temporary().get::<_, u64>(&key);
|
|
212
|
+
value
|
|
213
|
+
}
|
|
214
|
+
pub fn set_temp_data(env: &soroban_sdk::Env, value: &u64) {
|
|
215
|
+
let key = StorageKeys::TempData;
|
|
216
|
+
env.storage().temporary().set(&key, value);
|
|
217
|
+
}
|
|
218
|
+
pub fn remove_temp_data(env: &soroban_sdk::Env) {
|
|
219
|
+
let key = StorageKeys::TempData;
|
|
220
|
+
env.storage().temporary().remove(&key);
|
|
221
|
+
}
|
|
222
|
+
pub fn set_or_remove_temp_data(env: &soroban_sdk::Env, value: &Option<u64>) {
|
|
223
|
+
match value.as_ref() {
|
|
224
|
+
Some(v) => Self::set_temp_data(env, v),
|
|
225
|
+
None => Self::remove_temp_data(env),
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
pub fn has_temp_data(env: &soroban_sdk::Env) -> bool {
|
|
229
|
+
let key = StorageKeys::TempData;
|
|
230
|
+
env.storage().temporary().has(&key)
|
|
231
|
+
}
|
|
232
|
+
pub fn extend_temp_data_ttl(env: &soroban_sdk::Env, threshold: u32, extend_to: u32) {
|
|
233
|
+
let key = StorageKeys::TempData;
|
|
234
|
+
env.storage().temporary().extend_ttl(&key, threshold, extend_to);
|
|
235
|
+
}
|
|
236
|
+
pub fn primitive_key(env: &soroban_sdk::Env, key: u32) -> Option<u32> {
|
|
237
|
+
let key = StorageKeys::PrimitiveKey(key);
|
|
238
|
+
let value = env.storage().persistent().get::<_, u32>(&key);
|
|
239
|
+
if value.is_some() {
|
|
240
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
241
|
+
}
|
|
242
|
+
value
|
|
243
|
+
}
|
|
244
|
+
pub fn set_primitive_key(env: &soroban_sdk::Env, key: u32, value: &u32) {
|
|
245
|
+
let key = StorageKeys::PrimitiveKey(key);
|
|
246
|
+
env.storage().persistent().set(&key, value);
|
|
247
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
248
|
+
}
|
|
249
|
+
pub fn remove_primitive_key(env: &soroban_sdk::Env, key: u32) {
|
|
250
|
+
let key = StorageKeys::PrimitiveKey(key);
|
|
251
|
+
env.storage().persistent().remove(&key);
|
|
252
|
+
}
|
|
253
|
+
pub fn set_or_remove_primitive_key(
|
|
254
|
+
env: &soroban_sdk::Env,
|
|
255
|
+
key: u32,
|
|
256
|
+
value: &Option<u32>,
|
|
257
|
+
) {
|
|
258
|
+
match value.as_ref() {
|
|
259
|
+
Some(v) => Self::set_primitive_key(env, key, v),
|
|
260
|
+
None => Self::remove_primitive_key(env, key),
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
pub fn has_primitive_key(env: &soroban_sdk::Env, key: u32) -> bool {
|
|
264
|
+
let key = StorageKeys::PrimitiveKey(key);
|
|
265
|
+
let exists = env.storage().persistent().has(&key);
|
|
266
|
+
if exists {
|
|
267
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
268
|
+
}
|
|
269
|
+
exists
|
|
270
|
+
}
|
|
271
|
+
pub fn extend_primitive_key_ttl(
|
|
272
|
+
env: &soroban_sdk::Env,
|
|
273
|
+
key: u32,
|
|
274
|
+
threshold: u32,
|
|
275
|
+
extend_to: u32,
|
|
276
|
+
) {
|
|
277
|
+
let key = StorageKeys::PrimitiveKey(key);
|
|
278
|
+
env.storage().persistent().extend_ttl(&key, threshold, extend_to);
|
|
279
|
+
}
|
|
280
|
+
pub fn non_primitive_key(env: &soroban_sdk::Env, key: &String) -> Option<u32> {
|
|
281
|
+
let key = StorageKeys::NonPrimitiveKey(key.clone());
|
|
282
|
+
let value = env.storage().instance().get::<_, u32>(&key);
|
|
283
|
+
value
|
|
284
|
+
}
|
|
285
|
+
pub fn set_non_primitive_key(env: &soroban_sdk::Env, key: &String, value: &u32) {
|
|
286
|
+
let key = StorageKeys::NonPrimitiveKey(key.clone());
|
|
287
|
+
env.storage().instance().set(&key, value);
|
|
288
|
+
}
|
|
289
|
+
pub fn remove_non_primitive_key(env: &soroban_sdk::Env, key: &String) {
|
|
290
|
+
let key = StorageKeys::NonPrimitiveKey(key.clone());
|
|
291
|
+
env.storage().instance().remove(&key);
|
|
292
|
+
}
|
|
293
|
+
pub fn set_or_remove_non_primitive_key(
|
|
294
|
+
env: &soroban_sdk::Env,
|
|
295
|
+
key: &String,
|
|
296
|
+
value: &Option<u32>,
|
|
297
|
+
) {
|
|
298
|
+
match value.as_ref() {
|
|
299
|
+
Some(v) => Self::set_non_primitive_key(env, key, v),
|
|
300
|
+
None => Self::remove_non_primitive_key(env, key),
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
pub fn has_non_primitive_key(env: &soroban_sdk::Env, key: &String) -> bool {
|
|
304
|
+
let key = StorageKeys::NonPrimitiveKey(key.clone());
|
|
305
|
+
env.storage().instance().has(&key)
|
|
306
|
+
}
|
|
307
|
+
pub fn named_variant(
|
|
308
|
+
env: &soroban_sdk::Env,
|
|
309
|
+
first: u32,
|
|
310
|
+
second: &String,
|
|
311
|
+
third: &Address,
|
|
312
|
+
) -> Option<u32> {
|
|
313
|
+
let key = StorageKeys::NamedVariant(first, second.clone(), third.clone());
|
|
314
|
+
let value = env.storage().persistent().get::<_, u32>(&key);
|
|
315
|
+
if value.is_some() {
|
|
316
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
317
|
+
}
|
|
318
|
+
value
|
|
319
|
+
}
|
|
320
|
+
pub fn set_named_variant(
|
|
321
|
+
env: &soroban_sdk::Env,
|
|
322
|
+
first: u32,
|
|
323
|
+
second: &String,
|
|
324
|
+
third: &Address,
|
|
325
|
+
value: &u32,
|
|
326
|
+
) {
|
|
327
|
+
let key = StorageKeys::NamedVariant(first, second.clone(), third.clone());
|
|
328
|
+
env.storage().persistent().set(&key, value);
|
|
329
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
330
|
+
}
|
|
331
|
+
pub fn remove_named_variant(
|
|
332
|
+
env: &soroban_sdk::Env,
|
|
333
|
+
first: u32,
|
|
334
|
+
second: &String,
|
|
335
|
+
third: &Address,
|
|
336
|
+
) {
|
|
337
|
+
let key = StorageKeys::NamedVariant(first, second.clone(), third.clone());
|
|
338
|
+
env.storage().persistent().remove(&key);
|
|
339
|
+
}
|
|
340
|
+
pub fn set_or_remove_named_variant(
|
|
341
|
+
env: &soroban_sdk::Env,
|
|
342
|
+
first: u32,
|
|
343
|
+
second: &String,
|
|
344
|
+
third: &Address,
|
|
345
|
+
value: &Option<u32>,
|
|
346
|
+
) {
|
|
347
|
+
match value.as_ref() {
|
|
348
|
+
Some(v) => Self::set_named_variant(env, first, second, third, v),
|
|
349
|
+
None => Self::remove_named_variant(env, first, second, third),
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
pub fn has_named_variant(
|
|
353
|
+
env: &soroban_sdk::Env,
|
|
354
|
+
first: u32,
|
|
355
|
+
second: &String,
|
|
356
|
+
third: &Address,
|
|
357
|
+
) -> bool {
|
|
358
|
+
let key = StorageKeys::NamedVariant(first, second.clone(), third.clone());
|
|
359
|
+
let exists = env.storage().persistent().has(&key);
|
|
360
|
+
if exists {
|
|
361
|
+
utils::ttl_configurable::extend_persistent_ttl(env, &key);
|
|
362
|
+
}
|
|
363
|
+
exists
|
|
364
|
+
}
|
|
365
|
+
pub fn extend_named_variant_ttl(
|
|
366
|
+
env: &soroban_sdk::Env,
|
|
367
|
+
first: u32,
|
|
368
|
+
second: &String,
|
|
369
|
+
third: &Address,
|
|
370
|
+
threshold: u32,
|
|
371
|
+
extend_to: u32,
|
|
372
|
+
) {
|
|
373
|
+
let key = StorageKeys::NamedVariant(first, second.clone(), third.clone());
|
|
374
|
+
env.storage().persistent().extend_ttl(&key, threshold, extend_to);
|
|
375
|
+
}
|
|
376
|
+
pub fn cached_value(env: &soroban_sdk::Env, key: &Address) -> Option<u64> {
|
|
377
|
+
let key = StorageKeys::CachedValue(key.clone());
|
|
378
|
+
let value = env.storage().persistent().get::<_, u64>(&key);
|
|
379
|
+
value
|
|
380
|
+
}
|
|
381
|
+
pub fn set_cached_value(env: &soroban_sdk::Env, key: &Address, value: &u64) {
|
|
382
|
+
let key = StorageKeys::CachedValue(key.clone());
|
|
383
|
+
env.storage().persistent().set(&key, value);
|
|
384
|
+
}
|
|
385
|
+
pub fn remove_cached_value(env: &soroban_sdk::Env, key: &Address) {
|
|
386
|
+
let key = StorageKeys::CachedValue(key.clone());
|
|
387
|
+
env.storage().persistent().remove(&key);
|
|
388
|
+
}
|
|
389
|
+
pub fn set_or_remove_cached_value(
|
|
390
|
+
env: &soroban_sdk::Env,
|
|
391
|
+
key: &Address,
|
|
392
|
+
value: &Option<u64>,
|
|
393
|
+
) {
|
|
394
|
+
match value.as_ref() {
|
|
395
|
+
Some(v) => Self::set_cached_value(env, key, v),
|
|
396
|
+
None => Self::remove_cached_value(env, key),
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
pub fn has_cached_value(env: &soroban_sdk::Env, key: &Address) -> bool {
|
|
400
|
+
let key = StorageKeys::CachedValue(key.clone());
|
|
401
|
+
env.storage().persistent().has(&key)
|
|
402
|
+
}
|
|
403
|
+
pub fn extend_cached_value_ttl(
|
|
404
|
+
env: &soroban_sdk::Env,
|
|
405
|
+
key: &Address,
|
|
406
|
+
threshold: u32,
|
|
407
|
+
extend_to: u32,
|
|
408
|
+
) {
|
|
409
|
+
let key = StorageKeys::CachedValue(key.clone());
|
|
410
|
+
env.storage().persistent().extend_ttl(&key, threshold, extend_to);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//! Unit tests for the `StorageKind` enum methods via wrapper functions.
|
|
2
|
+
|
|
3
|
+
use crate::storage::test::{
|
|
4
|
+
storage_kind_instance_accessor, storage_kind_instance_name, storage_kind_persistent_accessor,
|
|
5
|
+
storage_kind_persistent_name, storage_kind_temporary_accessor, storage_kind_temporary_name,
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
#[test]
|
|
9
|
+
fn test_instance_name() {
|
|
10
|
+
assert_eq!(storage_kind_instance_name(), "instance");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#[test]
|
|
14
|
+
fn test_persistent_name() {
|
|
15
|
+
assert_eq!(storage_kind_persistent_name(), "persistent");
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
#[test]
|
|
19
|
+
fn test_temporary_name() {
|
|
20
|
+
assert_eq!(storage_kind_temporary_name(), "temporary");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[test]
|
|
24
|
+
fn test_instance_accessor() {
|
|
25
|
+
let accessor = storage_kind_instance_accessor();
|
|
26
|
+
assert_eq!(accessor.to_string(), "env . storage () . instance ()");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
#[test]
|
|
30
|
+
fn test_persistent_accessor() {
|
|
31
|
+
let accessor = storage_kind_persistent_accessor();
|
|
32
|
+
assert_eq!(accessor.to_string(), "env . storage () . persistent ()");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#[test]
|
|
36
|
+
fn test_temporary_accessor() {
|
|
37
|
+
let accessor = storage_kind_temporary_accessor();
|
|
38
|
+
assert_eq!(accessor.to_string(), "env . storage () . temporary ()");
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//! Shared helpers for storage macro unit tests.
|
|
2
|
+
//!
|
|
3
|
+
//! Keep these helpers scoped to the storage test module to avoid leaking
|
|
4
|
+
//! test-only utilities across the crate.
|
|
5
|
+
/// Parse the first `syn::Variant` from a single-variant `enum` token stream.
|
|
6
|
+
pub(in crate::tests::storage) fn parse_variant(input: proc_macro2::TokenStream) -> syn::Variant {
|
|
7
|
+
let item_enum: syn::ItemEnum = syn::parse2(input).expect("failed to parse enum");
|
|
8
|
+
item_enum.variants.into_iter().next().expect("no variant found")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/// Parse the attributes from the first variant in a single-variant `enum` token stream.
|
|
12
|
+
pub(in crate::tests::storage) fn parse_attrs(input: proc_macro2::TokenStream) -> Vec<syn::Attribute> {
|
|
13
|
+
let item_enum: syn::ItemEnum = syn::parse2(input).expect("failed to parse enum");
|
|
14
|
+
item_enum.variants.into_iter().next().expect("no variant found").attrs
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Normalize whitespace in a `TokenStream` for stable string comparisons.
|
|
18
|
+
pub(in crate::tests::storage) fn normalize(ts: proc_macro2::TokenStream) -> String {
|
|
19
|
+
ts.to_string().split_whitespace().collect::<Vec<_>>().join(" ")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// Convenience for tests building input via `format!(...)`.
|
|
23
|
+
pub(in crate::tests::storage) fn parse_variant_str(input: &str) -> syn::Variant {
|
|
24
|
+
parse_variant(input.parse().expect("failed to parse token stream"))
|
|
25
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
//! Unit tests for the `validate_attrs` function.
|
|
2
|
+
|
|
3
|
+
use crate::storage::test::{known_attrs_for_test, validate_attrs_for_test};
|
|
4
|
+
use quote::{format_ident, quote};
|
|
5
|
+
|
|
6
|
+
use super::test_setup::parse_attrs;
|
|
7
|
+
|
|
8
|
+
#[test]
|
|
9
|
+
fn test_accepts_known_attributes() {
|
|
10
|
+
let known_attrs = known_attrs_for_test();
|
|
11
|
+
|
|
12
|
+
for attr_name in known_attrs {
|
|
13
|
+
if *attr_name == "doc" {
|
|
14
|
+
// doc attribute uses /// syntax
|
|
15
|
+
let attrs = parse_attrs(quote! {
|
|
16
|
+
enum Test {
|
|
17
|
+
/// This is a doc comment
|
|
18
|
+
#[persistent(u32)]
|
|
19
|
+
Variant,
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
let variant_ident = format_ident!("Variant");
|
|
23
|
+
assert!(validate_attrs_for_test(&attrs, &variant_ident).is_ok(), "doc attribute should be accepted");
|
|
24
|
+
} else {
|
|
25
|
+
// Other attributes use #[attr] or #[attr(...)] syntax
|
|
26
|
+
let input = match *attr_name {
|
|
27
|
+
"instance" => quote! {
|
|
28
|
+
enum Test {
|
|
29
|
+
#[instance(u32)]
|
|
30
|
+
Variant,
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"persistent" => quote! {
|
|
34
|
+
enum Test {
|
|
35
|
+
#[persistent(u32)]
|
|
36
|
+
Variant,
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"temporary" => quote! {
|
|
40
|
+
enum Test {
|
|
41
|
+
#[temporary(u32)]
|
|
42
|
+
Variant,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"default" => quote! {
|
|
46
|
+
enum Test {
|
|
47
|
+
#[persistent(u32)]
|
|
48
|
+
#[default(0)]
|
|
49
|
+
Variant,
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"name" => quote! {
|
|
53
|
+
enum Test {
|
|
54
|
+
#[persistent(u32)]
|
|
55
|
+
#[name("custom")]
|
|
56
|
+
Variant,
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"no_ttl_extension" => quote! {
|
|
60
|
+
enum Test {
|
|
61
|
+
#[persistent(u32)]
|
|
62
|
+
#[no_ttl_extension]
|
|
63
|
+
Variant,
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
_ => continue,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
let attrs = parse_attrs(input);
|
|
70
|
+
let variant_ident = format_ident!("Variant");
|
|
71
|
+
assert!(
|
|
72
|
+
validate_attrs_for_test(&attrs, &variant_ident).is_ok(),
|
|
73
|
+
"attribute '{}' should be accepted",
|
|
74
|
+
attr_name
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
#[test]
|
|
81
|
+
fn test_rejects_unknown_attribute() {
|
|
82
|
+
let attrs = parse_attrs(quote! {
|
|
83
|
+
enum Test {
|
|
84
|
+
#[persistent(u32)]
|
|
85
|
+
#[unknown_attr]
|
|
86
|
+
Variant,
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
let variant_ident = format_ident!("Variant");
|
|
90
|
+
|
|
91
|
+
let result = validate_attrs_for_test(&attrs, &variant_ident);
|
|
92
|
+
assert!(result.is_err(), "unknown attribute should be rejected");
|
|
93
|
+
let err = result.unwrap_err();
|
|
94
|
+
assert!(
|
|
95
|
+
err.contains("unknown attribute 'unknown_attr' on variant 'Variant'"),
|
|
96
|
+
"error should mention unknown attribute"
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#[test]
|
|
101
|
+
fn test_accepts_multiple_valid_attributes() {
|
|
102
|
+
let attrs = parse_attrs(quote! {
|
|
103
|
+
enum Test {
|
|
104
|
+
/// Doc comment
|
|
105
|
+
#[persistent(u32)]
|
|
106
|
+
#[default(0)]
|
|
107
|
+
#[name("custom")]
|
|
108
|
+
Variant,
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
let variant_ident = format_ident!("Variant");
|
|
112
|
+
|
|
113
|
+
assert!(validate_attrs_for_test(&attrs, &variant_ident).is_ok(), "multiple valid attributes should be accepted");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#[test]
|
|
117
|
+
fn test_empty_attrs_is_valid() {
|
|
118
|
+
let attrs: Vec<syn::Attribute> = vec![];
|
|
119
|
+
let variant_ident = format_ident!("Variant");
|
|
120
|
+
|
|
121
|
+
// Empty attrs is valid for validate_attrs (storage type check is separate)
|
|
122
|
+
assert!(validate_attrs_for_test(&attrs, &variant_ident).is_ok());
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
#[test]
|
|
126
|
+
fn test_rejects_path_attribute() {
|
|
127
|
+
let attrs = parse_attrs(quote! {
|
|
128
|
+
enum Test {
|
|
129
|
+
#[persistent(u32)]
|
|
130
|
+
#[some::path::attr]
|
|
131
|
+
Variant,
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
let variant_ident = format_ident!("Variant");
|
|
135
|
+
|
|
136
|
+
let result = validate_attrs_for_test(&attrs, &variant_ident);
|
|
137
|
+
assert!(result.is_err(), "path attributes should be rejected");
|
|
138
|
+
}
|