@layerzerolabs/protocol-stellar-v2 0.2.29 → 0.2.30

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 (205) hide show
  1. package/.turbo/turbo-build.log +371 -321
  2. package/.turbo/turbo-lint.log +211 -202
  3. package/.turbo/turbo-test.log +1766 -1673
  4. package/Cargo.lock +11 -1
  5. package/contracts/common-macros/src/lib.rs +0 -2
  6. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +1 -0
  7. package/contracts/endpoint-v2/src/messaging_channel.rs +32 -3
  8. package/contracts/endpoint-v2/src/tests/endpoint_setup.rs +1 -1
  9. package/contracts/endpoint-v2/src/tests/messaging_channel/clear_payload.rs +1 -1
  10. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound.rs +6 -6
  11. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound_payload_hash.rs +1 -1
  12. package/contracts/endpoint-v2/src/tests/messaging_channel/outbound.rs +16 -10
  13. package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +10 -10
  14. package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +3 -3
  15. package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +4 -3
  16. package/contracts/macro-integration-tests/tests/runtime/upgradeable/migrate_guard_and_state.rs +1 -57
  17. package/contracts/macro-integration-tests/tests/ui/lz_contract/fail/upgradeable_missing_internal.stderr +0 -30
  18. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.stderr +5 -3
  19. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.stderr +6 -4
  20. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.stderr +5 -3
  21. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.stderr +5 -3
  22. package/contracts/macro-integration-tests/tests/ui/upgradeable/fail/missing_auth_trait.stderr +0 -30
  23. package/contracts/macro-integration-tests/tests/ui/upgradeable/fail/missing_upgradeable_internal.stderr +0 -30
  24. package/contracts/macro-integration-tests/tests/ui/upgradeable/pass/basic.rs +0 -2
  25. package/contracts/macro-integration-tests/tests/ui/upgradeable/pass/multisig_contract.rs +0 -2
  26. package/contracts/macro-integration-tests/tests/ui/upgradeable/pass/no_migration.rs +0 -2
  27. package/contracts/macro-integration-tests/tests/ui/upgradeable/pass/no_user_contractimpl.rs +1 -3
  28. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +3 -6
  29. package/contracts/message-libs/message-lib-common/src/tests/worker_options/extract_type_3_options.rs +10 -0
  30. package/contracts/message-libs/message-lib-common/src/worker_options.rs +6 -2
  31. package/contracts/message-libs/treasury/src/interfaces/zro_fee_lib.rs +3 -3
  32. package/contracts/message-libs/treasury/src/lib.rs +2 -1
  33. package/contracts/message-libs/treasury/src/tests/setup.rs +1 -1
  34. package/contracts/message-libs/treasury/src/treasury.rs +5 -2
  35. package/contracts/message-libs/uln-302/src/errors.rs +2 -0
  36. package/contracts/message-libs/uln-302/src/events.rs +3 -3
  37. package/contracts/message-libs/uln-302/src/interfaces/receive_uln.rs +8 -0
  38. package/contracts/message-libs/uln-302/src/lib.rs +2 -1
  39. package/contracts/message-libs/uln-302/src/receive_uln.rs +16 -13
  40. package/contracts/message-libs/uln-302/src/send_uln.rs +51 -24
  41. package/contracts/message-libs/uln-302/src/storage.rs +2 -2
  42. package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +45 -1
  43. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verifiable.rs +63 -0
  44. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +47 -2
  45. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +50 -1
  46. package/contracts/message-libs/uln-302/src/uln302.rs +0 -8
  47. package/contracts/oapps/counter/Cargo.toml +4 -4
  48. package/contracts/oapps/counter/integration_tests/setup_uln.rs +22 -2
  49. package/contracts/oapps/counter/src/counter.rs +8 -8
  50. package/contracts/oapps/oapp/src/interfaces/oapp_msg_inspector.rs +33 -10
  51. package/contracts/oapps/oapp/src/lib.rs +6 -2
  52. package/contracts/oapps/oapp/src/oapp_core.rs +49 -24
  53. package/contracts/oapps/oapp/src/oapp_options_type3.rs +21 -14
  54. package/contracts/oapps/oapp/src/oapp_receiver.rs +17 -16
  55. package/contracts/oapps/oapp/src/oapp_sender.rs +66 -15
  56. package/contracts/oapps/oapp/src/tests/oapp_core.rs +5 -5
  57. package/contracts/oapps/oapp/src/tests/oapp_options_type3.rs +18 -18
  58. package/contracts/oapps/oapp/src/tests/oapp_receiver.rs +4 -4
  59. package/contracts/oapps/oapp/src/tests/oapp_sender.rs +3 -3
  60. package/contracts/oapps/oapp-macros/Cargo.toml +0 -1
  61. package/contracts/oapps/oapp-macros/src/generators.rs +87 -46
  62. package/contracts/oapps/oapp-macros/src/lib.rs +3 -61
  63. package/contracts/oapps/oapp-macros/src/tests/oapp.rs +9 -23
  64. package/contracts/oapps/oapp-macros/src/tests/parse_custom_impls.rs +15 -11
  65. package/contracts/oapps/oft/Cargo.toml +1 -1
  66. package/contracts/oapps/oft/integration-tests/extensions/test_oft_fee.rs +3 -3
  67. package/contracts/oapps/oft/integration-tests/extensions/test_pausable.rs +4 -4
  68. package/contracts/oapps/oft/integration-tests/extensions/test_rate_limiter.rs +144 -8
  69. package/contracts/oapps/oft/integration-tests/setup.rs +4 -2
  70. package/contracts/oapps/oft/integration-tests/utils.rs +25 -11
  71. package/contracts/oapps/oft/src/extensions/oft_fee.rs +65 -63
  72. package/contracts/oapps/oft/src/extensions/pausable.rs +2 -3
  73. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +22 -5
  74. package/contracts/oapps/oft/src/interfaces/mint_burnable.rs +18 -0
  75. package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
  76. package/contracts/oapps/oft/src/lib.rs +4 -2
  77. package/contracts/oapps/oft/src/oft.rs +35 -36
  78. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +13 -9
  79. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +14 -9
  80. package/contracts/oapps/oft/src/oft_types/mod.rs +14 -12
  81. package/contracts/oapps/oft/src/tests/extensions/oft_fee.rs +28 -20
  82. package/contracts/oapps/oft/src/tests/extensions/rate_limiter.rs +136 -2
  83. package/contracts/oapps/oft/src/tests/oft_types/lock_unlock.rs +12 -8
  84. package/contracts/oapps/oft-core/integration-tests/setup.rs +8 -9
  85. package/contracts/oapps/oft-core/integration-tests/test_with_sml.rs +7 -6
  86. package/contracts/oapps/oft-core/integration-tests/utils.rs +5 -4
  87. package/contracts/oapps/oft-core/src/codec/oft_compose_msg_codec.rs +2 -2
  88. package/contracts/oapps/oft-core/src/codec/oft_msg_codec.rs +33 -37
  89. package/contracts/oapps/oft-core/src/errors.rs +2 -1
  90. package/contracts/oapps/oft-core/src/events.rs +6 -0
  91. package/contracts/oapps/oft-core/src/lib.rs +8 -4
  92. package/contracts/oapps/oft-core/src/oft_core.rs +205 -148
  93. package/contracts/oapps/oft-core/src/storage.rs +4 -2
  94. package/contracts/oapps/oft-core/src/tests/test_decimals.rs +2 -2
  95. package/contracts/oapps/oft-core/src/tests/test_lz_receive.rs +6 -6
  96. package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +7 -6
  97. package/contracts/oapps/oft-core/src/tests/test_oft_msg_codec.rs +11 -82
  98. package/contracts/oapps/oft-core/src/tests/test_quote_oft.rs +13 -13
  99. package/contracts/oapps/oft-core/src/tests/test_quote_send.rs +1 -1
  100. package/contracts/oapps/oft-core/src/tests/test_resolve_address.rs +2 -2
  101. package/contracts/oapps/oft-core/src/tests/test_send.rs +22 -22
  102. package/contracts/oapps/oft-core/src/tests/test_utils.rs +20 -22
  103. package/contracts/oapps/oft-core/src/utils.rs +12 -8
  104. package/contracts/sac-manager/Cargo.toml +25 -0
  105. package/contracts/sac-manager/src/errors.rs +18 -0
  106. package/contracts/sac-manager/src/extensions/mod.rs +6 -0
  107. package/contracts/sac-manager/src/extensions/redistribution.rs +109 -0
  108. package/contracts/sac-manager/src/extensions/supply_control/mod.rs +488 -0
  109. package/contracts/sac-manager/src/extensions/supply_control/rate_limit.rs +126 -0
  110. package/contracts/sac-manager/src/interfaces/mod.rs +3 -0
  111. package/contracts/sac-manager/src/interfaces/sac_manager.rs +52 -0
  112. package/contracts/sac-manager/src/lib.rs +23 -0
  113. package/contracts/sac-manager/src/sac_manager.rs +193 -0
  114. package/contracts/sac-manager/src/storage.rs +20 -0
  115. package/contracts/sac-manager/src/tests/mod.rs +14 -0
  116. package/contracts/sac-manager/src/tests/redistribution/mod.rs +1 -0
  117. package/contracts/sac-manager/src/tests/redistribution/redistribute_funds.rs +82 -0
  118. package/contracts/sac-manager/src/tests/sac_manager/admin_mint.rs +206 -0
  119. package/contracts/sac-manager/src/tests/sac_manager/burn.rs +215 -0
  120. package/contracts/sac-manager/src/tests/sac_manager/clawback.rs +209 -0
  121. package/contracts/sac-manager/src/tests/sac_manager/mint.rs +252 -0
  122. package/contracts/sac-manager/src/tests/sac_manager/mod.rs +9 -0
  123. package/contracts/sac-manager/src/tests/sac_manager/set_admin.rs +36 -0
  124. package/contracts/sac-manager/src/tests/sac_manager/set_authorized.rs +43 -0
  125. package/contracts/sac-manager/src/tests/sac_manager/set_oft_address.rs +47 -0
  126. package/contracts/sac-manager/src/tests/sac_manager/test_helper.rs +75 -0
  127. package/contracts/sac-manager/src/tests/sac_manager/view_functions.rs +60 -0
  128. package/contracts/sac-manager/src/tests/supply_control/enumerable_set.rs +256 -0
  129. package/contracts/sac-manager/src/tests/supply_control/mod.rs +8 -0
  130. package/contracts/sac-manager/src/tests/supply_control/refill.rs +90 -0
  131. package/contracts/sac-manager/src/tests/supply_control/set_mint_whitelist.rs +245 -0
  132. package/contracts/sac-manager/src/tests/supply_control/set_supply_controller.rs +267 -0
  133. package/contracts/sac-manager/src/tests/supply_control/set_supply_controller_manager.rs +122 -0
  134. package/contracts/sac-manager/src/tests/supply_control/test_helper.rs +38 -0
  135. package/contracts/sac-manager/src/tests/supply_control/update_allow_any_mint_burn.rs +114 -0
  136. package/contracts/sac-manager/src/tests/supply_control/update_limit_config.rs +257 -0
  137. package/contracts/sac-manager/src/tests/test_helper.rs +190 -0
  138. package/contracts/upgrader/src/lib.rs +2 -1
  139. package/contracts/utils/src/errors.rs +0 -1
  140. package/contracts/utils/src/tests/upgradeable.rs +0 -66
  141. package/contracts/utils/src/upgradeable.rs +0 -18
  142. package/contracts/workers/dvn/src/dvn.rs +2 -2
  143. package/contracts/workers/dvn/src/interfaces/dvn.rs +2 -2
  144. package/contracts/workers/dvn/src/lib.rs +2 -1
  145. package/contracts/workers/dvn-fee-lib/src/lib.rs +3 -1
  146. package/contracts/workers/executor/src/auth.rs +42 -26
  147. package/contracts/workers/executor/src/executor.rs +28 -3
  148. package/contracts/workers/executor/src/lib.rs +4 -2
  149. package/contracts/workers/executor/src/storage.rs +21 -1
  150. package/contracts/workers/executor/src/tests/auth.rs +64 -20
  151. package/contracts/workers/executor/src/tests/executor.rs +1 -1
  152. package/contracts/workers/executor/src/tests/setup.rs +18 -0
  153. package/contracts/workers/executor-fee-lib/src/lib.rs +4 -1
  154. package/contracts/workers/executor-helper/src/executor_helper.rs +24 -10
  155. package/contracts/workers/executor-helper/src/tests/setup.rs +147 -34
  156. package/contracts/workers/price-feed/src/lib.rs +3 -1
  157. package/contracts/workers/worker/src/lib.rs +2 -1
  158. package/contracts/workers/worker/src/worker.rs +31 -17
  159. package/docs/oapp-guide.md +17 -8
  160. package/docs/oft-guide.md +3 -3
  161. package/package.json +3 -3
  162. package/sdk/.turbo/turbo-test.log +512 -351
  163. package/sdk/dist/generated/bml.d.ts +3 -9
  164. package/sdk/dist/generated/bml.js +6 -7
  165. package/sdk/dist/generated/counter.d.ts +22 -28
  166. package/sdk/dist/generated/counter.js +11 -12
  167. package/sdk/dist/generated/dvn.d.ts +36 -54
  168. package/sdk/dist/generated/dvn.js +10 -15
  169. package/sdk/dist/generated/dvn_fee_lib.d.ts +3 -21
  170. package/sdk/dist/generated/dvn_fee_lib.js +6 -11
  171. package/sdk/dist/generated/endpoint.d.ts +3 -9
  172. package/sdk/dist/generated/endpoint.js +6 -7
  173. package/sdk/dist/generated/executor.d.ts +80 -54
  174. package/sdk/dist/generated/executor.js +16 -16
  175. package/sdk/dist/generated/executor_fee_lib.d.ts +3 -21
  176. package/sdk/dist/generated/executor_fee_lib.js +6 -11
  177. package/sdk/dist/generated/executor_helper.d.ts +36 -42
  178. package/sdk/dist/generated/executor_helper.js +9 -10
  179. package/sdk/dist/generated/layerzero_view.d.ts +20 -32
  180. package/sdk/dist/generated/layerzero_view.js +25 -26
  181. package/sdk/dist/generated/oft.d.ts +147 -79
  182. package/sdk/dist/generated/oft.js +47 -54
  183. package/sdk/dist/generated/price_feed.d.ts +20 -38
  184. package/sdk/dist/generated/price_feed.js +15 -20
  185. package/sdk/dist/generated/sac_manager.d.ts +1309 -0
  186. package/sdk/dist/generated/sac_manager.js +484 -0
  187. package/sdk/dist/generated/sml.d.ts +3 -9
  188. package/sdk/dist/generated/sml.js +6 -7
  189. package/sdk/dist/generated/treasury.d.ts +3 -9
  190. package/sdk/dist/generated/treasury.js +8 -9
  191. package/sdk/dist/generated/uln302.d.ts +20 -20
  192. package/sdk/dist/generated/uln302.js +25 -22
  193. package/sdk/dist/generated/upgrader.d.ts +3 -9
  194. package/sdk/dist/generated/upgrader.js +6 -7
  195. package/sdk/dist/index.d.ts +1 -0
  196. package/sdk/dist/index.js +1 -0
  197. package/sdk/package.json +1 -1
  198. package/sdk/src/index.ts +1 -0
  199. package/sdk/test/oft-sml.test.ts +7 -5
  200. package/sdk/test/sac-manager-redistribution.test.ts +578 -0
  201. package/sdk/test/suites/globalSetup.ts +11 -6
  202. package/sdk/test/test_data/test_upgradeable_dvn.wasm +0 -0
  203. package/sdk/test/upgrader.test.ts +75 -202
  204. package/sdk/test/utils.ts +40 -0
  205. package/tools/ts-bindings-gen/src/main.rs +1 -0
