@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.10

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 (239) hide show
  1. package/.turbo/turbo-build.log +443 -302
  2. package/.turbo/turbo-lint.log +118 -96
  3. package/.turbo/turbo-test.log +853 -731
  4. package/Cargo.lock +120 -37
  5. package/Cargo.toml +8 -5
  6. package/contracts/common-macros/src/contract_impl.rs +44 -0
  7. package/contracts/common-macros/src/lib.rs +86 -40
  8. package/contracts/common-macros/src/ownable.rs +24 -32
  9. package/contracts/common-macros/src/storage.rs +95 -120
  10. package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
  11. package/contracts/common-macros/src/tests/mod.rs +9 -0
  12. package/contracts/common-macros/src/tests/ownable.rs +151 -0
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
  18. package/contracts/common-macros/src/tests/storage.rs +485 -0
  19. package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
  20. package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
  21. package/contracts/common-macros/src/ttl_configurable.rs +31 -14
  22. package/contracts/common-macros/src/utils.rs +27 -0
  23. package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
  24. package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
  25. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
  26. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
  27. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
  28. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
  29. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
  30. package/contracts/endpoint-v2/src/lib.rs +6 -5
  31. package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
  32. package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
  33. package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
  34. package/contracts/endpoint-v2/src/storage.rs +10 -7
  35. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
  36. package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
  37. package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
  38. package/contracts/endpoint-v2/src/util.rs +8 -2
  39. package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
  40. package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
  41. package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
  42. package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
  43. package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
  44. package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
  45. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
  46. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
  47. package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
  48. package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
  49. package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
  50. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
  51. package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
  52. package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
  53. package/contracts/message-libs/treasury/src/storage.rs +1 -2
  54. package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
  55. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
  56. package/contracts/message-libs/treasury/src/treasury.rs +18 -21
  57. package/contracts/message-libs/uln-302/Cargo.toml +1 -0
  58. package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
  59. package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
  60. package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
  61. package/contracts/message-libs/uln-302/src/lib.rs +5 -4
  62. package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
  63. package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
  64. package/contracts/message-libs/uln-302/src/storage.rs +1 -2
  65. package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
  66. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
  67. package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
  68. package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
  69. package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
  70. package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
  71. package/contracts/oapp-macros/Cargo.toml +2 -8
  72. package/contracts/oapp-macros/src/lib.rs +57 -311
  73. package/contracts/oapp-macros/src/oapp_core.rs +23 -32
  74. package/contracts/oapp-macros/src/oapp_full.rs +8 -2
  75. package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
  76. package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
  77. package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
  78. package/contracts/oapp-macros/src/util.rs +14 -10
  79. package/contracts/oapps/counter/Cargo.toml +2 -1
  80. package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
  81. package/contracts/oapps/counter/src/codec.rs +8 -9
  82. package/contracts/oapps/counter/src/counter.rs +156 -147
  83. package/contracts/oapps/counter/src/storage.rs +1 -2
  84. package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
  85. package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
  86. package/contracts/oapps/oapp/Cargo.toml +1 -0
  87. package/contracts/oapps/oapp/src/errors.rs +1 -1
  88. package/contracts/oapps/oapp/src/lib.rs +3 -0
  89. package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
  90. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
  91. package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
  92. package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
  93. package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
  94. package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
  95. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
  96. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
  97. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
  98. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
  99. package/contracts/oapps/oft/Cargo.toml +27 -0
  100. package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
  101. package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
  102. package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
  103. package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
  104. package/contracts/oapps/oft/src/codec/mod.rs +2 -0
  105. package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
  106. package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
  107. package/contracts/oapps/oft/src/constants.rs +5 -0
  108. package/contracts/oapps/oft/src/errors.rs +8 -0
  109. package/contracts/oapps/oft/src/events.rs +19 -0
  110. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
  111. package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
  112. package/contracts/oapps/oft/src/lib.rs +22 -0
  113. package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
  114. package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
  115. package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
  116. package/contracts/oapps/oft/src/oft.rs +320 -0
  117. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
  118. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
  119. package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
  120. package/contracts/oapps/oft/src/storage.rs +11 -0
  121. package/contracts/oapps/oft/src/tests/mod.rs +13 -0
  122. package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
  123. package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
  124. package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
  125. package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
  126. package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
  127. package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
  128. package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
  129. package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
  130. package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
  131. package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
  132. package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
  133. package/contracts/oapps/oft/src/types.rs +38 -0
  134. package/contracts/oapps/oft/src/utils.rs +67 -0
  135. package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
  136. package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
  137. package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
  138. package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
  139. package/contracts/utils/src/buffer_reader.rs +8 -9
  140. package/contracts/utils/src/buffer_writer.rs +11 -5
  141. package/contracts/utils/src/errors.rs +5 -5
  142. package/contracts/utils/src/ownable.rs +14 -6
  143. package/contracts/utils/src/testing_utils.rs +11 -1
  144. package/contracts/utils/src/tests/buffer_reader.rs +491 -730
  145. package/contracts/utils/src/tests/buffer_writer.rs +336 -148
  146. package/contracts/utils/src/tests/bytes_ext.rs +125 -40
  147. package/contracts/utils/src/tests/mod.rs +3 -0
  148. package/contracts/utils/src/tests/ownable.rs +379 -27
  149. package/contracts/utils/src/tests/test_helper.rs +47 -0
  150. package/contracts/utils/src/tests/testing_utils.rs +555 -0
  151. package/contracts/utils/src/tests/ttl.rs +421 -0
  152. package/contracts/utils/src/ttl.rs +29 -89
  153. package/contracts/workers/dvn/Cargo.toml +31 -0
  154. package/contracts/workers/dvn/src/auth.rs +66 -0
  155. package/contracts/workers/dvn/src/dvn.rs +143 -0
  156. package/contracts/workers/dvn/src/errors.rs +21 -0
  157. package/contracts/workers/dvn/src/events.rs +19 -0
  158. package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
  159. package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
  160. package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
  161. package/contracts/workers/dvn/src/lib.rs +24 -0
  162. package/contracts/workers/dvn/src/multisig.rs +127 -0
  163. package/contracts/workers/dvn/src/storage.rs +35 -0
  164. package/contracts/workers/dvn/src/tests/auth.rs +237 -0
  165. package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
  166. package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
  167. package/contracts/workers/dvn/src/tests/mod.rs +5 -0
  168. package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
  169. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
  170. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
  171. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
  172. package/contracts/workers/dvn/src/tests/setup.rs +109 -0
  173. package/contracts/workers/dvn/src/types.rs +26 -0
  174. package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
  175. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
  176. package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
  177. package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
  178. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
  179. package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
  180. package/contracts/workers/executor/Cargo.toml +10 -7
  181. package/contracts/workers/executor/src/errors.rs +8 -0
  182. package/contracts/workers/executor/src/events.rs +4 -7
  183. package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
  184. package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
  185. package/contracts/workers/executor/src/lib.rs +16 -7
  186. package/contracts/workers/executor/src/lz_executor.rs +308 -0
  187. package/contracts/workers/executor/src/storage.rs +24 -16
  188. package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
  189. package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
  190. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
  191. package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
  192. package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
  193. package/contracts/workers/executor-helper/Cargo.toml +29 -0
  194. package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
  195. package/contracts/workers/executor-helper/src/lib.rs +11 -0
  196. package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
  197. package/contracts/workers/worker/src/errors.rs +24 -0
  198. package/contracts/workers/worker/src/events.rs +62 -0
  199. package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
  200. package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
  201. package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
  202. package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
  203. package/contracts/workers/worker/src/lib.rs +14 -0
  204. package/contracts/workers/worker/src/storage.rs +63 -0
  205. package/contracts/workers/worker/src/worker.rs +459 -0
  206. package/package.json +3 -3
  207. package/sdk/dist/generated/bml.d.ts +88 -17
  208. package/sdk/dist/generated/bml.js +62 -16
  209. package/sdk/dist/generated/counter.d.ts +281 -102
  210. package/sdk/dist/generated/counter.js +93 -41
  211. package/sdk/dist/generated/endpoint.d.ts +128 -105
  212. package/sdk/dist/generated/endpoint.js +47 -45
  213. package/sdk/dist/generated/sml.d.ts +212 -69
  214. package/sdk/dist/generated/sml.js +103 -53
  215. package/sdk/dist/generated/uln302.d.ts +270 -173
  216. package/sdk/dist/generated/uln302.js +112 -64
  217. package/sdk/package.json +11 -11
  218. package/sdk/test/index.test.ts +147 -42
  219. package/sdk/test/suites/constants.ts +7 -3
  220. package/sdk/test/suites/deploy.ts +65 -42
  221. package/sdk/test/suites/localnet.ts +2 -2
  222. package/sdk/test/suites/scan.ts +28 -25
  223. package/sdk/test/utils.ts +199 -0
  224. package/sdk/tsconfig.json +93 -95
  225. package/tools/ts-bindings-gen/src/main.rs +2 -0
  226. package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
  227. package/contracts/common-macros/src/tests.rs +0 -287
  228. package/contracts/oapp-macros/tests/test_macros.rs +0 -522
  229. package/contracts/workers/executor/src/executor.rs +0 -347
  230. package/contracts/workers/executor/src/interfaces/types.rs +0 -51
  231. package/contracts/workers/worker-common/src/constants.rs +0 -17
  232. package/contracts/workers/worker-common/src/errors.rs +0 -6
  233. package/contracts/workers/worker-common/src/events.rs +0 -34
  234. package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
  235. package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
  236. package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
  237. package/contracts/workers/worker-common/src/lib.rs +0 -19
  238. package/contracts/workers/worker-common/src/storage.rs +0 -32
  239. package/contracts/workers/worker-common/src/worker_common.rs +0 -166
