@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.
- package/.turbo/turbo-build.log +443 -302
- package/.turbo/turbo-lint.log +118 -96
- package/.turbo/turbo-test.log +853 -731
- package/Cargo.lock +120 -37
- package/Cargo.toml +8 -5
- package/contracts/common-macros/src/contract_impl.rs +44 -0
- package/contracts/common-macros/src/lib.rs +86 -40
- package/contracts/common-macros/src/ownable.rs +24 -32
- package/contracts/common-macros/src/storage.rs +95 -120
- package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
- package/contracts/common-macros/src/tests/mod.rs +9 -0
- package/contracts/common-macros/src/tests/ownable.rs +151 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
- package/contracts/common-macros/src/tests/storage.rs +485 -0
- package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
- package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
- package/contracts/common-macros/src/ttl_configurable.rs +31 -14
- package/contracts/common-macros/src/utils.rs +27 -0
- package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
- package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
- package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
- package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
- package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
- package/contracts/endpoint-v2/src/lib.rs +6 -5
- package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
- package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
- package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
- package/contracts/endpoint-v2/src/storage.rs +10 -7
- package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
- package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
- package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
- package/contracts/endpoint-v2/src/util.rs +8 -2
- package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
- package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
- package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
- package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
- package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
- package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
- package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
- package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
- package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
- package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
- package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
- package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
- package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
- package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
- package/contracts/message-libs/treasury/src/storage.rs +1 -2
- package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
- package/contracts/message-libs/treasury/src/treasury.rs +18 -21
- package/contracts/message-libs/uln-302/Cargo.toml +1 -0
- package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
- package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
- package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
- package/contracts/message-libs/uln-302/src/lib.rs +5 -4
- package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
- package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
- package/contracts/message-libs/uln-302/src/storage.rs +1 -2
- package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
- package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
- package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
- package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
- package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
- package/contracts/oapp-macros/Cargo.toml +2 -8
- package/contracts/oapp-macros/src/lib.rs +57 -311
- package/contracts/oapp-macros/src/oapp_core.rs +23 -32
- package/contracts/oapp-macros/src/oapp_full.rs +8 -2
- package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
- package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
- package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
- package/contracts/oapp-macros/src/util.rs +14 -10
- package/contracts/oapps/counter/Cargo.toml +2 -1
- package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
- package/contracts/oapps/counter/src/codec.rs +8 -9
- package/contracts/oapps/counter/src/counter.rs +156 -147
- package/contracts/oapps/counter/src/storage.rs +1 -2
- package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
- package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
- package/contracts/oapps/oapp/Cargo.toml +1 -0
- package/contracts/oapps/oapp/src/errors.rs +1 -1
- package/contracts/oapps/oapp/src/lib.rs +3 -0
- package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
- package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
- package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
- package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
- package/contracts/oapps/oft/Cargo.toml +27 -0
- package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
- package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
- package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
- package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
- package/contracts/oapps/oft/src/codec/mod.rs +2 -0
- package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
- package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
- package/contracts/oapps/oft/src/constants.rs +5 -0
- package/contracts/oapps/oft/src/errors.rs +8 -0
- package/contracts/oapps/oft/src/events.rs +19 -0
- package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
- package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/oft/src/lib.rs +22 -0
- package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
- package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
- package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
- package/contracts/oapps/oft/src/oft.rs +320 -0
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
- package/contracts/oapps/oft/src/storage.rs +11 -0
- package/contracts/oapps/oft/src/tests/mod.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
- package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
- package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
- package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
- package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
- package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
- package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
- package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
- package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
- package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
- package/contracts/oapps/oft/src/types.rs +38 -0
- package/contracts/oapps/oft/src/utils.rs +67 -0
- package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
- package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
- package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
- package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
- package/contracts/utils/src/buffer_reader.rs +8 -9
- package/contracts/utils/src/buffer_writer.rs +11 -5
- package/contracts/utils/src/errors.rs +5 -5
- package/contracts/utils/src/ownable.rs +14 -6
- package/contracts/utils/src/testing_utils.rs +11 -1
- package/contracts/utils/src/tests/buffer_reader.rs +491 -730
- package/contracts/utils/src/tests/buffer_writer.rs +336 -148
- package/contracts/utils/src/tests/bytes_ext.rs +125 -40
- package/contracts/utils/src/tests/mod.rs +3 -0
- package/contracts/utils/src/tests/ownable.rs +379 -27
- package/contracts/utils/src/tests/test_helper.rs +47 -0
- package/contracts/utils/src/tests/testing_utils.rs +555 -0
- package/contracts/utils/src/tests/ttl.rs +421 -0
- package/contracts/utils/src/ttl.rs +29 -89
- package/contracts/workers/dvn/Cargo.toml +31 -0
- package/contracts/workers/dvn/src/auth.rs +66 -0
- package/contracts/workers/dvn/src/dvn.rs +143 -0
- package/contracts/workers/dvn/src/errors.rs +21 -0
- package/contracts/workers/dvn/src/events.rs +19 -0
- package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
- package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
- package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
- package/contracts/workers/dvn/src/lib.rs +24 -0
- package/contracts/workers/dvn/src/multisig.rs +127 -0
- package/contracts/workers/dvn/src/storage.rs +35 -0
- package/contracts/workers/dvn/src/tests/auth.rs +237 -0
- package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
- package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
- package/contracts/workers/dvn/src/tests/mod.rs +5 -0
- package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
- package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
- package/contracts/workers/dvn/src/tests/setup.rs +109 -0
- package/contracts/workers/dvn/src/types.rs +26 -0
- package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
- package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
- package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
- package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
- package/contracts/workers/executor/Cargo.toml +10 -7
- package/contracts/workers/executor/src/errors.rs +8 -0
- package/contracts/workers/executor/src/events.rs +4 -7
- package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
- package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
- package/contracts/workers/executor/src/lib.rs +16 -7
- package/contracts/workers/executor/src/lz_executor.rs +308 -0
- package/contracts/workers/executor/src/storage.rs +24 -16
- package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
- package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
- package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
- package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
- package/contracts/workers/executor-helper/Cargo.toml +29 -0
- package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
- package/contracts/workers/executor-helper/src/lib.rs +11 -0
- package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
- package/contracts/workers/worker/src/errors.rs +24 -0
- package/contracts/workers/worker/src/events.rs +62 -0
- package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
- package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
- package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
- package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
- package/contracts/workers/worker/src/lib.rs +14 -0
- package/contracts/workers/worker/src/storage.rs +63 -0
- package/contracts/workers/worker/src/worker.rs +459 -0
- package/package.json +3 -3
- package/sdk/dist/generated/bml.d.ts +88 -17
- package/sdk/dist/generated/bml.js +62 -16
- package/sdk/dist/generated/counter.d.ts +281 -102
- package/sdk/dist/generated/counter.js +93 -41
- package/sdk/dist/generated/endpoint.d.ts +128 -105
- package/sdk/dist/generated/endpoint.js +47 -45
- package/sdk/dist/generated/sml.d.ts +212 -69
- package/sdk/dist/generated/sml.js +103 -53
- package/sdk/dist/generated/uln302.d.ts +270 -173
- package/sdk/dist/generated/uln302.js +112 -64
- package/sdk/package.json +11 -11
- package/sdk/test/index.test.ts +147 -42
- package/sdk/test/suites/constants.ts +7 -3
- package/sdk/test/suites/deploy.ts +65 -42
- package/sdk/test/suites/localnet.ts +2 -2
- package/sdk/test/suites/scan.ts +28 -25
- package/sdk/test/utils.ts +199 -0
- package/sdk/tsconfig.json +93 -95
- package/tools/ts-bindings-gen/src/main.rs +2 -0
- package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
- package/contracts/common-macros/src/tests.rs +0 -287
- package/contracts/oapp-macros/tests/test_macros.rs +0 -522
- package/contracts/workers/executor/src/executor.rs +0 -347
- package/contracts/workers/executor/src/interfaces/types.rs +0 -51
- package/contracts/workers/worker-common/src/constants.rs +0 -17
- package/contracts/workers/worker-common/src/errors.rs +0 -6
- package/contracts/workers/worker-common/src/events.rs +0 -34
- package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
- package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
- package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
- package/contracts/workers/worker-common/src/lib.rs +0 -19
- package/contracts/workers/worker-common/src/storage.rs +0 -32
- package/contracts/workers/worker-common/src/worker_common.rs +0 -166
|
@@ -6,35 +6,12 @@ use heck::ToSnakeCase;
|
|
|
6
6
|
use itertools::Itertools;
|
|
7
7
|
use proc_macro2::{Ident, TokenStream};
|
|
8
8
|
use quote::{format_ident, quote};
|
|
9
|
-
use syn::{
|
|
10
|
-
parse::{Parse, ParseStream},
|
|
11
|
-
Expr, Fields, FieldsNamed, Meta, Result, Type, TypePath, Variant,
|
|
12
|
-
};
|
|
9
|
+
use syn::{Expr, Fields, FieldsNamed, Type, Variant};
|
|
13
10
|
|
|
14
11
|
// ============================================================================
|
|
15
12
|
// Types & Parsing
|
|
16
13
|
// ============================================================================
|
|
17
14
|
|
|
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
15
|
/// Storage type parsed from `#[instance(Type)]`, `#[persistent(Type)]`, or `#[temporary(Type)]`.
|
|
39
16
|
#[derive(Debug, Clone)]
|
|
40
17
|
enum StorageType {
|
|
@@ -54,6 +31,10 @@ impl StorageType {
|
|
|
54
31
|
matches!(self, Self::Instance(_))
|
|
55
32
|
}
|
|
56
33
|
|
|
34
|
+
fn is_persistent(&self) -> bool {
|
|
35
|
+
matches!(self, Self::Persistent(_))
|
|
36
|
+
}
|
|
37
|
+
|
|
57
38
|
/// Returns the storage accessor method name.
|
|
58
39
|
fn accessor_name(&self) -> &'static str {
|
|
59
40
|
match self {
|
|
@@ -86,7 +67,7 @@ pub(crate) struct StorageVariantConfig {
|
|
|
86
67
|
name: String,
|
|
87
68
|
storage_type: StorageType,
|
|
88
69
|
default_value: Option<Expr>,
|
|
89
|
-
|
|
70
|
+
no_ttl_extension: bool,
|
|
90
71
|
}
|
|
91
72
|
|
|
92
73
|
impl StorageVariantConfig {
|
|
@@ -98,7 +79,7 @@ impl StorageVariantConfig {
|
|
|
98
79
|
setter: format_ident!("set_{}", base),
|
|
99
80
|
remover: format_ident!("remove_{}", base),
|
|
100
81
|
set_or_remove: format_ident!("set_or_remove_{}", base),
|
|
101
|
-
ttl_extender: format_ident!("
|
|
82
|
+
ttl_extender: format_ident!("extend_{}_ttl", base),
|
|
102
83
|
has: format_ident!("has_{}", base),
|
|
103
84
|
}
|
|
104
85
|
}
|
|
@@ -112,7 +93,7 @@ impl TryFrom<&Variant> for StorageVariantConfig {
|
|
|
112
93
|
|
|
113
94
|
// Known attribute identifiers for this macro ("doc" allows /// comments on variants)
|
|
114
95
|
const KNOWN_ATTRS: &[&str] =
|
|
115
|
-
&["doc", "instance", "persistent", "temporary", "default", "
|
|
96
|
+
&["doc", "instance", "persistent", "temporary", "default", "name", "no_ttl_extension"];
|
|
116
97
|
|
|
117
98
|
// Check for unsupported attributes
|
|
118
99
|
if let Some(unknown) = attrs
|
|
@@ -148,18 +129,6 @@ impl TryFrom<&Variant> for StorageVariantConfig {
|
|
|
148
129
|
.transpose()
|
|
149
130
|
.map_err(|e| format!("failed to parse default value: {}", e))?;
|
|
150
131
|
|
|
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
132
|
// Parse optional name override for storage key generation
|
|
164
133
|
// If no #[name("custom_name")] attribute is provided, defaults to snake_case of variant name
|
|
165
134
|
let name = attrs
|
|
@@ -172,7 +141,18 @@ impl TryFrom<&Variant> for StorageVariantConfig {
|
|
|
172
141
|
.map_err(|e| format!("failed to parse name attribute: {}", e))?
|
|
173
142
|
.unwrap_or_else(|| variant.ident.to_string().to_snake_case());
|
|
174
143
|
|
|
175
|
-
|
|
144
|
+
// Parse optional #[no_ttl_extension] to skip automatic TTL extension (persistent only)
|
|
145
|
+
let no_ttl_extension = attrs
|
|
146
|
+
.iter()
|
|
147
|
+
.filter(|attr| attr.path().is_ident("no_ttl_extension"))
|
|
148
|
+
.at_most_one()
|
|
149
|
+
.map_err(|_| "multiple #[no_ttl_extension] attributes specified")?
|
|
150
|
+
.is_some();
|
|
151
|
+
if no_ttl_extension && !storage_type.is_persistent() {
|
|
152
|
+
return Err("#[no_ttl_extension] can only be used with #[persistent(...)] storage".to_string());
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
Ok(Self { storage_type, default_value, name, no_ttl_extension })
|
|
176
156
|
}
|
|
177
157
|
}
|
|
178
158
|
|
|
@@ -193,17 +173,18 @@ struct FunctionNames {
|
|
|
193
173
|
/// Generates the storage API from the `#[storage]` attribute macro.
|
|
194
174
|
pub(crate) fn generate_storage(attr: TokenStream, input: TokenStream) -> TokenStream {
|
|
195
175
|
let item_enum: syn::ItemEnum = syn::parse2(input).unwrap_or_else(|e| panic!("failed to parse enum: {}", e));
|
|
196
|
-
|
|
176
|
+
|
|
177
|
+
// Ensure no arguments are passed to #[storage]
|
|
178
|
+
if !attr.is_empty() {
|
|
179
|
+
panic!("the #[storage] attribute does not accept arguments");
|
|
180
|
+
}
|
|
197
181
|
|
|
198
182
|
let enum_name = &item_enum.ident;
|
|
199
183
|
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();
|
|
184
|
+
let inherent_impls: Vec<_> = item_enum.variants.iter().map(|v| gen_storage_functions(enum_name, v)).collect();
|
|
202
185
|
|
|
203
186
|
let visibility = &item_enum.vis;
|
|
204
187
|
quote! {
|
|
205
|
-
use utils::ttl::TtlConfigProvider as _;
|
|
206
|
-
|
|
207
188
|
#[soroban_sdk::contracttype]
|
|
208
189
|
#visibility enum #enum_name {
|
|
209
190
|
#(#contracttype_variants,)*
|
|
@@ -229,7 +210,7 @@ fn gen_contracttype_variant(variant: &Variant) -> TokenStream {
|
|
|
229
210
|
}
|
|
230
211
|
|
|
231
212
|
/// Generates all storage accessor functions for a variant.
|
|
232
|
-
fn gen_storage_functions(enum_name: &Ident, variant: &Variant
|
|
213
|
+
fn gen_storage_functions(enum_name: &Ident, variant: &Variant) -> TokenStream {
|
|
233
214
|
let config = StorageVariantConfig::try_from(variant)
|
|
234
215
|
.unwrap_or_else(|e| panic!("failed to parse storage variant for {}: {}", variant.ident, e));
|
|
235
216
|
|
|
@@ -241,19 +222,36 @@ fn gen_storage_functions(enum_name: &Ident, variant: &Variant, ttl_provider: &Tt
|
|
|
241
222
|
let storage_acc = gen_storage_accessor(&config.storage_type);
|
|
242
223
|
let value_type = config.storage_type.value_type();
|
|
243
224
|
|
|
244
|
-
//
|
|
245
|
-
let
|
|
246
|
-
.
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
.unwrap_or_default();
|
|
225
|
+
// Automatic TTL extension for persistent storage (unless #[no_ttl_extension] is specified)
|
|
226
|
+
let auto_ttl_extend = if config.storage_type.is_persistent() && !config.no_ttl_extension {
|
|
227
|
+
gen_ttl_extension(&config.storage_type, true)
|
|
228
|
+
} else {
|
|
229
|
+
TokenStream::new()
|
|
230
|
+
};
|
|
251
231
|
|
|
252
|
-
let getter_impl =
|
|
253
|
-
|
|
232
|
+
let getter_impl = gen_getter_fn(
|
|
233
|
+
&getter,
|
|
234
|
+
&fn_params,
|
|
235
|
+
&storage_key,
|
|
236
|
+
&storage_acc,
|
|
237
|
+
value_type,
|
|
238
|
+
&config.default_value,
|
|
239
|
+
&auto_ttl_extend,
|
|
240
|
+
);
|
|
254
241
|
|
|
255
242
|
// Manual TTL extension (user provides threshold/extend_to)
|
|
256
|
-
let
|
|
243
|
+
let manual_ttl_extend = gen_ttl_extension(&config.storage_type, false);
|
|
244
|
+
|
|
245
|
+
// Has implementation (conditionally includes TTL extension)
|
|
246
|
+
let has_impl = if auto_ttl_extend.is_empty() {
|
|
247
|
+
quote! { #storage_acc.has(&key) }
|
|
248
|
+
} else {
|
|
249
|
+
quote! {
|
|
250
|
+
let exists = #storage_acc.has(&key);
|
|
251
|
+
if exists { #auto_ttl_extend }
|
|
252
|
+
exists
|
|
253
|
+
}
|
|
254
|
+
};
|
|
257
255
|
|
|
258
256
|
quote! {
|
|
259
257
|
#getter_impl
|
|
@@ -261,7 +259,7 @@ fn gen_storage_functions(enum_name: &Ident, variant: &Variant, ttl_provider: &Tt
|
|
|
261
259
|
pub fn #setter(#fn_params, value: &#value_type) {
|
|
262
260
|
let key = #storage_key;
|
|
263
261
|
#storage_acc.set(&key, value);
|
|
264
|
-
#
|
|
262
|
+
#auto_ttl_extend
|
|
265
263
|
}
|
|
266
264
|
|
|
267
265
|
pub fn #remover(#fn_params) {
|
|
@@ -278,14 +276,12 @@ fn gen_storage_functions(enum_name: &Ident, variant: &Variant, ttl_provider: &Tt
|
|
|
278
276
|
|
|
279
277
|
pub fn #has(#fn_params) -> bool {
|
|
280
278
|
let key = #storage_key;
|
|
281
|
-
|
|
282
|
-
if exists { #auto_ttl }
|
|
283
|
-
exists
|
|
279
|
+
#has_impl
|
|
284
280
|
}
|
|
285
281
|
|
|
286
282
|
pub fn #ttl_extender(#fn_params, threshold: u32, extend_to: u32) {
|
|
287
283
|
let key = #storage_key;
|
|
288
|
-
#
|
|
284
|
+
#manual_ttl_extend
|
|
289
285
|
}
|
|
290
286
|
}
|
|
291
287
|
}
|
|
@@ -297,14 +293,9 @@ fn gen_storage_accessor(storage_type: &StorageType) -> TokenStream {
|
|
|
297
293
|
}
|
|
298
294
|
|
|
299
295
|
/// Generates TTL extension code.
|
|
300
|
-
/// -
|
|
301
|
-
/// -
|
|
302
|
-
fn gen_ttl_extension(storage_type: &StorageType,
|
|
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
|
-
|
|
296
|
+
/// - use_stored_config=true: fetches TTL config from TtlConfigStorage, only extends if config is set
|
|
297
|
+
/// - use_stored_config=false: uses local variables `threshold` and `extend_to` (for manual extension)
|
|
298
|
+
fn gen_ttl_extension(storage_type: &StorageType, use_stored_config: bool) -> TokenStream {
|
|
308
299
|
let accessor = gen_storage_accessor(storage_type);
|
|
309
300
|
let extend_call = if storage_type.is_instance() {
|
|
310
301
|
quote! { #accessor.extend_ttl(threshold, extend_to); }
|
|
@@ -312,25 +303,24 @@ fn gen_ttl_extension(storage_type: &StorageType, provider: Option<&Type>) -> Tok
|
|
|
312
303
|
quote! { #accessor.extend_ttl(&key, threshold, extend_to); }
|
|
313
304
|
};
|
|
314
305
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
306
|
+
if use_stored_config {
|
|
307
|
+
let method = format_ident!("{}", storage_type.accessor_name());
|
|
308
|
+
quote! {
|
|
309
|
+
if let Some(utils::ttl::TtlConfig { threshold, extend_to }) = utils::ttl::TtlConfigStorage::#method(env) {
|
|
310
|
+
#extend_call
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
} else {
|
|
314
|
+
extend_call
|
|
318
315
|
}
|
|
319
316
|
}
|
|
320
317
|
|
|
321
318
|
/// Checks if a type is a primitive type
|
|
322
|
-
fn is_primitive_type(ty: &Type) -> bool {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
matches!(ident.to_string().as_str(), "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "bool")
|
|
328
|
-
} else {
|
|
329
|
-
false
|
|
330
|
-
}
|
|
331
|
-
} else {
|
|
332
|
-
false
|
|
333
|
-
}
|
|
319
|
+
pub(crate) fn is_primitive_type(ty: &Type) -> bool {
|
|
320
|
+
let Type::Path(type_path) = ty else { return false };
|
|
321
|
+
let Some(segment) = type_path.path.segments.first() else { return false };
|
|
322
|
+
type_path.path.segments.len() == 1
|
|
323
|
+
&& matches!(segment.ident.to_string().as_str(), "u32" | "i32" | "u64" | "i64" | "u128" | "i128" | "bool")
|
|
334
324
|
}
|
|
335
325
|
|
|
336
326
|
/// Generates function parameters: `env: &Env` or `env: &Env, field1: Type1, ...`.
|
|
@@ -398,42 +388,27 @@ fn gen_getter_fn(
|
|
|
398
388
|
key: &TokenStream,
|
|
399
389
|
accessor: &TokenStream,
|
|
400
390
|
value_type: &Type,
|
|
401
|
-
|
|
402
|
-
|
|
391
|
+
default_value: &Option<Expr>,
|
|
392
|
+
auto_ttl_extend: &TokenStream,
|
|
403
393
|
) -> TokenStream {
|
|
404
|
-
let
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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
|
-
},
|
|
394
|
+
let (return_type, return_expr) = match default_value {
|
|
395
|
+
Some(expr) => (quote! { #value_type }, quote! { value.unwrap_or(#expr) }),
|
|
396
|
+
None => (quote! { Option<#value_type> }, quote! { value }),
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// If auto TTL extension is enabled, check if the value is not None and extend the TTL
|
|
400
|
+
let ttl_check = if auto_ttl_extend.is_empty() {
|
|
401
|
+
TokenStream::new()
|
|
402
|
+
} else {
|
|
403
|
+
quote! { if value.is_some() { #auto_ttl_extend } }
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
quote! {
|
|
407
|
+
pub fn #name(#params) -> #return_type {
|
|
408
|
+
let key = #key;
|
|
409
|
+
let value = #accessor.get::<_, #value_type>(&key);
|
|
410
|
+
#ttl_check
|
|
411
|
+
#return_expr
|
|
412
|
+
}
|
|
438
413
|
}
|
|
439
414
|
}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
use proc_macro2::TokenStream;
|
|
2
|
+
use quote::quote;
|
|
3
|
+
|
|
4
|
+
use crate::tests::test_helpers::assert_panics_contains;
|
|
5
|
+
|
|
6
|
+
// ============================================
|
|
7
|
+
// Snapshot Test: ContractImpl Code Generation
|
|
8
|
+
// ============================================
|
|
9
|
+
|
|
10
|
+
/// Comprehensive snapshot test covering all contract_impl macro features:
|
|
11
|
+
/// - Inherent impl: public methods with Env (adds TTL), private/pub(crate) methods (skipped)
|
|
12
|
+
/// - Trait impl: all methods with Env get TTL extension
|
|
13
|
+
/// - Qualified Env types (soroban_sdk::Env)
|
|
14
|
+
/// - Env parameter not in first position
|
|
15
|
+
/// - Methods without Env (skipped)
|
|
16
|
+
#[test]
|
|
17
|
+
fn snapshot_generated_contract_impl_code() {
|
|
18
|
+
// Test inherent impl with empty attr
|
|
19
|
+
let empty_attr = TokenStream::new();
|
|
20
|
+
let inherent_input = quote! {
|
|
21
|
+
impl MyContract {
|
|
22
|
+
/// Public method with Env - should have TTL extension
|
|
23
|
+
pub fn public_with_env(env: Env, value: u32) -> u32 {
|
|
24
|
+
value * 2
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// Public method with qualified Env path - should have TTL extension
|
|
28
|
+
pub fn with_qualified_env(env: soroban_sdk::Env) -> u32 {
|
|
29
|
+
42
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/// Public method with Env not as first parameter - should have TTL extension
|
|
33
|
+
pub fn env_second(value: u32, env: Env) -> u32 {
|
|
34
|
+
value * 2
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Public method without Env - should NOT have TTL extension
|
|
38
|
+
pub fn public_without_env(value: u32) -> u32 {
|
|
39
|
+
value * 4
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Private method with Env - should NOT have TTL extension (not public)
|
|
43
|
+
fn private_with_env(env: Env, value: u32) -> u32 {
|
|
44
|
+
value * 5
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Pub(crate) method with Env - should NOT have TTL extension (not fully public)
|
|
48
|
+
pub(crate) fn pub_crate_with_env(env: Env, value: u32) -> u32 {
|
|
49
|
+
value * 7
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
let inherent_result = crate::contract_impl::contract_impl(empty_attr.clone(), inherent_input);
|
|
55
|
+
let inherent_formatted =
|
|
56
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(inherent_result).expect("failed to parse generated code"));
|
|
57
|
+
|
|
58
|
+
// Test trait impl with empty attr
|
|
59
|
+
let trait_input = quote! {
|
|
60
|
+
impl SomeTrait for MyContract {
|
|
61
|
+
/// Trait method with Env - should have TTL extension
|
|
62
|
+
fn trait_method_with_env(env: Env, value: u32) -> u32 {
|
|
63
|
+
value * 2
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Trait method without Env - should NOT have TTL extension
|
|
67
|
+
fn trait_method_without_env(value: u32) -> u32 {
|
|
68
|
+
value * 4
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
let trait_result = crate::contract_impl::contract_impl(empty_attr, trait_input);
|
|
74
|
+
let trait_formatted =
|
|
75
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(trait_result).expect("failed to parse generated code"));
|
|
76
|
+
|
|
77
|
+
// Test trait impl with contracttrait attr
|
|
78
|
+
let contracttrait_attr = quote! { contracttrait };
|
|
79
|
+
let contracttrait_input = quote! {
|
|
80
|
+
impl AnotherTrait for MyContract {
|
|
81
|
+
/// Trait method with contracttrait attr - should have TTL extension
|
|
82
|
+
fn contracttrait_method(env: Env, value: u32) -> u32 {
|
|
83
|
+
value * 3
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
let contracttrait_result = crate::contract_impl::contract_impl(contracttrait_attr, contracttrait_input);
|
|
89
|
+
let contracttrait_formatted =
|
|
90
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(contracttrait_result).expect("failed to parse generated code"));
|
|
91
|
+
|
|
92
|
+
// Combine all for single snapshot
|
|
93
|
+
let combined = format!(
|
|
94
|
+
"// === Inherent Impl (no attr) ===\n\n{}\n\n// === Trait Impl (no attr) ===\n\n{}\n\n// === Trait Impl (contracttrait attr) ===\n\n{}",
|
|
95
|
+
inherent_formatted, trait_formatted, contracttrait_formatted
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
insta::assert_snapshot!(combined);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ============================================
|
|
102
|
+
// Error Cases: Invalid Input
|
|
103
|
+
// ============================================
|
|
104
|
+
|
|
105
|
+
#[test]
|
|
106
|
+
fn test_non_impl_block_input() {
|
|
107
|
+
let invalid_inputs = vec![
|
|
108
|
+
(
|
|
109
|
+
"struct",
|
|
110
|
+
quote! {
|
|
111
|
+
struct MyStruct {
|
|
112
|
+
field: u32,
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
),
|
|
116
|
+
(
|
|
117
|
+
"enum",
|
|
118
|
+
quote! {
|
|
119
|
+
enum MyEnum {
|
|
120
|
+
Variant1,
|
|
121
|
+
Variant2,
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
),
|
|
125
|
+
("function", quote! { fn a_function() {} }),
|
|
126
|
+
("const item", quote! { const A_CONST: u32 = 1; }),
|
|
127
|
+
("type alias", quote! { type AnAlias = u32; }),
|
|
128
|
+
(
|
|
129
|
+
"trait",
|
|
130
|
+
quote! {
|
|
131
|
+
trait ATrait {
|
|
132
|
+
fn method(&self);
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
),
|
|
136
|
+
];
|
|
137
|
+
|
|
138
|
+
for (case, input) in invalid_inputs {
|
|
139
|
+
assert_panics_contains(case, "failed to parse impl block", || {
|
|
140
|
+
crate::contract_impl::contract_impl(TokenStream::new(), input.clone());
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ============================================
|
|
146
|
+
// Unit Tests: Behavior Verification
|
|
147
|
+
// ============================================
|
|
148
|
+
|
|
149
|
+
/// Verifies that the macro adds #[soroban_sdk::contractimpl] attribute without parentheses when attr is empty
|
|
150
|
+
#[test]
|
|
151
|
+
fn test_adds_soroban_contractimpl_attribute_without_attr() {
|
|
152
|
+
let input = quote! {
|
|
153
|
+
impl MyContract {
|
|
154
|
+
pub fn my_method(env: Env) {}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
let result = crate::contract_impl::contract_impl(TokenStream::new(), input);
|
|
159
|
+
let result_str = result.to_string();
|
|
160
|
+
|
|
161
|
+
// Should have contractimpl without parentheses when attr is empty
|
|
162
|
+
assert!(
|
|
163
|
+
result_str.contains("# [soroban_sdk :: contractimpl]"),
|
|
164
|
+
"should add #[soroban_sdk::contractimpl] attribute without parentheses when attr is empty. Got: {}",
|
|
165
|
+
result_str
|
|
166
|
+
);
|
|
167
|
+
// Should NOT have empty parentheses
|
|
168
|
+
assert!(
|
|
169
|
+
!result_str.contains("contractimpl ()"),
|
|
170
|
+
"should NOT have empty parentheses when attr is empty. Got: {}",
|
|
171
|
+
result_str
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Verifies that the macro adds #[soroban_sdk::contractimpl(attr)] when attr is provided
|
|
176
|
+
#[test]
|
|
177
|
+
fn test_adds_soroban_contractimpl_attribute_with_attr() {
|
|
178
|
+
let input = quote! {
|
|
179
|
+
impl SomeTrait for MyContract {
|
|
180
|
+
fn my_method(env: Env) {}
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
let attr = quote! { contracttrait };
|
|
185
|
+
let result = crate::contract_impl::contract_impl(attr, input);
|
|
186
|
+
let result_str = result.to_string();
|
|
187
|
+
|
|
188
|
+
// Should have contractimpl with the attr in parentheses
|
|
189
|
+
assert!(
|
|
190
|
+
result_str.contains("contractimpl (contracttrait)"),
|
|
191
|
+
"should add #[soroban_sdk::contractimpl(contracttrait)] attribute. Got: {}",
|
|
192
|
+
result_str
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/// Helper to assert TTL extension behavior in generated code
|
|
197
|
+
fn assert_ttl_extension(input: TokenStream, expected: bool, env_ident: Option<&str>, case: &str) {
|
|
198
|
+
let result = crate::contract_impl::contract_impl(TokenStream::new(), input);
|
|
199
|
+
let result_str = result.to_string();
|
|
200
|
+
|
|
201
|
+
let has_ttl = result_str.contains("TtlConfigStorage :: instance");
|
|
202
|
+
|
|
203
|
+
assert_eq!(
|
|
204
|
+
has_ttl,
|
|
205
|
+
expected,
|
|
206
|
+
"{}: TTL extension {} but {}",
|
|
207
|
+
case,
|
|
208
|
+
if expected { "expected" } else { "not expected" },
|
|
209
|
+
if has_ttl { "was found" } else { "was not found" }
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
if expected {
|
|
213
|
+
assert!(result_str.contains("extend_ttl"), "{}: should insert extend_ttl call", case);
|
|
214
|
+
|
|
215
|
+
// Verify correct env identifier is used in TTL extension code
|
|
216
|
+
if let Some(env) = env_ident {
|
|
217
|
+
let instance_pattern = format!("TtlConfigStorage :: instance ({})", env);
|
|
218
|
+
let storage_pattern = format!("{} . storage ()", env);
|
|
219
|
+
assert!(
|
|
220
|
+
result_str.contains(&instance_pattern),
|
|
221
|
+
"{}: should use '{}' in TtlConfigStorage::instance call",
|
|
222
|
+
case,
|
|
223
|
+
env
|
|
224
|
+
);
|
|
225
|
+
assert!(result_str.contains(&storage_pattern), "{}: should use '{}' for storage access", case, env);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#[test]
|
|
231
|
+
fn test_ttl_extension_insertion() {
|
|
232
|
+
let cases: Vec<(&str, TokenStream, bool, Option<&str>)> = vec![
|
|
233
|
+
// (case name, input, should have TTL extension, optional env ident to verify)
|
|
234
|
+
(
|
|
235
|
+
"public method with Env",
|
|
236
|
+
quote! {
|
|
237
|
+
impl MyContract {
|
|
238
|
+
pub fn my_method(env: Env) { let x = 1; }
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
true,
|
|
242
|
+
Some("env"),
|
|
243
|
+
),
|
|
244
|
+
(
|
|
245
|
+
"private method with Env",
|
|
246
|
+
quote! {
|
|
247
|
+
impl MyContract {
|
|
248
|
+
fn private_method(env: Env) { let x = 1; }
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
false,
|
|
252
|
+
None,
|
|
253
|
+
),
|
|
254
|
+
(
|
|
255
|
+
"public method without Env",
|
|
256
|
+
quote! {
|
|
257
|
+
impl MyContract {
|
|
258
|
+
pub fn no_env_method(value: u32) -> u32 { value }
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
false,
|
|
262
|
+
None,
|
|
263
|
+
),
|
|
264
|
+
(
|
|
265
|
+
"custom Env identifier",
|
|
266
|
+
quote! {
|
|
267
|
+
impl MyContract {
|
|
268
|
+
pub fn my_method(my_custom_env: Env) { let x = 1; }
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
true,
|
|
272
|
+
Some("my_custom_env"),
|
|
273
|
+
),
|
|
274
|
+
(
|
|
275
|
+
"trait impl method with Env",
|
|
276
|
+
quote! {
|
|
277
|
+
impl SomeTrait for MyContract {
|
|
278
|
+
fn trait_method(env: Env) { let x = 1; }
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
true,
|
|
282
|
+
Some("env"),
|
|
283
|
+
),
|
|
284
|
+
];
|
|
285
|
+
|
|
286
|
+
for (case, input, expected, env_ident) in cases {
|
|
287
|
+
assert_ttl_extension(input, expected, env_ident, case);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
mod contract_impl;
|
|
2
|
+
mod ownable;
|
|
3
|
+
mod storage;
|
|
4
|
+
mod test_helpers;
|
|
5
|
+
mod ttl_configurable;
|
|
6
|
+
|
|
7
|
+
// Note: error.rs and event.rs use proc_macro::TokenStream which cannot be tested
|
|
8
|
+
// outside of a procedural macro context. These macros are tested via integration
|
|
9
|
+
// tests in the contracts that use them (e.g., utils crate).
|