@@ -1,11 +1,53 @@
1
1
  use crate::{
2
2
  errors::OAppError,
3
- oapp_core::{endpoint_client, OAppCore},
3
+ oapp_core::{endpoint_client, get_peer_or_panic, OAppCore},
4
4
  };
5
5
  use endpoint_v2::{MessagingFee, MessagingParams, MessagingReceipt};
6
6
  use soroban_sdk::{token::TokenClient, Address, Bytes, Env};
7
7
  use utils::option_ext::OptionExt;
8
8
 
9
+ /// The version of the OAppSender implementation.
10
+ /// Version is bumped when changes are made to this contract.
11
+ pub const SENDER_VERSION: u64 = 1;
12
+
13
+ /// Represents a fee payer address with explicit authorization state.
14
+ ///
15
+ /// This enum forces callers of `__lz_send` to explicitly declare whether
16
+ /// `require_auth()` has already been called for the fee payer address.
17
+ /// This prevents the common mistake of forgetting to authorize the fee payer.
18
+ ///
19
+ /// # Variants
20
+ /// - `Unverified` — Safe default. `__lz_send` will call `require_auth()` on the address.
21
+ /// Use this when the caller has **not** already authorized the fee payer.
22
+ /// - `Verified` — Caller asserts that `require_auth()` has already been called.
23
+ /// Use this to avoid a duplicate `require_auth()` node in the Soroban auth tree
24
+ /// (e.g., when the same address was already authorized as the message sender).
25
+ #[derive(Clone)]
26
+ pub enum FeePayer {
27
+ /// The fee payer has **not** been authorized yet.
28
+ /// `__lz_send` will call `fee_payer.require_auth()` before transferring fees.
29
+ /// This is the safe default — use this if unsure.
30
+ Unverified(Address),
31
+
32
+ /// The fee payer has **already** been authorized by the caller via `require_auth()`.
33
+ /// `__lz_send` will skip the auth check to avoid creating a duplicate auth node
34
+ /// in the Soroban authorization tree.
35
+ ///
36
+ /// # Safety
37
+ /// Only use this variant if you have already called `require_auth()` on this address
38
+ /// in the current contract invocation. Misuse may allow unauthorized fee deductions.
39
+ Verified(Address),
40
+ }
41
+
42
+ impl FeePayer {
43
+ /// Returns a reference to the underlying address.
44
+ pub fn address(&self) -> &Address {
45
+ match self {
46
+ FeePayer::Unverified(addr) | FeePayer::Verified(addr) => addr,
47
+ }
48
+ }
49
+ }
50
+
9
51
  /// A helper trait for sending cross-chain messages via LayerZero.
