Skip to content

Commit ae45db5

Browse files
committed
refactor: ensure send calls from AppClient for methods parse output to arc56 values
1 parent 5350426 commit ae45db5

File tree

4 files changed

+65
-35
lines changed

4 files changed

+65
-35
lines changed

src/algokit_utils/applications/app_client.py

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ABIStruct,
2020
ABIType,
2121
ABIValue,
22+
Arc56ReturnValueType,
2223
BoxABIValue,
2324
get_abi_decoded_value,
2425
get_abi_encoded_value,
@@ -27,6 +28,7 @@
2728
from algokit_utils.applications.app_spec.arc32 import Arc32Contract
2829
from algokit_utils.applications.app_spec.arc56 import (
2930
Arc56Contract,
31+
Method,
3032
PcOffsetMethod,
3133
ProgramSourceInfo,
3234
SourceInfo,
@@ -941,29 +943,43 @@ def fund_app_account(self, params: FundAppAccountParams) -> SendSingleTransactio
941943
lambda: self._algorand.send.payment(self._client.params.fund_app_account(params))
942944
)
943945

944-
def opt_in(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[ABIReturn]:
946+
def opt_in(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[Arc56ReturnValueType]:
945947
return self._client._handle_call_errors(
946-
lambda: self._algorand.send.app_call_method_call(self._client.params.opt_in(params))
948+
lambda: self._client._process_method_call_return(
949+
lambda: self._algorand.send.app_call_method_call(self._client.params.opt_in(params)),
950+
self._app_spec.get_arc56_method(params.method),
951+
)
947952
)
948953

949-
def delete(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[ABIReturn]:
954+
def delete(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[Arc56ReturnValueType]:
950955
return self._client._handle_call_errors(
951-
lambda: self._algorand.send.app_delete_method_call(self._client.params.delete(params))
956+
lambda: self._client._process_method_call_return(
957+
lambda: self._algorand.send.app_delete_method_call(self._client.params.delete(params)),
958+
self._app_spec.get_arc56_method(params.method),
959+
)
952960
)
953961

954962
def update(
955963
self, params: AppClientMethodCallWithCompilationAndSendParams
956-
) -> SendAppUpdateTransactionResult[ABIReturn]:
957-
return self._client._handle_call_errors(
958-
lambda: self._algorand.send.app_update_method_call(self._client.params.update(params))
964+
) -> SendAppUpdateTransactionResult[Arc56ReturnValueType]:
965+
result = self._client._handle_call_errors(
966+
lambda: self._client._process_method_call_return(
967+
lambda: self._algorand.send.app_update_method_call(self._client.params.update(params)),
968+
self._app_spec.get_arc56_method(params.method),
969+
)
959970
)
971+
assert isinstance(result, SendAppUpdateTransactionResult)
972+
return result
960973

961-
def close_out(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[ABIReturn]:
974+
def close_out(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[Arc56ReturnValueType]:
962975
return self._client._handle_call_errors(
963-
lambda: self._algorand.send.app_call_method_call(self._client.params.close_out(params))
976+
lambda: self._client._process_method_call_return(
977+
lambda: self._algorand.send.app_call_method_call(self._client.params.close_out(params)),
978+
self._app_spec.get_arc56_method(params.method),
979+
)
964980
)
965981

966-
def call(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[ABIReturn]:
982+
def call(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionResult[Arc56ReturnValueType]:
967983
is_read_only_call = (
968984
params.on_complete == algosdk.transaction.OnComplete.NoOpOC or params.on_complete is None
969985
) and self._app_spec.get_arc56_method(params.method).readonly
@@ -985,19 +1001,24 @@ def call(self, params: AppClientMethodCallWithSendParams) -> SendAppTransactionR
9851001
)
9861002
)
9871003

988-
return SendAppTransactionResult[ABIReturn](
1004+
return SendAppTransactionResult[Arc56ReturnValueType](
9891005
tx_ids=simulate_response.tx_ids,
9901006
transactions=simulate_response.transactions,
9911007
transaction=simulate_response.transactions[-1],
9921008
confirmation=simulate_response.confirmations[-1] if simulate_response.confirmations else b"",
9931009
confirmations=simulate_response.confirmations,
9941010
group_id=simulate_response.group_id or "",
9951011
returns=simulate_response.returns,
996-
abi_return=simulate_response.returns[-1],
1012+
abi_return=simulate_response.returns[-1].get_arc56_value(
1013+
self._app_spec.get_arc56_method(params.method), self._app_spec.structs
1014+
),
9971015
)
9981016

9991017
return self._client._handle_call_errors(
1000-
lambda: self._algorand.send.app_call_method_call(self._client.params.call(params))
1018+
lambda: self._client._process_method_call_return(
1019+
lambda: self._algorand.send.app_call_method_call(self._client.params.call(params)),
1020+
self._app_spec.get_arc56_method(params.method),
1021+
)
10011022
)
10021023

10031024

@@ -1570,8 +1591,8 @@ def _get_abi_args_with_default_values( # noqa: C901, PLR0912
15701591
self._app_spec.structs,
15711592
)
15721593
)
1573-
elif call_result.abi_return.value:
1574-
result.append(call_result.abi_return.value)
1594+
elif call_result.abi_return:
1595+
result.append(call_result.abi_return)
15751596

15761597
case "local" | "global":
15771598
# Get state value
@@ -1624,3 +1645,21 @@ def _get_abi_params(self, params: dict[str, Any], on_complete: algosdk.transacti
16241645
"onComplete": on_complete,
16251646
"args": args,
16261647
}
1648+
1649+
def _process_method_call_return(
1650+
self,
1651+
result: Callable[[], SendAppUpdateTransactionResult[ABIReturn] | SendAppTransactionResult[ABIReturn]],
1652+
method: Method,
1653+
) -> SendAppUpdateTransactionResult[Arc56ReturnValueType] | SendAppTransactionResult[Arc56ReturnValueType]:
1654+
result_value = result()
1655+
abi_return = (
1656+
result_value.abi_return.get_arc56_value(method, self._app_spec.structs)
1657+
if isinstance(result_value.abi_return, ABIReturn)
1658+
else None
1659+
)
1660+
1661+
if isinstance(result_value, SendAppUpdateTransactionResult):
1662+
return SendAppUpdateTransactionResult[Arc56ReturnValueType](
1663+
**{**result_value.__dict__, "abi_return": abi_return}
1664+
)
1665+
return SendAppTransactionResult[Arc56ReturnValueType](**{**result_value.__dict__, "abi_return": abi_return})

src/algokit_utils/applications/app_factory.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from dataclasses import asdict, dataclass, replace
44
from typing import Any, Generic, Literal, Protocol, TypeVar
55

6-
from algosdk.abi import Method
76
from algosdk.atomic_transaction_composer import TransactionSigner
87
from algosdk.source_map import SourceMap
98
from algosdk.transaction import OnComplete, Transaction
@@ -39,7 +38,7 @@
3938
OperationPerformed,
4039
)
4140
from algokit_utils.applications.app_manager import DELETABLE_TEMPLATE_NAME, UPDATABLE_TEMPLATE_NAME
42-
from algokit_utils.applications.app_spec.arc56 import Arc56Contract
41+
from algokit_utils.applications.app_spec.arc56 import Arc56Contract, Method
4342
from algokit_utils.models.application import (
4443
AppSourceMaps,
4544
)
@@ -453,7 +452,7 @@ def create(
453452
result = self._factory._handle_call_errors(
454453
lambda: self._factory._parse_method_call_return(
455454
lambda: self._algorand.send.app_create_method_call(self._factory.params.create(create_params)),
456-
self._factory._app_spec.get_arc56_method(params.method).to_abi_method(),
455+
self._factory._app_spec.get_arc56_method(params.method),
457456
)
458457
)
459458

tests/applications/test_app_client.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -353,10 +353,9 @@ def test_construct_transaction_with_abi_encoding_including_transaction(
353353
result.confirmation, test_app_client.app_spec.get_arc56_method("call_abi_txn").to_abi_method()
354354
)
355355
expected_return = f"Sent {amount.micro_algos}. test"
356-
assert result.abi_return
357-
assert result.abi_return.value == expected_return
356+
assert result.abi_return == expected_return
358357
assert response
359-
assert response.value == result.abi_return.value
358+
assert response.value == result.abi_return
360359

361360

362361
def test_sign_all_transactions_in_group_with_abi_call_with_transaction_arg(
@@ -450,10 +449,9 @@ def test_construct_transaction_with_abi_encoding_including_foreign_references_no
450449
test_app_client.app_spec.get_arc56_method("call_abi_foreign_refs").to_abi_method(),
451450
)
452451
assert result.abi_return
453-
assert result.abi_return.value
454-
assert str(result.abi_return.value).startswith("App: 345, Asset: 567, Account: ")
452+
assert str(result.abi_return).startswith("App: 345, Asset: 567, Account: ")
455453
assert expected_return
456-
assert expected_return.value == result.abi_return.value
454+
assert expected_return.value == result.abi_return
457455

458456

459457
def test_retrieve_state(test_app_client: AppClient, funded_account: Account) -> None:
@@ -710,14 +708,12 @@ def test_abi_with_default_arg_method(
710708
AppClientMethodCallWithSendParams(method=method_signature, args=[defined_value])
711709
)
712710

713-
assert defined_value_result.abi_return
714-
assert defined_value_result.abi_return.value == "Local state, defined value"
711+
assert defined_value_result.abi_return == "Local state, defined value"
715712

716713
# Test with default value
717714
default_value_result = app_client.send.call(AppClientMethodCallWithSendParams(method=method_signature, args=[None]))
718715
assert default_value_result
719-
assert default_value_result.abi_return
720-
assert default_value_result.abi_return.value == "Local state, banana"
716+
assert default_value_result.abi_return == "Local state, banana"
721717

722718

723719
def test_exposing_logic_error(test_app_client_with_sourcemaps: AppClient) -> None:

tests/applications/test_app_factory.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -331,9 +331,7 @@ def test_create_then_call_app(factory: AppFactory) -> None:
331331
)
332332

333333
call = app_client.send.call(AppClientMethodCallWithSendParams(method="call_abi", args=["test"]))
334-
335-
assert call.abi_return
336-
assert call.abi_return.value == "Hello, test"
334+
assert call.abi_return == "Hello, test"
337335

338336

339337
def test_call_app_with_rekey(funded_account: Account, algorand: AlgorandClient, factory: AppFactory) -> None:
@@ -395,8 +393,7 @@ def test_update_app_with_abi(factory: AppFactory) -> None:
395393
)
396394
)
397395

398-
assert call_return.abi_return
399-
assert call_return.abi_return.value == "string_io"
396+
assert call_return.abi_return == "string_io"
400397
# assert call_return.compiled_approval is not None # TODO: centralize approval/clear compilation
401398

402399

@@ -418,8 +415,7 @@ def test_delete_app_with_abi(factory: AppFactory) -> None:
418415
)
419416
)
420417

421-
assert call_return.abi_return
422-
assert call_return.abi_return.value == "string_io"
418+
assert call_return.abi_return == "string_io"
423419

424420

425421
def test_export_import_sourcemaps(

0 commit comments

Comments
 (0)