Skip to content

Commit 6d27d07

Browse files
committed
refactor: addressing pr comments
1 parent e66d176 commit 6d27d07

File tree

8 files changed

+610
-687
lines changed

8 files changed

+610
-687
lines changed

crates/algokit_utils/src/applications/app_client/abi_integration.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,7 @@ impl AppClient {
2222
.map_err(|e| e.to_string())?;
2323
let common_params = CommonTransactionParams {
2424
sender: self.get_sender_address(&sender.map(|s| s.to_string()))?,
25-
signer: None,
26-
rekey_to: None,
27-
note: None,
28-
lease: None,
29-
static_fee: None,
30-
extra_fee: None,
31-
max_fee: None,
32-
validity_window: None,
33-
first_valid_round: None,
34-
last_valid_round: None,
25+
..Default::default()
3526
};
3627
Ok(AppCallMethodCallParams {
3728
common_params,

crates/algokit_utils/src/applications/app_client/params_builder.rs

Lines changed: 198 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use algokit_abi::ABIMethod;
22
use algokit_transact::OnApplicationComplete;
33

44
use crate::transactions::{
5-
AppCallMethodCallParams, AppCallParams, AppMethodCallArg, CommonTransactionParams,
5+
AppCallMethodCallParams, AppCallParams, AppDeleteMethodCallParams, AppDeleteParams,
6+
AppMethodCallArg, AppUpdateMethodCallParams, AppUpdateParams, CommonTransactionParams,
67
PaymentParams,
78
};
89

@@ -58,19 +59,52 @@ impl<'a> ParamsBuilder<'a> {
5859
pub async fn delete(
5960
&self,
6061
params: AppClientMethodCallParams,
61-
) -> Result<AppCallMethodCallParams, String> {
62-
self.method_call_with_on_complete(params, OnApplicationComplete::DeleteApplication)
63-
.await
62+
) -> Result<AppDeleteMethodCallParams, String> {
63+
let method_params = self
64+
.method_call_with_on_complete(params, OnApplicationComplete::DeleteApplication)
65+
.await?;
66+
67+
Ok(AppDeleteMethodCallParams {
68+
common_params: method_params.common_params,
69+
app_id: method_params.app_id,
70+
method: method_params.method,
71+
args: method_params.args,
72+
account_references: method_params.account_references,
73+
app_references: method_params.app_references,
74+
asset_references: method_params.asset_references,
75+
box_references: method_params.box_references,
76+
})
6477
}
6578

6679
/// Update the application with a method call.
6780
pub async fn update(
6881
&self,
6982
params: AppClientMethodCallParams,
70-
_compilation_params: Option<CompilationParams>,
71-
) -> Result<AppCallMethodCallParams, String> {
72-
self.method_call_with_on_complete(params, OnApplicationComplete::UpdateApplication)
83+
compilation_params: Option<CompilationParams>,
84+
) -> Result<AppUpdateMethodCallParams, String> {
85+
// Compile programs (and populate AppManager cache/source maps)
86+
let cp = compilation_params.unwrap_or_default();
87+
let (approval_program, clear_state_program) = self
88+
.client
89+
.compile_with_params(&cp)
7390
.await
91+
.map_err(|e| e.to_string())?;
92+
93+
// Reuse method_call to resolve method + args + common params
94+
let method_params = self.method_call(&params).await?;
95+
96+
Ok(AppUpdateMethodCallParams {
97+
common_params: method_params.common_params,
98+
app_id: method_params.app_id,
99+
approval_program,
100+
clear_state_program,
101+
method: method_params.method,
102+
args: method_params.args,
103+
account_references: method_params.account_references,
104+
app_references: method_params.app_references,
105+
asset_references: method_params.asset_references,
106+
box_references: method_params.box_references,
107+
})
74108
}
75109

76110
/// Fund the application account.
@@ -177,44 +211,135 @@ impl<'a> ParamsBuilder<'a> {
177211
provided: &Option<Vec<AppMethodCallArg>>,
178212
sender: Option<&str>,
179213
) -> Result<Vec<AppMethodCallArg>, String> {
180-
use crate::transactions::app_call::AppMethodCallArg as Arg;
181-
let mut resolved: Vec<Arg> = Vec::with_capacity(method.args.len());
214+
use algokit_abi::ABIMethodArgType;
215+
let mut resolved: Vec<AppMethodCallArg> = Vec::with_capacity(method.args.len());
216+
217+
// Pre-fetch ARC-56 method once if available
218+
let arc56_method = method
219+
.signature()
220+
.ok()
221+
.and_then(|sig| self.client.app_spec().get_arc56_method(&sig).ok());
222+
182223
for (i, m_arg) in method.args.iter().enumerate() {
183-
if let Some(Some(arg)) = provided.as_ref().map(|v| v.get(i)) {
184-
resolved.push(arg.clone());
185-
continue;
186-
}
224+
let provided_arg = provided.as_ref().and_then(|v| v.get(i)).cloned();
187225

188-
// Fill defaults only for value-type args
189-
if let Ok(signature) = method.signature() {
190-
if let Ok(m) = self.client.app_spec().get_arc56_method(&signature) {
191-
if let Some(def) = m.args.get(i).and_then(|a| a.default_value.clone()) {
192-
let arg_type_string = match &m_arg.arg_type {
193-
algokit_abi::ABIMethodArgType::Value(t) => t.to_string(),
194-
other => format!("{:?}", other),
195-
};
226+
match (&m_arg.arg_type, provided_arg) {
227+
// Value-type arguments
228+
(ABIMethodArgType::Value(value_type), Some(AppMethodCallArg::ABIValue(v))) => {
229+
// Provided concrete ABI value
230+
// (we don't type-check here; encoder will validate)
231+
let _ = value_type; // silence unused variable warning if any
232+
resolved.push(AppMethodCallArg::ABIValue(v));
233+
}
234+
(ABIMethodArgType::Value(value_type), Some(AppMethodCallArg::DefaultValue)) => {
235+
// Explicit request to use ARC-56 default
236+
let def = arc56_method
237+
.as_ref()
238+
.and_then(|m| m.args.get(i))
239+
.and_then(|a| a.default_value.clone())
240+
.ok_or_else(|| {
241+
format!(
242+
"No default value defined for argument {} in call to method {}",
243+
m_arg
244+
.name
245+
.clone()
246+
.unwrap_or_else(|| format!("arg{}", i + 1)),
247+
method.name
248+
)
249+
})?;
250+
let abi_type_string = value_type.to_string();
251+
let value = self
252+
.client
253+
.resolve_default_value_for_arg(&def, &abi_type_string, sender)
254+
.await?;
255+
resolved.push(AppMethodCallArg::ABIValue(value));
256+
}
257+
(ABIMethodArgType::Value(_), Some(other)) => {
258+
return Err(format!(
259+
"Invalid argument type for value argument {} in call to method {}: {:?}",
260+
m_arg
261+
.name
262+
.clone()
263+
.unwrap_or_else(|| format!("arg{}", i + 1)),
264+
method.name,
265+
other
266+
));
267+
}
268+
(ABIMethodArgType::Value(value_type), None) => {
269+
// No provided value; try default, else error
270+
if let Some(def) = arc56_method
271+
.as_ref()
272+
.and_then(|m| m.args.get(i))
273+
.and_then(|a| a.default_value.clone())
274+
{
275+
let abi_type_string = value_type.to_string();
196276
let value = self
197277
.client
198-
.resolve_default_value_for_arg(&def, &arg_type_string, sender)
278+
.resolve_default_value_for_arg(&def, &abi_type_string, sender)
199279
.await?;
200-
resolved.push(Arg::ABIValue(value));
201-
continue;
280+
resolved.push(AppMethodCallArg::ABIValue(value));
281+
} else {
282+
return Err(format!(
283+
"No value provided for required argument {} in call to method {}",
284+
m_arg
285+
.name
286+
.clone()
287+
.unwrap_or_else(|| format!("arg{}", i + 1)),
288+
method.name
289+
));
202290
}
203291
}
204-
}
205292

206-
// No provided value or default
207-
if let algokit_abi::ABIMethodArgType::Value(_) = &m_arg.arg_type {
208-
return Err(format!(
209-
"No value provided for required argument {} in call to method {}",
210-
m_arg
211-
.name
212-
.clone()
213-
.unwrap_or_else(|| format!("arg{}", i + 1)),
214-
method.name
215-
));
293+
// Reference-type arguments must be provided explicitly as ABIReference
294+
(ABIMethodArgType::Reference(_), Some(AppMethodCallArg::ABIReference(r))) => {
295+
resolved.push(AppMethodCallArg::ABIReference(r));
296+
}
297+
(ABIMethodArgType::Reference(_), Some(AppMethodCallArg::DefaultValue)) => {
298+
return Err(format!(
299+
"DefaultValue sentinel not supported for reference argument {} in call to method {}",
300+
m_arg
301+
.name
302+
.clone()
303+
.unwrap_or_else(|| format!("arg{}", i + 1)),
304+
method.name
305+
));
306+
}
307+
(ABIMethodArgType::Reference(_), Some(other)) => {
308+
return Err(format!(
309+
"Invalid argument type for reference argument {} in call to method {}: {:?}",
310+
m_arg
311+
.name
312+
.clone()
313+
.unwrap_or_else(|| format!("arg{}", i + 1)),
314+
method.name,
315+
other
316+
));
317+
}
318+
(ABIMethodArgType::Reference(_), None) => {
319+
return Err(format!(
320+
"No value provided for required reference argument {} in call to method {}",
321+
m_arg
322+
.name
323+
.clone()
324+
.unwrap_or_else(|| format!("arg{}", i + 1)),
325+
method.name
326+
));
327+
}
328+
329+
// Transaction-type arguments: allow omission or DefaultValue -> placeholder
330+
(ABIMethodArgType::Transaction(_), Some(AppMethodCallArg::DefaultValue)) => {
331+
resolved.push(AppMethodCallArg::TransactionPlaceholder);
332+
}
333+
(ABIMethodArgType::Transaction(_), Some(arg)) => {
334+
// Any transaction-bearing variant or explicit placeholder is accepted
335+
resolved.push(arg);
336+
}
337+
(ABIMethodArgType::Transaction(_), None) => {
338+
resolved.push(AppMethodCallArg::TransactionPlaceholder);
339+
}
216340
}
217341
}
342+
218343
Ok(resolved)
219344
}
220345
}
@@ -236,8 +361,18 @@ impl BareParamsBuilder<'_> {
236361
}
237362

238363
/// Call with Delete.
239-
pub fn delete(&self, params: AppClientBareCallParams) -> Result<AppCallParams, String> {
240-
self.build_bare_app_call_params(params, OnApplicationComplete::DeleteApplication)
364+
pub fn delete(&self, params: AppClientBareCallParams) -> Result<AppDeleteParams, String> {
365+
let app_call =
366+
self.build_bare_app_call_params(params, OnApplicationComplete::DeleteApplication)?;
367+
Ok(AppDeleteParams {
368+
common_params: app_call.common_params,
369+
app_id: app_call.app_id,
370+
args: app_call.args,
371+
account_references: app_call.account_references,
372+
app_references: app_call.app_references,
373+
asset_references: app_call.asset_references,
374+
box_references: app_call.box_references,
375+
})
241376
}
242377

243378
/// Call with ClearState.
@@ -246,12 +381,34 @@ impl BareParamsBuilder<'_> {
246381
}
247382

248383
/// Update with bare call.
249-
pub fn update(
384+
pub async fn update(
250385
&self,
251386
params: AppClientBareCallParams,
252-
_compilation_params: Option<CompilationParams>,
253-
) -> Result<AppCallParams, String> {
254-
self.build_bare_app_call_params(params, OnApplicationComplete::UpdateApplication)
387+
compilation_params: Option<CompilationParams>,
388+
) -> Result<AppUpdateParams, String> {
389+
// Compile programs (and populate AppManager cache/source maps)
390+
let cp = compilation_params.unwrap_or_default();
391+
let (approval_program, clear_state_program) = self
392+
.client
393+
.compile_with_params(&cp)
394+
.await
395+
.map_err(|e| e.to_string())?;
396+
397+
// Resolve common/bare fields
398+
let app_call =
399+
self.build_bare_app_call_params(params, OnApplicationComplete::UpdateApplication)?;
400+
401+
Ok(AppUpdateParams {
402+
common_params: app_call.common_params,
403+
app_id: app_call.app_id,
404+
approval_program,
405+
clear_state_program,
406+
args: app_call.args,
407+
account_references: app_call.account_references,
408+
app_references: app_call.app_references,
409+
asset_references: app_call.asset_references,
410+
box_references: app_call.box_references,
411+
})
255412
}
256413

257414
fn build_bare_app_call_params(

0 commit comments

Comments
 (0)