10
52
  ///
11
53
  /// Contracts should implement this trait to gain access to the `__lz_quote` and `__lz_send` helper
@@ -29,7 +71,7 @@ pub trait OAppSenderInternal: OAppCore {
29
71
  /// # Returns
30
72
  /// * `MessagingFee`: The messaging fee for the message
31
73
  fn __quote(env: &Env, dst_eid: u32, message: &Bytes, options: &Bytes, pay_in_zro: bool) -> MessagingFee {
32
- let receiver = Self::peer(env, dst_eid).unwrap_or_panic(env, OAppError::NoPeer);
74
+ let receiver = get_peer_or_panic::<Self>(env, dst_eid);
33
75
  endpoint_client::<Self>(env).quote(
34
76
  &env.current_contract_address(),
35
77
  &MessagingParams { dst_eid, receiver, message: message.clone(), options: options.clone(), pay_in_zro },
@@ -42,7 +84,9 @@ pub trait OAppSenderInternal: OAppCore {
42
84
  /// * `dst_eid`: The destination endpoint ID
43
85
  /// * `message`: The message to send
44
86
  /// * `options`: The options for the message
45
- /// * `fee_payer`: The address of the payer for paying the messaging fees
87
+ /// * `fee_payer`: The fee payer, wrapped in [`FeePayer`] to indicate authorization state.
88
+ /// Use `FeePayer::Unverified(addr)` if auth has not been checked (safe default),
89
+ /// or `FeePayer::Verified(addr)` if `addr.require_auth()` was already called by the caller.
46
90
  /// * `fee`: The messaging fee
47
91
  /// * `refund_address`: The address to receive any excess fees
48
92
  ///
@@ -53,27 +97,34 @@ pub trait OAppSenderInternal: OAppCore {
53
97
  dst_eid: u32,
54
98
  message: &Bytes,
55
99
  options: &Bytes,
56
- fee_payer: &Address,
100
+ fee_payer: &FeePayer,
57
101
  fee: &MessagingFee,
58
102
  refund_address: &Address,
59
103
  ) -> MessagingReceipt {
104
+ // Enforce fee payer authorization if not already verified by the caller
105
+ let payer = match fee_payer {
106
+ FeePayer::Unverified(addr) => {
107
+ addr.require_auth();
108
+ addr
109
+ }
110
+ FeePayer::Verified(addr) => addr,
111
+ };
112
+
60
113
  // Pay the messaging fees
61
- Self::__pay_native(env, fee_payer, fee.native_fee);
62
- if fee.zro_fee != 0 {
63
- Self::__pay_zro(env, fee_payer, fee.zro_fee);
114
+ Self::__pay_native(env, payer, fee.native_fee);
115
+ // Skip the ZRO payment call only when the fee is exactly zero. Using `!= 0` instead of
116
+ // `> 0` so that an invalid negative value still reaches `__pay_zro` and fails loudly
117
+ // rather than being silently ignored.
118
+ let pay_in_zro = fee.zro_fee != 0;
119
+ if pay_in_zro {
120
+ Self::__pay_zro(env, payer, fee.zro_fee);
64
121
  }
65
122
 
66
123
  // Send the message to the other chain
67
- let receiver = Self::peer(env, dst_eid).unwrap_or_panic(env, OAppError::NoPeer);
124
+ let receiver = get_peer_or_panic::<Self>(env, dst_eid);
68
125
  endpoint_client::<Self>(env).send(
69
126
  &env.current_contract_address(),
70
- &MessagingParams {
71
- dst_eid,
72
- receiver,
73
- message: message.clone(),
74
- options: options.clone(),
75
- pay_in_zro: fee.zro_fee > 0,
76
- },
127
+ &MessagingParams { dst_eid, receiver, message: message.clone(), options: options.clone(), pay_in_zro },
77
128
  refund_address,
78
129
  )
79
130
  }
@@ -51,7 +51,7 @@ impl LzReceiveInternal for DummyOApp {
51
51
  #[contractimpl]
52
52
  impl DummyOApp {
53
53
  pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address) {
54
- oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, &None);
54
+ oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, owner);
55
55
  }
56
56
  }
57
57
 
@@ -111,18 +111,18 @@ fn set_delegate_with_auth(env: &Env, signer: &Address, oapp_client: &DummyOAppCl
111
111
  }
112
112
 
113
113
  #[test]
114
- fn test_constructor_initializes_owner_and_endpoint_and_clears_delegate() {
114
+ fn test_constructor_initializes_owner_and_endpoint_and_delegate() {
115
115
  let TestSetup { env, owner, endpoint, oapp_client } = setup();
116
116
 
117
117
  // owner initialized via oapp_initialize -> init_owner
118
- assert_eq!(Some(owner), oapp_client.owner());
118
+ assert_eq!(Some(owner.clone()), oapp_client.owner());
119
119
 
120
120
  // endpoint stored via OAppCoreStorage::set_endpoint
121
121
  assert_eq!(endpoint, oapp_client.endpoint());
122
122
 
123
- // delegate set via oapp_initialize(..., &None) -> endpoint.set_delegate(..., None)
123
+ // delegate set via oapp_initialize(..., owner) -> endpoint.set_delegate(..., Some(owner))
124
124
  let endpoint_client = DummyEndpointClient::new(&env, &endpoint);
125
- assert_eq!(None, endpoint_client.get_delegate(&oapp_client.address));
125
+ assert_eq!(Some(owner), endpoint_client.get_delegate(&oapp_client.address));
126
126
  }
127
127
 
128
128
  #[test]
@@ -54,7 +54,7 @@ impl OAppReceiver for DummyOAppOptionsType3 {}
54
54
 
55
55
  #[contract_impl]
56
56
  impl DummyOAppOptionsType3 {
57
- pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address, delegate: &Option<Address>) {
57
+ pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address, delegate: &Address) {
58
58
  oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, delegate);
59
59
  }
60
60
  }
@@ -70,7 +70,7 @@ fn setup<'a>() -> TestSetup<'a> {
70
70
 
71
71
  let owner = Address::generate(&env);
72
72
  let endpoint = env.register(DummyEndpoint, ());
73
- let delegate: Option<Address> = Some(owner.clone());
73
+ let delegate = owner.clone();
74
74
  let oapp = env.register(DummyOAppOptionsType3, (&owner, &endpoint, &delegate));
75
75
  let oapp_client = DummyOAppOptionsType3Client::new(&env, &oapp);
76
76
 
@@ -105,33 +105,33 @@ fn set_enforced_options_with_auth(
105
105
  fn test_enforced_options_lifecycle() {
106
106
  let TestSetup { env, owner, oapp_client, .. } = setup();
107
107
 
108
- // Unset returns empty
109
- assert_eq!(oapp_client.enforced_options(&999, &999), Bytes::new(&env));
108
+ // Unset returns None
109
+ assert_eq!(oapp_client.enforced_options(&999, &999), None);
110
110
 
111
111
  // Set enforced options for different eid/msg_type combinations
112
112
  let enforced1 = create_valid_options(&env, &[1, 2, 3, 4]);
113
113
  let enforced2 = create_valid_options(&env, &[5, 6, 7, 8]);
114
114
  let enforced_params = vec![
115
115
  &env,
116
- EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: enforced1.clone() },
117
- EnforcedOptionParam { eid: REMOTE_EID_2, msg_type: MSG_TYPE_RECEIVE, options: enforced2.clone() },
116
+ EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(enforced1.clone()) },
117
+ EnforcedOptionParam { eid: REMOTE_EID_2, msg_type: MSG_TYPE_RECEIVE, options: Some(enforced2.clone()) },
118
118
  ];
119
119
  set_enforced_options_with_auth(&env, &owner, &oapp_client, &enforced_params);
120
120
 
121
121
  // assert events
122
- assert_eq_event(&env, &oapp_client.address, EnforcedOptionSet { enforced_option_params: enforced_params.clone() });
122
+ assert_eq_event(&env, &oapp_client.address, EnforcedOptionSet { enforced_options: enforced_params.clone() });
123
123
 
124
124
  // Verify options were set correctly
125
- assert_eq!(oapp_client.enforced_options(&REMOTE_EID_1, &MSG_TYPE_SEND), enforced1.clone());
126
- assert_eq!(oapp_client.enforced_options(&REMOTE_EID_2, &MSG_TYPE_RECEIVE), enforced2.clone());
125
+ assert_eq!(oapp_client.enforced_options(&REMOTE_EID_1, &MSG_TYPE_SEND), Some(enforced1.clone()));
126
+ assert_eq!(oapp_client.enforced_options(&REMOTE_EID_2, &MSG_TYPE_RECEIVE), Some(enforced2.clone()));
127
127
 
128
128
  // Update enforced options for one combination
129
129
  let updated = create_valid_options(&env, &[9, 8, 7, 6, 5]);
130
130
  let update_params =
131
- vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: updated.clone() }];
131
+ vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(updated.clone()) }];
132
132
  set_enforced_options_with_auth(&env, &owner, &oapp_client, &update_params);