@@ -0,0 +1,45 @@
1
+ ---
2
+ source: contracts/common-macros/src/tests/ttl_configurable.rs
3
+ assertion_line: 20
4
+ expression: formatted
5
+ ---
6
+ #[common_macros::ownable]
7
+ pub struct MyContract {
8
+ some_field: u32,
9
+ }
10
+ use utils::ttl::TtlConfigurable as _;
11
+ #[soroban_sdk::contractimpl]
12
+ impl utils::ttl::TtlConfigurable for MyContract {
13
+ #[common_macros::only_owner]
14
+ fn set_ttl_configs(
15
+ env: &soroban_sdk::Env,
16
+ instance: &Option<utils::ttl::TtlConfig>,
17
+ persistent: &Option<utils::ttl::TtlConfig>,
18
+ ) {
19
+ utils::ttl::DefaultTtlConfigurable::set_ttl_configs(env, instance, persistent);
20
+ }
21
+ fn ttl_configs(
22
+ env: &soroban_sdk::Env,
23
+ ) -> (Option<utils::ttl::TtlConfig>, Option<utils::ttl::TtlConfig>) {
24
+ utils::ttl::DefaultTtlConfigurable::ttl_configs(env)
25
+ }
26
+ #[common_macros::only_owner]
27
+ fn freeze_ttl_configs(env: &soroban_sdk::Env) {
28
+ utils::ttl::DefaultTtlConfigurable::freeze_ttl_configs(env);
29
+ }
30
+ fn is_ttl_configs_frozen(env: &soroban_sdk::Env) -> bool {
31
+ utils::ttl::DefaultTtlConfigurable::is_ttl_configs_frozen(env)
32
+ }
33
+ }
34
+ #[soroban_sdk::contractimpl]
35
+ impl MyContract {
36
+ /// Extends the instance TTL.
37
+ ///
38
+ /// # Arguments
39
+ ///
40
+ /// * `threshold` - The threshold to extend the TTL.
41
+ /// * `extend_to` - The TTL to extend to.
42
+ pub fn extend_instance_ttl(env: &soroban_sdk::Env, threshold: u32, extend_to: u32) {
43
+ env.storage().instance().extend_ttl(threshold, extend_to);
44
+ }
45
+ }
@@ -0,0 +1,485 @@
1
+ use quote::quote;
2
+
3
+ use crate::tests::test_helpers::{assert_panics_contains, non_enum_item_inputs};
4
+
5
+ #[test]
6
+ fn test_non_enum_input() {
7
+ for (case, input) in non_enum_item_inputs() {
8
+ assert_panics_contains(case, "failed to parse enum", || {
9
+ crate::storage::generate_storage(quote! {}, input.clone());
10
+ });
11
+ }
12
+ }
13
+
14
+ #[test]
15
+ fn test_tuple_variant_rejected() {
16
+ let cases = vec![
17
+ (
18
+ "instance tuple variant",
19
+ quote! {
20
+ enum TestEnum {
21
+ #[instance(u32)]
22
+ TupleVariant(String, u32),
23
+ }
24
+ },
25
+ ),
26
+ (
27
+ "persistent tuple variant",
28
+ quote! {
29
+ enum TestEnum {
30
+ #[persistent(u32)]
31
+ TupleVariant(String, u32),
32
+ }
33
+ },
34
+ ),
35
+ ];
36
+
37
+ for (case, input) in cases {
38
+ assert_panics_contains(case, "only unit variants or named fields are supported", || {
39
+ crate::storage::generate_storage(quote! {}, input.clone());
40
+ });
41
+ }
42
+ }
43
+
44
+ #[test]
45
+ fn test_attribute_errors() {
46
+ let cases_storage_type = vec![
47
+ (
48
+ "missing storage type",
49
+ "storage type must be specified exactly once",
50
+ quote! {
51
+ enum TestEnum { Counter }
52
+ },
53
+ ),
54
+ (
55
+ "multiple storage types",
56
+ "storage type must be specified exactly once",
57
+ quote! {
58
+ enum TestEnum {
59
+ #[instance(u32)]
60
+ #[persistent(u32)]
61
+ Counter,
62
+ }
63
+ },
64
+ ),
65
+ (
66
+ "missing type param",
67
+ "failed to parse storage variant for Counter",
68
+ quote! {
69
+ enum TestEnum {
70
+ #[instance]
71
+ Counter,
72
+ }
73
+ },
74
+ ),
75
+ (
76
+ "invalid type param",
77
+ "failed to parse storage variant for",
78
+ quote! {
79
+ enum TestEnum {
80
+ #[persistent(u32, String)]
81
+ Counter,
82
+ }
83
+ },
84
+ ),
85
+ ];
86
+
87
+ for (case, expected, input) in cases_storage_type {
88
+ assert_panics_contains(case, expected, || {
89
+ crate::storage::generate_storage(quote! {}, input.clone());
90
+ });
91
+ }
92
+
93
+ let cases_default = vec![
94
+ (
95
+ "multiple defaults",
96
+ "multiple default values specified",
97
+ quote! {
98
+ enum TestEnum {
99
+ #[persistent(u32)]
100
+ #[default(0)]
101
+ #[default(1)]
102
+ Counter,
103
+ }
104
+ },
105
+ ),
106
+ (
107
+ "invalid default value",
108
+ "failed to parse default value",
109
+ quote! {
110
+ enum TestEnum {
111
+ #[persistent(u32)]
112
+ #[default(!@#$%)]
113
+ Counter,
114
+ }
115
+ },
116
+ ),
117
+ (
118
+ "default without parens",
119
+ "failed to parse default value",
120
+ quote! {
121
+ enum TestEnum {
122
+ #[persistent(u32)]
123
+ #[default]
124
+ Counter,
125
+ }
126
+ },
127
+ ),
128
+ (
129
+ "default with empty parens",
130
+ "failed to parse default value",
131
+ quote! {
132
+ enum TestEnum {
133
+ #[persistent(u32)]
134
+ #[default()]
135
+ Counter,
136
+ }
137
+ },
138
+ ),
139
+ ];
140
+
141
+ for (case, expected, input) in cases_default {
142
+ assert_panics_contains(case, expected, || {
143
+ crate::storage::generate_storage(quote! {}, input.clone());
144
+ });
145
+ }
146
+
147
+ let cases_name = vec![
148
+ (
149
+ "multiple name attrs",
150
+ "multiple name attributes specified",
151
+ quote! {
152
+ enum TestEnum {
153
+ #[persistent(u32)]
154
+ #[name("foo")]
155
+ #[name("bar")]
156
+ Counter,
157
+ }
158
+ },
159
+ ),
160
+ (
161
+ "invalid name attr",
162
+ "failed to parse name attribute",
163
+ quote! {
164
+ enum TestEnum {
165
+ #[persistent(u32)]
166
+ #[name(123)]
167
+ Counter,
168
+ }
169
+ },
170
+ ),
171
+ (
172
+ "name without parens",
173
+ "failed to parse name attribute",
174
+ quote! {
175
+ enum TestEnum {
176
+ #[persistent(u32)]
177
+ #[name]
178
+ Counter,
179
+ }
180
+ },
181
+ ),
182
+ (
183
+ "name with empty parens",
184
+ "failed to parse name attribute",
185
+ quote! {
186
+ enum TestEnum {
187
+ #[persistent(u32)]
188
+ #[name()]
189
+ Counter,
190
+ }
191
+ },
192
+ ),
193
+ ];
194
+
195
+ for (case, expected, input) in cases_name {
196
+ assert_panics_contains(case, expected, || {
197
+ crate::storage::generate_storage(quote! {}, input.clone());
198
+ });
199
+ }
200
+
201
+ assert_panics_contains("unknown attribute", "unknown attribute", || {
202
+ let input = quote! {
203
+ enum TestEnum {
204
+ #[persistent(u32)]
205
+ #[unknown_attr]
206
+ Counter,
207
+ }
208
+ };
209
+ crate::storage::generate_storage(quote! {}, input);
210
+ });
211
+
212
+ // Test #[no_ttl_extension] validation
213
+ let cases_no_ttl = vec![
214
+ (
215
+ "multiple no_ttl_extension",
216
+ "multiple #[no_ttl_extension]",
217
+ quote! {
218
+ enum TestEnum {
219
+ #[persistent(u32)]
220
+ #[no_ttl_extension]
221
+ #[no_ttl_extension]
222
+ Counter,
223
+ }
224
+ },
225
+ ),
226
+ (
227
+ "triple no_ttl_extension",
228
+ "multiple #[no_ttl_extension]",
229
+ quote! {
230
+ enum TestEnum {
231
+ #[persistent(u32)]
232
+ #[no_ttl_extension]
233
+ #[no_ttl_extension]
234
+ #[no_ttl_extension]
235
+ Counter,
236
+ }
237
+ },
238
+ ),
239
+ (
240
+ "no_ttl_extension on instance",
241
+ "can only be used with #[persistent",
242
+ quote! {
243
+ enum TestEnum {
244
+ #[instance(u32)]
245
+ #[no_ttl_extension]
246
+ Counter,
247
+ }
248
+ },
249
+ ),
250
+ (
251
+ "no_ttl_extension on instance with default",
252
+ "can only be used with #[persistent",
253
+ quote! {
254
+ enum TestEnum {
255
+ #[instance(u32)]
256
+ #[default(0)]
257
+ #[no_ttl_extension]
258
+ Counter,
259
+ }
260
+ },
261
+ ),
262
+ (
263
+ "no_ttl_extension before instance storage type",
264
+ "can only be used with #[persistent",
265
+ quote! {
266
+ enum TestEnum {
267
+ #[no_ttl_extension]
268
+ #[instance(u32)]
269
+ Counter,
270
+ }
271
+ },
272
+ ),
273
+ (
274
+ "no_ttl_extension on temporary",
275
+ "can only be used with #[persistent",
276
+ quote! {
277
+ enum TestEnum {
278
+ #[temporary(u32)]
279
+ #[no_ttl_extension]
280
+ Counter,
281
+ }
282
+ },
283
+ ),
284
+ (
285
+ "no_ttl_extension before temporary storage type",
286
+ "can only be used with #[persistent",
287
+ quote! {
288
+ enum TestEnum {
289
+ #[no_ttl_extension]
290
+ #[temporary(u32)]
291
+ Counter,
292
+ }
293
+ },
294
+ ),
295
+ (
296
+ "no_ttl_extension on instance in multi-variant enum",
297
+ "can only be used with #[persistent",
298
+ quote! {
299
+ enum TestEnum {
300
+ #[persistent(u32)]
301
+ ValidVariant,
302
+
303
+ #[instance(u32)]
304
+ #[no_ttl_extension]
305
+ InvalidVariant,
306
+ }
307
+ },
308
+ ),
309
+ ];
310
+
311
+ for (case, expected, input) in cases_no_ttl {
312
+ assert_panics_contains(case, expected, || {
313
+ crate::storage::generate_storage(quote! {}, input.clone());
314
+ });
315
+ }
316
+
317
+ // Test that #[storage] does not accept arguments
318
+ let cases_attr = vec![
319
+ ("unknown arg", "does not accept arguments", quote! { unknown }),
320
+ ("key-value arg", "does not accept arguments", quote! { unknown = SomeType }),
321
+ ("function-like arg", "does not accept arguments", quote! { foo(bar) }),
322
+ ];
323
+ let input = quote! {
324
+ enum TestEnum {
325
+ #[instance(u32)]
326
+ Counter,
327
+ }
328
+ };
329
+
330
+ for (case, expected, attr) in cases_attr {
331
+ assert_panics_contains(case, expected, || {
332
+ crate::storage::generate_storage(attr.clone(), input.clone());
333
+ });
334
+ }
335
+ }
336
+
337
+ // ============================================
338
+ // Valid Cases: Snapshot Tests for Generated Code
339
+ // ============================================
340
+
341
+ /// Comprehensive snapshot test covering all storage macro features:
342
+ /// - All storage types: instance, persistent, temporary
343
+ /// - Unit variants and named field variants
344
+ /// - Default values (with and without)
345
+ /// - TTL extension control (TTL extended by default for persistent storage, opt-out with #[no_ttl_extension])
346
+ /// - Custom name attribute
347
+ /// - Function naming rules: snake_case conversion (UserBalance -> user_balance) and custom name override
348
+ /// - Primitive type detection: u32/i64/bool passed by value, u8/usize/String/Vec/Address passed by reference
349
+ /// - Clone behavior: primitive types not cloned, non-primitive types cloned in key construction
350
+ /// - Field extraction: Unit variants have no fields, Named variants extract fields in order
351
+ /// - Doc comments and visibility
352
+ #[test]
353
+ fn snapshot_generated_storage_code() {
354
+ let input = quote! {
355
+ /// Enum-level doc comment
356
+ pub enum StorageKeys {
357
+ /// Instance storage with default value (no auto TTL for instance)
358
+ #[instance(u32)]
359
+ #[default(0)]
360
+ Counter,
361
+
362
+ /// Persistent storage with named field and default (has auto TTL by default)
363
+ #[persistent(String)]
364
+ #[default("hello".to_string())]
365
+ Message { sender: Address },
366
+
367
+ /// Temporary storage (no auto TTL for temporary)
368
+ #[temporary(bool)]
369
+ Flag { key: String },
370
+
371
+ /// Persistent storage with multiple fields (no default)
372
+ #[persistent(Vec<u8>)]
373
+ Data { id: u64, name: String },
374
+
375
+ /// Persistent storage without fields or default
376
+ #[persistent(Address)]
377
+ Owner,
378
+
379
+ /// Persistent storage with custom name override
380
+ #[persistent(Option<Address>)]
381
+ #[name("custom_key_name")]
382
+ OptionalData { key: BytesN<32> },
383
+
384
+ /// Temporary storage (no auto TTL for temporary)
385
+ #[temporary(u64)]
386
+ TempData,
387
+
388
+ /// Test snake_case naming: UserBalance -> user_balance
389
+ #[persistent(u32)]
390
+ UserBalance { user: Address },
391
+
392
+ /// Test custom name override: #[name("custom")] -> custom
393
+ #[persistent(u32)]
394
+ #[name("custom")]
395
+ AnotherVariant { key: Address },
396
+
397
+ /// Test primitive types: passed by value, not cloned
398
+ #[persistent(u32)]
399
+ U32Value { key: u32 },
400
+ #[persistent(i64)]
401
+ I64Value { key: i64 },
402
+ #[persistent(bool)]
403
+ BoolValue { key: bool },
404
+
405
+ /// Test non-primitive types: passed by reference, cloned
406
+ #[persistent(u32)]
407
+ U8Value { key: u8 },
408
+ #[persistent(u32)]
409
+ UsizeValue { key: usize },
410
+ #[persistent(String)]
411
+ StringValue { key: String },
412
+ #[persistent(Vec<u32>)]
413
+ VecValue { key: Vec<u32> },
414
+ #[persistent(Address)]
415
+ AddressValue { key: Address },
416
+
417
+ /// Test Unit variant: no fields
418
+ #[persistent(u32)]
419
+ UnitVariant,
420
+
421
+ /// Test Named variant: fields extracted in order
422
+ #[persistent(u32)]
423
+ NamedVariant { first: u32, second: String, third: Address },
424
+
425
+ /// Test #[no_ttl_extension] opt-out for persistent storage
426
+ #[persistent(u64)]
427
+ #[no_ttl_extension]
428
+ CachedValue { key: Address },
429
+ }
430
+ };
431
+
432
+ let result = crate::storage::generate_storage(quote! {}, input);
433
+ let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
434
+
435
+ insta::assert_snapshot!(formatted);
436
+ }
437
+
438
+ // ============================================
439
+ // is_primitive_type Unit Tests
440
+ // ============================================
441
+
442
+ #[test]
443
+ fn test_is_primitive_type_recognizes_primitive_types() {
444
+ let primitives = ["u32", "i32", "u64", "i64", "u128", "i128", "bool"];
445
+ for ty_str in primitives {
446
+ let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
447
+ assert!(crate::storage::is_primitive_type(&ty), "{ty_str} should be recognized as primitive");
448
+ }
449
+ }
450
+
451
+ #[test]
452
+ fn test_is_primitive_type_rejects_non_primitive_types() {
453
+ let non_primitives = [
454
+ "u8", // not in primitive list
455
+ "usize", // not in primitive list
456
+ "String",
457
+ "Address",
458
+ "Vec<u8>",
459
+ "Option<u32>",
460
+ "std::u32", // multi-segment path
461
+ "soroban_sdk::Address",
462
+ ];
463
+
464
+ for ty_str in non_primitives {
465
+ let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
466
+ assert!(!crate::storage::is_primitive_type(&ty), "{ty_str} should NOT be recognized as primitive");
467
+ }
468
+ }
469
+
470
+ #[test]
471
+ fn test_is_primitive_type_rejects_other_type_variants() {
472
+ let other_variants = [
473
+ ("&u32", "reference"),
474
+ ("&mut u32", "mutable reference"),
475
+ ("(u32, i32)", "tuple"),
476
+ ("[u32; 4]", "array"),
477
+ ("[u32]", "slice"),
478
+ ("!", "never"),
479
+ ];
480
+
481
+ for (ty_str, label) in other_variants {
482
+ let ty = syn::parse_str::<syn::Type>(ty_str).expect("failed to parse type");
483
+ assert!(!crate::storage::is_primitive_type(&ty), "{label} type {ty_str} should NOT be recognized as primitive");
484
+ }
485
+ }
@@ -0,0 +1,93 @@
1
+ #![allow(unused_macros)]
2
+
3
+ pub(in crate::tests) fn assert_panics_contains<F>(case: &str, expected_substring: &str, f: F)
4
+ where
5
+ F: FnOnce() + std::panic::UnwindSafe,
6
+ {
7
+ let result = std::panic::catch_unwind(f);
8
+ assert!(result.is_err(), "{case}: expected panic, but function returned normally");
9
+
10
+ let payload = result.expect_err("checked above");
11
+ let msg = if let Some(s) = payload.downcast_ref::<&str>() {
12
+ (*s).to_string()
13
+ } else if let Some(s) = payload.downcast_ref::<String>() {
14
+ s.clone()
15
+ } else {
16
+ format!("{payload:?}")
17
+ };
18
+
19
+ assert!(
20
+ msg.contains(expected_substring),
21
+ "{case}: expected panic message to contain '{expected_substring}', got '{msg}'"
22
+ );
23
+ }
24
+
25
+ pub(in crate::tests) fn non_struct_item_inputs() -> Vec<(&'static str, proc_macro2::TokenStream)> {
26
+ filter_item_inputs_excluding_labels(&["struct"])
27
+ }
28
+
29
+ pub(in crate::tests) fn non_enum_item_inputs() -> Vec<(&'static str, proc_macro2::TokenStream)> {
30
+ filter_item_inputs_excluding_labels(&["enum"])
31
+ }
32
+
33
+ /// Canonical list of syntactically-valid `syn::Item` inputs.
34
+ ///
35
+ /// Keep this list broad and reusable; other helpers should filter it by AST kind.
36
+ pub(in crate::tests) fn item_inputs() -> Vec<(&'static str, proc_macro2::TokenStream)> {
37
+ vec![
38
+ (
39
+ "struct",
40
+ quote::quote! {
41
+ struct AStruct {
42
+ field: u32,
43
+ }
44
+ },
45
+ ),
46
+ (
47
+ "enum",
48
+ quote::quote! {
49
+ enum AnEnum {
50
+ Variant1,
51
+ Variant2,
52
+ }
53
+ },
54
+ ),
55
+ ("function", quote::quote! { fn a_function() {} }),
56
+ ("macro invocation", quote::quote! { some_macro!(); }),
57
+ ("const item", quote::quote! { const A_CONST: u32 = 1; }),
58
+ ("static item", quote::quote! { static A_STATIC: u32 = 1; }),
59
+ ("use item", quote::quote! { use core::mem; }),
60
+ ("mod item", quote::quote! { mod a_module {} }),
61
+ ("extern crate", quote::quote! { extern crate core; }),
62
+ (
63
+ "union",
64
+ quote::quote! {
65
+ union AUnion {
66
+ a: u32,
67
+ b: u32,
68
+ }
69
+ },
70
+ ),
71
+ (
72
+ "impl block",
73
+ quote::quote! {
74
+ impl SomeType {
75
+ fn method(&self) {}
76
+ }
77
+ },
78
+ ),
79
+ (
80
+ "trait",
81
+ quote::quote! {
82
+ trait ATrait {
83
+ fn method(&self);
84
+ }
85
+ },
86
+ ),
87
+ ("type alias", quote::quote! { type AnAlias = u32; }),
88
+ ]
89
+ }
90
+
91
+ fn filter_item_inputs_excluding_labels(excluded: &[&str]) -> Vec<(&'static str, proc_macro2::TokenStream)> {
92
+ item_inputs().into_iter().filter(|(label, _)| !excluded.iter().any(|x| x == label)).collect()
93
+ }
@@ -0,0 +1,34 @@
1
+ use quote::quote;
2
+
3
+ use crate::tests::test_helpers::{assert_panics_contains, non_struct_item_inputs};
4
+
5
+ // ============================================
6
+ // Snapshot Test: TtlConfigurable Code Generation
7
+ // ============================================
8
+
9
+ #[test]
10
+ fn snapshot_generated_ttl_configurable_code() {
11
+ // Test with a public unit struct
12
+ let input = quote! {
13
+ pub struct MyContract {
14
+ some_field: u32,
15
+ }
16
+ };
17
+ let result = crate::ttl_configurable::generate_ttl_configurable_impl(input);
18
+ let formatted = prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"));
19
+
20
+ insta::assert_snapshot!(formatted);
21
+ }
22
+
23
+ // ============================================
24
+ // Error Cases: Non-Struct Input
25
+ // ============================================
26
+
27
+ #[test]
28
+ fn test_ttl_configurable_rejects_non_struct_inputs() {
29
+ for (case, input) in non_struct_item_inputs() {
30
+ assert_panics_contains(case, "failed to parse struct", || {
31
+ crate::ttl_configurable::generate_ttl_configurable_impl(input.clone());
32
+ });
33
+ }
34
+ }