diff --git a/contracts/feature-tests/multi-contract-features/multicontract.toml b/contracts/feature-tests/multi-contract-features/multicontract.toml index b6c3c8efb1..dd9eaa5add 100644 --- a/contracts/feature-tests/multi-contract-features/multicontract.toml +++ b/contracts/feature-tests/multi-contract-features/multicontract.toml @@ -17,7 +17,7 @@ features = [] [contracts.multi-contract-main.profile] # these are just the defaults, checking that parsing works fine -codegen-units = 1 +codegen-units = 1 opt-level = "z" lto = true debug = false @@ -31,9 +31,18 @@ add-unlabelled = false add-labels = ["mcs-external-view"] [contracts.multi-contract-example-feature] -add-unlabelled = true # optional here, since the default is true +add-unlabelled = true # optional here, since the default is true features = ["example_feature"] [contracts.multi-contract-alt-impl] add-unlabelled = false add-labels = ["alt-impl"] + +[[proxy]] +variant = "multi_contract_example_feature" +path = "src/multi_contract_example_feature_proxy.rs" + + +[[proxy]] +variant = "multi_contract_alt_impl" +path = "src/multi_contract_alt_impl_proxy.rs" diff --git a/contracts/feature-tests/multi-contract-features/src/multi_contract_alt_impl_proxy.rs b/contracts/feature-tests/multi-contract-features/src/multi_contract_alt_impl_proxy.rs new file mode 100644 index 0000000000..8a7b345766 --- /dev/null +++ b/contracts/feature-tests/multi-contract-features/src/multi_contract_alt_impl_proxy.rs @@ -0,0 +1,73 @@ +// 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 MultiContractFeaturesProxy; + +impl TxProxyTrait for MultiContractFeaturesProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = MultiContractFeaturesProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + MultiContractFeaturesProxyMethods { wrapped_tx: tx } + } +} + +pub struct MultiContractFeaturesProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl MultiContractFeaturesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn alternative_init( + self, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .original_result() + } +} + +#[rustfmt::skip] +impl MultiContractFeaturesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn alternative_sample_value( + self, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("sample_value") + .original_result() + } +} diff --git a/contracts/feature-tests/multi-contract-features/src/multi_contract_example_feature_proxy.rs b/contracts/feature-tests/multi-contract-features/src/multi_contract_example_feature_proxy.rs new file mode 100644 index 0000000000..0f1dbdd125 --- /dev/null +++ b/contracts/feature-tests/multi-contract-features/src/multi_contract_example_feature_proxy.rs @@ -0,0 +1,86 @@ +// 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 MultiContractFeaturesProxy; + +impl TxProxyTrait for MultiContractFeaturesProxy +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + type TxProxyMethods = MultiContractFeaturesProxyMethods; + + fn proxy_methods(self, tx: Tx) -> Self::TxProxyMethods { + MultiContractFeaturesProxyMethods { wrapped_tx: tx } + } +} + +pub struct MultiContractFeaturesProxyMethods +where + Env: TxEnv, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + wrapped_tx: Tx, +} + +#[rustfmt::skip] +impl MultiContractFeaturesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + Gas: TxGas, +{ + pub fn default_init< + Arg0: ProxyArg>, + >( + self, + sample_value: Arg0, + ) -> TxTypedDeploy { + self.wrapped_tx + .payment(NotPayable) + .raw_deploy() + .argument(&sample_value) + .original_result() + } +} + +#[rustfmt::skip] +impl MultiContractFeaturesProxyMethods +where + Env: TxEnv, + Env::Api: VMApi, + From: TxFrom, + To: TxTo, + Gas: TxGas, +{ + pub fn sample_value( + self, + ) -> TxTypedCall> { + self.wrapped_tx + .payment(NotPayable) + .raw_call("sample_value") + .original_result() + } + + pub fn example_feature_message( + self, + ) -> TxTypedCall { + self.wrapped_tx + .payment(NotPayable) + .raw_call("example_feature_message") + .original_result() + } +} diff --git a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs index 4ef8582bcb..0619a65cb5 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_gen_main.rs @@ -1,3 +1,5 @@ +use multiversx_sc::abi::ContractAbi; + use crate::cmd::contract::sc_config::ProxyConfigSerde; use super::{ @@ -14,8 +16,28 @@ impl MetaConfig { } } -fn write_proxy_with_explicit_path(proxy_config: &ProxyConfigSerde, meta_config: &mut MetaConfig) { +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); + let mut proxy_generator = + ProxyGenerator::new(meta_config, &mut file, proxy_config, contract_abi); 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/src/cmd/contract/generate_proxy/proxy_generator.rs b/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs index 0bc7a73447..015d7afc90 100644 --- a/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs +++ b/framework/meta/src/cmd/contract/generate_proxy/proxy_generator.rs @@ -1,8 +1,8 @@ use std::{fmt::Display, fs::File, io::Write}; use multiversx_sc::abi::{ - EndpointAbi, EnumVariantDescription, InputAbi, OutputAbi, StructFieldDescription, TypeContents, - TypeDescription, + ContractAbi, EndpointAbi, EnumVariantDescription, InputAbi, OutputAbi, StructFieldDescription, + TypeContents, TypeDescription, }; use crate::cmd::contract::{meta_config::MetaConfig, sc_config::ProxyConfigSerde}; @@ -43,6 +43,7 @@ pub struct ProxyGenerator<'a> { pub meta_config: &'a MetaConfig, pub file: Option<&'a mut File>, pub proxy_config: &'a ProxyConfigSerde, + pub contract_abi: &'a ContractAbi, } impl<'a> ProxyGenerator<'a> { @@ -50,11 +51,13 @@ impl<'a> ProxyGenerator<'a> { meta_config: &'a MetaConfig, file: &'a mut File, proxy_config: &'a ProxyConfigSerde, + contract_abi: &'a ContractAbi, ) -> Self { Self { meta_config, file: Some(file), proxy_config, + contract_abi, } } @@ -86,7 +89,7 @@ impl<'a> ProxyGenerator<'a> { } fn write_tx_proxy_type_def(&mut self) { - let proxy_type_name = proxy_type_name(&self.meta_config.original_contract_abi.name); + let proxy_type_name = proxy_type_name(&self.contract_abi.name); self.writeln(format!( r#" pub struct {proxy_type_name};"# @@ -94,9 +97,8 @@ pub struct {proxy_type_name};"# } fn write_impl_for_tx_proxy(&mut self) { - let proxy_type_name = proxy_type_name(&self.meta_config.original_contract_abi.name); - let proxy_methods_type_name = - proxy_methods_type_name(&self.meta_config.original_contract_abi.name); + let proxy_type_name = proxy_type_name(&self.contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); self.writeln(format!( r#" impl TxProxyTrait for {proxy_type_name} @@ -116,8 +118,7 @@ where } fn write_struct_tx_proxy_methods(&mut self) { - let proxy_methods_type_name = - proxy_methods_type_name(&self.meta_config.original_contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); self.writeln(format!( r#" pub struct {proxy_methods_type_name} @@ -133,35 +134,22 @@ where } fn write_content(&mut self) { - if !self - .meta_config - .original_contract_abi - .constructors - .is_empty() - { + if !self.contract_abi.constructors.is_empty() { self.write_constructors(); } - if !self - .meta_config - .original_contract_abi - .upgrade_constructors - .is_empty() - { + if !self.contract_abi.upgrade_constructors.is_empty() { self.write_upgrades(); } - if !self.meta_config.original_contract_abi.endpoints.is_empty() { + if !self.contract_abi.endpoints.is_empty() { self.write_endpoints(); } } fn write_types(&mut self) { - for (_, type_description) in &self.meta_config.original_contract_abi.type_descriptions.0 { - if self - .meta_config - .original_contract_abi - .get_crate_name_for_code() + for (_, type_description) in &self.contract_abi.type_descriptions.0 { + if self.contract_abi.get_crate_name_for_code() != extract_struct_crate(type_description.names.rust.as_str()) { continue; @@ -186,8 +174,7 @@ where } fn write_constructors(&mut self) { - let constructors: Vec = - self.meta_config.original_contract_abi.constructors.clone(); + let constructors: Vec = self.contract_abi.constructors.clone(); self.write_header_impl_constructor(); for (i, constructor_abi) in constructors.into_iter().enumerate() { @@ -205,8 +192,7 @@ where fn write_upgrades(&mut self) { self.write_header_impl_upgrade(); for (i, upgrade) in self - .meta_config - .original_contract_abi + .contract_abi .upgrade_constructors .clone() .into_iter() @@ -224,7 +210,7 @@ where } fn write_endpoints(&mut self) { - let endpoints: Vec = self.meta_config.original_contract_abi.endpoints.clone(); + let endpoints: Vec = self.contract_abi.endpoints.clone(); self.write_header_impl_endpoints(); for (i, endpoint_abi) in endpoints.into_iter().enumerate() { @@ -240,8 +226,7 @@ where } fn write_header_impl_constructor(&mut self) { - let proxy_methods_type_name = - proxy_methods_type_name(&self.meta_config.original_contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); self.writeln(format!( r#" #[rustfmt::skip] @@ -256,8 +241,7 @@ where } fn write_header_impl_upgrade(&mut self) { - let proxy_methods_type_name = - proxy_methods_type_name(&self.meta_config.original_contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); self.writeln(format!( r#" #[rustfmt::skip] @@ -273,8 +257,7 @@ where } fn write_header_impl_endpoints(&mut self) { - let proxy_methods_type_name = - proxy_methods_type_name(&self.meta_config.original_contract_abi.name); + let proxy_methods_type_name = proxy_methods_type_name(&self.contract_abi.name); self.writeln(format!( r#" #[rustfmt::skip] @@ -606,10 +589,7 @@ where fn process_paths(&self, paths: &Vec) -> Vec { let mut processed_paths: Vec = Vec::new(); - let crate_name = self - .meta_config - .original_contract_abi - .get_crate_name_for_code(); + let crate_name = self.contract_abi.get_crate_name_for_code(); for path in paths { let type_rust_name = path.split("::").last().unwrap(); @@ -665,6 +645,7 @@ pub mod tests { meta_config: &meta_config, file: None, proxy_config: &ProxyConfigSerde::new(), + contract_abi: &meta_config.original_contract_abi, }; let cleaned_path_unsanitized = proxy_generator.clean_paths( @@ -696,6 +677,7 @@ pub mod tests { meta_config: &meta_config, file: None, proxy_config: &ProxyConfigSerde::new(), + contract_abi: &meta_config.original_contract_abi, }; let cleaned_path_sanitized = proxy_generator.clean_paths( diff --git a/framework/meta/src/cmd/contract/sc_config/sc_config_proxy.rs b/framework/meta/src/cmd/contract/sc_config/sc_config_proxy.rs index 56c9a5257a..88721fe6e7 100644 --- a/framework/meta/src/cmd/contract/sc_config/sc_config_proxy.rs +++ b/framework/meta/src/cmd/contract/sc_config/sc_config_proxy.rs @@ -15,6 +15,9 @@ pub struct ProxyConfigSerde { #[serde(default)] #[serde(rename = "path-rename")] pub path_rename: Option>, + + #[serde(default)] + pub variant: Option, } impl ProxyConfigSerde { @@ -23,6 +26,7 @@ impl ProxyConfigSerde { path: DEFAULT_PATH.to_string(), override_import: None, path_rename: None, + variant: None, } } }