133
- assert_eq_event(&env, &oapp_client.address, EnforcedOptionSet { enforced_option_params: update_params.clone() });
134
- assert_eq!(oapp_client.enforced_options(&REMOTE_EID_1, &MSG_TYPE_SEND), updated);
133
+ assert_eq_event(&env, &oapp_client.address, EnforcedOptionSet { enforced_options: update_params.clone() });
134
+ assert_eq!(oapp_client.enforced_options(&REMOTE_EID_1, &MSG_TYPE_SEND), Some(updated));
135
135
  }
136
136
 
137
137
  #[test]
@@ -148,7 +148,7 @@ fn test_combine_options() {
148
148
  // Set enforced options for the combine tests
149
149
  let enforced = create_valid_options(&env, &[1, 2, 3, 4]);
150
150
  let enforced_params =
151
- vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: enforced.clone() }];
151
+ vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(enforced.clone()) }];
152
152
  set_enforced_options_with_auth(&env, &owner, &oapp_client, &enforced_params);
153
153
 
154
154
  // combine_options: enforced present -> empty extra returns enforced
@@ -168,7 +168,7 @@ fn test_set_enforced_options_unauthorized() {
168
168
 
169
169
  let options = create_valid_options(&env, &[1, 2, 3, 4]);
170
170
  let enforced_params =
171
- vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: options.clone() }];
171
+ vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(options.clone()) }];
172
172
  oapp_client.set_enforced_options(&enforced_params);
