algokit-utils 5.0.0a3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (337) hide show
  1. algokit_abi/__init__.py +9 -0
  2. algokit_abi/_arc32_to_arc56.py +242 -0
  3. algokit_abi/_arc56_serde.py +161 -0
  4. algokit_abi/abi.py +667 -0
  5. algokit_abi/arc32.py +210 -0
  6. algokit_abi/arc56.py +821 -0
  7. algokit_abi/py.typed +0 -0
  8. algokit_algo25/__init__.py +38 -0
  9. algokit_algo25/_encoding.py +46 -0
  10. algokit_algo25/_wordlist.py +2065 -0
  11. algokit_algo25/exceptions.py +29 -0
  12. algokit_algo25/mnemonic.py +128 -0
  13. algokit_algo25/py.typed +0 -0
  14. algokit_algod_client/__init__.py +10 -0
  15. algokit_algod_client/client.py +1585 -0
  16. algokit_algod_client/config.py +36 -0
  17. algokit_algod_client/exceptions.py +59 -0
  18. algokit_algod_client/models/__init__.py +229 -0
  19. algokit_algod_client/models/_account.py +150 -0
  20. algokit_algod_client/models/_account_application_response.py +25 -0
  21. algokit_algod_client/models/_account_asset_response.py +25 -0
  22. algokit_algod_client/models/_account_participation.py +53 -0
  23. algokit_algod_client/models/_account_state_delta.py +30 -0
  24. algokit_algod_client/models/_allocations_for_genesis_file.py +23 -0
  25. algokit_algod_client/models/_allocations_for_genesis_file_state_model.py +42 -0
  26. algokit_algod_client/models/_application.py +23 -0
  27. algokit_algod_client/models/_application_initial_states.py +37 -0
  28. algokit_algod_client/models/_application_kvstorage.py +29 -0
  29. algokit_algod_client/models/_application_local_state.py +33 -0
  30. algokit_algod_client/models/_application_params.py +63 -0
  31. algokit_algod_client/models/_application_state_operation.py +41 -0
  32. algokit_algod_client/models/_application_state_schema.py +22 -0
  33. algokit_algod_client/models/_asset.py +23 -0
  34. algokit_algod_client/models/_asset_holding.py +29 -0
  35. algokit_algod_client/models/_asset_params.py +102 -0
  36. algokit_algod_client/models/_avm_key_value.py +28 -0
  37. algokit_algod_client/models/_avm_value.py +32 -0
  38. algokit_algod_client/models/_block.py +363 -0
  39. algokit_algod_client/models/_block_hash_response.py +14 -0
  40. algokit_algod_client/models/_block_txids_response.py +14 -0
  41. algokit_algod_client/models/_box.py +36 -0
  42. algokit_algod_client/models/_box_descriptor.py +24 -0
  43. algokit_algod_client/models/_boxes_response.py +21 -0
  44. algokit_algod_client/models/_build_version_contains_the_current_algod_build_version_information.py +34 -0
  45. algokit_algod_client/models/_compile_response.py +24 -0
  46. algokit_algod_client/models/_disassemble_response.py +14 -0
  47. algokit_algod_client/models/_error_response.py +22 -0
  48. algokit_algod_client/models/_eval_delta.py +32 -0
  49. algokit_algod_client/models/_eval_delta_key_value.py +28 -0
  50. algokit_algod_client/models/_genesis_file_in_json.py +53 -0
  51. algokit_algod_client/models/_get_block_time_stamp_offset_response.py +14 -0
  52. algokit_algod_client/models/_get_sync_round_response.py +14 -0
  53. algokit_algod_client/models/_ledger_state_delta.py +389 -0
  54. algokit_algod_client/models/_light_block_header_proof.py +32 -0
  55. algokit_algod_client/models/_node_status_response.py +118 -0
  56. algokit_algod_client/models/_pending_transaction_response.py +91 -0
  57. algokit_algod_client/models/_pending_transactions_response.py +29 -0
  58. algokit_algod_client/models/_post_transactions_response.py +14 -0
  59. algokit_algod_client/models/_scratch_change.py +23 -0
  60. algokit_algod_client/models/_serde_helpers.py +241 -0
  61. algokit_algod_client/models/_simulate_initial_states.py +25 -0
  62. algokit_algod_client/models/_simulate_request.py +54 -0
  63. algokit_algod_client/models/_simulate_request_transaction_group.py +25 -0
  64. algokit_algod_client/models/_simulate_response.py +44 -0
  65. algokit_algod_client/models/_simulate_trace_config.py +30 -0
  66. algokit_algod_client/models/_simulate_transaction_group_result.py +46 -0
  67. algokit_algod_client/models/_simulate_transaction_result.py +41 -0
  68. algokit_algod_client/models/_simulate_unnamed_resources_accessed.py +64 -0
  69. algokit_algod_client/models/_simulation_eval_overrides.py +40 -0
  70. algokit_algod_client/models/_simulation_opcode_trace_unit.py +55 -0
  71. algokit_algod_client/models/_simulation_transaction_exec_trace.py +82 -0
  72. algokit_algod_client/models/_source_map.py +30 -0
  73. algokit_algod_client/models/_state_delta.py +6 -0
  74. algokit_algod_client/models/_state_proof.py +28 -0
  75. algokit_algod_client/models/_state_proof_message.py +44 -0
  76. algokit_algod_client/models/_supply_response.py +26 -0
  77. algokit_algod_client/models/_teal_key_value.py +28 -0
  78. algokit_algod_client/models/_teal_key_value_store.py +6 -0
  79. algokit_algod_client/models/_teal_value.py +32 -0
  80. algokit_algod_client/models/_transaction_group_ledger_state_deltas_for_round_response.py +21 -0
  81. algokit_algod_client/models/_transaction_parameters_response.py +45 -0
  82. algokit_algod_client/models/_transaction_proof.py +44 -0
  83. algokit_algod_client/models/_version_contains_the_current_algod_version.py +38 -0
  84. algokit_algod_client/models/suggested_params.py +42 -0
  85. algokit_algod_client/py.typed +1 -0
  86. algokit_algod_client/types.py +7 -0
  87. algokit_algosdk/__init__.py +38 -0
  88. algokit_algosdk/account.py +32 -0
  89. algokit_algosdk/app_access.py +228 -0
  90. algokit_algosdk/box_reference.py +100 -0
  91. algokit_algosdk/constants.py +147 -0
  92. algokit_algosdk/encoding.py +89 -0
  93. algokit_algosdk/error.py +180 -0
  94. algokit_algosdk/logic.py +61 -0
  95. algokit_algosdk/logicsig.py +218 -0
  96. algokit_algosdk/mnemonic.py +216 -0
  97. algokit_algosdk/multisig.py +161 -0
  98. algokit_algosdk/py.typed +0 -0
  99. algokit_algosdk/transaction.py +596 -0
  100. algokit_algosdk/wordlist.py +2054 -0
  101. algokit_common/__init__.py +50 -0
  102. algokit_common/address.py +34 -0
  103. algokit_common/constants.py +47 -0
  104. algokit_common/hashing.py +25 -0
  105. algokit_common/py.typed +0 -0
  106. algokit_common/serde/__init__.py +40 -0
  107. algokit_common/serde/_core.py +610 -0
  108. algokit_common/serde/_primitives.py +135 -0
  109. algokit_common/source_map.py +158 -0
  110. algokit_indexer_client/__init__.py +10 -0
  111. algokit_indexer_client/client.py +1456 -0
  112. algokit_indexer_client/config.py +36 -0
  113. algokit_indexer_client/exceptions.py +59 -0
  114. algokit_indexer_client/models/__init__.py +148 -0
  115. algokit_indexer_client/models/_account.py +161 -0
  116. algokit_indexer_client/models/_account_participation.py +53 -0
  117. algokit_indexer_client/models/_account_response.py +19 -0
  118. algokit_indexer_client/models/_account_state_delta.py +29 -0
  119. algokit_indexer_client/models/_accounts_response.py +29 -0
  120. algokit_indexer_client/models/_application.py +35 -0
  121. algokit_indexer_client/models/_application_local_state.py +45 -0
  122. algokit_indexer_client/models/_application_local_states_response.py +29 -0
  123. algokit_indexer_client/models/_application_log_data.py +28 -0
  124. algokit_indexer_client/models/_application_logs_response.py +33 -0
  125. algokit_indexer_client/models/_application_params.py +62 -0
  126. algokit_indexer_client/models/_application_response.py +20 -0
  127. algokit_indexer_client/models/_application_state_schema.py +22 -0
  128. algokit_indexer_client/models/_applications_response.py +29 -0
  129. algokit_indexer_client/models/_asset.py +35 -0
  130. algokit_indexer_client/models/_asset_balances_response.py +29 -0
  131. algokit_indexer_client/models/_asset_holding.py +41 -0
  132. algokit_indexer_client/models/_asset_holdings_response.py +29 -0
  133. algokit_indexer_client/models/_asset_params.py +102 -0
  134. algokit_indexer_client/models/_asset_response.py +19 -0
  135. algokit_indexer_client/models/_assets_response.py +29 -0
  136. algokit_indexer_client/models/_block.py +150 -0
  137. algokit_indexer_client/models/_block_headers_response.py +29 -0
  138. algokit_indexer_client/models/_block_rewards.py +38 -0
  139. algokit_indexer_client/models/_block_upgrade_state.py +34 -0
  140. algokit_indexer_client/models/_block_upgrade_vote.py +26 -0
  141. algokit_indexer_client/models/_box.py +36 -0
  142. algokit_indexer_client/models/_box_descriptor.py +24 -0
  143. algokit_indexer_client/models/_box_reference.py +28 -0
  144. algokit_indexer_client/models/_boxes_response.py +29 -0
  145. algokit_indexer_client/models/_error_response.py +18 -0
  146. algokit_indexer_client/models/_eval_delta.py +32 -0
  147. algokit_indexer_client/models/_eval_delta_key_value.py +28 -0
  148. algokit_indexer_client/models/_hash_factory.py +14 -0
  149. algokit_indexer_client/models/_hb_proof_fields.py +57 -0
  150. algokit_indexer_client/models/_health_check.py +42 -0
  151. algokit_indexer_client/models/_holding_ref.py +23 -0
  152. algokit_indexer_client/models/_indexer_state_proof_message.py +40 -0
  153. algokit_indexer_client/models/_locals_ref.py +23 -0
  154. algokit_indexer_client/models/_merkle_array_proof.py +29 -0
  155. algokit_indexer_client/models/_mini_asset_holding.py +38 -0
  156. algokit_indexer_client/models/_on_completion.py +25 -0
  157. algokit_indexer_client/models/_participation_updates.py +22 -0
  158. algokit_indexer_client/models/_resource_ref.py +42 -0
  159. algokit_indexer_client/models/_serde_helpers.py +241 -0
  160. algokit_indexer_client/models/_state_delta.py +6 -0
  161. algokit_indexer_client/models/_state_proof_fields.py +57 -0
  162. algokit_indexer_client/models/_state_proof_participant.py +20 -0
  163. algokit_indexer_client/models/_state_proof_reveal.py +25 -0
  164. algokit_indexer_client/models/_state_proof_sig_slot.py +20 -0
  165. algokit_indexer_client/models/_state_proof_signature.py +37 -0
  166. algokit_indexer_client/models/_state_proof_tracking.py +32 -0
  167. algokit_indexer_client/models/_state_proof_verifier.py +24 -0
  168. algokit_indexer_client/models/_state_schema.py +25 -0
  169. algokit_indexer_client/models/_teal_key_value.py +28 -0
  170. algokit_indexer_client/models/_teal_key_value_store.py +6 -0
  171. algokit_indexer_client/models/_teal_value.py +32 -0
  172. algokit_indexer_client/models/_transaction.py +213 -0
  173. algokit_indexer_client/models/_transaction_application.py +105 -0
  174. algokit_indexer_client/models/_transaction_asset_config.py +31 -0
  175. algokit_indexer_client/models/_transaction_asset_freeze.py +29 -0
  176. algokit_indexer_client/models/_transaction_asset_transfer.py +41 -0
  177. algokit_indexer_client/models/_transaction_heartbeat.py +52 -0
  178. algokit_indexer_client/models/_transaction_keyreg.py +59 -0
  179. algokit_indexer_client/models/_transaction_payment.py +33 -0
  180. algokit_indexer_client/models/_transaction_response.py +19 -0
  181. algokit_indexer_client/models/_transaction_signature.py +35 -0
  182. algokit_indexer_client/models/_transaction_signature_logicsig.py +59 -0
  183. algokit_indexer_client/models/_transaction_signature_multisig.py +36 -0
  184. algokit_indexer_client/models/_transaction_signature_multisig_subsignature.py +28 -0
  185. algokit_indexer_client/models/_transaction_state_proof.py +32 -0
  186. algokit_indexer_client/models/_transactions_response.py +29 -0
  187. algokit_indexer_client/py.typed +1 -0
  188. algokit_indexer_client/types.py +7 -0
  189. algokit_kmd_client/__init__.py +10 -0
  190. algokit_kmd_client/client.py +1240 -0
  191. algokit_kmd_client/config.py +36 -0
  192. algokit_kmd_client/exceptions.py +59 -0
  193. algokit_kmd_client/models/__init__.py +112 -0
  194. algokit_kmd_client/models/_classical_signatures.py +4 -0
  195. algokit_kmd_client/models/_create_wallet_request.py +30 -0
  196. algokit_kmd_client/models/_create_wallet_response.py +19 -0
  197. algokit_kmd_client/models/_delete_key_request.py +27 -0
  198. algokit_kmd_client/models/_delete_multisig_request.py +27 -0
  199. algokit_kmd_client/models/_digest_represents_a32_byte_value_holding_the256_bit_hash_digest.py +4 -0
  200. algokit_kmd_client/models/_ed25519_public_key.py +4 -0
  201. algokit_kmd_client/models/_export_key_request.py +27 -0
  202. algokit_kmd_client/models/_export_key_response.py +24 -0
  203. algokit_kmd_client/models/_export_master_key_request.py +22 -0
  204. algokit_kmd_client/models/_export_master_key_response.py +18 -0
  205. algokit_kmd_client/models/_export_multisig_request.py +23 -0
  206. algokit_kmd_client/models/_export_multisig_response.py +26 -0
  207. algokit_kmd_client/models/_generate_key_request.py +18 -0
  208. algokit_kmd_client/models/_generate_key_response.py +19 -0
  209. algokit_kmd_client/models/_import_key_request.py +28 -0
  210. algokit_kmd_client/models/_import_key_response.py +19 -0
  211. algokit_kmd_client/models/_import_multisig_request.py +30 -0
  212. algokit_kmd_client/models/_import_multisig_response.py +19 -0
  213. algokit_kmd_client/models/_init_wallet_handle_token_request.py +22 -0
  214. algokit_kmd_client/models/_init_wallet_handle_token_response.py +18 -0
  215. algokit_kmd_client/models/_list_keys_request.py +18 -0
  216. algokit_kmd_client/models/_list_keys_response.py +18 -0
  217. algokit_kmd_client/models/_list_multisig_request.py +18 -0
  218. algokit_kmd_client/models/_list_multisig_response.py +18 -0
  219. algokit_kmd_client/models/_list_wallets_request.py +11 -0
  220. algokit_kmd_client/models/_list_wallets_response.py +25 -0
  221. algokit_kmd_client/models/_master_derivation_key.py +4 -0
  222. algokit_kmd_client/models/_multisig_sig.py +33 -0
  223. algokit_kmd_client/models/_multisig_subsig.py +23 -0
  224. algokit_kmd_client/models/_public_key.py +4 -0
  225. algokit_kmd_client/models/_release_wallet_handle_token_request.py +18 -0
  226. algokit_kmd_client/models/_rename_wallet_request.py +26 -0
  227. algokit_kmd_client/models/_rename_wallet_response.py +19 -0
  228. algokit_kmd_client/models/_renew_wallet_handle_token_request.py +18 -0
  229. algokit_kmd_client/models/_renew_wallet_handle_token_response.py +19 -0
  230. algokit_kmd_client/models/_serde_helpers.py +241 -0
  231. algokit_kmd_client/models/_sign_multisig_response.py +24 -0
  232. algokit_kmd_client/models/_sign_multisig_txn_request.py +45 -0
  233. algokit_kmd_client/models/_sign_program_multisig_request.py +50 -0
  234. algokit_kmd_client/models/_sign_program_multisig_response.py +24 -0
  235. algokit_kmd_client/models/_sign_program_request.py +37 -0
  236. algokit_kmd_client/models/_sign_program_response.py +24 -0
  237. algokit_kmd_client/models/_sign_transaction_response.py +24 -0
  238. algokit_kmd_client/models/_sign_txn_request.py +36 -0
  239. algokit_kmd_client/models/_signature.py +4 -0
  240. algokit_kmd_client/models/_tx_type.py +4 -0
  241. algokit_kmd_client/models/_versions_request.py +11 -0
  242. algokit_kmd_client/models/_versions_response.py +19 -0
  243. algokit_kmd_client/models/_wallet.py +38 -0
  244. algokit_kmd_client/models/_wallet_handle.py +24 -0
  245. algokit_kmd_client/models/_wallet_info_request.py +18 -0
  246. algokit_kmd_client/models/_wallet_info_response.py +19 -0
  247. algokit_kmd_client/py.typed +1 -0
  248. algokit_kmd_client/types.py +7 -0
  249. algokit_transact/__init__.py +190 -0
  250. algokit_transact/codec/__init__.py +0 -0
  251. algokit_transact/codec/msgpack.py +11 -0
  252. algokit_transact/codec/serde.py +7 -0
  253. algokit_transact/codec/signed.py +57 -0
  254. algokit_transact/codec/transaction.py +65 -0
  255. algokit_transact/exceptions.py +17 -0
  256. algokit_transact/logicsig.py +220 -0
  257. algokit_transact/models/__init__.py +0 -0
  258. algokit_transact/models/app_call.py +447 -0
  259. algokit_transact/models/asset_config.py +19 -0
  260. algokit_transact/models/asset_freeze.py +11 -0
  261. algokit_transact/models/asset_transfer.py +13 -0
  262. algokit_transact/models/common.py +17 -0
  263. algokit_transact/models/heartbeat.py +21 -0
  264. algokit_transact/models/key_registration.py +14 -0
  265. algokit_transact/models/payment.py +14 -0
  266. algokit_transact/models/signed_transaction.py +21 -0
  267. algokit_transact/models/state_proof.py +150 -0
  268. algokit_transact/models/transaction.py +88 -0
  269. algokit_transact/multisig.py +93 -0
  270. algokit_transact/ops/__init__.py +0 -0
  271. algokit_transact/ops/fees.py +47 -0
  272. algokit_transact/ops/group.py +28 -0
  273. algokit_transact/ops/ids.py +14 -0
  274. algokit_transact/ops/validate.py +503 -0
  275. algokit_transact/py.typed +0 -0
  276. algokit_transact/signer.py +195 -0
  277. algokit_transact/signing/__init__.py +0 -0
  278. algokit_transact/signing/logic_signature.py +19 -0
  279. algokit_transact/signing/multisig.py +84 -0
  280. algokit_transact/signing/types.py +39 -0
  281. algokit_transact/signing/validation.py +63 -0
  282. algokit_utils/__init__.py +23 -0
  283. algokit_utils/_debugging.py +304 -0
  284. algokit_utils/accounts/__init__.py +2 -0
  285. algokit_utils/accounts/account_manager.py +1051 -0
  286. algokit_utils/accounts/kmd_account_manager.py +206 -0
  287. algokit_utils/algo25.py +46 -0
  288. algokit_utils/algorand.py +383 -0
  289. algokit_utils/applications/__init__.py +7 -0
  290. algokit_utils/applications/abi.py +280 -0
  291. algokit_utils/applications/app_client.py +2193 -0
  292. algokit_utils/applications/app_deployer.py +788 -0
  293. algokit_utils/applications/app_factory.py +1140 -0
  294. algokit_utils/applications/app_manager.py +575 -0
  295. algokit_utils/applications/app_spec/__init__.py +6 -0
  296. algokit_utils/applications/enums.py +40 -0
  297. algokit_utils/assets/__init__.py +1 -0
  298. algokit_utils/assets/asset_manager.py +344 -0
  299. algokit_utils/clients/__init__.py +41 -0
  300. algokit_utils/clients/client_manager.py +756 -0
  301. algokit_utils/clients/dispenser_api_client.py +212 -0
  302. algokit_utils/common.py +40 -0
  303. algokit_utils/config.py +159 -0
  304. algokit_utils/errors/__init__.py +1 -0
  305. algokit_utils/errors/logic_error.py +160 -0
  306. algokit_utils/models/__init__.py +7 -0
  307. algokit_utils/models/account.py +12 -0
  308. algokit_utils/models/amount.py +198 -0
  309. algokit_utils/models/application.py +90 -0
  310. algokit_utils/models/network.py +29 -0
  311. algokit_utils/models/simulate.py +7 -0
  312. algokit_utils/models/state.py +53 -0
  313. algokit_utils/models/transaction.py +49 -0
  314. algokit_utils/protocols/__init__.py +3 -0
  315. algokit_utils/protocols/account.py +11 -0
  316. algokit_utils/protocols/signer.py +17 -0
  317. algokit_utils/protocols/typed_clients.py +110 -0
  318. algokit_utils/py.typed +0 -0
  319. algokit_utils/transact.py +195 -0
  320. algokit_utils/transactions/__init__.py +3 -0
  321. algokit_utils/transactions/builders/__init__.py +67 -0
  322. algokit_utils/transactions/builders/app.py +248 -0
  323. algokit_utils/transactions/builders/asset.py +256 -0
  324. algokit_utils/transactions/builders/common.py +263 -0
  325. algokit_utils/transactions/builders/keyreg.py +103 -0
  326. algokit_utils/transactions/builders/method_call.py +380 -0
  327. algokit_utils/transactions/builders/payment.py +43 -0
  328. algokit_utils/transactions/composer_resources.py +409 -0
  329. algokit_utils/transactions/fee_coverage.py +79 -0
  330. algokit_utils/transactions/helpers.py +9 -0
  331. algokit_utils/transactions/transaction_composer.py +1574 -0
  332. algokit_utils/transactions/transaction_creator.py +699 -0
  333. algokit_utils/transactions/transaction_sender.py +1240 -0
  334. algokit_utils/transactions/types.py +262 -0
  335. algokit_utils-5.0.0a3.dist-info/METADATA +105 -0
  336. algokit_utils-5.0.0a3.dist-info/RECORD +337 -0
  337. algokit_utils-5.0.0a3.dist-info/WHEEL +4 -0
