@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.
Files changed (58) hide show
  1. package/Cargo.toml +21 -0
  2. package/LICENSE +23 -0
  3. package/clippy.toml +7 -0
  4. package/package.json +37 -0
  5. package/rust-toolchain.toml +4 -0
  6. package/rustfmt.toml +15 -0
  7. package/src/auth.rs +95 -0
  8. package/src/contract_ttl.rs +92 -0
  9. package/src/error.rs +43 -0
  10. package/src/lib.rs +585 -0
  11. package/src/lz_contract.rs +105 -0
  12. package/src/rbac.rs +90 -0
  13. package/src/storage.rs +522 -0
  14. package/src/tests/auth.rs +230 -0
  15. package/src/tests/contract_ttl.rs +695 -0
  16. package/src/tests/error.rs +156 -0
  17. package/src/tests/lz_contract.rs +87 -0
  18. package/src/tests/mod.rs +11 -0
  19. package/src/tests/rbac.rs +523 -0
  20. package/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +31 -0
  21. package/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +39 -0
  22. package/src/tests/snapshots/common_macros__tests__auth__snapshot_only_auth_preserves_function_signature.snap +19 -0
  23. package/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap +77 -0
  24. package/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contracttrait_code.snap +46 -0
  25. package/src/tests/snapshots/common_macros__tests__error__snapshot_generated_contract_error_code.snap +20 -0
  26. package/src/tests/snapshots/common_macros__tests__lz_contract__snapshot_generated_lz_contract_code.snap +51 -0
  27. package/src/tests/snapshots/common_macros__tests__rbac__snapshot_authorizer_role.snap +21 -0
  28. package/src/tests/snapshots/common_macros__tests__rbac__snapshot_preserve_function_signature.snap +21 -0
  29. package/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +10 -0
  30. package/src/tests/snapshots/common_macros__tests__ttl_extendable__snapshot_generated_ttl_extendable_code.snap +8 -0
  31. package/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +28 -0
  32. package/src/tests/storage/extract_fields.rs +87 -0
  33. package/src/tests/storage/gen_accessor_methods.rs +223 -0
  34. package/src/tests/storage/gen_args.rs +65 -0
  35. package/src/tests/storage/gen_enum_variant.rs +78 -0
  36. package/src/tests/storage/gen_key.rs +108 -0
  37. package/src/tests/storage/gen_params.rs +105 -0
  38. package/src/tests/storage/generate_storage.rs +410 -0
  39. package/src/tests/storage/is_primitive_type.rs +48 -0
  40. package/src/tests/storage/mod.rs +16 -0
  41. package/src/tests/storage/parse_default.rs +164 -0
  42. package/src/tests/storage/parse_name.rs +158 -0
  43. package/src/tests/storage/parse_no_ttl_extension.rs +124 -0
  44. package/src/tests/storage/parse_storage_type.rs +174 -0
  45. package/src/tests/storage/snapshots/common_macros__tests__storage__generate_storage__snapshot_generated_storage_code.snap +412 -0
  46. package/src/tests/storage/storage_kind.rs +39 -0
  47. package/src/tests/storage/test_setup.rs +25 -0
  48. package/src/tests/storage/validate_attrs.rs +138 -0
  49. package/src/tests/storage/variant_config.rs +226 -0
  50. package/src/tests/test_helpers.rs +87 -0
  51. package/src/tests/ttl_configurable.rs +34 -0
  52. package/src/tests/ttl_extendable.rs +32 -0
  53. package/src/tests/upgradeable.rs +169 -0
  54. package/src/tests/utils.rs +267 -0
  55. package/src/ttl_configurable.rs +24 -0
  56. package/src/ttl_extendable.rs +28 -0
  57. package/src/upgradeable.rs +136 -0
  58. package/src/utils.rs +56 -0