173
173
  }
174
174
 
@@ -181,7 +181,7 @@ fn test_set_enforced_options_non_owner_authorized() {
181
181
 
182
182
  let options = create_valid_options(&env, &[1, 2, 3, 4]);
183
183
  let enforced_params =
184
- vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: options.clone() }];
184
+ vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(options.clone()) }];
185
185
 
186
186
  set_enforced_options_with_auth(&env, &non_owner, &oapp_client, &enforced_params);
187
187
  }
@@ -195,7 +195,7 @@ fn test_set_enforced_options_invalid_options_returns_error() {
195
195
  invalid.extend_from_slice(&[1, 2, 3]);
196
196
 
197
197
  let enforced_params =
198
- vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: invalid }];
198
+ vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(invalid) }];
199
199
 
200
200
  env.mock_auths(&[MockAuth {
201
201
  address: &owner,
@@ -215,7 +215,7 @@ fn test_combine_options_extra_invalid_type_returns_error_when_enforced_present()
215
215
  let TestSetup { env, owner, oapp_client, .. } = setup();
216
216
 
217
217
  let enforced = create_valid_options(&env, &[1, 2, 3]);
218
- let params = vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: enforced }];
218
+ let params = vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(enforced) }];
219
219
  set_enforced_options_with_auth(&env, &owner, &oapp_client, &params);
