diff --git a/contracts/examples/multisig/sc-config.toml b/contracts/examples/multisig/sc-config.toml index 79c3aeaa20..22ff09f5dd 100644 --- a/contracts/examples/multisig/sc-config.toml +++ b/contracts/examples/multisig/sc-config.toml @@ -17,3 +17,8 @@ add-labels = ["multisig-external-view"] [[proxy]] path = "src/multisig_proxy.rs" + +[[proxy]] +path = "src/multisig_view_proxy.rs" +add-unlabelled = false +add-labels = ["multisig-external-view"] diff --git a/contracts/examples/multisig/src/multisig.rs b/contracts/examples/multisig/src/multisig.rs index 96d3d5cdfa..d1e177df02 100644 --- a/contracts/examples/multisig/src/multisig.rs +++ b/contracts/examples/multisig/src/multisig.rs @@ -6,6 +6,7 @@ pub mod multisig_perform; pub mod multisig_propose; pub mod multisig_proxy; pub mod multisig_state; +pub mod multisig_view_proxy; pub mod user_role; use action::ActionFullInfo; diff --git a/contracts/examples/multisig/src/multisig_proxy.rs b/contracts/examples/multisig/src/multisig_proxy.rs index d3a3e32e0e..6e4b78df16 100644 --- a/contracts/examples/multisig/src/multisig_proxy.rs +++ b/contracts/examples/multisig/src/multisig_proxy.rs @@ -104,20 +104,6 @@ where .original_result() } - /// Iterates through all actions and retrieves those that are still pending. - /// Serialized full action data: - /// - the action id - /// - the serialized action data - /// - (number of signers followed by) list of signer addresses. - pub fn get_pending_action_full_info( - self, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getPendingActionFullInfo") - .original_result() - } - /// Returns `true` (`1`) if the user has signed the action. /// Does not check whether or not the user is still a board member and the signature valid. pub fn signed< @@ -136,43 +122,6 @@ where .original_result() } - /// Indicates user rights. - /// `0` = no rights, - /// `1` = can propose, but not sign, - /// `2` = can propose and sign. - pub fn user_role< - Arg0: ProxyArg>, - >( - self, - user: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("userRole") - .argument(&user) - .original_result() - } - - /// Lists all users that can sign actions. - pub fn get_all_board_members( - self, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getAllBoardMembers") - .original_result() - } - - /// Lists all proposers that are not board members. - pub fn get_all_proposers( - self, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getAllProposers") - .original_result() - } - /// Used by board members to sign actions. pub fn sign< Arg0: ProxyArg, @@ -261,69 +210,6 @@ where .original_result() } - /// Serialized action data of an action with index. - pub fn get_action_data< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionData") - .argument(&action_id) - .original_result() - } - - /// Gets addresses of all users who signed an action. - /// Does not check if those users are still board members or not, - /// so the result may contain invalid signers. - pub fn get_action_signers< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall>> { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionSigners") - .argument(&action_id) - .original_result() - } - - /// Gets addresses of all users who signed an action and are still board members. - /// All these signatures are currently valid. - pub fn get_action_signer_count< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionSignerCount") - .argument(&action_id) - .original_result() - } - - /// It is possible for board members to lose their role. - /// They are not automatically removed from all actions when doing so, - /// therefore the contract needs to re-check every time when actions are performed. - /// This function is used to validate the signers before performing an action. - /// It also makes it easy to check before performing an action. - pub fn get_action_valid_signer_count< - Arg0: ProxyArg, - >( - self, - action_id: Arg0, - ) -> TxTypedCall { - self.wrapped_tx - .payment(NotPayable) - .raw_call("getActionValidSignerCount") - .argument(&action_id) - .original_result() - } - /// Initiates board member addition process. /// Can also be used to promote a proposer to board member. pub fn propose_add_board_member< diff --git a/contracts/examples/multisig/src/multisig_view_proxy.rs b/contracts/examples/multisig/src/multisig_view_proxy.rs new file mode 100644 index 0000000000..f17bdc4212 --- /dev/null +++ b/contracts/examples/multisig/src/multisig_view_proxy.rs @@ -0,0 +1,220 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + +use multiversx_sc::proxy_imports::*; + +pub struct MultisigProxy; + +impl TxProxyTrait for MultisigProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = MultisigProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + MultisigProxyMethods { wrapped_tx: tx } + } +} + +pub struct MultisigProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl MultisigProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + /// Iterates through all actions and retrieves those that are still pending. + /// Serialized full action data: + /// - the action id + /// - the serialized action data + /// - (number of signers followed by) list of signer addresses. + pub fn get_pending_action_full_info( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getPendingActionFullInfo") + .original_result() + } + + /// Indicates user rights. + /// `0` = no rights, + /// `1` = can propose, but not sign, + /// `2` = can propose and sign. + pub fn user_role< + Arg0: ProxyArg>, + >( + self, + user: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("userRole") + .argument(&user) + .original_result() + } + + /// Lists all users that can sign actions. + pub fn get_all_board_members( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getAllBoardMembers") + .original_result() + } + + /// Lists all proposers that are not board members. + pub fn get_all_proposers( + self, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getAllProposers") + .original_result() + } + + /// Serialized action data of an action with index. + pub fn get_action_data< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionData") + .argument(&action_id) + .original_result() + } + + /// Gets addresses of all users who signed an action. + /// Does not check if those users are still board members or not, + /// so the result may contain invalid signers. + pub fn get_action_signers< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall>> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionSigners") + .argument(&action_id) + .original_result() + } + + /// Gets addresses of all users who signed an action and are still board members. + /// All these signatures are currently valid. + pub fn get_action_signer_count< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionSignerCount") + .argument(&action_id) + .original_result() + } + + /// It is possible for board members to lose their role. + /// They are not automatically removed from all actions when doing so, + /// therefore the contract needs to re-check every time when actions are performed. + /// This function is used to validate the signers before performing an action. + /// It also makes it easy to check before performing an action. + pub fn get_action_valid_signer_count< + Arg0: ProxyArg, + >( + self, + action_id: Arg0, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("getActionValidSignerCount") + .argument(&action_id) + .original_result() + } +} + +#[type_abi] +#[derive(TopEncode)] +pub struct ActionFullInfo +where + Api: ManagedTypeApi, +{ + pub action_id: usize, + pub action_data: Action, + pub signers: ManagedVec>, +} + +#[rustfmt::skip] +#[type_abi] +#[derive(NestedEncode, NestedDecode, TopEncode, TopDecode, Clone)] +pub enum Action +where + Api: ManagedTypeApi, +{ + Nothing, + AddBoardMember(ManagedAddress), + AddProposer(ManagedAddress), + RemoveUser(ManagedAddress), + ChangeQuorum(usize), + SendTransferExecute(CallActionData), + SendAsyncCall(CallActionData), + SCDeployFromSource { + amount: BigUint, + source: ManagedAddress, + code_metadata: CodeMetadata, + arguments: ManagedVec>, + }, + SCUpgradeFromSource { + sc_address: ManagedAddress, + amount: BigUint, + source: ManagedAddress, + code_metadata: CodeMetadata, + arguments: ManagedVec>, + }, +} + +#[type_abi] +#[derive(NestedEncode, NestedDecode, Clone)] +pub struct CallActionData +where + Api: ManagedTypeApi, +{ + pub to: ManagedAddress, + pub egld_amount: BigUint, + pub endpoint_name: ManagedBuffer, + pub arguments: ManagedVec>, +} + +#[type_abi] +#[derive(TopEncode, TopDecode)] +pub enum UserRole { + None, + Proposer, + BoardMember, +} diff --git a/contracts/examples/multisig/tests/multisig_blackbox_test.rs b/contracts/examples/multisig/tests/multisig_blackbox_test.rs index 083a6c6be6..e8067bb73a 100644 --- a/contracts/examples/multisig/tests/multisig_blackbox_test.rs +++ b/contracts/examples/multisig/tests/multisig_blackbox_test.rs @@ -2,7 +2,7 @@ use multiversx_sc::codec::top_encode_to_vec_u8_or_panic; use multiversx_sc_scenario::imports::*; use adder::adder_proxy; -use multisig::multisig_proxy; +use multisig::{multisig_proxy, multisig_view_proxy}; use num_bigint::BigUint; const ADDER_ADDRESS: TestSCAddress = TestSCAddress::new("adder"); @@ -71,7 +71,7 @@ impl MultisigTestState { self.sign(action_id); self.perform(action_id); - self.expect_user_role(PROPOSER_ADDRESS, multisig_proxy::UserRole::Proposer); + self.expect_user_role(PROPOSER_ADDRESS, multisig_view_proxy::UserRole::Proposer); self } @@ -232,12 +232,12 @@ impl MultisigTestState { fn expect_user_role( &mut self, user: TestAddress, - expected_user_role: multisig_proxy::UserRole, + expected_user_role: multisig_view_proxy::UserRole, ) { self.world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .user_role(user) .returns(ExpectValue(expected_user_role)) .run(); @@ -253,7 +253,7 @@ fn test_add_board_member() { state.world.account(new_board_member_expr).nonce(1); - state.expect_user_role(new_board_member_expr, multisig_proxy::UserRole::None); + state.expect_user_role(new_board_member_expr, multisig_view_proxy::UserRole::None); let action_id = state.propose_add_board_member(new_board_member_expr); state.sign(action_id); @@ -261,12 +261,15 @@ fn test_add_board_member() { let expected_value = MultiValueVec::from(vec![BOARD_MEMBER_ADDRESS, new_board_member_expr]); - state.expect_user_role(new_board_member_expr, multisig_proxy::UserRole::BoardMember); + state.expect_user_role( + new_board_member_expr, + multisig_view_proxy::UserRole::BoardMember, + ); state .world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .get_all_board_members() .returns(ExpectValue(expected_value)) .run() @@ -281,7 +284,10 @@ fn test_add_proposer() { state.world.account(new_proposer_address_expr).nonce(1); - state.expect_user_role(new_proposer_address_expr, multisig_proxy::UserRole::None); + state.expect_user_role( + new_proposer_address_expr, + multisig_view_proxy::UserRole::None, + ); let action_id = state.propose_add_proposer(new_proposer_address_expr); state.sign(action_id); @@ -289,7 +295,7 @@ fn test_add_proposer() { state.expect_user_role( new_proposer_address_expr, - multisig_proxy::UserRole::Proposer, + multisig_view_proxy::UserRole::Proposer, ); let expected_value = MultiValueVec::from(vec![PROPOSER_ADDRESS, new_proposer_address_expr]); @@ -297,7 +303,7 @@ fn test_add_proposer() { .world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .get_all_proposers() .returns(ExpectValue(expected_value)) .run(); @@ -308,18 +314,18 @@ fn test_remove_proposer() { let mut state = MultisigTestState::new(); state.deploy_multisig_contract(); - state.expect_user_role(PROPOSER_ADDRESS, multisig_proxy::UserRole::Proposer); + state.expect_user_role(PROPOSER_ADDRESS, multisig_view_proxy::UserRole::Proposer); let action_id = state.propose_remove_user(PROPOSER_ADDRESS); state.sign(action_id); state.perform(action_id); - state.expect_user_role(PROPOSER_ADDRESS, multisig_proxy::UserRole::None); + state.expect_user_role(PROPOSER_ADDRESS, multisig_view_proxy::UserRole::None); state .world .query() .to(MULTISIG_ADDRESS) - .typed(multisig_proxy::MultisigProxy) + .typed(multisig_view_proxy::MultisigProxy) .get_all_proposers() .returns(ExpectValue(MultiValueVec::
::new())) .run(); diff --git a/contracts/feature-tests/basic-features/sc-config.toml b/contracts/feature-tests/basic-features/sc-config.toml index c870fda7cb..82698d1dab 100644 --- a/contracts/feature-tests/basic-features/sc-config.toml +++ b/contracts/feature-tests/basic-features/sc-config.toml @@ -8,3 +8,8 @@ overflow-checks = true # needed for overflow tests add-unlabelled = false add-endpoints = ["init", "load_bytes", "store_bytes"] kill_legacy_callback = true + +[[proxy]] +path = "src/basic_features_proxy.rs" +add-unlabelled = false +add-endpoints = ["init", "store_bytes", "load_bytes", "returns_egld_decimal"] diff --git a/contracts/feature-tests/basic-features/src/basic_features_proxy.rs b/contracts/feature-tests/basic-features/src/basic_features_proxy.rs index 7131607d8c..469b2d3323 100644 --- a/contracts/feature-tests/basic-features/src/basic_features_proxy.rs +++ b/contracts/feature-tests/basic-features/src/basic_features_proxy.rs @@ -1,3 +1,12 @@ +// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. + +//////////////////////////////////////////////////// +////////////////// AUTO-GENERATED ////////////////// +//////////////////////////////////////////////////// + +#![allow(dead_code)] +#![allow(clippy::all)] + use multiversx_sc::proxy_imports::*; pub struct BasicFeaturesProxy; diff --git a/contracts/feature-tests/multi-contract-features/multicontract.toml b/contracts/feature-tests/multi-contract-features/multicontract.toml index dd9eaa5add..f06e039526 100644 --- a/contracts/feature-tests/multi-contract-features/multicontract.toml +++ b/contracts/feature-tests/multi-contract-features/multicontract.toml @@ -39,10 +39,10 @@ add-unlabelled = false add-labels = ["alt-impl"] [[proxy]] -variant = "multi_contract_example_feature" +variant = "multi-contract-example-feature" path = "src/multi_contract_example_feature_proxy.rs" [[proxy]] -variant = "multi_contract_alt_impl" +variant = "multi-contract-alt-impl" path = "src/multi_contract_alt_impl_proxy.rs" diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs index d6c913a0e4..2179dddc40 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_gen_main.rs @@ -1,8 +1,6 @@ use colored::Colorize; use std::fs; -use multiversx_sc::abi::ContractAbi; - use crate::contract::sc_config::ProxyConfigSerde; use super::{ @@ -13,25 +11,21 @@ const PROXY_COMPARE_ERR_MSG: &str = "Contract has been modified and proxies have impl MetaConfig { pub fn generate_proxy(&mut self) { - let default_proxy = ProxyConfigSerde::new(); - write_proxy_with_explicit_path(&default_proxy, self); - for proxy_config in self.sc_config.proxy_configs.clone() { - write_proxy_with_explicit_path(&proxy_config, self); + for proxy_config in &self.sc_config.proxy_configs { + write_proxy_with_explicit_path(proxy_config.0, self); } } pub fn compare_proxy(&mut self) { - for proxy_config in self.sc_config.proxy_configs.clone() { - compare_proxy_explicit_path(&proxy_config, self); + for proxy_config in &self.sc_config.proxy_configs { + compare_proxy_explicit_path(proxy_config.0, self); } } } fn compare_proxy_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &MetaConfig) { - let contract_abi = extract_contract_abi(proxy_config, meta_config); let mut temp = Vec::::new(); - let mut proxy_generator = - ProxyGenerator::new(meta_config, &mut temp, proxy_config, contract_abi); + let mut proxy_generator = ProxyGenerator::new(meta_config, &mut temp, proxy_config); proxy_generator.write_proxy_to_file(); let existent_proxy_path = format!("../{}", proxy_config.path); @@ -44,27 +38,7 @@ fn compare_proxy_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &Me } fn write_proxy_with_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &MetaConfig) { - let contract_abi = extract_contract_abi(proxy_config, meta_config); let mut file = create_file(&proxy_config.path); - let mut proxy_generator = - ProxyGenerator::new(meta_config, &mut file, proxy_config, contract_abi); + let mut proxy_generator = ProxyGenerator::new(meta_config, &mut file, proxy_config); proxy_generator.write_proxy_to_file(); } - -fn extract_contract_abi<'a>( - proxy_config: &'a ProxyConfigSerde, - meta_config: &'a MetaConfig, -) -> &'a ContractAbi { - if proxy_config.variant.is_some() { - let variant = proxy_config.variant.as_ref().unwrap(); - for contract_variant in &meta_config.sc_config.contracts { - if variant == &contract_variant.public_name_snake_case() { - return &contract_variant.abi; - } - } - - panic!("No variant with name \"{}\" in multicontract", variant); - } - - &meta_config.original_contract_abi -} diff --git a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs index d2e0b22036..b0a9267967 100644 --- a/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta-lib/src/contract/generate_proxy/proxy_generator.rs @@ -52,13 +52,17 @@ impl<'a> ProxyGenerator<'a> { meta_config: &'a MetaConfig, file: &'a mut dyn std::io::Write, proxy_config: &'a ProxyConfigSerde, - contract_abi: &'a ContractAbi, ) -> Self { Self { meta_config, file: Some(file), proxy_config, - contract_abi, + contract_abi: &meta_config + .sc_config + .proxy_configs + .get(proxy_config) + .unwrap() + .abi, } } diff --git a/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs b/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs index bb6a439245..2c9f37208d 100644 --- a/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs +++ b/framework/meta-lib/src/contract/sc_config/contract_variant_builder.rs @@ -1,3 +1,4 @@ +use core::panic; use multiversx_sc::abi::{ContractAbi, EndpointAbi}; use std::{ collections::{BTreeSet, HashMap, HashSet}, @@ -11,7 +12,7 @@ use super::{ contract_variant_settings::{parse_allocator, parse_stack_size}, sc_config_model::SC_CONFIG_FILE_NAMES, ContractVariant, ContractVariantProfile, ContractVariantSerde, ContractVariantSettings, - ScConfig, ScConfigSerde, + ProxyConfigSerde, ScConfig, ScConfigSerde, }; /// Temporary structure, to help create instances of `ContractVariant`. Not publicly exposed. @@ -253,40 +254,112 @@ fn validate_contract_variants(contracts: &[ContractVariant]) { } } -impl ScConfig { - /// Assembles an `ContractVariantConfig` from a raw config object that was loaded via Serde. - /// - /// In most cases the config will be loaded from a .toml file, use `load_from_file` for that. - pub fn load_from_config(config: &ScConfigSerde, original_abi: &ContractAbi) -> Self { - let mut contract_builders: HashMap = config - .contracts - .iter() - .map(ContractVariantBuilder::map_from_config) - .collect(); +fn process_contracts(config: &ScConfigSerde, original_abi: &ContractAbi) -> Vec { + let mut contract_builders: HashMap = config + .contracts + .iter() + .map(ContractVariantBuilder::map_from_config) + .collect(); + + collect_and_process_endpoints( + &mut contract_builders, + original_abi, + &config.labels_for_contracts, + ); + + let mut contracts: Vec = contract_builders + .into_values() + .map(|builder| build_contract(builder, original_abi)) + .collect(); + + if contracts.is_empty() { + contracts.push(ContractVariant::default_from_abi(original_abi)); + } + set_main_contract_flag(&mut contracts, &config.settings.main); + validate_contract_variants(&contracts); + + contracts +} + +fn process_proxy_contracts( + config: &ScConfigSerde, + original_abi: &ContractAbi, +) -> HashMap { + let mut proxy_contracts = HashMap::new(); + + let main_contract = process_contracts(config, original_abi) + .into_iter() + .find(|contract| contract.main) + .unwrap(); + + proxy_contracts.insert(ProxyConfigSerde::new(), main_contract); + + for proxy_config in &config.proxy { + let mut contract_builders = HashMap::new(); + + match &proxy_config.variant { + Some(variant) => { + let setting_contract = config + .contracts + .iter() + .find(|setting| setting.0.eq(variant)) + .unwrap_or_else(|| panic!("No contact with this name")); + let (contract_id, mut contract_builder) = + ContractVariantBuilder::map_from_config(setting_contract); + alter_builder_with_proxy_config(proxy_config, &mut contract_builder); + + contract_builders = HashMap::from([(contract_id, contract_builder)]); + }, + None => { + let mut contract_builder = ContractVariantBuilder::default(); + alter_builder_with_proxy_config(proxy_config, &mut contract_builder); + + contract_builders.insert(proxy_config.path.clone(), contract_builder); + }, + } + collect_and_process_endpoints( &mut contract_builders, original_abi, &config.labels_for_contracts, ); + if let Some((_, builder)) = contract_builders.into_iter().next() { + let contract = build_contract(builder, original_abi); - let mut contracts: Vec = contract_builders - .into_values() - .map(|builder| build_contract(builder, original_abi)) - .collect(); - if contracts.is_empty() { - contracts.push(ContractVariant::default_from_abi(original_abi)); + proxy_contracts.insert(proxy_config.clone(), contract); } - set_main_contract_flag(&mut contracts, &config.settings.main); - validate_contract_variants(&contracts); + } + + proxy_contracts +} + +impl ScConfig { + /// Assembles an `ContractVariantConfig` from a raw config object that was loaded via Serde. + /// + /// In most cases the config will be loaded from a .toml file, use `load_from_file` for that. + pub fn load_from_config(config: &ScConfigSerde, original_abi: &ContractAbi) -> Self { let default_contract_config_name = config.settings.main.clone().unwrap_or_default(); ScConfig { default_contract_config_name, - contracts, - proxy_configs: config.proxy.clone(), + contracts: process_contracts(config, original_abi), + proxy_configs: process_proxy_contracts(config, original_abi), } } } +fn alter_builder_with_proxy_config( + proxy_config: &ProxyConfigSerde, + contract_builder: &mut ContractVariantBuilder, +) { + let default = ContractVariantBuilder::default(); + + contract_builder.add_unlabelled = proxy_config + .add_unlabelled + .unwrap_or(default.add_unlabelled); + contract_builder.add_endpoints = proxy_config.add_endpoints.iter().cloned().collect(); + contract_builder.add_labels = proxy_config.add_labels.iter().cloned().collect(); +} + fn collect_and_process_endpoints( contract_builders: &mut HashMap, original_abi: &ContractAbi, @@ -315,7 +388,7 @@ impl ScConfig { wasm_crate_name, abi: original_abi.clone(), }], - proxy_configs: Vec::new(), + proxy_configs: HashMap::new(), } } diff --git a/framework/meta-lib/src/contract/sc_config/sc_config_model.rs b/framework/meta-lib/src/contract/sc_config/sc_config_model.rs index 076e91a2f7..813ff929ea 100644 --- a/framework/meta-lib/src/contract/sc_config/sc_config_model.rs +++ b/framework/meta-lib/src/contract/sc_config/sc_config_model.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use super::{ contract_variant_validate::validate_contract_variant, sc_config_proxy::ProxyConfigSerde, ContractVariant, @@ -18,7 +20,7 @@ pub const SC_CONFIG_FILE_NAMES: &[&str] = &["sc-config.toml", "multicontract.tom pub struct ScConfig { pub default_contract_config_name: String, pub contracts: Vec, - pub proxy_configs: Vec, + pub proxy_configs: HashMap, } impl ScConfig { diff --git a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs index 88721fe6e7..ada8b230cc 100644 --- a/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs +++ b/framework/meta-lib/src/contract/sc_config/sc_config_proxy.rs @@ -2,7 +2,7 @@ use serde::Deserialize; const DEFAULT_PATH: &str = "/output/proxy.rs"; -#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)] #[serde(deny_unknown_fields)] pub struct ProxyConfigSerde { #[serde(default)] @@ -18,6 +18,17 @@ pub struct ProxyConfigSerde { #[serde(default)] pub variant: Option, + + #[serde(rename = "add-unlabelled")] + pub add_unlabelled: Option, + + #[serde(default)] + #[serde(rename = "add-labels")] + pub add_labels: Vec, + + #[serde(default)] + #[serde(rename = "add-endpoints")] + pub add_endpoints: Vec, } impl ProxyConfigSerde { @@ -27,11 +38,14 @@ impl ProxyConfigSerde { override_import: None, path_rename: None, variant: None, + add_unlabelled: None, + add_labels: Vec::new(), + add_endpoints: Vec::new(), } } } -#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Hash)] pub struct PathRename { #[serde(default)] pub from: String,