@layerzerolabs/protocol-stellar-v2 0.2.8

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 (265) hide show
  1. package/.turbo/turbo-build.log +727 -0
  2. package/.turbo/turbo-lint.log +158 -0
  3. package/.turbo/turbo-test.log +796 -0
  4. package/Cargo.lock +2237 -0
  5. package/Cargo.toml +63 -0
  6. package/clippy.toml +7 -0
  7. package/contracts/common-macros/Cargo.toml +20 -0
  8. package/contracts/common-macros/src/error.rs +53 -0
  9. package/contracts/common-macros/src/event.rs +16 -0
  10. package/contracts/common-macros/src/lib.rs +255 -0
  11. package/contracts/common-macros/src/ownable.rs +63 -0
  12. package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +310 -0
  13. package/contracts/common-macros/src/storage.rs +439 -0
  14. package/contracts/common-macros/src/tests.rs +287 -0
  15. package/contracts/common-macros/src/ttl_configurable.rs +60 -0
  16. package/contracts/endpoint-v2/ARCHITECTURE.md +233 -0
  17. package/contracts/endpoint-v2/Cargo.toml +30 -0
  18. package/contracts/endpoint-v2/src/constants.rs +52 -0
  19. package/contracts/endpoint-v2/src/endpoint_v2.rs +305 -0
  20. package/contracts/endpoint-v2/src/errors.rs +29 -0
  21. package/contracts/endpoint-v2/src/events.rs +207 -0
  22. package/contracts/endpoint-v2/src/interfaces/layerzero_composer.rs +26 -0
  23. package/contracts/endpoint-v2/src/interfaces/layerzero_endpoint_v2.rs +170 -0
  24. package/contracts/endpoint-v2/src/interfaces/layerzero_receiver.rs +43 -0
  25. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +62 -0
  26. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +220 -0
  27. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +121 -0
  28. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +63 -0
  29. package/contracts/endpoint-v2/src/interfaces/mod.rs +17 -0
  30. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +70 -0
  31. package/contracts/endpoint-v2/src/lib.rs +22 -0
  32. package/contracts/endpoint-v2/src/message_lib_manager.rs +315 -0
  33. package/contracts/endpoint-v2/src/messaging_channel.rs +218 -0
  34. package/contracts/endpoint-v2/src/messaging_composer.rs +76 -0
  35. package/contracts/endpoint-v2/src/storage.rs +78 -0
  36. package/contracts/endpoint-v2/src/tests/endpoint_setup.rs +131 -0
  37. package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +237 -0
  38. package/contracts/endpoint-v2/src/tests/endpoint_v2/delegate.rs +42 -0
  39. package/contracts/endpoint-v2/src/tests/endpoint_v2/initializable.rs +76 -0
  40. package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +211 -0
  41. package/contracts/endpoint-v2/src/tests/endpoint_v2/mod.rs +18 -0
  42. package/contracts/endpoint-v2/src/tests/endpoint_v2/native_token.rs +10 -0
  43. package/contracts/endpoint-v2/src/tests/endpoint_v2/owner.rs +10 -0
  44. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +424 -0
  45. package/contracts/endpoint-v2/src/tests/endpoint_v2/quote.rs +144 -0
  46. package/contracts/endpoint-v2/src/tests/endpoint_v2/recover_token.rs +72 -0
  47. package/contracts/endpoint-v2/src/tests/endpoint_v2/require_oapp_auth.rs +29 -0
  48. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +513 -0
  49. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +43 -0
  50. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +27 -0
  51. package/contracts/endpoint-v2/src/tests/endpoint_v2/transfer_ownership.rs +30 -0
  52. package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +202 -0
  53. package/contracts/endpoint-v2/src/tests/endpoint_v2/verifiable.rs +59 -0
  54. package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +172 -0
  55. package/contracts/endpoint-v2/src/tests/endpoint_v2/zro.rs +23 -0
  56. package/contracts/endpoint-v2/src/tests/message_lib_manager/mod.rs +10 -0
  57. package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +131 -0
  58. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_registered.rs +35 -0
  59. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_supported_eid.rs +28 -0
  60. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_config.rs +79 -0
  61. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +246 -0
  62. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +285 -0
  63. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +180 -0
  64. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +405 -0
  65. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +80 -0
  66. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +131 -0
  67. package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +358 -0
  68. package/contracts/endpoint-v2/src/tests/messaging_channel/clear.rs +316 -0
  69. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound_nonce.rs +288 -0
  70. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound_payload_hash.rs +316 -0
  71. package/contracts/endpoint-v2/src/tests/messaging_channel/internal.rs +388 -0
  72. package/contracts/endpoint-v2/src/tests/messaging_channel/lazy_inbound_nonce.rs +307 -0
  73. package/contracts/endpoint-v2/src/tests/messaging_channel/mod.rs +10 -0
  74. package/contracts/endpoint-v2/src/tests/messaging_channel/next_guid.rs +239 -0
  75. package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +324 -0
  76. package/contracts/endpoint-v2/src/tests/messaging_channel/outbound_nonce.rs +242 -0
  77. package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +232 -0
  78. package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +212 -0
  79. package/contracts/endpoint-v2/src/tests/messaging_composer/compose_queue.rs +213 -0
  80. package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +269 -0
  81. package/contracts/endpoint-v2/src/tests/messaging_composer/mod.rs +4 -0
  82. package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +173 -0
  83. package/contracts/endpoint-v2/src/tests/mock.rs +132 -0
  84. package/contracts/endpoint-v2/src/tests/mod.rs +12 -0
  85. package/contracts/endpoint-v2/src/tests/util/build_payload.rs +126 -0
  86. package/contracts/endpoint-v2/src/tests/util/compute_guid.rs +82 -0
  87. package/contracts/endpoint-v2/src/tests/util/keccak256.rs +115 -0
  88. package/contracts/endpoint-v2/src/tests/util/mod.rs +3 -0
  89. package/contracts/endpoint-v2/src/util.rs +52 -0
  90. package/contracts/message-libs/Cargo.toml +12 -0
  91. package/contracts/message-libs/block-message-lib/Cargo.toml +19 -0
  92. package/contracts/message-libs/block-message-lib/src/lib.rs +70 -0
  93. package/contracts/message-libs/lib.rs +2 -0
  94. package/contracts/message-libs/message-lib-common/Cargo.toml +24 -0
  95. package/contracts/message-libs/message-lib-common/src/errors.rs +20 -0
  96. package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +55 -0
  97. package/contracts/message-libs/message-lib-common/src/interfaces/executor.rs +46 -0
  98. package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +7 -0
  99. package/contracts/message-libs/message-lib-common/src/interfaces/treasury.rs +17 -0
  100. package/contracts/message-libs/message-lib-common/src/lib.rs +14 -0
  101. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +99 -0
  102. package/contracts/message-libs/message-lib-common/src/testing_utils.rs +27 -0
  103. package/contracts/message-libs/message-lib-common/src/tests/mod.rs +2 -0
  104. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +162 -0
  105. package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +319 -0
  106. package/contracts/message-libs/message-lib-common/src/worker_options.rs +190 -0
  107. package/contracts/message-libs/simple-message-lib/Cargo.toml +26 -0
  108. package/contracts/message-libs/simple-message-lib/src/errors.rs +11 -0
  109. package/contracts/message-libs/simple-message-lib/src/lib.rs +14 -0
  110. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +136 -0
  111. package/contracts/message-libs/simple-message-lib/src/storage.rs +27 -0
  112. package/contracts/message-libs/simple-message-lib/src/test.rs +280 -0
  113. package/contracts/message-libs/treasury/Cargo.toml +27 -0
  114. package/contracts/message-libs/treasury/src/errors.rs +10 -0
  115. package/contracts/message-libs/treasury/src/events.rs +28 -0
  116. package/contracts/message-libs/treasury/src/interfaces/mod.rs +3 -0
  117. package/contracts/message-libs/treasury/src/interfaces/zro_fee_lib.rs +20 -0
  118. package/contracts/message-libs/treasury/src/lib.rs +20 -0
  119. package/contracts/message-libs/treasury/src/storage.rs +18 -0
  120. package/contracts/message-libs/treasury/src/tests/mod.rs +2 -0
  121. package/contracts/message-libs/treasury/src/tests/setup.rs +112 -0
  122. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +562 -0
  123. package/contracts/message-libs/treasury/src/treasury.rs +140 -0
  124. package/contracts/message-libs/uln-302/Cargo.toml +28 -0
  125. package/contracts/message-libs/uln-302/src/config_validation.rs +173 -0
  126. package/contracts/message-libs/uln-302/src/errors.rs +29 -0
  127. package/contracts/message-libs/uln-302/src/events.rs +72 -0
  128. package/contracts/message-libs/uln-302/src/interfaces/mod.rs +5 -0
  129. package/contracts/message-libs/uln-302/src/interfaces/receive.rs +82 -0
  130. package/contracts/message-libs/uln-302/src/interfaces/send.rs +159 -0
  131. package/contracts/message-libs/uln-302/src/lib.rs +20 -0
  132. package/contracts/message-libs/uln-302/src/receive.rs +199 -0
  133. package/contracts/message-libs/uln-302/src/send.rs +349 -0
  134. package/contracts/message-libs/uln-302/src/storage.rs +47 -0
  135. package/contracts/message-libs/uln-302/src/tests/config/mod.rs +2 -0
  136. package/contracts/message-libs/uln-302/src/tests/config/oapp_uln_config.rs +291 -0
  137. package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +163 -0
  138. package/contracts/message-libs/uln-302/src/tests/mod.rs +7 -0
  139. package/contracts/message-libs/uln-302/src/tests/receive_uln302/commit_verification.rs +183 -0
  140. package/contracts/message-libs/uln-302/src/tests/receive_uln302/confirmations.rs +128 -0
  141. package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +104 -0
  142. package/contracts/message-libs/uln-302/src/tests/receive_uln302/mod.rs +66 -0
  143. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +79 -0
  144. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verifiable.rs +463 -0
  145. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +173 -0
  146. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +132 -0
  147. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +117 -0
  148. package/contracts/message-libs/uln-302/src/tests/send_uln302/mod.rs +6 -0
  149. package/contracts/message-libs/uln-302/src/tests/send_uln302/quote.rs +586 -0
  150. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +834 -0
  151. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +95 -0
  152. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +80 -0
  153. package/contracts/message-libs/uln-302/src/tests/setup.rs +268 -0
  154. package/contracts/message-libs/uln-302/src/tests/testing_utils.rs +47 -0
  155. package/contracts/message-libs/uln-302/src/tests/uln302/get_app_receive_uln_config.rs +51 -0
  156. package/contracts/message-libs/uln-302/src/tests/uln302/get_app_send_uln_config.rs +51 -0
  157. package/contracts/message-libs/uln-302/src/tests/uln302/get_oapp_executor_config.rs +48 -0
  158. package/contracts/message-libs/uln-302/src/tests/uln302/mod.rs +4 -0
  159. package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +998 -0
  160. package/contracts/message-libs/uln-302/src/uln302.rs +117 -0
  161. package/contracts/oapp-macros/Cargo.toml +21 -0
  162. package/contracts/oapp-macros/src/lib.rs +408 -0
  163. package/contracts/oapp-macros/src/oapp_core.rs +49 -0
  164. package/contracts/oapp-macros/src/oapp_full.rs +15 -0
  165. package/contracts/oapp-macros/src/oapp_options_type3.rs +46 -0
  166. package/contracts/oapp-macros/src/oapp_receiver.rs +67 -0
  167. package/contracts/oapp-macros/src/oapp_sender.rs +23 -0
  168. package/contracts/oapp-macros/src/util.rs +103 -0
  169. package/contracts/oapp-macros/tests/test_macros.rs +522 -0
  170. package/contracts/oapps/Cargo.toml +12 -0
  171. package/contracts/oapps/counter/Cargo.toml +24 -0
  172. package/contracts/oapps/counter/integration_tests/mod.rs +3 -0
  173. package/contracts/oapps/counter/integration_tests/setup.rs +201 -0
  174. package/contracts/oapps/counter/integration_tests/test_with_sml.rs +166 -0
  175. package/contracts/oapps/counter/integration_tests/utils.rs +144 -0
  176. package/contracts/oapps/counter/src/codec.rs +63 -0
  177. package/contracts/oapps/counter/src/counter.rs +235 -0
  178. package/contracts/oapps/counter/src/errors.rs +9 -0
  179. package/contracts/oapps/counter/src/lib.rs +16 -0
  180. package/contracts/oapps/counter/src/options.rs +30 -0
  181. package/contracts/oapps/counter/src/storage.rs +33 -0
  182. package/contracts/oapps/counter/src/tests/mod.rs +37 -0
  183. package/contracts/oapps/counter/src/tests/test_codec.rs +64 -0
  184. package/contracts/oapps/counter/src/tests/test_counter.rs +390 -0
  185. package/contracts/oapps/counter/src/u256_ext.rs +21 -0
  186. package/contracts/oapps/lib.rs +2 -0
  187. package/contracts/oapps/oapp/Cargo.toml +21 -0
  188. package/contracts/oapps/oapp/src/errors.rs +9 -0
  189. package/contracts/oapps/oapp/src/lib.rs +10 -0
  190. package/contracts/oapps/oapp/src/oapp_core.rs +92 -0
  191. package/contracts/oapps/oapp/src/oapp_options_type3.rs +89 -0
  192. package/contracts/oapps/oapp/src/oapp_receiver.rs +72 -0
  193. package/contracts/oapps/oapp/src/oapp_sender.rs +66 -0
  194. package/contracts/oapps/oapp/src/tests/mod.rs +4 -0
  195. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +162 -0
  196. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +180 -0
  197. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +157 -0
  198. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +283 -0
  199. package/contracts/utils/Cargo.toml +21 -0
  200. package/contracts/utils/src/buffer_reader.rs +143 -0
  201. package/contracts/utils/src/buffer_writer.rs +117 -0
  202. package/contracts/utils/src/bytes_ext.rs +19 -0
  203. package/contracts/utils/src/errors.rs +30 -0
  204. package/contracts/utils/src/lib.rs +15 -0
  205. package/contracts/utils/src/option_ext.rs +38 -0
  206. package/contracts/utils/src/ownable.rs +88 -0
  207. package/contracts/utils/src/testing_utils.rs +100 -0
  208. package/contracts/utils/src/tests/buffer_reader.rs +1006 -0
  209. package/contracts/utils/src/tests/buffer_writer.rs +330 -0
  210. package/contracts/utils/src/tests/bytes_ext.rs +77 -0
  211. package/contracts/utils/src/tests/mod.rs +4 -0
  212. package/contracts/utils/src/tests/ownable.rs +149 -0
  213. package/contracts/utils/src/ttl.rs +164 -0
  214. package/contracts/workers/Cargo.toml +13 -0
  215. package/contracts/workers/executor/Cargo.toml +26 -0
  216. package/contracts/workers/executor/src/events.rs +22 -0
  217. package/contracts/workers/executor/src/executor.rs +347 -0
  218. package/contracts/workers/executor/src/interfaces/executor.rs +40 -0
  219. package/contracts/workers/executor/src/interfaces/mod.rs +5 -0
  220. package/contracts/workers/executor/src/interfaces/types.rs +51 -0
  221. package/contracts/workers/executor/src/lib.rs +10 -0
  222. package/contracts/workers/executor/src/storage.rs +23 -0
  223. package/contracts/workers/lib.rs +2 -0
  224. package/contracts/workers/worker-common/Cargo.toml +18 -0
  225. package/contracts/workers/worker-common/src/constants.rs +17 -0
  226. package/contracts/workers/worker-common/src/errors.rs +6 -0
  227. package/contracts/workers/worker-common/src/events.rs +34 -0
  228. package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +35 -0
  229. package/contracts/workers/worker-common/src/interfaces/mod.rs +7 -0
  230. package/contracts/workers/worker-common/src/interfaces/price_feed.rs +40 -0
  231. package/contracts/workers/worker-common/src/interfaces/worker.rs +60 -0
  232. package/contracts/workers/worker-common/src/lib.rs +19 -0
  233. package/contracts/workers/worker-common/src/storage.rs +32 -0
  234. package/contracts/workers/worker-common/src/worker_common.rs +166 -0
  235. package/package.json +25 -0
  236. package/rust-toolchain.toml +4 -0
  237. package/rustfmt.toml +17 -0
  238. package/sdk/.turbo/turbo-build.log +4 -0
  239. package/sdk/dist/generated/bml.d.ts +452 -0
  240. package/sdk/dist/generated/bml.js +72 -0
  241. package/sdk/dist/generated/counter.d.ts +824 -0
  242. package/sdk/dist/generated/counter.js +125 -0
  243. package/sdk/dist/generated/endpoint.d.ts +1676 -0
  244. package/sdk/dist/generated/endpoint.js +216 -0
  245. package/sdk/dist/generated/sml.d.ts +810 -0
  246. package/sdk/dist/generated/sml.js +132 -0
  247. package/sdk/dist/generated/uln302.d.ts +1227 -0
  248. package/sdk/dist/generated/uln302.js +185 -0
  249. package/sdk/dist/index.d.ts +5 -0
  250. package/sdk/dist/index.js +5 -0
  251. package/sdk/node_modules/.bin/tsc +21 -0
  252. package/sdk/node_modules/.bin/tsserver +21 -0
  253. package/sdk/node_modules/.bin/vitest +21 -0
  254. package/sdk/node_modules/.bin/zx +21 -0
  255. package/sdk/package.json +40 -0
  256. package/sdk/src/index.ts +5 -0
  257. package/sdk/test/index.test.ts +271 -0
  258. package/sdk/test/suites/constants.ts +13 -0
  259. package/sdk/test/suites/deploy.ts +277 -0
  260. package/sdk/test/suites/localnet.ts +42 -0
  261. package/sdk/test/suites/scan.ts +189 -0
  262. package/sdk/tsconfig.json +106 -0
  263. package/tools/ts-bindings-gen/Cargo.toml +14 -0
  264. package/tools/ts-bindings-gen/src/main.rs +147 -0
  265. package/turbo.json +12 -0
