@@ -185,7 +185,7 @@ def __init__(
185185 self .app_spec = app_spec
186186 self ._approval_program : Program | None = None
187187 self ._clear_program : Program | None = None
188- self ._approval_source_map : SourceMap | None = None
188+ self .approval_source_map : SourceMap | None = None
189189 self .existing_deployments = existing_deployments
190190 self ._indexer_client = indexer_client
191191 if creator is not None :
@@ -226,17 +226,12 @@ def __init__(
226226 def app_address (self ) -> str :
227227 return get_application_address (self .app_id )
228228
229- # TODO: source map changes
230229 @property
231- def approval (self ) -> Program :
232- if not self ._approval_program :
233- self ._approval_program = Program (self .app_spec .approval_program , self .algod_client )
230+ def approval (self ) -> Program | None :
234231 return self ._approval_program
235232
236233 @property
237- def clear (self ) -> Program :
238- if not self ._clear_program :
239- self ._clear_program = Program (self .app_spec .clear_program , self .algod_client )
234+ def clear (self ) -> Program | None :
240235 return self ._clear_program
241236
242237 def deploy (
@@ -502,7 +497,7 @@ def compose_create(
502497 extra_pages : int | None = None ,
503498 note : bytes | str | None = None ,
504499 lease : bytes | None = None ,
505- ) -> None :
500+ ) -> tuple [ Program , Program ] :
506501 """Adds a signed transaction with application id == 0 and the schema and source of client's app_spec to atc"""
507502
508503 approval_program , clear_program = self ._substitute_template_and_compile (template_values )
@@ -529,6 +524,8 @@ def compose_create(
529524 lease = lease ,
530525 )
531526
527+ return approval_program , clear_program
528+
532529 def create (
533530 self ,
534531 abi_method : Method | str | bool | None = None ,
@@ -547,7 +544,7 @@ def create(
547544
548545 atc = AtomicTransactionComposer ()
549546
550- self .compose_create (
547+ self ._approval_program , self . _clear_program = self . compose_create (
551548 atc ,
552549 abi_method ,
553550 args ,
@@ -576,7 +573,7 @@ def compose_update(
576573 template_values : TemplateValueDict | None = None ,
577574 note : bytes | str | None = None ,
578575 lease : bytes | None = None ,
579- ) -> None :
576+ ) -> tuple [ Program , Program ] :
580577 """Adds a signed transaction with on_complete=UpdateApplication to atc"""
581578
582579 self ._load_reference_and_check_app_id ()
@@ -597,6 +594,8 @@ def compose_update(
597594 lease = lease ,
598595 )
599596
597+ return approval_program , clear_program
598+
600599 def update (
601600 self ,
602601 abi_method : Method | str | bool | None = None ,
@@ -612,7 +611,7 @@ def update(
612611 """Submits a signed transaction with on_complete=UpdateApplication"""
613612
614613 atc = AtomicTransactionComposer ()
615- self .compose_update (
614+ self ._approval_program , self . _clear_program = self . compose_update (
616615 atc ,
617616 abi_method ,
618617 args ,
@@ -1069,21 +1068,11 @@ def _substitute_template_and_compile(
10691068 self ._clear_program = Program (clear , self .algod_client )
10701069 return self ._approval_program , self ._clear_program
10711070
1072- def _get_approval_source_map (self ) -> SourceMap :
1073- def _find_template_vars (program : str ) -> list [str ]:
1074- pattern = re .compile (r"\bTMPL_(\w*)\b" )
1075- return pattern .findall (program )
1071+ def _get_approval_source_map (self ) -> SourceMap | None :
1072+ if self .approval :
1073+ return self .approval .source_map
10761074
1077- if not self ._approval_source_map :
1078- if self ._approval_program :
1079- self ._approval_source_map = self ._approval_program .source_map
1080- else :
1081- # TODO: this will produce an incorrect source map for bytes as their length is not fixed
1082- template_values : TemplateValueDict = {k : 0 for k in _find_template_vars (self .app_spec .approval_program )}
1083- approval_program = replace_template_variables (self .app_spec .approval_program , template_values )
1084- approval = Program (approval_program , self .algod_client )
1085- self ._approval_source_map = approval .source_map
1086- return self ._approval_source_map
1075+ return self .approval_source_map
10871076
10881077 def _add_method_call (
10891078 self ,
@@ -1254,21 +1243,13 @@ def _execute_atc_tr(self, atc: AtomicTransactionComposer) -> TransactionResponse
12541243 confirmed_round = result .confirmed_round ,
12551244 )
12561245
1257- def _execute_atc (self , atc : AtomicTransactionComposer , wait_rounds : int = 4 ) -> AtomicTransactionResponse :
1258- try :
1259- return atc .execute (self .algod_client , wait_rounds = wait_rounds )
1260- except Exception as ex :
1261- logic_error_data = parse_logic_error (str (ex ))
1262- if logic_error_data is not None :
1263- source_map = self ._get_approval_source_map ()
1264- if source_map :
1265- raise LogicError (
1266- logic_error = ex ,
1267- program = self .app_spec .approval_program ,
1268- source_map = source_map ,
1269- ** logic_error_data ,
1270- ) from ex
1271- raise ex
1246+ def _execute_atc (self , atc : AtomicTransactionComposer ) -> AtomicTransactionResponse :
1247+ return execute_atc_with_logic_error (
1248+ atc ,
1249+ self .algod_client ,
1250+ approval_program = self .approval .teal if self .approval else self .app_spec .approval_program ,
1251+ approval_source_map = self ._get_approval_source_map (),
1252+ )
12721253
12731254 def _set_app_id_from_tx_id (self , tx_id : str ) -> None :
12741255 self .app_id = get_app_id_from_tx_id (self .algod_client , tx_id )
@@ -1455,3 +1436,25 @@ def _get_deploy_control(
14551436 return _get_call_config (app_spec .bare_call_config , on_complete ) != CallConfig .NEVER or any (
14561437 h for h in app_spec .hints .values () if _get_call_config (h .call_config , on_complete ) != CallConfig .NEVER
14571438 )
1439+
1440+
1441+ def execute_atc_with_logic_error (
1442+ atc : AtomicTransactionComposer ,
1443+ algod_client : AlgodClient ,
1444+ wait_rounds : int = 4 ,
1445+ approval_program : str | None = None ,
1446+ approval_source_map : SourceMap | None = None ,
1447+ ) -> AtomicTransactionResponse :
1448+ try :
1449+ return atc .execute (algod_client , wait_rounds = wait_rounds )
1450+ except Exception as ex :
1451+ if approval_source_map and approval_program :
1452+ logic_error_data = parse_logic_error (str (ex ))
1453+ if logic_error_data is not None :
1454+ raise LogicError (
1455+ logic_error = ex ,
1456+ program = approval_program ,
1457+ source_map = approval_source_map ,
1458+ ** logic_error_data ,
1459+ ) from ex
1460+ raise ex
0 commit comments