Skip to content

Commit db1df15

Browse files
solved deserializing issue, still more generation issues to be solved
1 parent 57b1e49 commit db1df15

4 files changed

Lines changed: 384 additions & 239 deletions

File tree

framework/meta-lib/src/contract/generate_snippets/snippet_abi_check.rs

Lines changed: 163 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,141 @@
11
use std::fs::File;
22
use std::io::Write;
33

4-
use multiversx_sc::abi::{ContractAbi, EndpointAbi, EndpointMutabilityAbi, InputAbi};
5-
use serde::Deserialize;
4+
use multiversx_sc::abi::{ContractAbi, EndpointAbi, InputAbi, OutputAbi};
5+
use serde::de::DeserializeOwned;
6+
use serde::{de, Deserialize, Deserializer};
67

78
use crate::abi_json::{serialize_abi_to_json, ContractAbiJson};
89

910
use super::snippet_crate_gen::LIB_SOURCE_FILE_NAME;
10-
use super::snippet_sc_functions_gen::endpoint_args_when_called;
1111
use super::snippet_type_map::map_abi_type_to_rust_type;
1212
use crate::contract::generate_snippets::snippet_sc_functions_gen::DEFAULT_GAS;
1313

14-
#[derive(PartialEq, Deserialize, Clone)]
14+
#[derive(PartialEq, Deserialize, Clone, Debug)]
1515
#[serde(rename_all = "camelCase")]
1616
pub(crate) struct ShortContractAbi {
1717
#[serde(default)]
1818
pub name: String,
19+
#[serde(default, deserialize_with = "deserialize_single_or_vec")]
20+
pub constructor: Vec<ShortEndpointAbi>,
21+
#[serde(
22+
default,
23+
rename = "upgradeConstructor",
24+
deserialize_with = "deserialize_single_or_vec"
25+
)]
26+
pub upgrade_constructor: Vec<ShortEndpointAbi>,
1927
#[serde(default)]
20-
pub constructors: Vec<EndpointAbi>,
21-
#[serde(default, rename = "upgradeConstructor")]
22-
pub upgrade_constructors: Vec<EndpointAbi>,
23-
pub endpoints: Vec<EndpointAbi>,
28+
pub endpoints: Vec<ShortEndpointAbi>,
29+
}
30+
31+
#[derive(PartialEq, Deserialize, Clone, Debug)]
32+
pub(crate) struct ShortEndpointAbi {
33+
#[serde(default)]
34+
pub name: String,
35+
#[serde(default)]
36+
pub mutability: String,
37+
#[serde(default, skip_deserializing)]
38+
pub rust_method_name: String,
39+
#[serde(default)]
40+
pub payable_in_tokens: Vec<String>,
41+
#[serde(default)]
42+
pub inputs: Vec<ShortInputAbi>,
43+
#[serde(default)]
44+
pub outputs: Vec<ShortOutputAbi>,
45+
#[serde(default)]
46+
pub allow_multiple_var_args: bool,
47+
}
48+
49+
#[derive(PartialEq, Deserialize, Clone, Debug)]
50+
pub(crate) struct ShortInputAbi {
51+
#[serde(default)]
52+
pub name: String,
53+
#[serde(rename = "type")]
54+
pub type_name: String,
55+
#[serde(default)]
56+
pub multi_arg: bool,
57+
}
58+
59+
#[derive(PartialEq, Deserialize, Clone, Debug)]
60+
pub(crate) struct ShortOutputAbi {
61+
#[serde(rename = "type")]
62+
pub type_name: String,
63+
#[serde(default)]
64+
pub multi_result: bool,
65+
}
66+
67+
fn deserialize_single_or_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
68+
where
69+
D: Deserializer<'de>,
70+
T: DeserializeOwned,
71+
{
72+
let value = serde_json::Value::deserialize(deserializer)?;
73+
match value {
74+
serde_json::Value::Array(vec) => {
75+
serde_json::from_value(serde_json::Value::Array(vec)).map_err(de::Error::custom)
76+
},
77+
_ => Ok(serde_json::from_value(value.clone())
78+
.map(|single| vec![single])
79+
.expect(&format!("error at {value:?}"))), // .map_err(de::Error::custom),
80+
}
81+
}
82+
83+
impl From<EndpointAbi> for ShortEndpointAbi {
84+
fn from(value: EndpointAbi) -> Self {
85+
Self {
86+
name: value.name,
87+
mutability: format!("{:?}", value.mutability).to_lowercase(),
88+
rust_method_name: value.rust_method_name,
89+
payable_in_tokens: value.payable_in_tokens,
90+
inputs: value.inputs.into_iter().map(ShortInputAbi::from).collect(),
91+
outputs: value
92+
.outputs
93+
.into_iter()
94+
.map(ShortOutputAbi::from)
95+
.collect(),
96+
allow_multiple_var_args: value.allow_multiple_var_args,
97+
}
98+
}
99+
}
100+
101+
impl From<InputAbi> for ShortInputAbi {
102+
fn from(value: InputAbi) -> Self {
103+
Self {
104+
name: value.arg_name,
105+
type_name: value.type_names.abi,
106+
multi_arg: value.multi_arg,
107+
}
108+
}
109+
}
110+
111+
impl From<OutputAbi> for ShortOutputAbi {
112+
fn from(value: OutputAbi) -> Self {
113+
Self {
114+
type_name: value.type_names.abi,
115+
multi_result: value.multi_result,
116+
}
117+
}
24118
}
25119