220
220
 
221
221
  // extra has wrong option type (not 3) but len >= 2 -> validated and should panic
@@ -230,7 +230,7 @@ fn test_combine_options_extra_too_short_returns_error_when_enforced_present() {
230
230
  let TestSetup { env, owner, oapp_client, .. } = setup();
231
231
 
232
232
  let enforced = create_valid_options(&env, &[1, 2, 3]);
233
- let params = vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: enforced }];
233
+ let params = vec![&env, EnforcedOptionParam { eid: REMOTE_EID_1, msg_type: MSG_TYPE_SEND, options: Some(enforced) }];
234
234
  set_enforced_options_with_auth(&env, &owner, &oapp_client, &params);
235
235
 
236
236
  // extra is non-empty but len < 2 -> should panic
@@ -27,7 +27,7 @@ impl LzReceiveInternal for DummyOAppReceiver {
27
27
  #[contractimpl]
28
28
  impl DummyOAppReceiver {
29
29
  pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address) {
30
- oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, &None);
30
+ oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, owner);
31
31
  }
32
32
  }
33
33
 
@@ -355,7 +355,7 @@ fn test_lz_receive_wrong_peer_returns_only_peer_error() {
355
355
  }
356
356
 
357
357
  #[test]
358
- fn test_lz_receive_no_peer_returns_only_peer_error() {
358
+ fn test_lz_receive_no_peer_returns_no_peer_error() {
359
359
  let TestSetup { env, oapp_client, .. } = setup();
360
360
 
361
361
  let executor = Address::generate(&env);
@@ -375,7 +375,7 @@ fn test_lz_receive_no_peer_returns_only_peer_error() {
375
375
  },
376
376
  }]);
377
377
 
378
- // No peer configured -> should fail the peer check with OnlyPeer
378
+ // No peer configured -> should fail with NoPeer since no peer is set for the source eid
379
379
  let result = oapp_client.try_lz_receive(&executor, &origin, &guid, &message, &extra_data, &value);
380
- assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::OnlyPeer.into());
380
+ assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::NoPeer.into());
381
381
  }
@@ -1,4 +1,4 @@
1
- use crate::{self as oapp, errors::OAppError, oapp_receiver::LzReceiveInternal};
1
+ use crate::{self as oapp, errors::OAppError, oapp_receiver::LzReceiveInternal, oapp_sender::FeePayer};
2
2
  use endpoint_v2::{MessagingFee, MessagingParams, MessagingReceipt, Origin};