@@ -0,0 +1,230 @@
1
+ use proc_macro2::TokenStream;
2
+ use quote::quote;
3
+
4
+ use crate::tests::test_helpers::{assert_panics_contains, filter_item_inputs_excluding_labels};
5
+
6
+ // ============================================
7
+ // Snapshot Test: Ownable Code Generation
8
+ // ============================================
9
+
10
+ #[test]
11
+ fn snapshot_generated_ownable_code() {
12
+ let input = quote! {
13
+ pub struct MyContract;
14
+ };
15
+ let result = crate::auth::generate_ownable_impl(input);
16
+ let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
17
+
18
+ let input = quote! {
19
+ #[derive(Clone, Debug)]
20
+ pub struct MyContract<T>
21
+ where
22
+ T: Clone,
23
+ {
24
+ pub value: T,
25
+ }
26
+ };
27
+ let result = crate::auth::generate_ownable_impl(input);
28
+ let formatted_with_generics_and_fields =
29
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
30
+
31
+ let combined = format!(
32
+ "// === Unit struct ===\n\n{}\n\n// === Generics + fields ===\n\n{}",
33
+ formatted, formatted_with_generics_and_fields
34
+ );
35
+
36
+ insta::assert_snapshot!(combined);
37
+ }
38
+
39
+ // ============================================
40
+ // Snapshot Test: MultiSig Code Generation
41
+ // ============================================
42
+
43
+ #[test]
44
+ fn snapshot_generated_multisig_code() {
45
+ let input = quote! {
46
+ pub struct MyContract;
47
+ };
48
+ let result = crate::auth::generate_multisig_impl(input);
49
+ let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
50
+
51
+ let input = quote! {
52
+ #[derive(Copy, Clone)]
53
+ pub struct MyContract(pub u32);
54
+ };
55
+ let result = crate::auth::generate_multisig_impl(input);
56
+ let formatted_with_tuple_struct =
57
+ prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
58
+
59
+ let combined = format!(
60
+ "// === Unit struct ===\n\n{}\n\n// === Tuple struct ===\n\n{}",
61
+ formatted, formatted_with_tuple_struct
62
+ );
63
+
64
+ insta::assert_snapshot!(combined);
65
+ }
66
+
67
+ // ============================================
68
+ // Snapshot Test: Only Auth Macro
69
+ // ============================================
70
+
71
+ #[test]
72
+ fn snapshot_only_auth_preserves_function_signature() {
73
+ // Test with borrowed Env (&Env) - should use env directly
74
+ let input_borrowed = quote! {
75
+ pub(crate) async fn admin_action<T: Clone>(env: &Env, value: T) -> Result<T, Error> {
76
+ Ok(value.clone())
77
+ }
78
+ };
79
+ let result_borrowed = crate::auth::prepend_only_auth_check(input_borrowed);
80
+ let formatted_borrowed =
81
+ prettyplease::unparse(&syn::parse2::<syn::File>(result_borrowed).expect("failed to parse generated code"));
82
+
83
+ // Test with owned Env - should produce &env reference in the generated code
84
+ let input_owned = quote! {
85
+ pub(crate) async fn admin_action<T: Clone>(env: Env, value: T) -> Result<T, Error> {
86
+ Ok(value.clone())
87
+ }
88
+ };
89
+ let result_owned = crate::auth::prepend_only_auth_check(input_owned);
90
+ let formatted_owned =
91
+ prettyplease::unparse(&syn::parse2::<syn::File>(result_owned).expect("failed to parse generated code"));
92
+
93
+ // Combine all for single snapshot
94
+ let combined = format!(
95
+ "// === Borrowed Env (&Env) ===\n\n{}\n\n// === Owned Env (Env) ===\n\n{}",
96
+ formatted_borrowed, formatted_owned
97
+ );
98
+
99
+ insta::assert_snapshot!(combined);
100
+ }
101
+
102
+ // ============================================
103
+ // prepend_only_auth_check Tests
104
+ // ============================================
105
+
106
+ /// Helper function to verify that the auth check is correctly inserted at the beginning of a function.
107
+ fn assert_auth_check_inserted(input: TokenStream, expected_env_ref: &str, test_name: &str) {
108
+ let result_tokens = crate::auth::prepend_only_auth_check(input);
109
+ let output_fn: syn::ItemFn =
110
+ syn::parse2(result_tokens).unwrap_or_else(|e| panic!("{}: failed to parse output function: {}", test_name, e));
111
+
112
+ assert!(!output_fn.block.stmts.is_empty(), "{}: function body should contain at least one statement", test_name);
113
+
114
+ let first_stmt = &output_fn.block.stmts[0];
115
+ let expected_stmt = format!("utils::auth::require_auth::<Self>({});", expected_env_ref);
116
+ let actual_stmt = quote::quote!(#first_stmt).to_string().replace(" ", "");
117
+
118
+ assert_eq!(
119
+ actual_stmt, expected_stmt,
120
+ "{}: expected auth check statement '{}', but got '{}'",
121
+ test_name, expected_stmt, actual_stmt
122
+ );
123
+ }
124
+
125
+ #[test]
126
+ fn test_only_auth_inserts_correct_code_at_the_beginning() {
127
+ // (description, input, expected_env_ref)
128
+ // Owned Env should produce &env, reference Env should produce env directly
129
+ let test_cases = vec![
130
+ ("Env by value", quote! { pub fn f(my_custom_env: Env) {} }, "&my_custom_env"),
131
+ ("Env not first param (ref)", quote! { pub fn f(x: u32, my_custom_env: &Env) {} }, "my_custom_env"),
132
+ ("Env after receiver", quote! { pub fn f(&self, my_custom_env: &Env) {} }, "my_custom_env"),
133
+ ("Env after mut receiver", quote! { pub fn f(&mut self, my_custom_env: &Env) {} }, "my_custom_env"),
134
+ ("Env after value receiver", quote! { pub fn f(self, my_custom_env: &Env) {} }, "my_custom_env"),
135
+ ("Env after mut value receiver", quote! { pub fn f(mut self, my_custom_env: &Env) {} }, "my_custom_env"),
136
+ ("Env with lifetime", quote! { pub fn f<'a>(my_custom_env: &'a Env) {} }, "my_custom_env"),
137
+ ("Env with mut ref", quote! { pub fn f(my_custom_env: &mut Env) {} }, "my_custom_env"),
138
+ ("Env with mut binding", quote! { pub fn f(mut my_custom_env: Env) {} }, "&my_custom_env"),
139
+ ("Ref Env with mut binding", quote! { pub fn f(mut my_custom_env: &Env) {} }, "my_custom_env"),
140
+ (
141
+ "Qualified path (soroban_sdk::Env)",
142
+ quote! { pub fn f(my_custom_env: soroban_sdk::Env) {} },
143
+ "&my_custom_env",
144
+ ),
145
+ ("Reference to qualified path", quote! { pub fn f(my_custom_env: &soroban_sdk::Env) {} }, "my_custom_env"),
146
+ (
147
+ "Leading :: qualified path (::soroban_sdk::Env)",
148
+ quote! { pub fn f(my_custom_env: ::soroban_sdk::Env) {} },
149
+ "&my_custom_env",
150
+ ),
151
+ ("Leading :: ref qualified path", quote! { pub fn f(my_custom_env: &::soroban_sdk::Env) {} }, "my_custom_env"),
152
+ (
153
+ "Mut reference to qualified path",
154
+ quote! { pub fn f(my_custom_env: &mut soroban_sdk::Env) {} },
155
+ "my_custom_env",
156
+ ),
157
+ ("Nested reference (&&Env)", quote! { pub fn f(my_custom_env: &&Env) {} }, "my_custom_env"),
158
+ ("Multiple Env params picks first", quote! { pub fn f(first_env: Env, second_env: Env) {} }, "&first_env"),
159
+ ];
160
+
161
+ for (description, input, expected_env_ref) in test_cases {
162
+ assert_auth_check_inserted(input, expected_env_ref, description);
163
+ }
164
+ }
165
+
166
+ #[test]
167
+ fn test_only_auth_requires_env_param() {
168
+ // ============================================
169
+ // Error Cases: Missing/Invalid Env Argument Patterns
170
+ // ============================================
171
+ let cases = vec![
172
+ ("no Env param", quote! { pub fn admin_action(value: u32) {} }),
173
+ // Tuple pattern destructuring is not supported - must use simple identifier
174
+ ("tuple pattern", quote! { pub fn admin_action((env, _other): (&Env, u32)) {} }),
175
+ // Wildcard pattern (_) is not supported - must use named identifier
176
+ ("wildcard pattern", quote! { pub fn admin_action(_: &Env) {} }),
177
+ // Struct destructuring pattern is not supported
178
+ ("struct pattern", quote! { pub fn admin_action(Env { .. }: Env) {} }),
179
+ // Non-Env wrapper/container types are not recognized as Env params.
180
+ ("Option<Env>", quote! { pub fn admin_action(env: Option<Env>) {} }),
181
+ ("Option<&Env>", quote! { pub fn admin_action(env: Option<&Env>) {} }),
182
+ ("Vec<Env>", quote! { pub fn admin_action(env: Vec<Env>) {} }),
183
+ ("Box<Env>", quote! { pub fn admin_action(env: Box<Env>) {} }),
184
+ ];
185
+
186
+ for (case, input) in cases {
187
+ assert_panics_contains(case, "function must have an Env argument", || {
188
+ crate::auth::prepend_only_auth_check(input.clone());
189
+ });
190
+ }
191
+ }
192
+
193
+ // ============================================
194
+ // Error Cases: only_auth macro non-function input
195
+ // ============================================
196
+
197
+ #[test]
198
+ fn test_only_auth_rejects_non_function_inputs() {
199
+ for (case, input) in filter_item_inputs_excluding_labels(&["function"]) {
200
+ assert_panics_contains(case, "failed to parse function", || {
201
+ crate::auth::prepend_only_auth_check(input.clone());
202
+ });
203
+ }
204
+ }
205
+
206
+ // ============================================
207
+ // Error Cases: ownable macro non-struct input
208
+ // ============================================
209
+
210
+ #[test]
211
+ fn test_ownable_rejects_non_struct_inputs() {
212
+ for (case, input) in filter_item_inputs_excluding_labels(&["struct"]) {
213
+ assert_panics_contains(case, "failed to parse struct", || {
214
+ crate::auth::generate_ownable_impl(input.clone());
215
+ });
216
+ }
217
+ }
218
+
219
+ // ============================================
220
+ // Error Cases: multisig macro non-struct input
221
+ // ============================================
222
+
223
+ #[test]
224
+ fn test_multisig_rejects_non_struct_inputs() {
225
+ for (case, input) in filter_item_inputs_excluding_labels(&["struct"]) {
226
+ assert_panics_contains(case, "failed to parse struct", || {
227
+ crate::auth::generate_multisig_impl(input.clone());
228
+ });
229
+ }
230
+ }