From 28fbf84d2284126397bf4cb721a02ed3745e3141 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Mon, 11 Sep 2023 18:09:06 +0300 Subject: [PATCH 1/3] 1st commit t1+t2 --- .../meta/src/cli_args/cli_args_contract.rs | 26 +++- framework/meta/src/cmd/contract.rs | 8 ++ .../src/cmd/contract/generate_proxy_struct.rs | 3 + .../proxy_struct_gen_main.rs | 32 +++++ .../proxy_struct_sc_functions_gen.rs | 69 +++++++++++ .../proxy_struct_template_gen.rs | 24 ++++ .../src/cmd/contract/generate_proxy_trait.rs | 4 + .../proxy_trait_crate_gen.rs | 99 ++++++++++++++++ .../proxy_trait_gen_main.rs | 46 +++++++ .../proxy_trait_sc_functions_gen.rs | 112 ++++++++++++++++++ .../proxy_trait_template_gen.rs | 13 ++ .../generate_snippets/snippet_gen_main.rs | 4 +- .../meta/src/cmd/contract/meta_config.rs | 6 + framework/wasm-adapter/src/lib.rs | 1 + framework/wasm-adapter/src/proxy_macro.rs | 50 ++++++++ 15 files changed, 492 insertions(+), 5 deletions(-) create mode 100644 framework/meta/src/cmd/contract/generate_proxy_struct.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_trait.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_sc_functions_gen.rs create mode 100644 framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_template_gen.rs create mode 100644 framework/wasm-adapter/src/proxy_macro.rs diff --git a/framework/meta/src/cli_args/cli_args_contract.rs b/framework/meta/src/cli_args/cli_args_contract.rs index 1853d64675..cdc2d41f61 100644 --- a/framework/meta/src/cli_args/cli_args_contract.rs +++ b/framework/meta/src/cli_args/cli_args_contract.rs @@ -65,7 +65,19 @@ pub enum ContractCliAction { name = "snippets", about = "Generates a snippets project, based on the contract ABI." )] - GenerateSnippets(GenerateSnippetsArgs), + GenerateSnippets(GenerateSnippetsAndProxiesArgs), + + #[command( + name = "proxy", + about = "Generates a proxy in trait" + )] + GenerateProxies(GenerateSnippetsAndProxiesArgs), + + #[command( + name = "proxy-struct", + about = "Generates a proxy in struct" + )] + GenerateProxiesStruct(GenerateSnippetsAndProxiesArgs) } impl CliArgsToRaw for ContractCliAction { @@ -97,19 +109,27 @@ impl CliArgsToRaw for ContractCliAction { raw.push("snippets".to_string()); raw.append(&mut args.to_raw()); }, + ContractCliAction::GenerateProxies(args) => { + raw.push("proxy".to_string()); + raw.append(&mut args.to_raw()); + }, + ContractCliAction::GenerateProxiesStruct(args) => { + raw.push("proxy-struct".to_string()); + raw.append(&mut args.to_raw()); + } } raw } } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] -pub struct GenerateSnippetsArgs { +pub struct GenerateSnippetsAndProxiesArgs { /// Override snippets project if it already exists. #[arg(long, verbatim_doc_comment)] pub overwrite: bool, } -impl CliArgsToRaw for GenerateSnippetsArgs { +impl CliArgsToRaw for GenerateSnippetsAndProxiesArgs { fn to_raw(&self) -> Vec { let mut raw = Vec::new(); if self.overwrite { diff --git a/framework/meta/src/cmd/contract.rs b/framework/meta/src/cmd/contract.rs index 1ef7607f6f..3e9992dd87 100644 --- a/framework/meta/src/cmd/contract.rs +++ b/framework/meta/src/cmd/contract.rs @@ -1,3 +1,5 @@ +mod generate_proxy_trait; +mod generate_proxy_struct; mod generate_snippets; mod meta_abi; mod meta_config; @@ -27,6 +29,12 @@ pub fn cli_main() { ContractCliAction::GenerateSnippets(gs_args) => { meta_config_opt.generate_rust_snippets(&gs_args) }, + ContractCliAction::GenerateProxies(gs_args) => { + meta_config_opt.generate_rust_proxies(&gs_args) + }, + ContractCliAction::GenerateProxiesStruct(gs_args) => { + meta_config_opt.generate_rust_proxies_struct(&gs_args) + } } } diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct.rs b/framework/meta/src/cmd/contract/generate_proxy_struct.rs new file mode 100644 index 0000000000..6544fc11fd --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_struct.rs @@ -0,0 +1,3 @@ +pub mod proxy_struct_gen_main; +pub mod proxy_struct_template_gen; +pub mod proxy_struct_sc_functions_gen; diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs new file mode 100644 index 0000000000..3ef38deb14 --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs @@ -0,0 +1,32 @@ +use std::fs::File; + +use multiversx_sc::abi::ContractAbi; + +use crate::cli_args::GenerateSnippetsAndProxiesArgs; +use crate::cmd::contract::generate_proxy_trait::proxy_trait_gen_main::create_proxies_crate_and_get_lib_file; + +use super::{ + proxy_struct_sc_functions_gen::write_content, + proxy_struct_template_gen::write_struct_template, + super::meta_config::MetaConfig, +}; + +impl MetaConfig { + pub fn generate_rust_proxies_struct(&self, args: &GenerateSnippetsAndProxiesArgs) { + let main_contract = self.output_contracts.main_contract(); + let crate_name = &main_contract.contract_name; + let file = create_proxies_crate_and_get_lib_file(&self.proxy_struct_dir, crate_name, args.overwrite); + write_proxies_struct_to_file( + file, + &self.original_contract_abi, + ); + } +} + +fn write_proxies_struct_to_file( + mut file: File, + abi: &ContractAbi, +) { + write_struct_template(&mut file); + write_content(&mut file, abi); +} diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs new file mode 100644 index 0000000000..65e3448d8e --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs @@ -0,0 +1,69 @@ +use std::{fs::File, io::Write}; + +use multiversx_sc::abi::{ContractAbi, EndpointAbi, InputAbi}; + +use crate::cmd::contract::generate_proxy_trait::proxy_trait_sc_functions_gen::write_endpoint_args_declaration; +use crate::cmd::contract::generate_snippets::snippet_gen_common::write_newline; + +pub(crate) fn write_content( + file: &mut File, + abi: &ContractAbi, +) +{ + write_name(file, abi.name); + + for constructor_abi in &abi.constructors { + write_endpoint(file, constructor_abi); + write_newline(file); + } + + for endpoint_abi in &abi.endpoints { + write_endpoint(file, endpoint_abi); + write_newline(file); + } + writeln!(file, "\t\t)").unwrap(); + writeln!(file, "\t}}").unwrap(); + + + // close impl block brackets + writeln!(file, "}}").unwrap(); +} + +fn write_endpoint(file: &mut File, endpoint_abi: &EndpointAbi) { + write_info_endpoint(file, endpoint_abi.docs); + write_endpoint_name(file, endpoint_abi.rust_method_name, endpoint_abi.name); + write_generic_args(file, &endpoint_abi.inputs); + write_endpoint_args_declaration(file, &endpoint_abi.inputs); +} + +fn write_endpoint_name(file: &mut File, rust_method_name: &str, endpoint_name: &str) { + write!(file, "\t\t\t{endpoint_name} => {rust_method_name}").unwrap(); + //(").unwrap(); +} + +fn write_info_endpoint(file: &mut File, abi_docs: &[&str]) { + if abi_docs.len() > 0 { + write!(file, "\t\t\t//").unwrap(); + } + + for &abi_doc in abi_docs { + writeln!(file, "{abi_doc} ").unwrap(); + } +} + +fn write_name(file: &mut File, name: &str) { + writeln!(file, " {name}").unwrap(); + writeln!(file, " (").unwrap(); +} + +fn write_generic_args(file: &mut File, inputs: &[InputAbi]) { + if inputs.is_empty() { + write!(file, "(").unwrap(); + return; + } + + for n in 0..inputs.len() { + write!(file, "").unwrap(); + } + write!(file, "(").unwrap(); +} diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs new file mode 100644 index 0000000000..beaf6c8cb2 --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs @@ -0,0 +1,24 @@ +use std::{fs::File, io::Write}; + +pub(crate) fn write_struct_template(file: &mut File) { + write!( + file, + "pub struct Proxy +where + A: multiversx_sc::api::VMApi + 'static, +{{ + pub address: multiversx_sc::types::ManagedOption< + A, + multiversx_sc::types::ManagedAddress, + >, +}} + +impl Proxy +where + A: multiversx_sc::api::VMApi + 'static, +{{ + multiversx_sc_wasm_adapter::endpoints_proxy! {{ +" + ) + .unwrap(); +} diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait.rs b/framework/meta/src/cmd/contract/generate_proxy_trait.rs new file mode 100644 index 0000000000..d286b94bd9 --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_trait.rs @@ -0,0 +1,4 @@ +pub mod proxy_trait_crate_gen; +pub mod proxy_trait_gen_main; +pub mod proxy_trait_template_gen; +pub mod proxy_trait_sc_functions_gen; diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs new file mode 100644 index 0000000000..860c5bd9fb --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs @@ -0,0 +1,99 @@ +use std::{ + fs::{self, File}, + io::Write, +}; + +static PROXIES_SOURCE_FILE_NAME: &str = "proxies_interactor_main.rs"; + +pub(crate) fn create_proxies_folder(proxies_folder_path: &str) { + // returns error if folder already exists, so we ignore the result + let _ = fs::create_dir(proxies_folder_path); +} + +pub(crate) fn create_proxies_gitignore(proxies_folder_path: &str, overwrite: bool) { + let gitignore_path = format!("{proxies_folder_path}/.gitignore"); + let mut file = if overwrite { + File::create(&gitignore_path).unwrap() + } else { + match File::options() + .create_new(true) + .write(true) + .open(&gitignore_path) + { + Ok(f) => f, + Err(_) => return, + } + }; + + writeln!( + &mut file, + "# For proxies -> Pem files are used for interactions, but shouldn't be committed +*.pem" + ) + .unwrap(); +} + +pub(crate) fn create_proxies_cargo_toml( + proxies_folder_path: &str, + contract_crate_name: &str, + overwrite: bool, +) { + let cargo_toml_path = format!("{proxies_folder_path}/Cargo.toml"); + let mut file = if overwrite { + File::create(&cargo_toml_path).unwrap() + } else { + match File::options() + .create_new(true) + .write(true) + .open(&cargo_toml_path) + { + Ok(f) => f, + Err(_) => return, + } + }; + + writeln!( + &mut file, + r#"[package] +name = "rust-interact" +version = "0.0.0" +authors = ["you"] +edition = "2023" +publish = false + +[[bin]] +name = "rust-interact" +path = "src/{PROXIES_SOURCE_FILE_NAME}" + +[dependencies.{contract_crate_name}] +path = ".." + +[dependencies.multiversx-sc-wasm-adapter] +version = "0.43.3" +path = "../../../../framework/wasm-adapter" + +# [workspace] + +"# + ) + .unwrap(); +} + +pub(crate) fn create_src_folder(proxies_folder_path: &str) { + // returns error if folder already exists, so we ignore the result + let src_folder_path = format!("{proxies_folder_path}/src"); + let _ = fs::create_dir(src_folder_path); +} + +#[must_use] +pub(crate) fn create_and_get_lib_file(proxies_folder_path: &str, overwrite: bool) -> File { + let lib_path = format!("{proxies_folder_path}/src/{PROXIES_SOURCE_FILE_NAME}"); + if overwrite { + File::create(&lib_path).unwrap() + } else { + match File::options().create_new(true).write(true).open(&lib_path) { + Ok(f) => f, + Err(_) => panic!("{lib_path} file already exists, --overwrite option for proxies was not provided"), + } + } +} diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs new file mode 100644 index 0000000000..4ccd95b85a --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs @@ -0,0 +1,46 @@ +use std::fs::File; + +use multiversx_sc::abi::ContractAbi; + +use crate::cli_args::GenerateSnippetsAndProxiesArgs; + +use super::{ + proxy_trait_crate_gen::{create_and_get_lib_file, create_proxies_cargo_toml, create_proxies_folder, + create_proxies_gitignore, create_src_folder}, + proxy_trait_sc_functions_gen::write_state_struct_impl, + proxy_trait_template_gen::write_proxy_imports, + super::meta_config::MetaConfig, +}; + +impl MetaConfig { + pub fn generate_rust_proxies(&self, args: &GenerateSnippetsAndProxiesArgs) { + let main_contract = self.output_contracts.main_contract(); + let crate_name = &main_contract.contract_name; + let file = create_proxies_crate_and_get_lib_file(&self.proxy_trait_dir, crate_name, args.overwrite); + write_proxies_to_file( + file, + &self.original_contract_abi, + ); + } +} + +#[must_use] +pub fn create_proxies_crate_and_get_lib_file( + proxies_folder_path: &str, + contract_crate_name: &str, + overwrite: bool, +) -> File { + create_proxies_folder(proxies_folder_path); + create_proxies_gitignore(proxies_folder_path, overwrite); + create_proxies_cargo_toml(proxies_folder_path, contract_crate_name, overwrite); + create_src_folder(proxies_folder_path); + create_and_get_lib_file(proxies_folder_path, overwrite) +} + +fn write_proxies_to_file( + mut file: File, + abi: &ContractAbi, +) { + write_proxy_imports(&mut file, abi.name); + write_state_struct_impl(&mut file, abi); +} diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_sc_functions_gen.rs new file mode 100644 index 0000000000..55b5b26b14 --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_sc_functions_gen.rs @@ -0,0 +1,112 @@ +use std::{fs::File, io::Write}; + +use multiversx_sc::abi::{ContractAbi, EndpointAbi, InputAbi, OutputAbi}; + +use crate::cmd::contract::generate_snippets::snippet_gen_common::write_newline; + +pub(crate) fn write_state_struct_impl( + file: &mut File, + abi: &ContractAbi, +) { + for constructor_abi in &abi.constructors { + write_endpoint_impl(file, constructor_abi); + write_newline(file); + } + + for endpoint_abi in &abi.endpoints { + write_endpoint_impl(file, endpoint_abi); + write_newline(file); + } + + // close impl block brackets + writeln!(file, "}}").unwrap(); +} + +fn write_endpoint_impl(file: &mut File, endpoint_abi: &EndpointAbi) { + write_method_attribute(file, endpoint_abi.name, endpoint_abi.rust_method_name); + write_method_declaration(file, endpoint_abi.rust_method_name); + write_comma(file, &endpoint_abi.inputs); + write_endpoint_args_declaration(file, &endpoint_abi.inputs); + write_endpoint_output(file, &endpoint_abi.outputs); + write_newline(file); +} + +fn write_comma(file: &mut File, inputs: &[InputAbi]) { + if !inputs.is_empty() { + write!( + file, + ", ", + ) + .unwrap(); + } +} + +fn write_method_attribute(file: &mut File, endpoint_name: &str, endpoint_method_name: &str) { + if endpoint_name != endpoint_method_name { + writeln!(file, " #[view({endpoint_name})]").unwrap(); + } else { + writeln!(file, " #[endpoint]").unwrap(); + } +} + +fn write_method_declaration(file: &mut File, endpoint_name: &str) { + write!(file, " fn {endpoint_name}(&mut self").unwrap(); +} + +fn write_endpoint_output(file: &mut File, outputs: &[OutputAbi]) { + if outputs.is_empty() { + write!( + file, + ";", + ) + .unwrap(); + return; + } + + for output in outputs { + write!( + file, + " -> {}", + output.type_name + ) + .unwrap(); + } + + write!( + file, + ";", + ) + .unwrap(); +} + +pub fn write_endpoint_args_declaration(file: &mut File, inputs: &[InputAbi]) { + if inputs.is_empty() { + write!( + file, + ")", + ) + .unwrap(); + return; + } + + for (index, input) in inputs.iter().enumerate() { + write!( + file, + "{}: {}", + input.arg_name, + input.type_name.to_string() + ) + .unwrap(); + + // Add a comma after each input except the last one + if index < inputs.len() - 1 { + write!(file, ", ").unwrap(); + } + } + + write!( + file, + ")", + ) + .unwrap(); +} \ No newline at end of file diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_template_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_template_gen.rs new file mode 100644 index 0000000000..37e4861447 --- /dev/null +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_template_gen.rs @@ -0,0 +1,13 @@ +use std::{fs::File, io::Write}; + +pub(crate) fn write_proxy_imports(file: &mut File, abi_name: &str) { + write!( + file, + "multiversx_sc::imports!(); + +#[multiversx_sc::proxy] +pub trait {abi_name} {{ +" + ) + .unwrap(); +} \ No newline at end of file diff --git a/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs b/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs index e46ffa83a7..53a8d043a4 100644 --- a/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs @@ -2,7 +2,7 @@ use std::fs::File; use multiversx_sc::abi::ContractAbi; -use crate::cli_args::GenerateSnippetsArgs; +use crate::cli_args::GenerateSnippetsAndProxiesArgs; use super::{ super::meta_config::MetaConfig, @@ -18,7 +18,7 @@ use super::{ }; impl MetaConfig { - pub fn generate_rust_snippets(&self, args: &GenerateSnippetsArgs) { + pub fn generate_rust_snippets(&self, args: &GenerateSnippetsAndProxiesArgs) { let main_contract = self.output_contracts.main_contract(); let crate_name = &main_contract.contract_name; let snake_case_name = &main_contract.public_name_snake_case(); diff --git a/framework/meta/src/cmd/contract/meta_config.rs b/framework/meta/src/cmd/contract/meta_config.rs index 12b983dd5a..f0013498a6 100644 --- a/framework/meta/src/cmd/contract/meta_config.rs +++ b/framework/meta/src/cmd/contract/meta_config.rs @@ -9,6 +9,8 @@ use super::output_contract::{OutputContract, OutputContractGlobalConfig}; const OUTPUT_RELATIVE_PATH: &str = "../output"; const SNIPPETS_RELATIVE_PATH: &str = "../interact-rs"; const MULTI_CONTRACT_CONFIG_RELATIVE_PATH: &str = "../multicontract.toml"; +const PROXY_TRAIT_RELATIVE_PATH: &str = "../proxy-trait-rs"; +const PROXY_STRUCT_RELATIVE_PATH: &str = "../proxy-struct-rs"; const WASM_LIB_PATH: &str = "../wasm/src/lib.rs"; const WASM_NO_MANAGED_EI: &str = "wasm-no-managed-ei"; const WASM_NO_MANAGED_EI_LIB_PATH: &str = "../wasm-no-managed-ei/src/lib.rs"; @@ -17,6 +19,8 @@ pub struct MetaConfig { pub load_abi_git_version: bool, pub output_dir: String, pub snippets_dir: String, + pub proxy_trait_dir: String, + pub proxy_struct_dir: String, pub original_contract_abi: ContractAbi, pub output_contracts: OutputContractGlobalConfig, } @@ -32,6 +36,8 @@ impl MetaConfig { load_abi_git_version, output_dir: OUTPUT_RELATIVE_PATH.to_string(), snippets_dir: SNIPPETS_RELATIVE_PATH.to_string(), + proxy_trait_dir: PROXY_TRAIT_RELATIVE_PATH.to_string(), + proxy_struct_dir: PROXY_STRUCT_RELATIVE_PATH.to_string(), original_contract_abi, output_contracts, } diff --git a/framework/wasm-adapter/src/lib.rs b/framework/wasm-adapter/src/lib.rs index bf7e6797d0..b55e991b9d 100644 --- a/framework/wasm-adapter/src/lib.rs +++ b/framework/wasm-adapter/src/lib.rs @@ -13,3 +13,4 @@ pub mod error_hook; pub mod panic; pub mod wasm_alloc; mod wasm_macros; +mod proxy_macro; diff --git a/framework/wasm-adapter/src/proxy_macro.rs b/framework/wasm-adapter/src/proxy_macro.rs new file mode 100644 index 0000000000..24701b0967 --- /dev/null +++ b/framework/wasm-adapter/src/proxy_macro.rs @@ -0,0 +1,50 @@ +#[macro_export] +macro_rules! endpoints_proxy { + ($mod_name:ident ( $( + ($docs:ident)? + $endpoint_name:ident => $method_name:ident$(< $generic:ident >)*( $($arg:ident: $arg_type:ident)* ) + )* ) ) => { + $( + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn $method_name< + $($generic: multiversx_sc::codec::CodecInto>,)* + >( + &mut self, + $( + $arg: $generic, + )* + ) -> multiversx_sc::types::ContractCallNoPayment { + let ___address___ = self.extract_address(); + let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( + ___address___, + stringify!($endpoint_name), + ); + + $( + multiversx_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, &$arg); + )* + + ___contract_call___ + } + )* + + $( + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn $method_name( + &mut self + ) -> multiversx_sc::types::ContractCallNoPayment< + Self::Api, + SingleValueMapper + > { + let ___address___ = self.extract_address(); + let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( + ___address___, + stringify!($endpoint_name), + ); + ___contract_call___ + } + )* + }; +} \ No newline at end of file From d5ac49d42827619aaae0747b98f6d82218ca8c82 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Wed, 13 Sep 2023 21:18:39 +0300 Subject: [PATCH 2/3] refactor struct proxy | remove proxy trait and proxy struct folder --- framework/base/src/macros.rs | 51 +++++++++++ .../proxy_struct_gen_main.rs | 11 ++- .../proxy_struct_sc_functions_gen.rs | 63 ++++++++++--- .../proxy_struct_template_gen.rs | 13 +++ .../src/cmd/contract/generate_proxy_trait.rs | 2 +- .../proxy_trait_crate_gen.rs | 91 +------------------ .../proxy_trait_gen_main.rs | 22 +---- .../meta/src/cmd/contract/meta_config.rs | 6 -- 8 files changed, 130 insertions(+), 129 deletions(-) diff --git a/framework/base/src/macros.rs b/framework/base/src/macros.rs index 159b639195..bbbbae9045 100644 --- a/framework/base/src/macros.rs +++ b/framework/base/src/macros.rs @@ -209,3 +209,54 @@ macro_rules! non_zero_usize { NonZeroUsize::new($input).unwrap_or_else(|| sc_panic!($error_msg)) }; } + +#[macro_export] +macro_rules! endpoints_proxy { + ($mod_name:ident ( $( + ($docs:ident)? + $endpoint_name:ident => $method_name:ident$(< $generic:ident >)*( $($arg:ident: $arg_type:ident)* ) + )* ) ) => { + $( + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn $method_name< + $($generic: multiversx_sc::codec::CodecInto>,)* + >( + &mut self, + $( + $arg: $generic, + )* + ) -> multiversx_sc::types::ContractCallNoPayment { + let ___address___ = self.extract_address(); + let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( + ___address___, + stringify!($endpoint_name), + ); + + $( + multiversx_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, &$arg); + )* + + ___contract_call___ + } + )* + + $( + #[allow(clippy::too_many_arguments)] + #[allow(clippy::type_complexity)] + fn $method_name( + &mut self + ) -> multiversx_sc::types::ContractCallNoPayment< + Self::Api, + SingleValueMapper + > { + let ___address___ = self.extract_address(); + let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( + ___address___, + stringify!($endpoint_name), + ); + ___contract_call___ + } + )* + }; +} \ No newline at end of file diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs index 3ef38deb14..03b6caca46 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs @@ -3,19 +3,19 @@ use std::fs::File; use multiversx_sc::abi::ContractAbi; use crate::cli_args::GenerateSnippetsAndProxiesArgs; -use crate::cmd::contract::generate_proxy_trait::proxy_trait_gen_main::create_proxies_crate_and_get_lib_file; +use crate::cmd::contract::generate_proxy_trait::proxy_trait_crate_gen::create_and_get_lib_file; use super::{ proxy_struct_sc_functions_gen::write_content, - proxy_struct_template_gen::write_struct_template, + proxy_struct_template_gen:: {write_imports, write_struct_template}, super::meta_config::MetaConfig, }; +static PROXIES_SOURCE_FILE_NAME: &str = "proxies_struct_interactor_main.rs"; + impl MetaConfig { pub fn generate_rust_proxies_struct(&self, args: &GenerateSnippetsAndProxiesArgs) { - let main_contract = self.output_contracts.main_contract(); - let crate_name = &main_contract.contract_name; - let file = create_proxies_crate_and_get_lib_file(&self.proxy_struct_dir, crate_name, args.overwrite); + let file = create_and_get_lib_file(PROXIES_SOURCE_FILE_NAME, args.overwrite); write_proxies_struct_to_file( file, &self.original_contract_abi, @@ -27,6 +27,7 @@ fn write_proxies_struct_to_file( mut file: File, abi: &ContractAbi, ) { + write_imports(&mut file); write_struct_template(&mut file); write_content(&mut file, abi); } diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs index 65e3448d8e..75d2553534 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs @@ -2,7 +2,6 @@ use std::{fs::File, io::Write}; use multiversx_sc::abi::{ContractAbi, EndpointAbi, InputAbi}; -use crate::cmd::contract::generate_proxy_trait::proxy_trait_sc_functions_gen::write_endpoint_args_declaration; use crate::cmd::contract::generate_snippets::snippet_gen_common::write_newline; pub(crate) fn write_content( @@ -19,6 +18,10 @@ pub(crate) fn write_content( for endpoint_abi in &abi.endpoints { write_endpoint(file, endpoint_abi); + write_endpoint_content_macro(file, endpoint_abi.name); + write_contract_call(file, &endpoint_abi.inputs); + writeln!(file, "\t\t\t\t___contract_call___").unwrap(); + writeln!(file, "\t\t\t}}").unwrap(); write_newline(file); } writeln!(file, "\t\t)").unwrap(); @@ -29,20 +32,51 @@ pub(crate) fn write_content( writeln!(file, "}}").unwrap(); } +fn write_contract_call(file: &mut File, inputs: &[InputAbi]) { + if inputs.is_empty() { + return; + } + + for input in inputs.iter() { + write_contract_call_input(file, &input.arg_name); + } +} + +fn write_contract_call_input(file: &mut File, arg_name: &&str) { + writeln!(file, "\t\t\t\tmultiversx_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, &{arg_name});").unwrap(); +} + +fn write_endpoint_content_macro(file: &mut File, name: &str) { + writeln!(file, "\t\t\t\tmultiversx_sc::endpoint_proxy!{{\n\t\t\t\t\t{name}\n\t\t\t\t}}").unwrap(); +} + fn write_endpoint(file: &mut File, endpoint_abi: &EndpointAbi) { write_info_endpoint(file, endpoint_abi.docs); - write_endpoint_name(file, endpoint_abi.rust_method_name, endpoint_abi.name); + write_endpoint_fn(file, endpoint_abi.name); write_generic_args(file, &endpoint_abi.inputs); - write_endpoint_args_declaration(file, &endpoint_abi.inputs); + write_parameters(file, &endpoint_abi.inputs); + // write_endpoint_args_declaration(file, &endpoint_abi.inputs); } -fn write_endpoint_name(file: &mut File, rust_method_name: &str, endpoint_name: &str) { - write!(file, "\t\t\t{endpoint_name} => {rust_method_name}").unwrap(); - //(").unwrap(); +fn write_parameters(file: &mut File, inputs: &[InputAbi]) { + writeln!(file, "(").unwrap(); + writeln!(file, "\t\t\t\t&mut self,").unwrap(); + for (index, input) in inputs.iter().enumerate() { + write_parameter_arg(file, index, &input.arg_name); + } + writeln!(file, "\t\t\t) -> multiversx_sc::types::ContractDeploy {{").unwrap(); +} + +fn write_parameter_arg(file: &mut File, index: usize, arg_name: &str) { + writeln!(file, "\t\t\t\t{arg_name}: Arg{index},").unwrap() +} + +fn write_endpoint_fn(file: &mut File, endpoint_name: &str) { + write!(file, "\t\t\tfn {endpoint_name}").unwrap(); } fn write_info_endpoint(file: &mut File, abi_docs: &[&str]) { - if abi_docs.len() > 0 { + if !abi_docs.is_empty() { write!(file, "\t\t\t//").unwrap(); } @@ -58,12 +92,19 @@ fn write_name(file: &mut File, name: &str) { fn write_generic_args(file: &mut File, inputs: &[InputAbi]) { if inputs.is_empty() { - write!(file, "(").unwrap(); return; } - for n in 0..inputs.len() { - write!(file, "").unwrap(); + writeln!(file, "<").unwrap(); + + + for (index, input) in inputs.iter().enumerate() { + write_argument(file, index, &input.type_name.to_string()); } - write!(file, "(").unwrap(); + + write!(file, "\t\t\t>").unwrap(); +} + +fn write_argument(file: &mut File, index: usize, type_name: &str) { + writeln!(file, "\t\t\t\tArg{index}: multiversx_sc::codec::CodecInto>,").unwrap(); } diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs index beaf6c8cb2..e5e0b54cf1 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs @@ -1,5 +1,18 @@ use std::{fs::File, io::Write}; +use crate::cmd::contract::generate_snippets::snippet_gen_common::write_newline; + +pub(crate) fn write_imports(file: &mut File) { + writeln!( + file, + r#"#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)]"# + ) + .unwrap(); + + write_newline(file); +} + pub(crate) fn write_struct_template(file: &mut File) { write!( file, diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait.rs b/framework/meta/src/cmd/contract/generate_proxy_trait.rs index d286b94bd9..1a589cfd73 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_trait.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_trait.rs @@ -1,4 +1,4 @@ pub mod proxy_trait_crate_gen; pub mod proxy_trait_gen_main; pub mod proxy_trait_template_gen; -pub mod proxy_trait_sc_functions_gen; +pub mod proxy_trait_sc_functions_gen; \ No newline at end of file diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs index 860c5bd9fb..752a3f3f98 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs @@ -1,93 +1,8 @@ -use std::{ - fs::{self, File}, - io::Write, -}; - -static PROXIES_SOURCE_FILE_NAME: &str = "proxies_interactor_main.rs"; - -pub(crate) fn create_proxies_folder(proxies_folder_path: &str) { - // returns error if folder already exists, so we ignore the result - let _ = fs::create_dir(proxies_folder_path); -} - -pub(crate) fn create_proxies_gitignore(proxies_folder_path: &str, overwrite: bool) { - let gitignore_path = format!("{proxies_folder_path}/.gitignore"); - let mut file = if overwrite { - File::create(&gitignore_path).unwrap() - } else { - match File::options() - .create_new(true) - .write(true) - .open(&gitignore_path) - { - Ok(f) => f, - Err(_) => return, - } - }; - - writeln!( - &mut file, - "# For proxies -> Pem files are used for interactions, but shouldn't be committed -*.pem" - ) - .unwrap(); -} - -pub(crate) fn create_proxies_cargo_toml( - proxies_folder_path: &str, - contract_crate_name: &str, - overwrite: bool, -) { - let cargo_toml_path = format!("{proxies_folder_path}/Cargo.toml"); - let mut file = if overwrite { - File::create(&cargo_toml_path).unwrap() - } else { - match File::options() - .create_new(true) - .write(true) - .open(&cargo_toml_path) - { - Ok(f) => f, - Err(_) => return, - } - }; - - writeln!( - &mut file, - r#"[package] -name = "rust-interact" -version = "0.0.0" -authors = ["you"] -edition = "2023" -publish = false - -[[bin]] -name = "rust-interact" -path = "src/{PROXIES_SOURCE_FILE_NAME}" - -[dependencies.{contract_crate_name}] -path = ".." - -[dependencies.multiversx-sc-wasm-adapter] -version = "0.43.3" -path = "../../../../framework/wasm-adapter" - -# [workspace] - -"# - ) - .unwrap(); -} - -pub(crate) fn create_src_folder(proxies_folder_path: &str) { - // returns error if folder already exists, so we ignore the result - let src_folder_path = format!("{proxies_folder_path}/src"); - let _ = fs::create_dir(src_folder_path); -} +use std::fs::File; #[must_use] -pub(crate) fn create_and_get_lib_file(proxies_folder_path: &str, overwrite: bool) -> File { - let lib_path = format!("{proxies_folder_path}/src/{PROXIES_SOURCE_FILE_NAME}"); +pub(crate) fn create_and_get_lib_file(proxies_file_name: &str, overwrite: bool) -> File { + let lib_path = format!("../{proxies_file_name}"); if overwrite { File::create(&lib_path).unwrap() } else { diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs index 4ccd95b85a..0d33b4a90a 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs @@ -5,18 +5,17 @@ use multiversx_sc::abi::ContractAbi; use crate::cli_args::GenerateSnippetsAndProxiesArgs; use super::{ - proxy_trait_crate_gen::{create_and_get_lib_file, create_proxies_cargo_toml, create_proxies_folder, - create_proxies_gitignore, create_src_folder}, + proxy_trait_crate_gen::create_and_get_lib_file, proxy_trait_sc_functions_gen::write_state_struct_impl, proxy_trait_template_gen::write_proxy_imports, super::meta_config::MetaConfig, }; +static PROXIES_SOURCE_FILE_NAME: &str = "proxies_trait_interactor_main.rs"; + impl MetaConfig { pub fn generate_rust_proxies(&self, args: &GenerateSnippetsAndProxiesArgs) { - let main_contract = self.output_contracts.main_contract(); - let crate_name = &main_contract.contract_name; - let file = create_proxies_crate_and_get_lib_file(&self.proxy_trait_dir, crate_name, args.overwrite); + let file = create_and_get_lib_file(PROXIES_SOURCE_FILE_NAME, args.overwrite); write_proxies_to_file( file, &self.original_contract_abi, @@ -24,19 +23,6 @@ impl MetaConfig { } } -#[must_use] -pub fn create_proxies_crate_and_get_lib_file( - proxies_folder_path: &str, - contract_crate_name: &str, - overwrite: bool, -) -> File { - create_proxies_folder(proxies_folder_path); - create_proxies_gitignore(proxies_folder_path, overwrite); - create_proxies_cargo_toml(proxies_folder_path, contract_crate_name, overwrite); - create_src_folder(proxies_folder_path); - create_and_get_lib_file(proxies_folder_path, overwrite) -} - fn write_proxies_to_file( mut file: File, abi: &ContractAbi, diff --git a/framework/meta/src/cmd/contract/meta_config.rs b/framework/meta/src/cmd/contract/meta_config.rs index f0013498a6..12b983dd5a 100644 --- a/framework/meta/src/cmd/contract/meta_config.rs +++ b/framework/meta/src/cmd/contract/meta_config.rs @@ -9,8 +9,6 @@ use super::output_contract::{OutputContract, OutputContractGlobalConfig}; const OUTPUT_RELATIVE_PATH: &str = "../output"; const SNIPPETS_RELATIVE_PATH: &str = "../interact-rs"; const MULTI_CONTRACT_CONFIG_RELATIVE_PATH: &str = "../multicontract.toml"; -const PROXY_TRAIT_RELATIVE_PATH: &str = "../proxy-trait-rs"; -const PROXY_STRUCT_RELATIVE_PATH: &str = "../proxy-struct-rs"; const WASM_LIB_PATH: &str = "../wasm/src/lib.rs"; const WASM_NO_MANAGED_EI: &str = "wasm-no-managed-ei"; const WASM_NO_MANAGED_EI_LIB_PATH: &str = "../wasm-no-managed-ei/src/lib.rs"; @@ -19,8 +17,6 @@ pub struct MetaConfig { pub load_abi_git_version: bool, pub output_dir: String, pub snippets_dir: String, - pub proxy_trait_dir: String, - pub proxy_struct_dir: String, pub original_contract_abi: ContractAbi, pub output_contracts: OutputContractGlobalConfig, } @@ -36,8 +32,6 @@ impl MetaConfig { load_abi_git_version, output_dir: OUTPUT_RELATIVE_PATH.to_string(), snippets_dir: SNIPPETS_RELATIVE_PATH.to_string(), - proxy_trait_dir: PROXY_TRAIT_RELATIVE_PATH.to_string(), - proxy_struct_dir: PROXY_STRUCT_RELATIVE_PATH.to_string(), original_contract_abi, output_contracts, } From 723f63f96c3810b4499d22c0e267ac65a702e151 Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Mon, 18 Sep 2023 20:19:54 +0300 Subject: [PATCH 3/3] implementation of command proxy-struct --- framework/base/src/macros.rs | 87 ++++++++-------- .../meta/src/cli_args/cli_args_contract.rs | 16 ++- framework/meta/src/cmd/contract.rs | 8 +- .../proxy_struct_gen_main.rs | 7 +- .../proxy_struct_sc_functions_gen.rs | 98 ++++++++++++------- .../proxy_struct_template_gen.rs | 14 +-- .../proxy_trait_crate_gen.rs | 12 +-- .../proxy_trait_gen_main.rs | 6 +- .../generate_snippets/snippet_gen_main.rs | 4 +- .../snippet_sc_functions_gen.rs | 2 +- .../generate_snippets/snippet_type_map.rs | 2 +- framework/wasm-adapter/src/lib.rs | 3 +- framework/wasm-adapter/src/proxy_macro.rs | 50 ---------- 13 files changed, 131 insertions(+), 178 deletions(-) delete mode 100644 framework/wasm-adapter/src/proxy_macro.rs diff --git a/framework/base/src/macros.rs b/framework/base/src/macros.rs index bbbbae9045..9060e8f5d3 100644 --- a/framework/base/src/macros.rs +++ b/framework/base/src/macros.rs @@ -158,8 +158,8 @@ macro_rules! sc_format { /// Equivalent to the `?` operator for SCResult. #[deprecated( - since = "0.16.0", - note = "The `?` operator can now be used on `SCResult`, please use it instead." +since = "0.16.0", +note = "The `?` operator can now be used on `SCResult`, please use it instead." )] #[macro_export] macro_rules! sc_try { @@ -190,8 +190,8 @@ macro_rules! sc_try { /// # } /// ``` #[deprecated( - since = "0.26.0", - note = "Replace with the `#[only_owner]` attribute that can be placed on an endpoint. That one is more compact and shows up in the ABI." +since = "0.26.0", +note = "Replace with the `#[only_owner]` attribute that can be placed on an endpoint. That one is more compact and shows up in the ABI." )] #[macro_export] macro_rules! only_owner { @@ -212,51 +212,44 @@ macro_rules! non_zero_usize { #[macro_export] macro_rules! endpoints_proxy { - ($mod_name:ident ( $( - ($docs:ident)? - $endpoint_name:ident => $method_name:ident$(< $generic:ident >)*( $($arg:ident: $arg_type:ident)* ) - )* ) ) => { - $( - #[allow(clippy::too_many_arguments)] - #[allow(clippy::type_complexity)] - fn $method_name< - $($generic: multiversx_sc::codec::CodecInto>,)* - >( - &mut self, - $( - $arg: $generic, - )* - ) -> multiversx_sc::types::ContractCallNoPayment { - let ___address___ = self.extract_address(); - let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( - ___address___, - stringify!($endpoint_name), - ); + ($endpoint_name:ident, $address:ident) + => { + multiversx_sc::types::ContractCallNoPayment::new( + $address, + stringify!($endpoint_name), + ); + }; +} - $( - multiversx_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, &$arg); - )* +#[macro_export] +macro_rules! constructors_proxy { + ($opt_address:ident) + => { + multiversx_sc::types::new_contract_deploy( + $opt_address, + ); + }; +} - ___contract_call___ - } - )* +#[macro_export] +macro_rules! extract_opt_address { + ($address:expr) => { + { + core::mem::replace( + &mut $address.address, + multiversx_sc::types::ManagedOption::none(), + ) + } + }; +} - $( - #[allow(clippy::too_many_arguments)] - #[allow(clippy::type_complexity)] - fn $method_name( - &mut self - ) -> multiversx_sc::types::ContractCallNoPayment< - Self::Api, - SingleValueMapper - > { - let ___address___ = self.extract_address(); - let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( - ___address___, - stringify!($endpoint_name), - ); - ___contract_call___ - } - )* +#[macro_export] +macro_rules! extract_address { + ($address:expr) + => { + { + multiversx_sc::extract_opt_address!($address) + .unwrap_or_sc_panic(multiversx_sc::err_msg::RECIPIENT_ADDRESS_NOT_SET) + } }; } \ No newline at end of file diff --git a/framework/meta/src/cli_args/cli_args_contract.rs b/framework/meta/src/cli_args/cli_args_contract.rs index cdc2d41f61..8c337ba989 100644 --- a/framework/meta/src/cli_args/cli_args_contract.rs +++ b/framework/meta/src/cli_args/cli_args_contract.rs @@ -65,19 +65,19 @@ pub enum ContractCliAction { name = "snippets", about = "Generates a snippets project, based on the contract ABI." )] - GenerateSnippets(GenerateSnippetsAndProxiesArgs), + GenerateSnippets(GenerateSnippetsArgs), #[command( name = "proxy", about = "Generates a proxy in trait" )] - GenerateProxies(GenerateSnippetsAndProxiesArgs), + GenerateProxies, #[command( name = "proxy-struct", about = "Generates a proxy in struct" )] - GenerateProxiesStruct(GenerateSnippetsAndProxiesArgs) + GenerateProxiesStruct } impl CliArgsToRaw for ContractCliAction { @@ -109,13 +109,11 @@ impl CliArgsToRaw for ContractCliAction { raw.push("snippets".to_string()); raw.append(&mut args.to_raw()); }, - ContractCliAction::GenerateProxies(args) => { + ContractCliAction::GenerateProxies => { raw.push("proxy".to_string()); - raw.append(&mut args.to_raw()); }, - ContractCliAction::GenerateProxiesStruct(args) => { + ContractCliAction::GenerateProxiesStruct => { raw.push("proxy-struct".to_string()); - raw.append(&mut args.to_raw()); } } raw @@ -123,13 +121,13 @@ impl CliArgsToRaw for ContractCliAction { } #[derive(Default, Clone, PartialEq, Eq, Debug, Args)] -pub struct GenerateSnippetsAndProxiesArgs { +pub struct GenerateSnippetsArgs { /// Override snippets project if it already exists. #[arg(long, verbatim_doc_comment)] pub overwrite: bool, } -impl CliArgsToRaw for GenerateSnippetsAndProxiesArgs { +impl CliArgsToRaw for GenerateSnippetsArgs { fn to_raw(&self) -> Vec { let mut raw = Vec::new(); if self.overwrite { diff --git a/framework/meta/src/cmd/contract.rs b/framework/meta/src/cmd/contract.rs index 3e9992dd87..e6fbeabb7d 100644 --- a/framework/meta/src/cmd/contract.rs +++ b/framework/meta/src/cmd/contract.rs @@ -29,12 +29,8 @@ pub fn cli_main() { ContractCliAction::GenerateSnippets(gs_args) => { meta_config_opt.generate_rust_snippets(&gs_args) }, - ContractCliAction::GenerateProxies(gs_args) => { - meta_config_opt.generate_rust_proxies(&gs_args) - }, - ContractCliAction::GenerateProxiesStruct(gs_args) => { - meta_config_opt.generate_rust_proxies_struct(&gs_args) - } + ContractCliAction::GenerateProxies => meta_config_opt.generate_rust_proxies(), + ContractCliAction::GenerateProxiesStruct => meta_config_opt.generate_rust_proxies_struct() } } diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs index 03b6caca46..c8f5a8fa0f 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_gen_main.rs @@ -2,20 +2,19 @@ use std::fs::File; use multiversx_sc::abi::ContractAbi; -use crate::cli_args::GenerateSnippetsAndProxiesArgs; use crate::cmd::contract::generate_proxy_trait::proxy_trait_crate_gen::create_and_get_lib_file; use super::{ proxy_struct_sc_functions_gen::write_content, - proxy_struct_template_gen:: {write_imports, write_struct_template}, + proxy_struct_template_gen::{write_imports, write_struct_template}, super::meta_config::MetaConfig, }; static PROXIES_SOURCE_FILE_NAME: &str = "proxies_struct_interactor_main.rs"; impl MetaConfig { - pub fn generate_rust_proxies_struct(&self, args: &GenerateSnippetsAndProxiesArgs) { - let file = create_and_get_lib_file(PROXIES_SOURCE_FILE_NAME, args.overwrite); + pub fn generate_rust_proxies_struct(&self) { + let file = create_and_get_lib_file(PROXIES_SOURCE_FILE_NAME); write_proxies_struct_to_file( file, &self.original_contract_abi, diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs index 75d2553534..d1e900fc91 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_sc_functions_gen.rs @@ -1,37 +1,47 @@ use std::{fs::File, io::Write}; -use multiversx_sc::abi::{ContractAbi, EndpointAbi, InputAbi}; +use multiversx_sc::abi::{ContractAbi, EndpointAbi, InputAbi, OutputAbis}; use crate::cmd::contract::generate_snippets::snippet_gen_common::write_newline; +use crate::cmd::contract::generate_snippets::snippet_sc_functions_gen::map_output_types_to_rust_types; +use crate::cmd::contract::generate_snippets::snippet_type_map::{handle_abi_type, RustTypeString}; pub(crate) fn write_content( file: &mut File, abi: &ContractAbi, ) { - write_name(file, abi.name); - for constructor_abi in &abi.constructors { - write_endpoint(file, constructor_abi); + write_endpoint(file, constructor_abi, "ContractDeploy"); + write_constructor_content_macro(file); + write_constructor_contract_deploy(file, &constructor_abi.inputs); + writeln!(file, "\t\t___contract_deploy___").unwrap(); + writeln!(file, "\t}}").unwrap(); write_newline(file); } for endpoint_abi in &abi.endpoints { - write_endpoint(file, endpoint_abi); + write_endpoint(file, endpoint_abi, "ContractCallNoPayment"); write_endpoint_content_macro(file, endpoint_abi.name); write_contract_call(file, &endpoint_abi.inputs); - writeln!(file, "\t\t\t\t___contract_call___").unwrap(); - writeln!(file, "\t\t\t}}").unwrap(); + writeln!(file, "\t\t___contract_call___").unwrap(); + writeln!(file, "\t}}").unwrap(); write_newline(file); } - writeln!(file, "\t\t)").unwrap(); - writeln!(file, "\t}}").unwrap(); - - // close impl block brackets writeln!(file, "}}").unwrap(); } +fn write_constructor_contract_deploy(file: &mut File, inputs: &[InputAbi]) { + if inputs.is_empty() { + return; + } + + for input in inputs.iter() { + write_constructor_contract_call(file, &input.arg_name); + } +} + fn write_contract_call(file: &mut File, inputs: &[InputAbi]) { if inputs.is_empty() { return; @@ -43,41 +53,61 @@ fn write_contract_call(file: &mut File, inputs: &[InputAbi]) { } fn write_contract_call_input(file: &mut File, arg_name: &&str) { - writeln!(file, "\t\t\t\tmultiversx_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, &{arg_name});").unwrap(); + writeln!(file, "\t\tContractCall::proxy_arg(&mut ___contract_call___, &{arg_name});").unwrap(); +} + +fn write_constructor_contract_call(file: &mut File, arg_name: &&str) { + writeln!(file, "\t\t___contract_deploy___.push_endpoint_arg(&{arg_name});").unwrap(); } fn write_endpoint_content_macro(file: &mut File, name: &str) { - writeln!(file, "\t\t\t\tmultiversx_sc::endpoint_proxy!{{\n\t\t\t\t\t{name}\n\t\t\t\t}}").unwrap(); + writeln!(file, "\t\tlet ___address___ = multiversx_sc::extract_address!(self);").unwrap(); + writeln!(file, "\t\tlet mut ___contract_call___ = multiversx_sc::endpoints_proxy!({name}, ___address___);").unwrap(); } -fn write_endpoint(file: &mut File, endpoint_abi: &EndpointAbi) { +fn write_constructor_content_macro(file: &mut File) { + writeln!(file, "\t\tlet ___opt_address___ = multiversx_sc::extract_opt_address!(self);").unwrap(); + writeln!(file, "\t\tlet mut ___contract_deploy___ = multiversx_sc::constructors_proxy!(___opt_address___);").unwrap(); +} + +fn write_endpoint(file: &mut File, endpoint_abi: &EndpointAbi, interaction_deploy: &str) { write_info_endpoint(file, endpoint_abi.docs); - write_endpoint_fn(file, endpoint_abi.name); + write_endpoint_fn(file, endpoint_abi.rust_method_name); write_generic_args(file, &endpoint_abi.inputs); - write_parameters(file, &endpoint_abi.inputs); - // write_endpoint_args_declaration(file, &endpoint_abi.inputs); + write_parameters(file, &endpoint_abi.inputs, interaction_deploy); + write_output(file, &endpoint_abi.outputs); +} + +fn write_output(file: &mut File, outputs: &OutputAbis) { + let output_type = map_output_types_to_rust_types(outputs); + + let output_type_print = output_type.replace("", ""); + write!(file, "{output_type_print}", ).unwrap(); + writeln!(file, "> {{").unwrap(); } -fn write_parameters(file: &mut File, inputs: &[InputAbi]) { +fn write_parameters(file: &mut File, inputs: &[InputAbi], interaction_deploy: &str) { writeln!(file, "(").unwrap(); - writeln!(file, "\t\t\t\t&mut self,").unwrap(); + writeln!(file, "\t\t&mut self,").unwrap(); + for (index, input) in inputs.iter().enumerate() { write_parameter_arg(file, index, &input.arg_name); } - writeln!(file, "\t\t\t) -> multiversx_sc::types::ContractDeploy {{").unwrap(); + + write!(file, "\t) -> {interaction_deploy}").unwrap(); + write!(file, "\t>").unwrap(); } -fn write_argument(file: &mut File, index: usize, type_name: &str) { - writeln!(file, "\t\t\t\tArg{index}: multiversx_sc::codec::CodecInto>,").unwrap(); +fn write_argument(file: &mut File, index: usize, type_name: String) { + let mut type_string = RustTypeString::default(); + handle_abi_type(&mut type_string, type_name); + let type_string_str = type_string.get_type_name().to_string(); + + let type_print = type_string_str.replace("", ""); + + writeln!(file, "\t\tArg{index}: multiversx_sc::codec::CodecInto<{}>,", type_print).unwrap(); } diff --git a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs index e5e0b54cf1..a33d14a0c4 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_struct/proxy_struct_template_gen.rs @@ -6,7 +6,8 @@ pub(crate) fn write_imports(file: &mut File) { writeln!( file, r#"#![allow(clippy::too_many_arguments)] -#![allow(clippy::type_complexity)]"# +#![allow(clippy::type_complexity)] +multiversx_sc::imports!();"# ) .unwrap(); @@ -20,18 +21,11 @@ pub(crate) fn write_struct_template(file: &mut File) { where A: multiversx_sc::api::VMApi + 'static, {{ - pub address: multiversx_sc::types::ManagedOption< - A, - multiversx_sc::types::ManagedAddress, - >, + pub address: ManagedOption>, }} impl Proxy where A: multiversx_sc::api::VMApi + 'static, -{{ - multiversx_sc_wasm_adapter::endpoints_proxy! {{ -" - ) - .unwrap(); +{{").unwrap(); } diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs index 752a3f3f98..3fb5c19510 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_crate_gen.rs @@ -1,14 +1,10 @@ use std::fs::File; #[must_use] -pub(crate) fn create_and_get_lib_file(proxies_file_name: &str, overwrite: bool) -> File { +pub(crate) fn create_and_get_lib_file(proxies_file_name: &str) -> File { let lib_path = format!("../{proxies_file_name}"); - if overwrite { - File::create(&lib_path).unwrap() - } else { - match File::options().create_new(true).write(true).open(&lib_path) { - Ok(f) => f, - Err(_) => panic!("{lib_path} file already exists, --overwrite option for proxies was not provided"), - } + match File::options().create_new(true).write(true).open(&lib_path) { + Ok(f) => f, + Err(_) => panic!("{lib_path} file already exists, --overwrite option for proxies was not provided"), } } diff --git a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs index 0d33b4a90a..ca4e9da8ba 100644 --- a/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_proxy_trait/proxy_trait_gen_main.rs @@ -2,8 +2,6 @@ use std::fs::File; use multiversx_sc::abi::ContractAbi; -use crate::cli_args::GenerateSnippetsAndProxiesArgs; - use super::{ proxy_trait_crate_gen::create_and_get_lib_file, proxy_trait_sc_functions_gen::write_state_struct_impl, @@ -14,8 +12,8 @@ use super::{ static PROXIES_SOURCE_FILE_NAME: &str = "proxies_trait_interactor_main.rs"; impl MetaConfig { - pub fn generate_rust_proxies(&self, args: &GenerateSnippetsAndProxiesArgs) { - let file = create_and_get_lib_file(PROXIES_SOURCE_FILE_NAME, args.overwrite); + pub fn generate_rust_proxies(&self) { + let file = create_and_get_lib_file(PROXIES_SOURCE_FILE_NAME); write_proxies_to_file( file, &self.original_contract_abi, diff --git a/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs b/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs index 53a8d043a4..e46ffa83a7 100644 --- a/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs +++ b/framework/meta/src/cmd/contract/generate_snippets/snippet_gen_main.rs @@ -2,7 +2,7 @@ use std::fs::File; use multiversx_sc::abi::ContractAbi; -use crate::cli_args::GenerateSnippetsAndProxiesArgs; +use crate::cli_args::GenerateSnippetsArgs; use super::{ super::meta_config::MetaConfig, @@ -18,7 +18,7 @@ use super::{ }; impl MetaConfig { - pub fn generate_rust_snippets(&self, args: &GenerateSnippetsAndProxiesArgs) { + pub fn generate_rust_snippets(&self, args: &GenerateSnippetsArgs) { let main_contract = self.output_contracts.main_contract(); let crate_name = &main_contract.contract_name; let snake_case_name = &main_contract.public_name_snake_case(); diff --git a/framework/meta/src/cmd/contract/generate_snippets/snippet_sc_functions_gen.rs b/framework/meta/src/cmd/contract/generate_snippets/snippet_sc_functions_gen.rs index 243d3d9b65..c8ec5c16db 100644 --- a/framework/meta/src/cmd/contract/generate_snippets/snippet_sc_functions_gen.rs +++ b/framework/meta/src/cmd/contract/generate_snippets/snippet_sc_functions_gen.rs @@ -205,7 +205,7 @@ fn write_contract_query(file: &mut File, endpoint_abi: &EndpointAbi) { .unwrap(); } -fn map_output_types_to_rust_types(outputs: &[OutputAbi]) -> String { +pub fn map_output_types_to_rust_types(outputs: &[OutputAbi]) -> String { let results_len = outputs.len(); if results_len == 0 { return "()".to_string(); diff --git a/framework/meta/src/cmd/contract/generate_snippets/snippet_type_map.rs b/framework/meta/src/cmd/contract/generate_snippets/snippet_type_map.rs index 803f8c6b29..5e6e28423b 100644 --- a/framework/meta/src/cmd/contract/generate_snippets/snippet_type_map.rs +++ b/framework/meta/src/cmd/contract/generate_snippets/snippet_type_map.rs @@ -183,7 +183,7 @@ fn get_abi_type(abi_type_str: &str) -> AbiType { } } -fn handle_abi_type(type_string: &mut RustTypeString, abi_type_str: String) { +pub fn handle_abi_type(type_string: &mut RustTypeString, abi_type_str: String) { let abi_type = get_abi_type(&abi_type_str); match abi_type { AbiType::UserDefined(user_type) => { diff --git a/framework/wasm-adapter/src/lib.rs b/framework/wasm-adapter/src/lib.rs index b55e991b9d..20d0b4088e 100644 --- a/framework/wasm-adapter/src/lib.rs +++ b/framework/wasm-adapter/src/lib.rs @@ -12,5 +12,4 @@ pub mod api; pub mod error_hook; pub mod panic; pub mod wasm_alloc; -mod wasm_macros; -mod proxy_macro; +mod wasm_macros; \ No newline at end of file diff --git a/framework/wasm-adapter/src/proxy_macro.rs b/framework/wasm-adapter/src/proxy_macro.rs deleted file mode 100644 index 24701b0967..0000000000 --- a/framework/wasm-adapter/src/proxy_macro.rs +++ /dev/null @@ -1,50 +0,0 @@ -#[macro_export] -macro_rules! endpoints_proxy { - ($mod_name:ident ( $( - ($docs:ident)? - $endpoint_name:ident => $method_name:ident$(< $generic:ident >)*( $($arg:ident: $arg_type:ident)* ) - )* ) ) => { - $( - #[allow(clippy::too_many_arguments)] - #[allow(clippy::type_complexity)] - fn $method_name< - $($generic: multiversx_sc::codec::CodecInto>,)* - >( - &mut self, - $( - $arg: $generic, - )* - ) -> multiversx_sc::types::ContractCallNoPayment { - let ___address___ = self.extract_address(); - let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( - ___address___, - stringify!($endpoint_name), - ); - - $( - multiversx_sc::types::ContractCall::proxy_arg(&mut ___contract_call___, &$arg); - )* - - ___contract_call___ - } - )* - - $( - #[allow(clippy::too_many_arguments)] - #[allow(clippy::type_complexity)] - fn $method_name( - &mut self - ) -> multiversx_sc::types::ContractCallNoPayment< - Self::Api, - SingleValueMapper - > { - let ___address___ = self.extract_address(); - let mut ___contract_call___ = multiversx_sc::types::ContractCallNoPayment::new( - ___address___, - stringify!($endpoint_name), - ); - ___contract_call___ - } - )* - }; -} \ No newline at end of file