3
3
  use soroban_sdk::{
4
4
  contract, contractimpl, symbol_short,
@@ -83,7 +83,7 @@ impl LzReceiveInternal for DummyOAppSender {
83
83
  #[contractimpl]
84
84
  impl DummyOAppSender {
85
85
  pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address) {
86
- oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, &None);
86
+ oapp::oapp_core::initialize_oapp::<Self>(env, owner, endpoint, owner);
87
87
  }
88
88
 
89
89
  pub fn quote(env: &Env, dst_eid: u32, message: &Bytes, options: &Bytes, pay_in_zro: bool) -> MessagingFee {
@@ -100,7 +100,7 @@ impl DummyOAppSender {
100
100
  refund_address: &Address,
101
101
  ) -> MessagingReceipt {
102
102
  sender.require_auth();
103
- Self::__lz_send(env, dst_eid, message, options, sender, fee, refund_address)
103
+ Self::__lz_send(env, dst_eid, message, options, &FeePayer::Verified(sender.clone()), fee, refund_address)
104
104
  }
105
105
 
106
106
  pub fn pay_native_fee(env: &Env, fee_payer: &Address, native_fee: i128) {
@@ -9,7 +9,6 @@ publish = false
9
9
  proc-macro = true
10
10
 
11
11
  [dependencies]
12
- heck = { workspace = true }
13
12
  proc-macro2 = { workspace = true }
14
13
  quote = { workspace = true }
15
14
  syn = { workspace = true }
@@ -1,9 +1,69 @@
1
1
  //! Code generators for OApp trait implementations.
2
2
 
3
- use crate::CustomImpls;
4
3
  use proc_macro2::TokenStream;
5
4
  use quote::quote;
6
- use syn::{Ident, ItemStruct};
5
+ use syn::{
6
+ bracketed,
7
+ parse::{Parse, ParseStream},
8
+ punctuated::Punctuated,
9
+ Error, Ident, ItemStruct, Token,
10
+ };
11
+
12
+ /// Specifies which OApp trait implementations the user will provide themselves.
13
+ ///
14
+ /// Parsed from `#[oapp(custom = [...])]`. When a field is `true`, the macro skips
15
+ /// generating that trait implementation, allowing the user to provide their own.
16
+ #[derive(Debug, Clone, Copy, Default)]
17
+ pub(crate) struct CustomImpls {
18
+ pub core: bool,
19
+ pub sender: bool,
20
+ pub receiver: bool,
21
+ pub options_type3: bool,
22
+ }
23
+
24
+ impl Parse for CustomImpls {
25
+ fn parse(input: ParseStream) -> syn::Result<Self> {
26
+ if input.is_empty() {
27
+ return Ok(Self::default());
28
+ }
29
+
30
+ // Consume the `custom` keyword
31
+ let key: Ident = input.parse()?;
32
+ if key != "custom" {
33
+ return Err(Error::new(key.span(), "expected `custom`"));
34
+ }
35
+
36
+ // Consume the `=` in `custom = [...]`
37
+ input.parse::<Token![=]>()?;
38
+
39
+ // Parse the `[...]` brackets and capture the inner tokens into `content`
40
+ let content;
41
+ bracketed!(content in input);
42
+
43
+ // Parse the comma-separated list of identifiers into `idents`
44
+ let idents = Punctuated::<Ident, Token![,]>::parse_terminated(&content)?;
45
+
46
+ // Initialize the custom implementations struct
47
+ let mut custom_impls = Self::default();
48
+
49
+ for ident in idents {
50
+ match ident.to_string().as_str() {
51
+ "core" => custom_impls.core = true,
52
+ "sender" => custom_impls.sender = true,
53
+ "receiver" => custom_impls.receiver = true,
54
+ "options_type3" => custom_impls.options_type3 = true,
55
+ _ => {
56
+ return Err(Error::new(
57
+ ident.span(),
58
+ "expected one of `core`, `sender`, `receiver`, `options_type3`",
59
+ ));
60
+ }
61
+ }
62
+ }
63
+
64
+ Ok(custom_impls)
65
+ }
66
+ }
7
67
 
8
68
  /// Generates a complete OApp implementation with contract attributes and trait implementations.
9
69
  ///
@@ -17,14 +77,17 @@ use syn::{Ident, ItemStruct};
17
77
  ///
18
78
  /// The `custom` parameter controls which trait implementations are generated vs.
19
79
  /// expected to be provided by the user.
20
- pub fn generate_oapp(item: ItemStruct, custom: CustomImpls) -> TokenStream {
21
- let core_impl = generate_oapp_core(&item.ident, custom.core);
22
- let sender_impl = generate_oapp_sender(&item.ident, custom.sender);
23
- let receiver_impl = generate_oapp_receiver(&item.ident, custom.receiver);
24
- let options_type3_impl = generate_oapp_options_type3(&item.ident, custom.options_type3);
80
+ pub fn generate_oapp(attr: TokenStream, input: TokenStream) -> TokenStream {
81
+ let custom: CustomImpls = syn::parse2(attr).unwrap_or_else(|e| panic!("failed to parse oapp attributes: {}", e));
82
+ let item_struct: ItemStruct = syn::parse2(input).unwrap_or_else(|e| panic!("failed to parse struct: {}", e));
83
+
84
+ let core_impl = (!custom.core).then(|| generate_oapp_core(&item_struct.ident));
85
+ let sender_impl = (!custom.sender).then(|| generate_oapp_sender(&item_struct.ident));
86
+ let receiver_impl = (!custom.receiver).then(|| generate_oapp_receiver(&item_struct.ident));
87
+ let options_type3_impl = (!custom.options_type3).then(|| generate_oapp_options_type3(&item_struct.ident));
25
88
  quote! {
26
89
  #[common_macros::lz_contract]
27
- #item
90
+ #item_struct
28
91
 
29
92
  #core_impl
30
93
  #sender_impl
@@ -33,15 +96,9 @@ pub fn generate_oapp(item: ItemStruct, custom: CustomImpls) -> TokenStream {
33
96
  }
34
97
  }
35
98
 
36
- /// Generates the `OAppCore` trait implementation.
37
- ///
38
- /// When `custom` is false, generates an empty `impl OAppCore` that uses the trait's
39
- /// default implementations for peer management and endpoint access.
40
- fn generate_oapp_core(name: &Ident, custom: bool) -> TokenStream {
41
- if custom {
42
- return TokenStream::new();
43
- }
44
-
99
+ /// Generates an empty `impl OAppCore` that uses the trait's default implementations
100
+ /// for peer management and endpoint access.
101
+ fn generate_oapp_core(name: &Ident) -> TokenStream {
45
102
  quote! {
46
103
  use oapp::oapp_core::OAppCore as _;
47
104
 
@@ -52,31 +109,21 @@ fn generate_oapp_core(name: &Ident, custom: bool) -> TokenStream {
52
109
 
53
110
  /// Generates the `OAppSenderInternal` trait implementation.
54
111
  ///
55
- /// When `custom` is false, generates an empty `impl OAppSenderInternal` that uses the
56
- /// trait's default implementations for `__lz_quote` and `__lz_send`.
57
- fn generate_oapp_sender(name: &Ident, custom: bool) -> TokenStream {
58
- if custom {
59
- TokenStream::new()
60
- } else {
61
- quote! {
62
- use oapp::oapp_sender::OAppSenderInternal as _;
63
-
64
- impl oapp::oapp_sender::OAppSenderInternal for #name {}
65
- }
112
+ /// Generates an empty `impl OAppSenderInternal` that uses the trait's default
113
+ /// implementations for `__lz_quote` and `__lz_send`.
114
+ fn generate_oapp_sender(name: &Ident) -> TokenStream {
115
+ quote! {
116
+ use oapp::oapp_sender::OAppSenderInternal as _;
117
+
118
+ impl oapp::oapp_sender::OAppSenderInternal for #name {}
66
119
  }
67
120
  }
68
121
 
69
- /// Generates the `OAppReceiver` trait implementation.
70
- ///
71
- /// When `custom` is false, generates an empty `impl OAppReceiver` that uses the trait's default
72
- /// `lz_receive` implementation (which calls `clear_payload_and_transfer` then `__lz_receive`).
122
+ /// Generates an empty `impl OAppReceiver` that uses the trait's default `lz_receive`
123
+ /// implementation (which calls `clear_payload_and_transfer` then `__lz_receive`).
73
124
  ///
74
125
  /// Users must implement `LzReceiveInternal` themselves to provide the `__lz_receive` method.
75
- fn generate_oapp_receiver(name: &Ident, custom: bool) -> TokenStream {
76
- if custom {
77
- return TokenStream::new();
78
- }
79
-
126
+ fn generate_oapp_receiver(name: &Ident) -> TokenStream {
80
127
  quote! {
81
128
  use oapp::oapp_receiver::OAppReceiver as _;
82
129
 
@@ -85,15 +132,9 @@ fn generate_oapp_receiver(name: &Ident, custom: bool) -> TokenStream {
85
132
  }
86
133
  }
87
134
 
88
- /// Generates the `OAppOptionsType3` trait implementation.
89
- ///
90
- /// When `custom` is false, generates an empty `impl OAppOptionsType3` that uses the
91
- /// trait's default implementations for enforced options management.
92
- fn generate_oapp_options_type3(name: &Ident, custom: bool) -> TokenStream {
93
- if custom {
94
- return TokenStream::new();
95
- }
96
-
135
+ /// Generates an empty `impl OAppOptionsType3` that uses the trait's default
136
+ /// implementations for enforced options management.
137
+ fn generate_oapp_options_type3(name: &Ident) -> TokenStream {
97
138
  quote! {
98
139
  use oapp::oapp_options_type3::OAppOptionsType3 as _;
99
140
 
@@ -125,15 +125,6 @@
125
125
  mod generators;
126
126
 
127
127
  use proc_macro::TokenStream;
128
- use syn::{
129
- bracketed,
130
- parse::{Parse, ParseStream},
131
- punctuated::Punctuated,
132
- Error, Ident, ItemStruct, Token,
133
- };
134
-
135
- #[cfg(test)]
136
- mod tests;
137
128
 
138
129
  /// Derives a complete OApp: `#[contract]` + `#[ownable]` + Core + Sender + Receiver + OptionsType3.
139
130
  ///
@@ -158,57 +149,8 @@ mod tests;
158
149
  /// You must implement `LzReceiveInternal` for your struct. See module docs for examples.
159
150
  #[proc_macro_attribute]
160
151
  pub fn oapp(attr: TokenStream, item: TokenStream) -> TokenStream {
161
- let custom = syn::parse_macro_input!(attr as CustomImpls);
162
- let item_struct = syn::parse_macro_input!(item as ItemStruct);
163
- generators::generate_oapp(item_struct, custom).into()
164
- }
165
-
166
- /// Specifies which OApp trait implementations the user will provide themselves.
167
- ///
168
- /// Parsed from `#[oapp(custom = [...])]`. When a field is `true`, the macro skips
169
- /// generating that trait implementation, allowing the user to provide their own.
170
- #[derive(Debug, Clone, Copy, Default)]
171
- struct CustomImpls {
172
- pub core: bool,
173
- pub sender: bool,
174
- pub receiver: bool,
175
- pub options_type3: bool,
152
+ generators::generate_oapp(attr.into(), item.into()).into()
176
153
  }
177
154
 
178
- impl Parse for CustomImpls {
179
- fn parse(input: ParseStream) -> syn::Result<Self> {
180
- if input.is_empty() {
181
- return Ok(Self::default());
182
- }
183
-
184
- let key: Ident = input.parse()?;
185
- if key != "custom" {
186
- return Err(Error::new(key.span(), "expected `custom`"));
187
- }
188
-
189
- input.parse::<Token![=]>()?;
190
-
191
- let content;
192
- bracketed!(content in input);
193
-
194
- let idents = Punctuated::<Ident, Token![,]>::parse_terminated(&content)?;
195
- let mut custom_impls = Self::default();
196
-
197
- for ident in idents {
198
- match ident.to_string().as_str() {
199
- "core" => custom_impls.core = true,
200
- "sender" => custom_impls.sender = true,
201
- "receiver" => custom_impls.receiver = true,
202
- "options_type3" => custom_impls.options_type3 = true,
203
- _ => {
204
- return Err(Error::new(
205
- ident.span(),
206
- "expected one of `core`, `sender`, `receiver`, `options_type3`",
207
- ));
208
- }
209
- }
210
- }
211
-
212
- Ok(custom_impls)
213
- }
214
- }
155
+ #[cfg(test)]
156
+ mod tests;
@@ -6,52 +6,39 @@ use quote::quote;
6
6
 
7
7
  #[test]
8
8
  fn snapshot_generate_oapp() {
9
- let input = quote! {
9
+ let struct_input = quote! {
10
10
  pub struct MyOApp;
11
11
  };
12
- let item_struct: syn::ItemStruct = syn::parse2(input).expect("failed to parse struct");
13
12
 
14
13
  let all_defaults = {
15
- let result = crate::generators::generate_oapp(item_struct.clone(), crate::CustomImpls::default());
14
+ let result = crate::generators::generate_oapp(quote! {}, struct_input.clone());
16
15
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
17
16
  };
18
17
 
19
18
  let custom_core_only = {
20
- let result = crate::generators::generate_oapp(
21
- item_struct.clone(),
22
- crate::CustomImpls { core: true, sender: false, receiver: false, options_type3: false },
23
- );
19
+ let result = crate::generators::generate_oapp(quote! { custom = [core] }, struct_input.clone());
24
20
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
25
21
  };
26
22
 
27
23
  let custom_sender_only = {
28
- let result = crate::generators::generate_oapp(
29
- item_struct.clone(),
30
- crate::CustomImpls { core: false, sender: true, receiver: false, options_type3: false },
31
- );
24
+ let result = crate::generators::generate_oapp(quote! { custom = [sender] }, struct_input.clone());
32
25
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
33
26
  };
34
27
 
35
28
  let custom_receiver_only = {
36
- let result = crate::generators::generate_oapp(
37
- item_struct.clone(),
38
- crate::CustomImpls { core: false, sender: false, receiver: true, options_type3: false },
39
- );
29
+ let result = crate::generators::generate_oapp(quote! { custom = [receiver] }, struct_input.clone());
40
30
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
41
31
  };
42
32
 
43
33
  let custom_options_type3_only = {
44
- let result = crate::generators::generate_oapp(
45
- item_struct.clone(),
46
- crate::CustomImpls { core: false, sender: false, receiver: false, options_type3: true },
47
- );
34
+ let result = crate::generators::generate_oapp(quote! { custom = [options_type3] }, struct_input.clone());
48
35
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
49
36
  };
50
37
 
51
38
  let custom_all = {
52
39
  let result = crate::generators::generate_oapp(
53
- item_struct.clone(),
54
- crate::CustomImpls { core: true, sender: true, receiver: true, options_type3: true },
40
+ quote! { custom = [core, sender, receiver, options_type3] },
41
+ struct_input.clone(),
55
42
  );
56
43
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
57
44
  };
@@ -63,8 +50,7 @@ fn snapshot_generate_oapp() {
63
50
  pub x: u32,
64
51
  }
65
52
  };
66
- let fancy_struct: syn::ItemStruct = syn::parse2(fancy_input).expect("failed to parse struct");
67
- let result = crate::generators::generate_oapp(fancy_struct, crate::CustomImpls::default());
53
+ let result = crate::generators::generate_oapp(quote! {}, fancy_input);
68
54
  prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
69
55
  };
70
56