26120
impl From<ContractAbi> for ShortContractAbi {
27121
fn from(value: ContractAbi) -> Self {
28122
Self {
29123
name: value.name,
30-
constructors: value.constructors,
31-
upgrade_constructors: value.upgrade_constructors,
32-
endpoints: value.endpoints,
124+
constructor: value
125+
.constructors
126+
.into_iter()
127+
.map(ShortEndpointAbi::from)
128+
.collect(),
129+
upgrade_constructor: value
130+
.upgrade_constructors
131+
.into_iter()
132+
.map(ShortEndpointAbi::from)
133+
.collect(),
134+
endpoints: value
135+
.endpoints
136+
.into_iter()
137+
.map(ShortEndpointAbi::from)
138+
.collect(),
33139
}
34140
}
35141
}
@@ -47,23 +153,23 @@ pub(crate) fn check_abi_differences(
47153
if let Ok(prev_abi) = serde_json::from_str::<ShortContractAbi>(&prev_abi_content) {
48154
let mut diff_abi = ShortContractAbi {
49155
name: current_contract_abi.name.clone(),
50-
constructors: vec![],
51-
upgrade_constructors: vec![],
156+
constructor: vec![],
157+
upgrade_constructor: vec![],
52158
endpoints: vec![],
53159
};
54160

55161
// changed and new constructors
56-
for constructor in &current_contract_abi.constructors {
57-
if !prev_abi.constructors.contains(constructor) {
58-
diff_abi.constructors.push(constructor.clone());
162+
for constructor in &current_contract_abi.constructor {
163+
if !prev_abi.constructor.contains(constructor) {
164+
diff_abi.constructor.push(constructor.clone());
59165
}
60166
}
61167

62168
// changed and new upgrade constructors
63-
for upgrade_constructor in &current_contract_abi.upgrade_constructors {
64-
if !prev_abi.upgrade_constructors.contains(upgrade_constructor) {
169+
for upgrade_constructor in &current_contract_abi.upgrade_constructor {
170+
if !prev_abi.upgrade_constructor.contains(upgrade_constructor) {
65171
diff_abi
66-
.upgrade_constructors
172+
.upgrade_constructor
67173
.push(upgrade_constructor.clone());
68174
}
69175
}
@@ -76,13 +182,17 @@ pub(crate) fn check_abi_differences(
76182
}
77183

78184
// deleted endpoints
185+
// bug here when deleting and diff with no overwrite
79186
for endpoint in &prev_abi.endpoints {
80187
if !current_contract_abi.endpoints.contains(endpoint) {
81188
diff_abi.endpoints.retain(|e| e.name != endpoint.name);
82189
}
83190
}
84191

192+
println!("diff_abi {diff_abi:?}");
85193
return diff_abi;
194+
} else {
195+
println!("here")
86196
}
87197
}
88198
}
@@ -99,7 +209,7 @@ pub(crate) fn create_prev_abi_file(snippets_dir: &String, contract_abi: &Contrac
99209
}
100210

101211
pub(crate) fn add_new_endpoints_to_file(snippets_dir: &String, diff_abi: &ShortContractAbi) {
102-
let interact_lib_path = format!("{snippets_dir}/{LIB_SOURCE_FILE_NAME}");
212+
let interact_lib_path = format!("{snippets_dir}/src/{LIB_SOURCE_FILE_NAME}");
103213
let file_content = std::fs::read_to_string(&interact_lib_path).unwrap();
104214
let mut updated_content = file_content.clone();
105215

@@ -108,21 +218,22 @@ pub(crate) fn add_new_endpoints_to_file(snippets_dir: &String, diff_abi: &ShortC
108218
insert_or_replace_function(&updated_content, endpoint_abi, &diff_abi.name);
109219
}
110220

111-
for constructor in &diff_abi.constructors {
221+
for constructor in &diff_abi.constructor {
112222
updated_content = insert_or_replace_function(&updated_content, constructor, &diff_abi.name);
113223
}
114224

115-
for upgrade_constructor in &diff_abi.upgrade_constructors {
225+
for upgrade_constructor in &diff_abi.upgrade_constructor {
116226
updated_content =
117227
insert_or_replace_function(&updated_content, upgrade_constructor, &diff_abi.name);
118228
}
119229

120230
std::fs::write(interact_lib_path, updated_content).unwrap();
121231
}
122232

233+
// this may be buggy
123234
fn insert_or_replace_function(
124235
file_content: &str,
125-
endpoint_abi: &EndpointAbi,
236+
endpoint_abi: &ShortEndpointAbi,
126237
contract_name: &String,
127238
) -> String {
128239
let function_signature = format!("pub async fn {}", endpoint_abi.rust_method_name);
@@ -163,14 +274,14 @@ fn insert_or_replace_function(
163274

164275
pub(crate) fn write_endpoint_impl_to_string(
165276
buffer: &mut String,
166-
endpoint_abi: &EndpointAbi,
277+
endpoint_abi: &ShortEndpointAbi,
167278
name: &String,
168279
) {
169280
write_method_declaration_to_string(buffer, &endpoint_abi.rust_method_name);
170281
write_payments_declaration_to_string(buffer, &endpoint_abi.payable_in_tokens);
171282
write_endpoint_args_declaration_to_string(buffer, &endpoint_abi.inputs);
172283

173-
if matches!(endpoint_abi.mutability, EndpointMutabilityAbi::Readonly) {
284+
if endpoint_abi.mutability == "readonly".to_string() {
174285
write_contract_query_to_string(buffer, endpoint_abi, name);
175286
} else {
176287
write_contract_call_to_string(buffer, endpoint_abi, name);
@@ -206,31 +317,35 @@ pub(crate) fn write_payments_declaration_to_string(
206317
let token_nonce = 0u64;
207318
let token_amount = ",
208319
);
209-
buffer.push_str(&biguint_default.get_default_value_expr());
320+
buffer.push_str(biguint_default.get_default_value_expr());
210321
buffer.push_str(";\n");
211322
}
212323

213324
buffer.push('\n');
214325
}
215326

216-
fn write_endpoint_args_declaration_to_string(buffer: &mut String, inputs: &[InputAbi]) {
327+
fn write_endpoint_args_declaration_to_string(buffer: &mut String, inputs: &[ShortInputAbi]) {
217328
if inputs.is_empty() {
218329
return;
219330
}
220331

221332
for input in inputs {
222-
let rust_type = map_abi_type_to_rust_type(input.type_names.abi.clone());
333+
let rust_type = map_abi_type_to_rust_type(input.type_name.clone());
223334
buffer.push_str(&format!(
224335
" let {} = {};\n",
225-
input.arg_name,
336+
input.name,
226337
rust_type.get_default_value_expr()
227338
));
228339
}
229340

230341
buffer.push('\n');
231342
}
232343

233-
fn write_contract_call_to_string(buffer: &mut String, endpoint_abi: &EndpointAbi, name: &String) {
344+
fn write_contract_call_to_string(
345+
buffer: &mut String,
346+
endpoint_abi: &ShortEndpointAbi,
347+
name: &String,
348+
) {
234349
let payment_snippet = if endpoint_abi.payable_in_tokens.is_empty() {
235350
"".to_string()
236351
} else if endpoint_abi.payable_in_tokens[0] == "EGLD" {
@@ -256,12 +371,16 @@ fn write_contract_call_to_string(buffer: &mut String, endpoint_abi: &EndpointAbi
256371
"#,
257372
name,
258373
endpoint_abi.rust_method_name,
259-
endpoint_args_when_called(endpoint_abi.inputs.as_slice()),
374+
endpoint_args_when_called_short(endpoint_abi.inputs.as_slice()),
260375
payment_snippet,
261376
));
262377
}
263378

264-
fn write_contract_query_to_string(buffer: &mut String, endpoint_abi: &EndpointAbi, name: &String) {
379+
fn write_contract_query_to_string(
380+
buffer: &mut String,
381+
endpoint_abi: &ShortEndpointAbi,
382+
name: &String,
383+
) {
265384
buffer.push_str(&format!(
266385
r#" let result_value = self
267386
.interactor
@@ -277,6 +396,17 @@ fn write_contract_query_to_string(buffer: &mut String, endpoint_abi: &EndpointAb
277396
"#,
278397
name,
279398
endpoint_abi.rust_method_name,
280-
endpoint_args_when_called(endpoint_abi.inputs.as_slice()),
399+
endpoint_args_when_called_short(endpoint_abi.inputs.as_slice()),
281400
));
282401
}
402+
403+
pub(crate) fn endpoint_args_when_called_short(inputs: &[ShortInputAbi]) -> String {
404+
let mut result = String::new();
405+
for input in inputs {
406+
if !result.is_empty() {
407+
result.push_str(", ");
408+
}
409+
result.push_str(&input.name);
410+
}
411+
result
412+
}

framework/meta-lib/src/contract/generate_snippets/snippet_gen_main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl MetaConfig {
3030
let original_contract_abi = ShortContractAbi::from(self.original_contract_abi.clone());
3131
let diff_abi =
3232
check_abi_differences(&original_contract_abi, &self.snippets_dir, args.overwrite);
33-
if &diff_abi == &original_contract_abi {
33+
if diff_abi == original_contract_abi {
3434
let mut file = create_snippets_crate_and_get_lib_file(
3535
&self.snippets_dir,
3636
crate_name,

0 commit comments

Comments
 (0)