@@ -0,0 +1,1140 @@
1
+ import base64
2
+ import dataclasses
3
+ from collections.abc import Callable, Sequence
4
+ from dataclasses import asdict, dataclass
5
+ from typing import Any, Generic, TypeVar
6
+
7
+ from typing_extensions import Self
8
+
9
+ from algokit_abi import arc56
10
+ from algokit_common import ProgramSourceMap
11
+ from algokit_transact import OnApplicationComplete
12
+ from algokit_transact.models.transaction import Transaction
13
+ from algokit_utils.algorand import AlgorandClient
14
+ from algokit_utils.applications.abi import (
15
+ ABIReturn,
16
+ Arc56ReturnValueType,
17
+ get_abi_decoded_value,
18
+ )
19
+ from algokit_utils.applications.app_client import (
20
+ AppClient,
21
+ AppClientBareCallCreateParams,
22
+ AppClientBareCallParams,
23
+ AppClientCompilationParams,
24
+ AppClientCompilationResult,
25
+ AppClientMethodCallCreateParams,
26
+ AppClientMethodCallParams,
27
+ AppClientParams,
28
+ CreateOnComplete,
29
+ )
30
+ from algokit_utils.applications.app_deployer import (
31
+ AppDeploymentMetaData,
32
+ AppDeployParams,
33
+ AppDeployResult,
34
+ ApplicationLookup,
35
+ ApplicationMetaData,
36
+ OnSchemaBreak,
37
+ OnUpdate,
38
+ OperationPerformed,
39
+ )
40
+ from algokit_utils.applications.app_manager import DELETABLE_TEMPLATE_NAME, UPDATABLE_TEMPLATE_NAME
41
+ from algokit_utils.models.application import AppSourceMaps
42
+ from algokit_utils.models.transaction import SendParams
43
+ from algokit_utils.protocols.signer import TransactionSigner
44
+ from algokit_utils.transactions.transaction_composer import (
45
+ AppCreateMethodCallParams,
46
+ AppCreateParams,
47
+ AppDeleteMethodCallParams,
48
+ AppDeleteParams,
49
+ AppUpdateMethodCallParams,
50
+ AppUpdateParams,
51
+ BuiltTransactions,
52
+ )
53
+ from algokit_utils.transactions.transaction_sender import (
54
+ SendAppCreateTransactionResult,
55
+ SendAppTransactionResult,
56
+ SendAppUpdateTransactionResult,
57
+ SendSingleTransactionResult,
58
+ )
59
+
60
+ T = TypeVar("T")
61
+
62
+ __all__ = [
63
+ "AppFactory",
64
+ "AppFactoryCreateMethodCallParams",
65
+ "AppFactoryCreateMethodCallResult",
66
+ "AppFactoryCreateParams",
67
+ "AppFactoryDeployResult",
68
+ "AppFactoryParams",
69
+ "SendAppCreateFactoryTransactionResult",
70
+ "SendAppFactoryTransactionResult",
71
+ "SendAppUpdateFactoryTransactionResult",
72
+ ]
73
+
74
+
75
+ @dataclass(kw_only=True, frozen=True)
76
+ class AppFactoryParams:
77
+ algorand: AlgorandClient
78
+ app_spec: arc56.Arc56Contract | str
79
+ app_name: str | None = None
80
+ default_sender: str | None = None
81
+ default_signer: TransactionSigner | None = None
82
+ version: str | None = None
83
+ compilation_params: AppClientCompilationParams | None = None
84
+
85
+
86
+ @dataclass(kw_only=True, frozen=True)
87
+ class AppFactoryCreateParams(AppClientBareCallCreateParams):
88
+ on_complete: CreateOnComplete | None = None
89
+
90
+
91
+ @dataclass(kw_only=True, frozen=True)
92
+ class AppFactoryCreateMethodCallParams(AppClientMethodCallCreateParams):
93
+ pass
94
+
95
+
96
+ ABIReturnT = TypeVar(
97
+ "ABIReturnT",
98
+ bound=Arc56ReturnValueType,
99
+ )
100
+
101
+
102
+ @dataclass(frozen=True, kw_only=True)
103
+ class AppFactoryCreateMethodCallResult(SendSingleTransactionResult, Generic[ABIReturnT]):
104
+ app_id: int
105
+ app_address: str
106
+ compiled_approval: Any | None = None
107
+ compiled_clear: Any | None = None
108
+ abi_return: ABIReturnT | None = None
109
+
110
+
111
+ @dataclass(frozen=True)
112
+ class SendAppFactoryTransactionResult(SendAppTransactionResult[Arc56ReturnValueType]):
113
+ pass
114
+
115
+
116
+ @dataclass(frozen=True)
117
+ class SendAppUpdateFactoryTransactionResult(SendAppUpdateTransactionResult[Arc56ReturnValueType]):
118
+ pass
119
+
120
+
121
+ @dataclass(frozen=True, kw_only=True)
122
+ class SendAppCreateFactoryTransactionResult(SendAppCreateTransactionResult[Arc56ReturnValueType]):
123
+ pass
124
+
125
+
126
+ @dataclass(frozen=True)
127
+ class AppFactoryDeployResult:
128
+ """Result from deploying an application via AppFactory"""
129
+
130
+ app: ApplicationMetaData
131
+ """The application metadata"""
132
+ operation_performed: OperationPerformed
133
+ """The operation performed"""
134
+ create_result: SendAppCreateFactoryTransactionResult | None = None
135
+ """The create result"""
136
+ update_result: SendAppUpdateFactoryTransactionResult | None = None
137
+ """The update result"""
138
+ delete_result: SendAppFactoryTransactionResult | None = None
139
+ """The delete result"""
140
+
141
+ @classmethod
142
+ def from_deploy_result(
143
+ cls,
144
+ response: AppDeployResult,
145
+ deploy_params: AppDeployParams,
146
+ app_spec: arc56.Arc56Contract, # noqa: ARG003
147
+ app_compilation_data: AppClientCompilationResult | None = None,
148
+ ) -> Self:
149
+ """
150
+ Construct an AppFactoryDeployResult from a deployment result.
151
+
152
+ :param response: The deployment response.
153
+ :param deploy_params: The deployment parameters.
154
+ :param app_spec: The application specification.
155
+ :param app_compilation_data: Optional app compilation data.
156
+ :return: An instance of AppFactoryDeployResult.
157
+ """
158
+
159
+ def to_factory_result(
160
+ response_data: SendAppTransactionResult[ABIReturn]
161
+ | SendAppCreateTransactionResult
162
+ | SendAppUpdateTransactionResult
163
+ | None,
164
+ params: Any, # noqa: ANN401
165
+ ) -> Any | None: # noqa: ANN401
166
+ _ = params # kept for compatibility
167
+ if not response_data:
168
+ return None
169
+
170
+ response_data_dict = {
171
+ field.name: getattr(response_data, field.name) for field in dataclasses.fields(type(response_data))
172
+ }
173
+ abi_return = response_data.abi_return
174
+ if abi_return and abi_return.method:
175
+ if abi_return.decode_error:
176
+ raise ValueError(abi_return.decode_error)
177
+ response_data_dict["abi_return"] = abi_return.value
178
+
179
+ match response_data:
180
+ case SendAppCreateTransactionResult():
181
+ return SendAppCreateFactoryTransactionResult(**response_data_dict)
182
+ case SendAppUpdateTransactionResult():
183
+ response_data_dict["compiled_approval"] = (
184
+ app_compilation_data.compiled_approval if app_compilation_data else None
185
+ )
186
+ response_data_dict["compiled_clear"] = (
187
+ app_compilation_data.compiled_clear if app_compilation_data else None
188
+ )
189
+ return SendAppUpdateFactoryTransactionResult(**response_data_dict)
190
+ case SendAppTransactionResult():
191
+ return SendAppFactoryTransactionResult(**response_data_dict)
192
+
193
+ return cls(
194
+ app=response.app,
195
+ operation_performed=response.operation_performed,
196
+ create_result=to_factory_result(
197
+ response.create_result,
198
+ deploy_params.create_params,
199
+ ),
200
+ update_result=to_factory_result(
201
+ response.update_result,
202
+ deploy_params.update_params,
203
+ ),
204
+ delete_result=to_factory_result(
205
+ response.delete_result,
206
+ deploy_params.delete_params,
207
+ ),
208
+ )
209
+
210
+
211
+ class _BareParamsBuilder:
212
+ """The bare params builder.
213
+
214
+ :param factory: The AppFactory instance.
215
+ """
216
+
217
+ def __init__(self, factory: "AppFactory") -> None:
218
+ self._factory = factory
219
+ self._algorand = factory._algorand
220
+
221
+ def create(
222
+ self, params: AppFactoryCreateParams | None = None, compilation_params: AppClientCompilationParams | None = None
223
+ ) -> AppCreateParams:
224
+ """
225
+ Create AppCreateParams using the provided parameters and compilation settings.
226
+
227
+ :param params: Optional AppFactoryCreateParams instance.
228
+ :param compilation_params: Optional AppClientCompilationParams instance.
229
+ :return: An instance of AppCreateParams.
230
+ """
231
+ base_params = params or AppFactoryCreateParams()
232
+ compiled = self._factory.compile(compilation_params)
233
+
234
+ return AppCreateParams(
235
+ **{
236
+ **{
237
+ param: value
238
+ for param, value in asdict(base_params).items()
239
+ if param in {f.name for f in dataclasses.fields(AppCreateParams)}
240
+ },
241
+ "approval_program": compiled.approval_program,
242
+ "clear_state_program": compiled.clear_state_program,
243
+ "schema": base_params.schema
244
+ or {
245
+ "global_byte_slices": self._factory._app_spec.state.schema.global_state.bytes,
246
+ "global_ints": self._factory._app_spec.state.schema.global_state.ints,
247
+ "local_byte_slices": self._factory._app_spec.state.schema.local_state.bytes,
248
+ "local_ints": self._factory._app_spec.state.schema.local_state.ints,
249
+ },
250
+ "sender": self._factory._get_sender(base_params.sender),
251
+ "signer": self._factory._get_signer(base_params.sender, base_params.signer),
252
+ "on_complete": base_params.on_complete or OnApplicationComplete.NoOp,
253
+ }
254
+ )
255
+
256
+ def deploy_update(self, params: AppClientBareCallParams | None = None) -> AppUpdateParams:
257
+ """
258
+ Create AppUpdateParams for an update operation.
259
+
260
+ :param params: Optional AppClientBareCallParams instance.
261
+ :return: An instance of AppUpdateParams.
262
+ """
263
+ return AppUpdateParams(
264
+ **{
265
+ **{
266
+ param: value
267
+ for param, value in asdict(params or AppClientBareCallParams()).items()
268
+ if param in {f.name for f in dataclasses.fields(AppUpdateParams)}
269
+ },
270
+ "app_id": 0,
271
+ "approval_program": "",
272
+ "clear_state_program": "",
273
+ "sender": self._factory._get_sender(params.sender if params else None),
274
+ "on_complete": OnApplicationComplete.UpdateApplication,
275
+ "signer": self._factory._get_signer(
276
+ params.sender if params else None, params.signer if params else None
277
+ ),
278
+ }
279
+ )
280
+
281
+ def deploy_delete(self, params: AppClientBareCallParams | None = None) -> AppDeleteParams:
282
+ """
283
+ Create AppDeleteParams for a delete operation.
284
+
285
+ :param params: Optional AppClientBareCallParams instance.
286
+ :return: An instance of AppDeleteParams.
287
+ """
288
+ return AppDeleteParams(
289
+ **{
290
+ **{
291
+ param: value
292
+ for param, value in asdict(params or AppClientBareCallParams()).items()
293
+ if param in {f.name for f in dataclasses.fields(AppDeleteParams)}
294
+ },
295
+ "app_id": 0,
296
+ "sender": self._factory._get_sender(params.sender if params else None),
297
+ "signer": self._factory._get_signer(
298
+ params.sender if params else None, params.signer if params else None
299
+ ),
300
+ "on_complete": OnApplicationComplete.DeleteApplication,
301
+ }
302
+ )
303
+
304
+
305
+ class _MethodParamsBuilder:
306
+ """The method params builder.
307
+
308
+ :param factory: The AppFactory instance.
309
+ """
310
+
311
+ def __init__(self, factory: "AppFactory") -> None:
312
+ self._factory = factory
313
+ self._bare = _BareParamsBuilder(factory)
314
+
315
+ @property
316
+ def bare(self) -> _BareParamsBuilder:
317
+ """
318
+ Get the bare parameters builder.
319
+
320
+ :return: The _BareParamsBuilder instance.
321
+ """
322
+ return self._bare
323
+
324
+ def create(
325
+ self, params: AppFactoryCreateMethodCallParams, compilation_params: AppClientCompilationParams | None = None
326
+ ) -> AppCreateMethodCallParams:
327
+ """
328
+ Create AppCreateMethodCallParams using the provided parameters and compilation settings.
329
+
330
+ :param params: AppFactoryCreateMethodCallParams instance.
331
+ :param compilation_params: Optional AppClientCompilationParams instance.
332
+ :return: An instance of AppCreateMethodCallParams.
333
+ """
334
+ compiled = self._factory.compile(compilation_params)
335
+
336
+ return AppCreateMethodCallParams(
337
+ **{
338
+ **{
339
+ param: value
340
+ for param, value in asdict(params).items()
341
+ if param in {f.name for f in dataclasses.fields(AppCreateMethodCallParams)}
342
+ },
343
+ "app_id": 0,
344
+ "approval_program": compiled.approval_program,
345
+ "clear_state_program": compiled.clear_state_program,
346
+ "schema": params.schema
347
+ or {
348
+ "global_byte_slices": self._factory._app_spec.state.schema.global_state.bytes,
349
+ "global_ints": self._factory._app_spec.state.schema.global_state.ints,
350
+ "local_byte_slices": self._factory._app_spec.state.schema.local_state.bytes,
351
+ "local_ints": self._factory._app_spec.state.schema.local_state.ints,
352
+ },
353
+ "sender": self._factory._get_sender(params.sender),
354
+ "signer": self._factory._get_signer(
355
+ params.sender if params else None, params.signer if params else None
356
+ ),
357
+ "method": self._factory._app_spec.get_abi_method(params.method),
358
+ "args": self._factory._get_create_abi_args_with_default_values(params.method, params.args),
359
+ "on_complete": params.on_complete or OnApplicationComplete.NoOp,
360
+ }
361
+ )
362
+
363
+ def deploy_update(self, params: AppClientMethodCallParams) -> AppUpdateMethodCallParams:
364
+ """
365
+ Create AppUpdateMethodCallParams for an update operation.
366
+
367
+ :param params: AppClientMethodCallParams instance.
368
+ :return: An instance of AppUpdateMethodCallParams.
369
+ """
370
+ return AppUpdateMethodCallParams(
371
+ **{
372
+ **{
373
+ param: value
374
+ for param, value in asdict(params).items()
375
+ if param in {f.name for f in dataclasses.fields(AppUpdateMethodCallParams)}
376
+ },
377
+ "app_id": 0,
378
+ "approval_program": "",
379
+ "clear_state_program": "",
380
+ "sender": self._factory._get_sender(params.sender),
381
+ "signer": self._factory._get_signer(
382
+ params.sender if params else None, params.signer if params else None
383
+ ),
384
+ "method": self._factory._app_spec.get_abi_method(params.method),
385
+ "args": self._factory._get_create_abi_args_with_default_values(params.method, params.args),
386
+ "on_complete": OnApplicationComplete.UpdateApplication,
387
+ }
388
+ )
389
+
390
+ def deploy_delete(self, params: AppClientMethodCallParams) -> AppDeleteMethodCallParams:
391
+ """
392
+ Create AppDeleteMethodCallParams for a delete operation.
393
+
394
+ :param params: AppClientMethodCallParams instance.
395
+ :return: An instance of AppDeleteMethodCallParams.
396
+ """
397
+ return AppDeleteMethodCallParams(
398
+ **{
399
+ **{
400
+ param: value
401
+ for param, value in asdict(params).items()
402
+ if param in {f.name for f in dataclasses.fields(AppDeleteMethodCallParams)}
403
+ },
404
+ "app_id": 0,
405
+ "sender": self._factory._get_sender(params.sender),
406
+ "signer": self._factory._get_signer(
407
+ params.sender if params else None, params.signer if params else None
408
+ ),
409
+ "method": self._factory.app_spec.get_abi_method(params.method),
410
+ "args": self._factory._get_create_abi_args_with_default_values(params.method, params.args),
411
+ "on_complete": OnApplicationComplete.DeleteApplication,
412
+ }
413
+ )
414
+
415
+
416
+ class _AppFactoryBareCreateTransactionAccessor:
417
+ """Initialize the bare create transaction accessor.
418
+
419
+ :param factory: The AppFactory instance.
420
+ """
421
+
422
+ def __init__(self, factory: "AppFactory") -> None:
423
+ self._factory = factory
424
+
425
+ def create(self, params: AppFactoryCreateParams | None = None) -> Transaction:
426
+ """
427
+ Create a transaction for app creation.
428
+
429
+ :param params: Optional AppFactoryCreateParams instance.
430
+ :return: A Transaction instance.
431
+ """
432
+ return self._factory._algorand.create_transaction.app_create(self._factory.params.bare.create(params))
433
+
434
+
435
+ class _TransactionCreator:
436
+ """
437
+ The transaction creator.
438
+
439
+ :param factory: The AppFactory instance.
440
+ """
441
+
442
+ def __init__(self, factory: "AppFactory") -> None:
443
+ self._factory = factory
444
+ self._bare = _AppFactoryBareCreateTransactionAccessor(factory)
445
+
446
+ @property
447
+ def bare(self) -> _AppFactoryBareCreateTransactionAccessor:
448
+ """
449
+ Get the bare create transaction accessor.
450
+
451
+ :return: The _AppFactoryBareCreateTransactionAccessor instance.
452
+ """
453
+ return self._bare
454
+
455
+ def create(self, params: AppFactoryCreateMethodCallParams) -> BuiltTransactions:
456
+ """
457
+ Create built transactions for an app method call.
458
+
459
+ :param params: AppFactoryCreateMethodCallParams instance.
460
+ :return: A BuiltTransactions instance.
461
+ """
462
+ return self._factory._algorand.create_transaction.app_create_method_call(self._factory.params.create(params))
463
+
464
+
465
+ class _AppFactoryBareSendAccessor:
466
+ """
467
+ The bare send accessor.
468
+
469
+ :param factory: The AppFactory instance.
470
+ """
471
+
472
+ def __init__(self, factory: "AppFactory") -> None:
473
+ self._factory = factory
474
+ self._algorand = factory._algorand
475
+
476
+ def create(
477
+ self,
478
+ params: AppFactoryCreateParams | None = None,
479
+ send_params: SendParams | None = None,
480
+ compilation_params: AppClientCompilationParams | None = None,
481
+ ) -> tuple[AppClient, SendAppCreateTransactionResult]:
482
+ """
483
+ Send an app creation transaction and return the app client along with the transaction result.
484
+
485
+ :param params: Optional AppFactoryCreateParams instance.
486
+ :param send_params: Optional SendParams instance.
487
+ :param compilation_params: Optional AppClientCompilationParams instance.
488
+ :return: A tuple containing the AppClient and SendAppCreateTransactionResult.
489
+ """
490
+ compilation_params = compilation_params or AppClientCompilationParams()
491
+ compilation_params["updatable"] = (
492
+ compilation_params.get("updatable")
493
+ if compilation_params.get("updatable") is not None
494
+ else self._factory._updatable
495
+ )
496
+ compilation_params["deletable"] = (
497
+ compilation_params.get("deletable")
498
+ if compilation_params.get("deletable") is not None
499
+ else self._factory._deletable
500
+ )
501
+ compilation_params["deploy_time_params"] = (
502
+ compilation_params.get("deploy_time_params")
503
+ if compilation_params.get("deploy_time_params") is not None
504
+ else self._factory._deploy_time_params
505
+ )
506
+
507
+ compiled = self._factory.compile(compilation_params)
508
+
509
+ result = self._factory._handle_call_errors(
510
+ lambda: self._algorand.send.app_create(
511
+ self._factory.params.bare.create(params, compilation_params), send_params
512
+ )
513
+ )
514
+
515
+ return (
516
+ self._factory.get_app_client_by_id(
517
+ app_id=result.app_id,
518
+ ),
519
+ SendAppCreateTransactionResult[ABIReturn](
520
+ transaction=result.transaction,
521
+ confirmation=result.confirmation,
522
+ app_id=result.app_id,
523
+ app_address=result.app_address,
524
+ compiled_approval=compiled.compiled_approval if compiled else None,
525
+ compiled_clear=compiled.compiled_clear if compiled else None,
526
+ group_id=result.group_id,
527
+ tx_ids=result.tx_ids,
528
+ transactions=result.transactions,
529
+ confirmations=result.confirmations,
530
+ ),
531
+ )
532
+
533
+
534
+ class _TransactionSender:
535
+ """
536
+ The transaction sender.
537
+
538
+ :param factory: The AppFactory instance.
539
+ """
540
+
541
+ def __init__(self, factory: "AppFactory") -> None:
542
+ self._factory = factory
543
+ self._algorand = factory._algorand
544
+ self._bare = _AppFactoryBareSendAccessor(factory)
545
+
546
+ @property
547
+ def bare(self) -> _AppFactoryBareSendAccessor:
548
+ """
549
+ Get the bare send accessor.
550
+
551
+ :return: The _AppFactoryBareSendAccessor instance.
552
+ """
553
+ return self._bare
554
+
555
+ def create(
556
+ self,
557
+ params: AppFactoryCreateMethodCallParams,
558
+ send_params: SendParams | None = None,
559
+ compilation_params: AppClientCompilationParams | None = None,
560
+ ) -> tuple[AppClient, AppFactoryCreateMethodCallResult[Arc56ReturnValueType]]:
561
+ """
562
+ Send an app creation method call and return the app client along with the method call result.
563
+
564
+ :param params: AppFactoryCreateMethodCallParams instance.
565
+ :param send_params: Optional SendParams instance.
566
+ :param compilation_params: Optional AppClientCompilationParams instance.
567
+ :return: A tuple containing the AppClient and AppFactoryCreateMethodCallResult.
568
+ """
569
+ compilation_params = compilation_params or AppClientCompilationParams()
570
+ compilation_params["updatable"] = (
571
+ compilation_params.get("updatable")
572
+ if compilation_params.get("updatable") is not None
573
+ else self._factory._updatable
574
+ )
575
+ compilation_params["deletable"] = (
576
+ compilation_params.get("deletable")
577
+ if compilation_params.get("deletable") is not None
578
+ else self._factory._deletable
579
+ )
580
+ compilation_params["deploy_time_params"] = (
581
+ compilation_params.get("deploy_time_params")
582
+ if compilation_params.get("deploy_time_params") is not None
583
+ else self._factory._deploy_time_params
584
+ )
585
+
586
+ compiled = self._factory.compile(compilation_params)
587
+ result = self._factory._handle_call_errors(
588
+ lambda: self._factory._parse_method_call_return(
589
+ lambda: self._algorand.send.app_create_method_call(
590
+ self._factory.params.create(params, compilation_params), send_params
591
+ ),
592
+ self._factory._app_spec.get_abi_method(params.method),
593
+ )
594
+ )
595
+
596
+ return (
597
+ self._factory.get_app_client_by_id(
598
+ app_id=result.app_id,
599
+ ),
600
+ AppFactoryCreateMethodCallResult[Arc56ReturnValueType](
601
+ transaction=result.transaction,
602
+ confirmation=result.confirmation,
603
+ tx_id=result.tx_id,
604
+ app_id=result.app_id,
605
+ app_address=result.app_address,
606
+ abi_return=result.abi_return,
607
+ compiled_approval=compiled.compiled_approval if compiled else None,
608
+ compiled_clear=compiled.compiled_clear if compiled else None,
609
+ group_id=result.group_id,
610
+ tx_ids=result.tx_ids,
611
+ transactions=result.transactions,
612
+ confirmations=result.confirmations,
613
+ returns=result.returns,
614
+ ),
615
+ )
616
+
617
+
618
+ class AppFactory:
619
+ """ARC-56/ARC-32 app factory that, for a given app spec, allows you to create
620
+ and deploy one or more app instances and to create one or more app clients
621
+ to interact with those (or other) app instances.
622
+
623
+ :param params: The parameters for the factory
624
+
625
+ :example:
626
+ >>> factory = AppFactory(AppFactoryParams(
627
+ >>> algorand=AlgorandClient.mainnet(),
628
+ >>> app_spec=app_spec,
629
+ >>> )
630
+ >>> )
631
+ """
632
+
633
+ def __init__(self, params: AppFactoryParams) -> None:
634
+ self._app_spec = AppClient.normalise_app_spec(params.app_spec)
635
+ self._app_name = params.app_name or self._app_spec.name
636
+ self._algorand = params.algorand
637
+ self._version = params.version or "1.0"
638
+ self._default_sender = params.default_sender
639
+ self._default_signer = params.default_signer
640
+ self._approval_source_map: ProgramSourceMap | None = None
641
+ self._clear_source_map: ProgramSourceMap | None = None
642
+ self._params_accessor = _MethodParamsBuilder(self)
643
+ self._send_accessor = _TransactionSender(self)
644
+ self._create_transaction_accessor = _TransactionCreator(self)
645
+
646
+ compilation_params = params.compilation_params or AppClientCompilationParams()
647
+ self._deploy_time_params = compilation_params.get("deploy_time_params")
648
+ self._updatable = compilation_params.get("updatable")
649
+ self._deletable = compilation_params.get("deletable")
650
+
651
+ @property
652
+ def app_name(self) -> str:
653
+ """The name of the app"""
654
+ return self._app_name
655
+
656
+ @property
657
+ def app_spec(self) -> arc56.Arc56Contract:
658
+ """The app spec"""
659
+ return self._app_spec
660
+
661
+ @property
662
+ def algorand(self) -> AlgorandClient:
663
+ """The algorand client"""
664
+ return self._algorand
665
+
666
+ @property
667
+ def params(self) -> _MethodParamsBuilder:
668
+ """Get parameters to create transactions (create and deploy related calls) for the current app.
669
+
670
+ A good mental model for this is that these parameters represent a deferred transaction creation.
671
+
672
+ :example: Create a transaction in the future using Algorand Client
673
+ >>> create_app_params = app_factory.params.create(
674
+ ... AppFactoryCreateMethodCallParams(
675
+ ... method='create_method',
676
+ ... args=[123, 'hello']
677
+ ... )
678
+ ... )
679
+ >>> # ...
680
+ >>> algorand.send.app_create_method_call(create_app_params)
681
+
682
+ :example: Define a nested transaction as an ABI argument
683
+ >>> create_app_params = appFactory.params.create(
684
+ ... AppFactoryCreateMethodCallParams(
685
+ ... method='create_method',
686
+ ... args=[123, 'hello']
687
+ ... )
688
+ ... )
689
+ >>> app_client.send.call(
690
+ ... AppClientMethodCallParams(
691
+ ... method='my_method',
692
+ ... args=[create_app_params]
693
+ ... )
694
+ ... )
695
+ """
696
+ return self._params_accessor
697
+
698
+ @property
699
+ def send(self) -> _TransactionSender:
700
+ """
701
+ Get the transaction sender.
702
+
703
+ :return: The _TransactionSender instance.
704
+ """
705
+ return self._send_accessor
706
+
707
+ @property
708
+ def create_transaction(self) -> _TransactionCreator:
709
+ """
710
+ Get the transaction creator.
711
+
712
+ :return: The _TransactionCreator instance.
713
+ """
714
+ return self._create_transaction_accessor
715
+
716
+ def deploy(
717
+ self,
718
+ *,
719
+ on_update: OnUpdate | None = None,
720
+ on_schema_break: OnSchemaBreak | None = None,
721
+ create_params: AppClientMethodCallCreateParams | AppClientBareCallCreateParams | None = None,
722
+ update_params: AppClientMethodCallParams | AppClientBareCallParams | None = None,
723
+ delete_params: AppClientMethodCallParams | AppClientBareCallParams | None = None,
724
+ existing_deployments: ApplicationLookup | None = None,
725
+ ignore_cache: bool = False,
726
+ app_name: str | None = None,
727
+ send_params: SendParams | None = None,
728
+ compilation_params: AppClientCompilationParams | None = None,
729
+ ) -> tuple[AppClient, AppFactoryDeployResult]:
730
+ """Idempotently deploy (create if not exists, update if changed) an app against the given name for the given
731
+ creator account, including deploy-time TEAL template placeholder substitutions (if specified).
732
+
733
+ **Note:** When using the return from this function be sure to check `operationPerformed` to get access to
734
+ various return properties like `transaction`, `confirmation` and `deleteResult`.
735
+
736
+ **Note:** if there is a breaking state schema change to an existing app (and `onSchemaBreak` is set to
737
+ `'replace'`) the existing app will be deleted and re-created.
738
+
739
+ **Note:** if there is an update (different TEAL code) to an existing app (and `onUpdate` is set to
740
+ `'replace'`) the existing app will be deleted and re-created.
741
+
742
+ :param on_update: The action to take if there is an update to the app
743
+ :param on_schema_break: The action to take if there is a breaking state schema change to the app
744
+ :param create_params: The arguments to create the app
745
+ :param update_params: The arguments to update the app
746
+ :param delete_params: The arguments to delete the app
747
+ :param existing_deployments: The existing deployments to use
748
+ :param ignore_cache: Whether to ignore the cache
749
+ :param app_name: The name of the app
750
+ :param send_params: The parameters for the send call
751
+ :param compilation_params: The parameters for the compilation
752
+ :returns: The app client and the result of the deployment
753
+
754
+ :example:
755
+ >>> app_client, result = factory.deploy({
756
+ >>> create_params=AppClientMethodCallCreateParams(
757
+ >>> sender='SENDER_ADDRESS',
758
+ >>> approval_program='APPROVAL PROGRAM',
759
+ >>> clear_state_program='CLEAR PROGRAM',
760
+ >>> schema={
761
+ >>> "global_byte_slices": 0,
762
+ >>> "global_ints": 0,
763
+ >>> "local_byte_slices": 0,
764
+ >>> "local_ints": 0
765
+ >>> }
766
+ >>> ),
767
+ >>> update_params=AppClientMethodCallParams(
768
+ >>> sender='SENDER_ADDRESS'
769
+ >>> ),
770
+ >>> delete_params=AppClientMethodCallParams(
771
+ >>> sender='SENDER_ADDRESS'
772
+ >>> ),
773
+ >>> compilation_params=AppClientCompilationParams(
774
+ >>> updatable=False,
775
+ >>> deletable=False
776
+ >>> ),
777
+ >>> app_name='my_app',
778
+ >>> on_schema_break=OnSchemaBreak.AppendApp,
779
+ >>> on_update=OnUpdate.AppendApp
780
+ >>> })
781
+ """
782
+ # Resolve control parameters with factory defaults
783
+ send_params = send_params or SendParams()
784
+ compilation_params = compilation_params or AppClientCompilationParams()
785
+ resolved_updatable = (
786
+ upd
787
+ if (upd := compilation_params.get("updatable")) is not None
788
+ else self._updatable or self._get_deploy_time_control("updatable")
789
+ )
790
+ resolved_deletable = (
791
+ dlb
792
+ if (dlb := compilation_params.get("deletable")) is not None
793
+ else self._deletable or self._get_deploy_time_control("deletable")
794
+ )
795
+ resolved_deploy_time_params = compilation_params.get("deploy_time_params") or self._deploy_time_params
796
+
797
+ def prepare_create_args() -> AppCreateMethodCallParams | AppCreateParams:
798
+ """Prepare create arguments based on parameter type."""
799
+ if create_params and isinstance(create_params, AppClientMethodCallCreateParams):
800
+ return self.params.create(
801
+ AppFactoryCreateMethodCallParams(
802
+ **asdict(create_params),
803
+ ),
804
+ compilation_params={
805
+ "updatable": resolved_updatable,
806
+ "deletable": resolved_deletable,
807
+ "deploy_time_params": resolved_deploy_time_params,
808
+ },
809
+ )
810
+
811
+ base_params = create_params or AppClientBareCallCreateParams()
812
+ return self.params.bare.create(
813
+ AppFactoryCreateParams(
814
+ **asdict(base_params) if base_params else {},
815
+ ),
816
+ compilation_params={
817
+ "updatable": resolved_updatable,
818
+ "deletable": resolved_deletable,
819
+ "deploy_time_params": resolved_deploy_time_params,
820
+ },
821
+ )
822
+
823
+ def prepare_update_args() -> AppUpdateMethodCallParams | AppUpdateParams:
824
+ """Prepare update arguments based on parameter type."""
825
+ return (
826
+ self.params.deploy_update(update_params)
827
+ if isinstance(update_params, AppClientMethodCallParams)
828
+ else self.params.bare.deploy_update(update_params)
829
+ )
830
+
831
+ def prepare_delete_args() -> AppDeleteMethodCallParams | AppDeleteParams:
832
+ """Prepare delete arguments based on parameter type."""
833
+ return (
834
+ self.params.deploy_delete(delete_params)
835
+ if isinstance(delete_params, AppClientMethodCallParams)
836
+ else self.params.bare.deploy_delete(delete_params)
837
+ )
838
+
839
+ # Execute deployment
840
+ deploy_params = AppDeployParams(
841
+ deploy_time_params=resolved_deploy_time_params,
842
+ on_schema_break=on_schema_break,
843
+ on_update=on_update,
844
+ existing_deployments=existing_deployments,
845
+ ignore_cache=ignore_cache,
846
+ create_params=prepare_create_args(),
847
+ update_params=prepare_update_args(),
848
+ delete_params=prepare_delete_args(),
849
+ metadata=AppDeploymentMetaData(
850
+ name=app_name or self._app_name,
851
+ version=self._version,
852
+ updatable=resolved_updatable,
853
+ deletable=resolved_deletable,
854
+ ),
855
+ send_params=send_params,
856
+ )
857
+ deploy_result = self._algorand.app_deployer.deploy(deploy_params)
858
+
859
+ # Prepare app client and factory deploy response
860
+ app_client = self.get_app_client_by_id(
861
+ app_id=deploy_result.app.app_id,
862
+ app_name=app_name,
863
+ default_sender=self._default_sender,
864
+ default_signer=self._default_signer,
865
+ )
866
+ factory_deploy_result = AppFactoryDeployResult.from_deploy_result(
867
+ response=deploy_result,
868
+ deploy_params=deploy_params,
869
+ app_spec=app_client.app_spec,
870
+ app_compilation_data=self.compile(
871
+ AppClientCompilationParams(
872
+ deploy_time_params=resolved_deploy_time_params,
873
+ updatable=resolved_updatable,
874
+ deletable=resolved_deletable,
875
+ )
876
+ ),
877
+ )
878
+
879
+ return app_client, factory_deploy_result
880
+
881
+ def get_app_client_by_id(
882
+ self,
883
+ app_id: int,
884
+ app_name: str | None = None,
885
+ default_sender: str | None = None, # Address can be string or bytes
886
+ default_signer: TransactionSigner | None = None,
887
+ approval_source_map: ProgramSourceMap | None = None,
888
+ clear_source_map: ProgramSourceMap | None = None,
889
+ ) -> AppClient:
890
+ """Returns a new `AppClient` client for an app instance of the given ID.
891
+
892
+ :param app_id: The id of the app
893
+ :param app_name: The name of the app
894
+ :param default_sender: The default sender address
895
+ :param default_signer: The default signer
896
+ :param approval_source_map: The approval source map
897
+ :param clear_source_map: The clear source map
898
+ :return AppClient: The app client
899
+
900
+ :example:
901
+ >>> app_client = factory.get_app_client_by_id(app_id=123)
902
+ """
903
+ return AppClient(
904
+ AppClientParams(
905
+ app_id=app_id,
906
+ algorand=self._algorand,
907
+ app_spec=self._app_spec,
908
+ app_name=app_name or self._app_name,
909
+ default_sender=default_sender or self._default_sender,
910
+ default_signer=default_signer or self._default_signer,
911
+ approval_source_map=approval_source_map or self._approval_source_map,
912
+ clear_source_map=clear_source_map or self._clear_source_map,
913
+ )
914
+ )
915
+
916
+ def get_app_client_by_creator_and_name(
917
+ self,
918
+ creator_address: str,
919
+ app_name: str,
920
+ default_sender: str | None = None,
921
+ default_signer: TransactionSigner | None = None,
922
+ ignore_cache: bool | None = None,
923
+ app_lookup_cache: ApplicationLookup | None = None,
924
+ approval_source_map: ProgramSourceMap | None = None,
925
+ clear_source_map: ProgramSourceMap | None = None,
926
+ ) -> AppClient:
927
+ """Returns a new `AppClient` client, resolving the app by creator address and name
928
+ using AlgoKit app deployment semantics (i.e. looking for the app creation transaction note).
929
+
930
+ :param creator_address: The creator address
931
+ :param app_name: The name of the app
932
+ :param default_sender: The default sender address
933
+ :param default_signer: The default signer
934
+ :param ignore_cache: Whether to ignore the cache and force a lookup
935
+ :param app_lookup_cache: Optional cache of existing app deployments to use instead of querying the indexer
936
+ :param approval_source_map: Optional source map for the approval program
937
+ :param clear_source_map: Optional source map for the clear state program
938
+ :return: An AppClient instance configured for the resolved application
939
+
940
+ :example:
941
+ >>> app_client = factory.get_app_client_by_creator_and_name(
942
+ ... creator_address='SENDER_ADDRESS',
943
+ ... app_name='my_app'
944
+ ... )
945
+ """
946
+ return AppClient.from_creator_and_name(
947
+ creator_address=creator_address,
948
+ app_name=app_name or self._app_name,
949
+ default_sender=default_sender or self._default_sender,
950
+ default_signer=default_signer or self._default_signer,
951
+ approval_source_map=approval_source_map or self._approval_source_map,
952
+ clear_source_map=clear_source_map or self._clear_source_map,
953
+ ignore_cache=ignore_cache,
954
+ app_lookup_cache=app_lookup_cache,
955
+ app_spec=self._app_spec,
956
+ algorand=self._algorand,
957
+ )
958
+
959
+ def export_source_maps(self) -> AppSourceMaps:
960
+ if not self._approval_source_map or not self._clear_source_map:
961
+ raise ValueError(
962
+ "Unable to export source maps; they haven't been loaded into this client - "
963
+ "you need to call create, update, or deploy first"
964
+ )
965
+ return AppSourceMaps(
966
+ approval_source_map=self._approval_source_map,
967
+ clear_source_map=self._clear_source_map,
968
+ )
969
+
970
+ def import_source_maps(self, source_maps: AppSourceMaps) -> None:
971
+ """
972
+ Import the provided source maps into the factory.
973
+
974
+ :param source_maps: An AppSourceMaps instance containing the approval and clear source maps.
975
+ """
976
+ self._approval_source_map = source_maps.approval_source_map
977
+ self._clear_source_map = source_maps.clear_source_map
978
+
979
+ def compile(self, compilation_params: AppClientCompilationParams | None = None) -> AppClientCompilationResult:
980
+ """Compile the app's TEAL code.
981
+
982
+ :param compilation_params: The compilation parameters
983
+ :return AppClientCompilationResult: The compilation result
984
+
985
+ :example:
986
+ >>> compilation_result = factory.compile()
987
+ """
988
+ compilation = compilation_params or AppClientCompilationParams()
989
+ result = AppClient.compile(
990
+ app_spec=self._app_spec,
991
+ app_manager=self._algorand.app,
992
+ compilation_params=compilation,
993
+ )
994
+
995
+ if result.compiled_approval:
996
+ self._approval_source_map = result.compiled_approval.source_map
997
+ if result.compiled_clear:
998
+ self._clear_source_map = result.compiled_clear.source_map
999
+
1000
+ return result
1001
+
1002
+ def _expose_logic_error(self, e: Exception, is_clear_state_program: bool = False) -> Exception: # noqa: FBT002 FBT001
1003
+ """
1004
+ Convert a low-level exception into a descriptive logic error.
1005
+
1006
+ :param e: The original exception.
1007
+ :param is_clear_state_program: Flag indicating if the error is related to the clear state program.
1008
+ :return: The transformed exception.
1009
+ """
1010
+ return AppClient._expose_logic_error_static(
1011
+ e=e,
1012
+ app_spec=self._app_spec,
1013
+ is_clear_state_program=is_clear_state_program,
1014
+ approval_source_map=self._approval_source_map,
1015
+ clear_source_map=self._clear_source_map,
1016
+ program=None,
1017
+ approval_source_info=(self._app_spec.source_info.approval if self._app_spec.source_info else None),
1018
+ clear_source_info=(self._app_spec.source_info.clear if self._app_spec.source_info else None),
1019
+ )
1020
+
1021
+ def _get_deploy_time_control(self, control: str) -> bool | None:
1022
+ """
1023
+ Determine the deploy time control flag for the specified control type.
1024
+
1025
+ :param control: The control type ('updatable' or 'deletable').
1026
+ :return: A boolean flag or None if not determinable.
1027
+ """
1028
+ approval = self._app_spec.source.get_decoded_approval() if self._app_spec.source else None
1029
+
1030
+ template_name = UPDATABLE_TEMPLATE_NAME if control == "updatable" else DELETABLE_TEMPLATE_NAME
1031
+ if not approval or template_name not in approval:
1032
+ return None
1033
+
1034
+ on_complete = "UpdateApplication" if control == "updatable" else "DeleteApplication"
1035
+ return on_complete in self._app_spec.bare_actions.call or any(
1036
+ on_complete in m.actions.call for m in self._app_spec.methods if m.actions and m.actions.call
1037
+ )
1038
+
1039
+ def _get_sender(self, sender: str | None) -> str:
1040
+ """
1041
+ Retrieve the sender address.
1042
+
1043
+ :param sender: The specified sender address.
1044
+ :return: The sender address.
1045
+ :raises Exception: If no sender is provided and no default sender is set.
1046
+ """
1047
+ if not sender and not self._default_sender:
1048
+ raise Exception(
1049
+ f"No sender provided and no default sender present in app client for call to app {self._app_name}"
1050
+ )
1051
+ return str(sender or self._default_sender)
1052
+
1053
+ def _get_signer(self, sender: str | None, signer: TransactionSigner | None) -> TransactionSigner | None:
1054
+ """
1055
+ Retrieve the transaction signer.
1056
+
1057
+ :param sender: The sender address.
1058
+ :param signer: The provided signer.
1059
+ :return: The transaction signer if available.
1060
+ """
1061
+ return signer or (self._default_signer if not sender or sender == self._default_sender else None)
1062
+
1063
+ def _handle_call_errors(self, call: Callable[[], T]) -> T:
1064
+ try:
1065
+ return call()
1066
+ except Exception as e:
1067
+ raise self._expose_logic_error(e) from None
1068
+
1069
+ def _parse_method_call_return(
1070
+ self,
1071
+ result: Callable[
1072
+ [], SendAppTransactionResult | SendAppCreateTransactionResult | SendAppUpdateTransactionResult
1073
+ ],
1074
+ method: arc56.Method,
1075
+ ) -> AppFactoryCreateMethodCallResult[Arc56ReturnValueType]:
1076
+ _ = method # kept for compatibility
1077
+ """
1078
+ Parse the method call return value and convert the ABI return.
1079
+
1080
+ :param result: A callable that returns the transaction result.
1081
+ :param method: The ABI method associated with the call.
1082
+ :return: An AppFactoryCreateMethodCallResult with the parsed ABI return.
1083
+ :raises ValueError: If ABI return decoding failed.
1084
+ """
1085
+ result_value = result()
1086
+ abi_return_value: Arc56ReturnValueType
1087
+ if isinstance(result_value.abi_return, ABIReturn):
1088
+ if result_value.abi_return.decode_error:
1089
+ raise ValueError(result_value.abi_return.decode_error)
1090
+ abi_return_value = result_value.abi_return.value
1091
+ else:
1092
+ abi_return_value = None
1093
+ return AppFactoryCreateMethodCallResult[Arc56ReturnValueType](
1094
+ **{
1095
+ **result_value.__dict__,
1096
+ "abi_return": abi_return_value,
1097
+ }
1098
+ )
1099
+
1100
+ def _get_create_abi_args_with_default_values(
1101
+ self,
1102
+ method_name_or_signature: str,
1103
+ user_args: Sequence[Any] | None,
1104
+ ) -> list[Any]:
1105
+ """
1106
+ Builds a list of ABI argument values for creation calls, applying default
1107
+ argument values when not provided.
1108
+ """
1109
+ method = self._app_spec.get_abi_method(method_name_or_signature)
1110
+
1111
+ results: list[Any] = []
1112
+
1113
+ for i, param in enumerate(method.args):
1114
+ if user_args and i < len(user_args):
1115
+ arg_value = user_args[i]
1116
+
1117
+ results.append(arg_value)
1118
+ continue
1119
+
1120
+ default_value = getattr(param, "default_value", None)
1121
+ if default_value:
1122
+ if default_value.source == "literal":
1123
+ raw_value = base64.b64decode(default_value.data)
1124
+ value_type = default_value.type or param.type
1125
+ assert not isinstance(value_type, arc56.TransactionType), (
1126
+ "transaction type cannot be a default value"
1127
+ )
1128
+ decoded_value = get_abi_decoded_value(raw_value, value_type)
1129
+ results.append(decoded_value)
1130
+ else:
1131
+ raise ValueError(
1132
+ f"Cannot provide default value from source={default_value.source} for a contract creation call."
1133
+ )
1134
+ else:
1135
+ param_name = param.name or f"arg{i + 1}"
1136
+ raise ValueError(
1137
+ f"No value provided for required argument {param_name} in call to method {method.name}"
1138
+ )
1139
+
1140
+ return results