2121from algosdk .transaction import OnComplete , SuggestedParams
2222from algosdk .v2client .algod import AlgodClient
2323from algosdk .v2client .models .simulate_request import SimulateRequest
24- from typing_extensions import deprecated
24+ from typing_extensions import Never , deprecated
2525
2626from algokit_utils .applications .abi import ABIReturn , ABIValue
2727from algokit_utils .applications .app_manager import AppManager
@@ -667,7 +667,7 @@ def _encode_lease(lease: str | bytes | None) -> bytes | None:
667667 raise TypeError (f"Unknown lease type received of { type (lease )} " )
668668
669669
670- def _get_group_execution_info ( # noqa: C901, PLR0912
670+ def _get_group_execution_info ( # noqa: C901
671671 atc : AtomicTransactionComposer ,
672672 algod : AlgodClient ,
673673 populate_app_call_resources : bool | None = None ,
@@ -682,6 +682,7 @@ def _get_group_execution_info( # noqa: C901, PLR0912
682682 txn_groups = [],
683683 allow_unnamed_resources = True ,
684684 allow_empty_signatures = True ,
685+ exec_trace_config = algosdk .v2client .models .SimulateTraceConfig (enable = True ),
685686 )
686687
687688 # Clone ATC with null signers
@@ -720,16 +721,8 @@ def _get_group_execution_info( # noqa: C901, PLR0912
720721 group_response = result .simulate_response ["txn-groups" ][0 ]
721722
722723 if group_response .get ("failure-message" ):
723- msg = group_response ["failure-message" ]
724- if cover_app_call_inner_transaction_fees and "fee too small" in msg :
725- raise ValueError (
726- "Fees were too small to resolve execution info via simulate. "
727- "You may need to increase an app call transaction maxFee."
728- )
729- failed_at = group_response .get ("failed-at" , [0 ])[0 ]
730- raise ValueError (
731- f"Error resolving execution info via simulate in transaction { failed_at } : "
732- f"{ group_response ['failure-message' ]} "
724+ _handle_simulation_error (
725+ group_response , cover_app_call_inner_transaction_fees = cover_app_call_inner_transaction_fees
733726 )
734727
735728 # Build execution info
@@ -782,6 +775,36 @@ def calculate_inner_fee_delta(inner_txns: list[dict], acc: int = 0) -> int:
782775 )
783776
784777
778+ def _handle_simulation_error (
779+ group_response : dict [str , Any ], * , cover_app_call_inner_transaction_fees : bool | None
780+ ) -> Never :
781+ msg = group_response ["failure-message" ]
782+ if cover_app_call_inner_transaction_fees and "fee too small" in msg :
783+ raise ValueError (
784+ "Fees were too small to resolve execution info via simulate. "
785+ "You may need to increase an app call transaction maxFee."
786+ )
787+ failed_at = group_response .get ("failed-at" , [0 ])[0 ]
788+ details = ""
789+ if "logic eval error" not in msg :
790+ # extract last pc from trace so we can format an error that can be parsed into a LogicError
791+ try :
792+ trace = group_response ["txn-results" ][failed_at ]["exec-trace" ]
793+ except (KeyError , IndexError ):
794+ pass
795+ else :
796+ try :
797+ program_trace = trace ["approval-program-trace" ]
798+ except KeyError :
799+ program_trace = trace ["clear-program-trace" ]
800+ pc = program_trace [- 1 ]["pc" ]
801+ details = f". Details: pc={ pc } "
802+ raise ValueError (
803+ f"Error resolving execution info via simulate in transaction { failed_at } : "
804+ f"{ group_response ['failure-message' ]} { details } "
805+ )
806+
807+
785808def _find_available_transaction_index (
786809 txns : list [TransactionWithSigner ], reference_type : str , reference : str | dict [str , Any ] | int
787810) -> int :
0 commit comments