@@ -0,0 +1,439 @@
1
+ //! Storage macro implementation for Stellar smart contracts.
2
+ //!
3
+ //! Generates strongly-typed storage API from enum variants with automatic TTL management.
4
+
5
+ use heck::ToSnakeCase;
6
+ use itertools::Itertools;
7
+ use proc_macro2::{Ident, TokenStream};
8
+ use quote::{format_ident, quote};
9
+ use syn::{
10
+ parse::{Parse, ParseStream},
11
+ Expr, Fields, FieldsNamed, Meta, Result, Type, TypePath, Variant,
12
+ };
13
+
14
+ // ============================================================================
15
+ // Types & Parsing
16
+ // ============================================================================
17
+
18
+ /// TTL provider configuration for auto-extending storage TTL.
19
+ /// Parsed from `#[storage(MyTtlProvider)]` attribute.
20
+ #[derive(Debug, Clone)]
21
+ struct TtlProvider(Option<Type>);
22
+
23
+ impl Parse for TtlProvider {
24
+ fn parse(input: ParseStream) -> Result<Self> {
25
+ if input.is_empty() {
26
+ return Ok(Self(None));
27
+ }
28
+
29
+ let meta: Meta = input.parse()?;
30
+ let Meta::Path(path) = meta else {
31
+ return Err(syn::Error::new(input.span(), "TTL provider must be a path"));
32
+ };
33
+
34
+ Ok(Self(Some(Type::Path(TypePath { qself: None, path }))))
35
+ }
36
+ }
37
+
38
+ /// Storage type parsed from `#[instance(Type)]`, `#[persistent(Type)]`, or `#[temporary(Type)]`.
39
+ #[derive(Debug, Clone)]
40
+ enum StorageType {
41
+ Instance(Type),
42
+ Persistent(Type),
43
+ Temporary(Type),
44
+ }
45
+
46
+ impl StorageType {
47
+ fn value_type(&self) -> &Type {
48
+ match self {
49
+ Self::Instance(t) | Self::Persistent(t) | Self::Temporary(t) => t,
50
+ }
51
+ }
52
+
53
+ fn is_instance(&self) -> bool {
54
+ matches!(self, Self::Instance(_))
55
+ }
56
+
57
+ /// Returns the storage accessor method name.
58
+ fn accessor_name(&self) -> &'static str {
59
+ match self {
60
+ Self::Instance(_) => "instance",
61
+ Self::Persistent(_) => "persistent",
62
+ Self::Temporary(_) => "temporary",
63
+ }
64
+ }
65
+ }
66
+
67
+ impl TryFrom<&syn::Attribute> for StorageType {
68
+ type Error = String;
69
+
70
+ fn try_from(attr: &syn::Attribute) -> std::result::Result<Self, Self::Error> {
71
+ let ident = attr.path().get_ident().ok_or("identifier expected to be instance, persistent, or temporary")?;
72
+ let value_type = attr.parse_args::<Type>().map_err(|e| format!("failed to parse value type: {}", e))?;
73
+
74
+ match ident.to_string().as_str() {
75
+ "instance" => Ok(Self::Instance(value_type)),
76
+ "persistent" => Ok(Self::Persistent(value_type)),
77
+ "temporary" => Ok(Self::Temporary(value_type)),
78
+ other => Err(format!("unknown storage type: {}", other)),
79
+ }
80
+ }
81
+ }
82
+
83
+ /// Parsed configuration for a single storage enum variant.
84
+ #[derive(Debug, Clone)]
85
+ pub(crate) struct StorageVariantConfig {
86
+ name: String,
87
+ storage_type: StorageType,
88
+ default_value: Option<Expr>,
89
+ no_auto_ttl_extension: bool,
90
+ }
91
+
92
+ impl StorageVariantConfig {
93
+ /// Returns generated function names for this storage variant.
94
+ fn function_names(&self) -> FunctionNames {
95
+ let base = &self.name;
96
+ FunctionNames {
97
+ getter: format_ident!("{}", base),
98
+ setter: format_ident!("set_{}", base),
99
+ remover: format_ident!("remove_{}", base),
100
+ set_or_remove: format_ident!("set_or_remove_{}", base),
101
+ ttl_extender: format_ident!("extend_ttl_{}", base),
102
+ has: format_ident!("has_{}", base),
103
+ }
104
+ }
105
+ }
106
+
107
+ impl TryFrom<&Variant> for StorageVariantConfig {
108
+ type Error = String;
109
+
110
+ fn try_from(variant: &Variant) -> std::result::Result<Self, Self::Error> {
111
+ let attrs = &variant.attrs;
112
+
113
+ // Known attribute identifiers for this macro ("doc" allows /// comments on variants)
114
+ const KNOWN_ATTRS: &[&str] =
115
+ &["doc", "instance", "persistent", "temporary", "default", "no_auto_ttl_extension", "name"];
116
+
117
+ // Check for unsupported attributes
118
+ if let Some(unknown) = attrs
119
+ .iter()
120
+ .filter_map(|attr| attr.path().get_ident())
121
+ .find(|ident| !KNOWN_ATTRS.contains(&ident.to_string().as_str()))
122
+ {
123
+ return Err(format!(
124
+ "unknown attribute '{}' on variant '{}'. Supported attributes are: {}",
125
+ unknown,
126
+ variant.ident,
127
+ KNOWN_ATTRS.join(", ")
128
+ ));
129
+ }
130
+
131
+ // Parse storage type (exactly one required)
132
+ let storage_type =
133
+ attrs.iter().filter_map(|attr| StorageType::try_from(attr).ok()).exactly_one().map_err(|e| {
134
+ format!(
135
+ "storage type must be specified exactly once as \
136
+ '#[instance(Type)]', '#[persistent(Type)]', or '#[temporary(Type)]': {}",
137
+ e
138
+ )
139
+ })?;
140
+
141
+ // Parse optional default value
142
+ let default_value = attrs
143
+ .iter()
144
+ .filter(|attr| attr.path().is_ident("default"))
145
+ .at_most_one()
146
+ .map_err(|_| "multiple default values specified")?
147
+ .map(|attr| attr.parse_args::<Expr>())
148
+ .transpose()
149
+ .map_err(|e| format!("failed to parse default value: {}", e))?;
150
+
151
+ // Check for no_auto_ttl_extension flag
152
+ let no_auto_ttl_extension = attrs
153
+ .iter()
154
+ .filter(|attr| attr.path().is_ident("no_auto_ttl_extension"))
155
+ .map(|attr| {
156
+ attr.meta.require_path_only().map_err(|_| "no_auto_ttl_extension does not accept arguments".to_string())
157
+ })
158
+ .at_most_one()
159
+ .map_err(|_| "multiple no_auto_ttl_extension attributes specified")?
160
+ .transpose()?
161
+ .is_some();
162
+
163
+ // Parse optional name override for storage key generation
164
+ // If no #[name("custom_name")] attribute is provided, defaults to snake_case of variant name
165
+ let name = attrs
166
+ .iter()
167
+ .filter(|attr| attr.path().is_ident("name"))
168
+ .at_most_one()
169
+ .map_err(|_| "multiple name attributes specified")?
170
+ .map(|attr| attr.parse_args::<syn::LitStr>().map(|lit| lit.value()))
171
+ .transpose()
172
+ .map_err(|e| format!("failed to parse name attribute: {}", e))?
173
+ .unwrap_or_else(|| variant.ident.to_string().to_snake_case());
174
+
175
+ Ok(Self { storage_type, default_value, no_auto_ttl_extension, name })
176
+ }
177
+ }
178
+
179
+ /// Generated function names for a storage variant.
180
+ struct FunctionNames {
181
+ getter: Ident,
182
+ setter: Ident,
183
+ remover: Ident,
184
+ set_or_remove: Ident,
185
+ ttl_extender: Ident,
186
+ has: Ident,
187
+ }
188
+
189
+ // ============================================================================
190
+ // Code Generation
191
+ // ============================================================================
192
+
193
+ /// Generates the storage API from the `#[storage]` attribute macro.
194
+ pub(crate) fn generate_storage(attr: TokenStream, input: TokenStream) -> TokenStream {
195
+ let item_enum: syn::ItemEnum = syn::parse2(input).unwrap_or_else(|e| panic!("failed to parse enum: {}", e));
196
+ let ttl_provider: TtlProvider = syn::parse2(attr).unwrap_or_else(|e| panic!("failed to parse attribute: {}", e));
197
+
198
+ let enum_name = &item_enum.ident;
199
+ let contracttype_variants: Vec<_> = item_enum.variants.iter().map(gen_contracttype_variant).collect();
200
+ let inherent_impls: Vec<_> =
201
+ item_enum.variants.iter().map(|v| gen_storage_functions(enum_name, v, &ttl_provider)).collect();
202
+
203
+ let visibility = &item_enum.vis;
204
+ quote! {
205
+ use utils::ttl::TtlConfigProvider as _;
206
+
207
+ #[soroban_sdk::contracttype]
208
+ #visibility enum #enum_name {
209
+ #(#contracttype_variants,)*
210
+ }
211
+
212
+ impl #enum_name {
213
+ #(#inherent_impls)*
214
+ }
215
+ }
216
+ }
217
+
218
+ /// Generates contracttype enum variant: `Variant` or `Variant(Type1, Type2, ...)`.
219
+ fn gen_contracttype_variant(variant: &Variant) -> TokenStream {
220
+ let name = &variant.ident;
221
+ match &variant.fields {
222
+ Fields::Unit => quote! { #name },
223
+ Fields::Named(FieldsNamed { named, .. }) => {
224
+ let types = named.iter().map(|f| &f.ty);
225
+ quote! { #name(#(#types),*) }
226
+ }
227
+ _ => panic!("only unit variants or named fields are supported in storage enums"),
228
+ }
229
+ }
230
+
231
+ /// Generates all storage accessor functions for a variant.
232
+ fn gen_storage_functions(enum_name: &Ident, variant: &Variant, ttl_provider: &TtlProvider) -> TokenStream {
233
+ let config = StorageVariantConfig::try_from(variant)
234
+ .unwrap_or_else(|e| panic!("failed to parse storage variant for {}: {}", variant.ident, e));
235
+
236
+ let FunctionNames { getter, setter, remover, set_or_remove, has, ttl_extender } = config.function_names();
237
+
238
+ let fn_params = gen_fn_params(variant);
239
+ let fn_args = gen_fn_args(variant);
240
+ let storage_key = gen_storage_key(variant, enum_name);
241
+ let storage_acc = gen_storage_accessor(&config.storage_type);
242
+ let value_type = config.storage_type.value_type();
243
+
244
+ // Auto TTL extension (if provider exists and not disabled)
245
+ let auto_ttl = ttl_provider
246
+ .0
247
+ .as_ref()
248
+ .filter(|_| !config.no_auto_ttl_extension)
249
+ .map(|p| gen_ttl_extension(&config.storage_type, Some(p)))
250
+ .unwrap_or_default();
251
+
252
+ let getter_impl =
253
+ gen_getter_fn(&getter, &fn_params, &storage_key, &storage_acc, value_type, &config.default_value, &auto_ttl);
254
+
255
+ // Manual TTL extension (user provides threshold/extend_to)
256
+ let manual_ttl = gen_ttl_extension(&config.storage_type, None);
257
+
258
+ quote! {
259
+ #getter_impl
260
+
261
+ pub fn #setter(#fn_params, value: &#value_type) {
262
+ let key = #storage_key;
263
+ #storage_acc.set(&key, value);
264
+ #auto_ttl
265
+ }
266
+
267
+ pub fn #remover(#fn_params) {
268
+ let key = #storage_key;
269
+ #storage_acc.remove(&key);
270
+ }
271
+
272
+ pub fn #set_or_remove(#fn_params, value: &Option<#value_type>) {
273
+ match value.as_ref() {
274
+ Some(v) => Self::#setter(#fn_args, v),
275
+ None => Self::#remover(#fn_args),
276
+ }
277
+ }
278
+
279
+ pub fn #has(#fn_params) -> bool {
280
+ let key = #storage_key;
281
+ let exists = #storage_acc.has(&key);
282
+ if exists { #auto_ttl }
283
+ exists
284
+ }
285
+
286
+ pub fn #ttl_extender(#fn_params, threshold: u32, extend_to: u32) {
287
+ let key = #storage_key;
288
+ #manual_ttl
289
+ }
290
+ }
291
+ }
292
+
293
+ /// Generates the storage accessor: `env.storage().instance()` etc.
294
+ fn gen_storage_accessor(storage_type: &StorageType) -> TokenStream {
295
+ let method = format_ident!("{}", storage_type.accessor_name());
296
+ quote! { env.storage().#method() }
297
+ }
298
+
299
+ /// Generates TTL extension code.
300
+ /// - With provider: uses provider to get threshold/extend_to
301
+ /// - Without provider (None): uses local variables `threshold` and `extend_to`
302
+ fn gen_ttl_extension(storage_type: &StorageType, provider: Option<&Type>) -> TokenStream {
303
+ let get_ttl_values = provider.map(|p| {
304
+ let method = format_ident!("{}", storage_type.accessor_name());
305
+ quote! { let utils::ttl::TtlConfig { threshold, extend_to } = utils::ttl::ttl_config::#method::<#p>(env); }
306
+ });
307
+
308
+ let accessor = gen_storage_accessor(storage_type);
309
+ let extend_call = if storage_type.is_instance() {
310
+ quote! { #accessor.extend_ttl(threshold, extend_to); }
311
+ } else {
312
+ quote! { #accessor.extend_ttl(&key, threshold, extend_to); }
313
+ };
314
+
315
+ quote! {
316
+ #get_ttl_values
317
+ #extend_call
318
+ }
319
+ }
320
+
321
+ /// Checks if a type is a primitive type
322
+ fn is_primitive_type(ty: &Type) -> bool {
323
+ if let Type::Path(type_path) = ty {
324
+ if type_path.path.segments.len() == 1 {
325
+ let segment = &type_path.path.segments[0];
326
+ let ident = &segment.ident;
327
+ matches!(ident.to_string().as_str(), "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "bool")
328
+ } else {
329
+ false
330
+ }
331
+ } else {
332
+ false
333
+ }
334
+ }
335
+
336
+ /// Generates function parameters: `env: &Env` or `env: &Env, field1: Type1, ...`.
337
+ /// For primitive types (u32, i32, u64, i64, u128, i128, bool), uses pass-by-value.
338
+ /// For other types, uses pass-by-reference.
339
+ fn gen_fn_params(variant: &Variant) -> TokenStream {
340
+ let fields = extract_named_fields(&variant.fields);
341
+ if fields.is_empty() {
342
+ quote! { env: &soroban_sdk::Env }
343
+ } else {
344
+ let params = fields.iter().map(|(name, ty)| {
345
+ if is_primitive_type(ty) {
346
+ quote! { #name: #ty }
347
+ } else {
348
+ quote! { #name: &#ty }
349
+ }
350
+ });
351
+ quote! { env: &soroban_sdk::Env, #(#params),* }
352
+ }
353
+ }
354
+
355
+ /// Generates function argument list for calls: `env, field1, field2, ...`.
356
+ fn gen_fn_args(variant: &Variant) -> TokenStream {
357
+ let fields = extract_named_fields(&variant.fields);
358
+ if fields.is_empty() {
359
+ quote! { env }
360
+ } else {
361
+ let field_names = fields.iter().map(|(name, _)| name);
362
+ quote! { env, #(#field_names),* }
363
+ }
364
+ }
365
+
366
+ /// Generates key constructor: `Enum::Variant` or `Enum::Variant(field1, field2)`.
367
+ /// For non-primitive types that are passed by reference, clones them.
368
+ fn gen_storage_key(variant: &Variant, enum_name: &Ident) -> TokenStream {
369
+ let fields = extract_named_fields(&variant.fields);
370
+ let variant_ident = &variant.ident;
371
+ if fields.is_empty() {
372
+ quote! { #enum_name::#variant_ident }
373
+ } else {
374
+ let field_names = fields.iter().map(|(name, ty)| {
375
+ if is_primitive_type(ty) {
376
+ quote! { #name }
377
+ } else {
378
+ quote! { #name.clone() }
379
+ }
380
+ });
381
+ quote! { #enum_name::#variant_ident(#(#field_names),*) }
382
+ }
383
+ }
384
+
385
+ /// Extracts (name, type) pairs from named fields.
386
+ fn extract_named_fields(fields: &Fields) -> Vec<(&Ident, &Type)> {
387
+ match fields {
388
+ Fields::Unit => vec![],
389
+ Fields::Named(named) => named.named.iter().map(|f| (f.ident.as_ref().unwrap(), &f.ty)).collect(),
390
+ _ => panic!("only unit variants or named fields are supported in storage enums"),
391
+ }
392
+ }
393
+
394
+ /// Generates the getter function with appropriate return type and TTL handling.
395
+ fn gen_getter_fn(
396
+ name: &Ident,
397
+ params: &TokenStream,
398
+ key: &TokenStream,
399
+ accessor: &TokenStream,
400
+ value_type: &Type,
401
+ has_default: &Option<Expr>,
402
+ ttl_extend: &TokenStream,
403
+ ) -> TokenStream {
404
+ let has_ttl = !ttl_extend.is_empty();
405
+ match (has_default, has_ttl) {
406
+ // Has default + has TTL extension
407
+ (Some(default_expr), true) => quote! {
408
+ pub fn #name(#params) -> #value_type {
409
+ let key = #key;
410
+ let value = #accessor.get::<_, #value_type>(&key);
411
+ if value.is_some() { #ttl_extend }
412
+ value.unwrap_or(#default_expr)
413
+ }
414
+ },
415
+ // Has default, no TTL extension
416
+ (Some(default_expr), false) => quote! {
417
+ pub fn #name(#params) -> #value_type {
418
+ let key = #key;
419
+ #accessor.get::<_, #value_type>(&key).unwrap_or(#default_expr)
420
+ }
421
+ },
422
+ // No default + has TTL extension
423
+ (None, true) => quote! {
424
+ pub fn #name(#params) -> Option<#value_type> {
425
+ let key = #key;
426
+ let value = #accessor.get::<_, #value_type>(&key);
427
+ if value.is_some() { #ttl_extend }
428
+ value
429
+ }
430
+ },
431
+ // No default, no TTL extension
432
+ (None, false) => quote! {
433
+ pub fn #name(#params) -> Option<#value_type> {
434
+ let key = #key;
435
+ #accessor.get::<_, #value_type>(&key)
436
+ }
437
+ },
438
+ }
439
+ }