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,1240 @@
1
+ from collections.abc import Callable
2
+ from dataclasses import dataclass
3
+ from typing import Any, Generic, TypeVar, cast
4
+
5
+ from typing_extensions import Self
6
+
7
+ from algokit_abi import arc56
8
+ from algokit_algod_client import AlgodClient
9
+ from algokit_algod_client import models as algod_models
10
+ from algokit_common import get_application_address
11
+ from algokit_transact import Transaction
12
+ from algokit_utils.applications.abi import ABIReturn
13
+ from algokit_utils.applications.app_manager import AppManager
14
+ from algokit_utils.assets.asset_manager import AssetManager
15
+ from algokit_utils.config import config
16
+ from algokit_utils.models.transaction import SendParams
17
+ from algokit_utils.transactions.transaction_composer import (
18
+ AppCallMethodCallParams,
19
+ AppCallParams,
20
+ AppCreateMethodCallParams,
21
+ AppCreateParams,
22
+ AppDeleteMethodCallParams,
23
+ AppDeleteParams,
24
+ AppUpdateMethodCallParams,
25
+ AppUpdateParams,
26
+ AssetConfigParams,
27
+ AssetCreateParams,
28
+ AssetDestroyParams,
29
+ AssetFreezeParams,
30
+ AssetOptInParams,
31
+ AssetOptOutParams,
32
+ AssetTransferParams,
33
+ OfflineKeyRegistrationParams,
34
+ OnlineKeyRegistrationParams,
35
+ PaymentParams,
36
+ SendTransactionComposerResults,
37
+ TransactionComposer,
38
+ TxnParams,
39
+ )
40
+
41
+ __all__ = [
42
+ "AlgorandClientTransactionSender",
43
+ "SendAppCreateTransactionResult",
44
+ "SendAppTransactionResult",
45
+ "SendAppUpdateTransactionResult",
46
+ "SendSingleAssetCreateTransactionResult",
47
+ "SendSingleTransactionResult",
48
+ ]
49
+
50
+
51
+ TxnParamsT = TypeVar("TxnParamsT", bound=TxnParams)
52
+
53
+
54
+ @dataclass(frozen=True, kw_only=True)
55
+ class SendSingleTransactionResult:
56
+ """Base class for transaction results.
57
+
58
+ Represents the result of sending a single transaction.
59
+ """
60
+
61
+ transaction: Transaction # Last transaction
62
+ """The last transaction"""
63
+
64
+ confirmation: algod_models.PendingTransactionResponse # Last confirmation
65
+ """The last confirmation"""
66
+
67
+ # Fields from SendTransactionComposerResults
68
+ group_id: str
69
+ """The group ID"""
70
+
71
+ tx_id: str | None = None
72
+ """The transaction ID"""
73
+
74
+ tx_ids: list[str] # Full array of transaction IDs
75
+ """The full array of transaction IDs"""
76
+ transactions: list[Transaction]
77
+ """The full array of transactions"""
78
+
79
+ confirmations: list[algod_models.PendingTransactionResponse]
80
+ """The full array of confirmations"""
81
+
82
+ returns: list[ABIReturn] | None = None
83
+ """The ABI return value if applicable"""
84
+
85
+ @classmethod
86
+ def from_composer_result(
87
+ cls, result: SendTransactionComposerResults, *, is_abi: bool = False, index: int = -1
88
+ ) -> Self:
89
+ wrapped_transactions = result.transactions
90
+
91
+ # Get base parameters
92
+ base_params = {
93
+ "transaction": wrapped_transactions[index],
94
+ "confirmation": result.confirmations[index],
95
+ "group_id": result.group_id or "",
96
+ "tx_id": result.tx_ids[index],
97
+ "tx_ids": result.tx_ids,
98
+ "transactions": [wrapped_transactions[index]],
99
+ "confirmations": result.confirmations,
100
+ "returns": result.returns,
101
+ }
102
+
103
+ # For asset creation, extract asset_id from confirmation
104
+ if cls is SendSingleAssetCreateTransactionResult:
105
+ confirmation = result.confirmations[index]
106
+ asset_id = confirmation.asset_id
107
+ if asset_id is None:
108
+ raise ValueError("Could not extract asset_id from confirmation")
109
+ base_params["asset_id"] = int(asset_id)
110
+ # For app creation, extract app_id and calculate app_address
111
+ elif cls is SendAppCreateTransactionResult:
112
+ confirmation = result.confirmations[index]
113
+ app_id_raw = confirmation.app_id
114
+ if app_id_raw is None:
115
+ raise ValueError("Could not extract app_id from confirmation")
116
+ app_id = int(app_id_raw)
117
+ base_params.update(
118
+ {
119
+ "app_id": app_id,
120
+ "app_address": get_application_address(app_id),
121
+ "abi_return": result.returns[index] if result.returns and is_abi else None,
122
+ }
123
+ )
124
+ # For regular app transactions, just add abi_return
125
+ elif cls is SendAppTransactionResult:
126
+ base_params["abi_return"] = result.returns[index] if result.returns and is_abi else None
127
+
128
+ return cls(**cast(dict[str, Any], base_params))
129
+
130
+
131
+ @dataclass(frozen=True, kw_only=True)
132
+ class SendSingleAssetCreateTransactionResult(SendSingleTransactionResult):
133
+ """Result of creating a new ASA (Algorand Standard Asset).
134
+
135
+ Contains the asset ID of the newly created asset.
136
+ """
137
+
138
+ asset_id: int
139
+ """The ID of the newly created asset"""
140
+
141
+
142
+ ABIReturnT = TypeVar("ABIReturnT")
143
+
144
+
145
+ @dataclass(frozen=True)
146
+ class SendAppTransactionResult(SendSingleTransactionResult, Generic[ABIReturnT]):
147
+ """Result of an application transaction.
148
+
149
+ Contains the ABI return value if applicable.
150
+ """
151
+
152
+ abi_return: ABIReturnT | None = None
153
+ """The ABI return value if applicable"""
154
+
155
+
156
+ @dataclass(frozen=True)
157
+ class SendAppUpdateTransactionResult(SendAppTransactionResult[ABIReturnT]):
158
+ """Result of updating an application.
159
+
160
+ Contains the compiled approval and clear programs.
161
+ """
162
+
163
+ compiled_approval: Any | None = None
164
+ """The compiled approval program"""
165
+
166
+ compiled_clear: Any | None = None
167
+ """The compiled clear state program"""
168
+
169
+
170
+ @dataclass(frozen=True, kw_only=True)
171
+ class SendAppCreateTransactionResult(SendAppUpdateTransactionResult[ABIReturnT]):
172
+ """Result of creating a new application.
173
+
174
+ Contains the app ID and address of the newly created application.
175
+ """
176
+
177
+ app_id: int
178
+ """The ID of the newly created application"""
179
+
180
+ app_address: str
181
+ """The address of the newly created application"""
182
+
183
+
184
+ class AlgorandClientTransactionSender:
185
+ """Orchestrates sending transactions for AlgorandClient.
186
+
187
+ Provides methods to send various types of transactions including payments,
188
+ asset operations, and application calls.
189
+ """
190
+
191
+ def __init__(
192
+ self,
193
+ new_group: Callable[[], TransactionComposer],
194
+ asset_manager: AssetManager,
195
+ app_manager: AppManager,
196
+ algod_client: AlgodClient,
197
+ ) -> None:
198
+ self._new_group = new_group
199
+ self._asset_manager = asset_manager
200
+ self._app_manager = app_manager
201
+ self._algod = algod_client
202
+
203
+ def new_group(self) -> TransactionComposer:
204
+ """Create a new transaction group.
205
+
206
+ :return: A new TransactionComposer instance
207
+
208
+ :example:
209
+ >>> sender = AlgorandClientTransactionSender(new_group, asset_manager, app_manager, algod_client)
210
+ >>> composer = sender.new_group()
211
+ >>> composer(PaymentParams(sender="sender", receiver="receiver", amount=AlgoAmount(algo=1)))
212
+ >>> composer.send()
213
+ """
214
+ return self._new_group()
215
+
216
+ def _send(
217
+ self,
218
+ c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
219
+ pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
220
+ post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
221
+ ) -> Callable[[TxnParamsT, SendParams | None], SendSingleTransactionResult]:
222
+ def send_transaction(params: TxnParamsT, send_params: SendParams | None = None) -> SendSingleTransactionResult:
223
+ composer = self.new_group()
224
+ c(composer)(params)
225
+
226
+ if pre_log:
227
+ built = composer.build()
228
+ last_txn = built.transactions[-1]
229
+ config.logger.debug(pre_log(params, last_txn))
230
+
231
+ raw_result = composer.send(
232
+ send_params,
233
+ )
234
+ transactions = raw_result.transactions
235
+ confirmations = list(raw_result.confirmations)
236
+ result = SendSingleTransactionResult(
237
+ transaction=transactions[-1],
238
+ confirmation=confirmations[-1],
239
+ group_id=raw_result.group_id or "",
240
+ tx_id=raw_result.tx_ids[-1],
241
+ tx_ids=raw_result.tx_ids,
242
+ transactions=transactions,
243
+ confirmations=confirmations,
244
+ returns=raw_result.returns,
245
+ )
246
+
247
+ if post_log:
248
+ config.logger.debug(post_log(params, result))
249
+
250
+ return result
251
+
252
+ return send_transaction
253
+
254
+ def _send_app_call(
255
+ self,
256
+ c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
257
+ pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
258
+ post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
259
+ ) -> Callable[[TxnParamsT, SendParams | None], SendAppTransactionResult[ABIReturn]]:
260
+ def send_app_call(
261
+ params: TxnParamsT, send_params: SendParams | None = None
262
+ ) -> SendAppTransactionResult[ABIReturn]:
263
+ result = self._send(c, pre_log, post_log)(params, send_params)
264
+ return SendAppTransactionResult[ABIReturn](
265
+ **result.__dict__,
266
+ abi_return=AppManager.get_abi_return(result.confirmation, getattr(params, "method", None)),
267
+ )
268
+
269
+ return send_app_call
270
+
271
+ def _send_app_update_call(
272
+ self,
273
+ c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
274
+ pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
275
+ post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
276
+ ) -> Callable[[TxnParamsT, SendParams | None], SendAppUpdateTransactionResult[ABIReturn]]:
277
+ def send_app_update_call(
278
+ params: TxnParamsT, send_params: SendParams | None = None
279
+ ) -> SendAppUpdateTransactionResult[ABIReturn]:
280
+ result = self._send_app_call(c, pre_log, post_log)(params, send_params)
281
+
282
+ if not isinstance(
283
+ params, AppCreateParams | AppUpdateParams | AppCreateMethodCallParams | AppUpdateMethodCallParams
284
+ ):
285
+ raise TypeError("Invalid parameter type")
286
+
287
+ compiled_approval = (
288
+ self._app_manager.get_compilation_result(params.approval_program)
289
+ if isinstance(params.approval_program, str)
290
+ else params.approval_program
291
+ )
292
+ compiled_clear = (
293
+ self._app_manager.get_compilation_result(params.clear_state_program)
294
+ if isinstance(params.clear_state_program, str)
295
+ else params.clear_state_program
296
+ )
297
+
298
+ return SendAppUpdateTransactionResult[ABIReturn](
299
+ **result.__dict__,
300
+ compiled_approval=compiled_approval,
301
+ compiled_clear=compiled_clear,
302
+ )
303
+
304
+ return send_app_update_call
305
+
306
+ def _send_app_create_call(
307
+ self,
308
+ c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
309
+ pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
310
+ post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
311
+ ) -> Callable[[TxnParamsT, SendParams | None], SendAppCreateTransactionResult[ABIReturn]]:
312
+ def send_app_create_call(
313
+ params: TxnParamsT, send_params: SendParams | None = None
314
+ ) -> SendAppCreateTransactionResult[ABIReturn]:
315
+ result = self._send_app_update_call(c, pre_log, post_log)(params, send_params)
316
+ app_id_raw = result.confirmation.app_id
317
+ if app_id_raw is None:
318
+ raise ValueError("Could not extract app_id from confirmation")
319
+ app_id = int(app_id_raw)
320
+
321
+ return SendAppCreateTransactionResult[ABIReturn](
322
+ **result.__dict__,
323
+ app_id=app_id,
324
+ app_address=get_application_address(app_id),
325
+ )
326
+
327
+ return send_app_create_call
328
+
329
+ def _get_method_call_for_log(self, method: arc56.Method, args: list[Any]) -> str:
330
+ """Helper function to format method call logs similar to TypeScript version"""
331
+ args_str = str([str(a) if not isinstance(a, bytes | bytearray) else a.hex() for a in args])
332
+ return f"{method.name}({args_str})"
333
+
334
+ def payment(self, params: PaymentParams, send_params: SendParams | None = None) -> SendSingleTransactionResult:
335
+ """Send a payment transaction to transfer Algo between accounts.
336
+
337
+ :param params: Payment transaction parameters
338
+ :param send_params: Send parameters
339
+ :return: Result of the payment transaction
340
+
341
+ :example:
342
+ >>> result = algorand.send.payment(PaymentParams(
343
+ >>> sender="SENDERADDRESS",
344
+ >>> receiver="RECEIVERADDRESS",
345
+ >>> amount=AlgoAmount(algo=4),
346
+ >>> ))
347
+
348
+ >>> # Advanced example
349
+ >>> result = algorand.send.payment(PaymentParams(
350
+ >>> amount=AlgoAmount(algo=4),
351
+ >>> receiver="RECEIVERADDRESS",
352
+ >>> sender="SENDERADDRESS",
353
+ >>> close_remainder_to="CLOSEREMAINDERTOADDRESS",
354
+ >>> lease="lease",
355
+ >>> note="note",
356
+ >>> rekey_to="REKEYTOADDRESS",
357
+ >>> first_valid_round=1000,
358
+ >>> validity_window=10,
359
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
360
+ >>> static_fee=AlgoAmount(micro_algo=1000),
361
+ >>> max_fee=AlgoAmount(micro_algo=3000),
362
+ >>> signer=transactionSigner
363
+ >>> ), send_params=SendParams(
364
+ >>> max_rounds_to_wait_for_confirmation=5,
365
+ >>> suppress_log=True,
366
+ >>> ))
367
+ """
368
+ return self._send(
369
+ lambda c: c.add_payment,
370
+ pre_log=lambda params, transaction: (
371
+ f"Sending {params.amount} from {params.sender} to {params.receiver} "
372
+ f"via transaction {transaction.tx_id()}"
373
+ ),
374
+ )(params, send_params)
375
+
376
+ def asset_create(
377
+ self, params: AssetCreateParams, send_params: SendParams | None = None
378
+ ) -> SendSingleAssetCreateTransactionResult:
379
+ """Create a new Algorand Standard Asset.
380
+
381
+ :param params: Asset creation parameters
382
+ :param send_params: Send parameters
383
+ :return: Result containing the new asset ID
384
+ :raises ValueError: If the confirmation payload does not include an asset_id
385
+
386
+ :example:
387
+ >>> result = algorand.send.asset_create(AssetCreateParams(
388
+ >>> sender="SENDERADDRESS",
389
+ >>> asset_name="ASSETNAME",
390
+ >>> unit_name="UNITNAME",
391
+ >>> total=1000,
392
+ >>> ))
393
+
394
+ >>> # Advanced example
395
+ >>> result = algorand.send.asset_create(AssetCreateParams(
396
+ >>> sender="CREATORADDRESS",
397
+ >>> total=100,
398
+ >>> decimals=2,
399
+ >>> asset_name="asset",
400
+ >>> unit_name="unit",
401
+ >>> url="url",
402
+ >>> metadata_hash="metadataHash",
403
+ >>> default_frozen=False,
404
+ >>> manager="MANAGERADDRESS",
405
+ >>> reserve="RESERVEADDRESS",
406
+ >>> freeze="FREEZEADDRESS",
407
+ >>> clawback="CLAWBACKADDRESS",
408
+ >>> lease="lease",
409
+ >>> note="note",
410
+ >>> # You wouldn't normally set this field
411
+ >>> first_valid_round=1000,
412
+ >>> validity_window=10,
413
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
414
+ >>> static_fee=AlgoAmount(micro_algo=1000),
415
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
416
+ >>> # already specified, but here for completeness
417
+ >>> max_fee=AlgoAmount(micro_algo=3000),
418
+ >>> # Signer only needed if you want to provide one,
419
+ >>> # generally you'd register it with AlgorandClient
420
+ >>> # against the sender and not need to pass it in
421
+ >>> signer=transactionSigner
422
+ >>> ), send_params=SendParams(
423
+ >>> max_rounds_to_wait_for_confirmation=5,
424
+ >>> suppress_log=True,
425
+ >>> ))
426
+ """
427
+ result = self._send(
428
+ lambda c: c.add_asset_create,
429
+ post_log=lambda params, result: (
430
+ f"Created asset{f' {params.asset_name}' if hasattr(params, 'asset_name') else ''}"
431
+ f"{f' ({params.unit_name})' if hasattr(params, 'unit_name') else ''} with "
432
+ f"{params.total} units and {getattr(params, 'decimals', 0)} decimals created by "
433
+ f"{params.sender} with ID {result.confirmation.asset_id} "
434
+ f"via transaction {result.tx_ids[-1]}"
435
+ ),
436
+ )(params, send_params)
437
+
438
+ asset_id_raw = result.confirmation.asset_id
439
+ if asset_id_raw is None:
440
+ raise ValueError("Could not extract asset_id from confirmation")
441
+ return SendSingleAssetCreateTransactionResult(
442
+ **result.__dict__,
443
+ asset_id=int(asset_id_raw),
444
+ )
445
+
446
+ def asset_config(
447
+ self, params: AssetConfigParams, send_params: SendParams | None = None
448
+ ) -> SendSingleTransactionResult:
449
+ """Configure an existing Algorand Standard Asset.
450
+
451
+ :param params: Asset configuration parameters
452
+ :param send_params: Send parameters
453
+ :return: Result of the configuration transaction
454
+
455
+ :example:
456
+ >>> result = algorand.send.asset_config(AssetConfigParams(
457
+ >>> sender="MANAGERADDRESS",
458
+ >>> asset_id=123456,
459
+ >>> manager="MANAGERADDRESS",
460
+ >>> reserve="RESERVEADDRESS",
461
+ >>> freeze="FREEZEADDRESS",
462
+ >>> clawback="CLAWBACKADDRESS",
463
+ >>> lease="lease",
464
+ >>> note="note",
465
+ >>> # You wouldn't normally set this field
466
+ >>> first_valid_round=1000,
467
+ >>> validity_window=10,
468
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
469
+ >>> static_fee=AlgoAmount(micro_algo=1000),
470
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
471
+ >>> # already specified, but here for completeness
472
+ >>> max_fee=AlgoAmount(micro_algo=3000),
473
+ >>> # Signer only needed if you want to provide one,
474
+ >>> # generally you'd register it with AlgorandClient
475
+ >>> # against the sender and not need to pass it in
476
+ >>> signer=transactionSigner
477
+ >>> ), send_params=SendParams(
478
+ >>> max_rounds_to_wait_for_confirmation=5,
479
+ >>> suppress_log=True,
480
+ >>> ))
481
+ """
482
+ return self._send(
483
+ lambda c: c.add_asset_config,
484
+ pre_log=lambda params, transaction: (
485
+ f"Configuring asset with ID {params.asset_id} via transaction {transaction.tx_id()}"
486
+ ),
487
+ )(params, send_params)
488
+
489
+ def asset_freeze(
490
+ self, params: AssetFreezeParams, send_params: SendParams | None = None
491
+ ) -> SendSingleTransactionResult:
492
+ """Freeze or unfreeze an Algorand Standard Asset for an account.
493
+
494
+ :param params: Asset freeze parameters
495
+ :param send_params: Send parameters
496
+ :return: Result of the freeze transaction
497
+
498
+ :example:
499
+ >>> result = algorand.send.asset_freeze(AssetFreezeParams(
500
+ >>> sender="MANAGERADDRESS",
501
+ >>> asset_id=123456,
502
+ >>> account="ACCOUNTADDRESS",
503
+ >>> frozen=True,
504
+ >>> ))
505
+
506
+ >>> # Advanced example
507
+ >>> result = algorand.send.asset_freeze(AssetFreezeParams(
508
+ >>> sender="MANAGERADDRESS",
509
+ >>> asset_id=123456,
510
+ >>> account="ACCOUNTADDRESS",
511
+ >>> frozen=True,
512
+ >>> lease="lease",
513
+ >>> note="note",
514
+ >>> # You wouldn't normally set this field
515
+ >>> first_valid_round=1000,
516
+ >>> validity_window=10,
517
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
518
+ >>> static_fee=AlgoAmount(micro_algo=1000),
519
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
520
+ >>> # already specified, but here for completeness
521
+ >>> max_fee=AlgoAmount(micro_algo=3000),
522
+ >>> # Signer only needed if you want to provide one,
523
+ >>> # generally you'd register it with AlgorandClient
524
+ >>> # against the sender and not need to pass it in
525
+ >>> signer=transactionSigner
526
+ >>> ), send_params=SendParams(
527
+ >>> max_rounds_to_wait_for_confirmation=5,
528
+ >>> suppress_log=True,
529
+ >>> ))
530
+ """
531
+ return self._send(
532
+ lambda c: c.add_asset_freeze,
533
+ pre_log=lambda params, transaction: (
534
+ f"Freezing asset with ID {params.asset_id} via transaction {transaction.tx_id()}"
535
+ ),
536
+ )(params, send_params)
537
+
538
+ def asset_destroy(
539
+ self, params: AssetDestroyParams, send_params: SendParams | None = None
540
+ ) -> SendSingleTransactionResult:
541
+ """Destroys an Algorand Standard Asset.
542
+
543
+ :param params: Asset destruction parameters
544
+ :param send_params: Send parameters
545
+ :return: Result of the destroy transaction
546
+
547
+ :example:
548
+ >>> result = algorand.send.asset_destroy(AssetDestroyParams(
549
+ >>> sender="MANAGERADDRESS",
550
+ >>> asset_id=123456,
551
+ >>> ))
552
+
553
+ >>> # Advanced example
554
+ >>> result = algorand.send.asset_destroy(AssetDestroyParams(
555
+ >>> sender="MANAGERADDRESS",
556
+ >>> asset_id=123456,
557
+ >>> lease="lease",
558
+ >>> note="note",
559
+ >>> # You wouldn't normally set this field
560
+ >>> first_valid_round=1000,
561
+ >>> validity_window=10,
562
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
563
+ >>> static_fee=AlgoAmount(micro_algo=1000),
564
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
565
+ >>> # already specified, but here for completeness
566
+ >>> max_fee=AlgoAmount(micro_algo=3000),
567
+ >>> # Signer only needed if you want to provide one,
568
+ >>> # generally you'd register it with AlgorandClient
569
+ >>> # against the sender and not need to pass it in
570
+ >>> signer=transactionSigner
571
+ >>> ), send_params=SendParams(
572
+ >>> max_rounds_to_wait_for_confirmation=5,
573
+ >>> suppress_log=True,
574
+ >>> ))
575
+ """
576
+ return self._send(
577
+ lambda c: c.add_asset_destroy,
578
+ pre_log=lambda params, transaction: (
579
+ f"Destroying asset with ID {params.asset_id} via transaction {transaction.tx_id()}"
580
+ ),
581
+ )(params, send_params)
582
+
583
+ def asset_transfer(
584
+ self, params: AssetTransferParams, send_params: SendParams | None = None
585
+ ) -> SendSingleTransactionResult:
586
+ """Transfer an Algorand Standard Asset.
587
+
588
+ :param params: Asset transfer parameters
589
+ :param send_params: Send parameters
590
+ :return: Result of the transfer transaction
591
+
592
+ :example:
593
+ >>> result = algorand.send.asset_transfer(AssetTransferParams(
594
+ >>> sender="HOLDERADDRESS",
595
+ >>> asset_id=123456,
596
+ >>> amount=1,
597
+ >>> receiver="RECEIVERADDRESS",
598
+ >>> ))
599
+
600
+ >>> # Advanced example (with clawback)
601
+ >>> result = algorand.send.asset_transfer(AssetTransferParams(
602
+ >>> sender="CLAWBACKADDRESS",
603
+ >>> asset_id=123456,
604
+ >>> amount=1,
605
+ >>> receiver="RECEIVERADDRESS",
606
+ >>> clawback_target="HOLDERADDRESS",
607
+ >>> # This field needs to be used with caution
608
+ >>> close_asset_to="ADDRESSTOCLOSETO",
609
+ >>> lease="lease",
610
+ >>> note="note",
611
+ >>> # You wouldn't normally set this field
612
+ >>> first_valid_round=1000,
613
+ >>> validity_window=10,
614
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
615
+ >>> static_fee=AlgoAmount(micro_algo=1000),
616
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
617
+ >>> # already specified, but here for completeness
618
+ >>> max_fee=AlgoAmount(micro_algo=3000),
619
+ >>> # Signer only needed if you want to provide one,
620
+ >>> # generally you'd register it with AlgorandClient
621
+ >>> # against the sender and not need to pass it in
622
+ >>> signer=transactionSigner
623
+ >>> ), send_params=SendParams(
624
+ >>> max_rounds_to_wait_for_confirmation=5,
625
+ >>> suppress_log=True,
626
+ >>> ))
627
+ """
628
+ return self._send(
629
+ lambda c: c.add_asset_transfer,
630
+ pre_log=lambda params, transaction: (
631
+ f"Transferring {params.amount} units of asset with ID {params.asset_id} from "
632
+ f"{params.sender} to {params.receiver} via transaction {transaction.tx_id()}"
633
+ ),
634
+ )(params, send_params)
635
+
636
+ def asset_opt_in(
637
+ self, params: AssetOptInParams, send_params: SendParams | None = None
638
+ ) -> SendSingleTransactionResult:
639
+ """Opt an account into an Algorand Standard Asset.
640
+
641
+ :param params: Asset opt-in parameters
642
+ :param send_params: Send parameters
643
+ :return: Result of the opt-in transaction
644
+
645
+ :example:
646
+ >>> result = algorand.send.asset_opt_in(AssetOptInParams(
647
+ >>> sender="SENDERADDRESS",
648
+ >>> asset_id=123456,
649
+ >>> ))
650
+
651
+ >>> # Advanced example
652
+ >>> result = algorand.send.asset_opt_in(AssetOptInParams(
653
+ >>> sender="SENDERADDRESS",
654
+ >>> asset_id=123456,
655
+ >>> lease="lease",
656
+ >>> note="note",
657
+ >>> # You wouldn't normally set this field
658
+ >>> first_valid_round=1000,
659
+ >>> validity_window=10,
660
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
661
+ >>> static_fee=AlgoAmount(micro_algo=1000),
662
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
663
+ >>> # already specified, but here for completeness
664
+ >>> max_fee=AlgoAmount(micro_algo=3000),
665
+ >>> # Signer only needed if you want to provide one,
666
+ >>> # generally you'd register it with AlgorandClient
667
+ >>> # against the sender and not need to pass it in
668
+ >>> signer=transactionSigner
669
+ >>> ), send_params=SendParams(
670
+ >>> max_rounds_to_wait_for_confirmation=5,
671
+ >>> suppress_log=True,
672
+ >>> ))
673
+ """
674
+ return self._send(
675
+ lambda c: c.add_asset_opt_in,
676
+ pre_log=lambda params, transaction: (
677
+ f"Opting in {params.sender} to asset with ID {params.asset_id} via transaction {transaction.tx_id()}"
678
+ ),
679
+ )(params, send_params)
680
+
681
+ def asset_opt_out(
682
+ self,
683
+ params: AssetOptOutParams,
684
+ send_params: SendParams | None = None,
685
+ *,
686
+ ensure_zero_balance: bool = True,
687
+ ) -> SendSingleTransactionResult:
688
+ """Opt an account out of an Algorand Standard Asset.
689
+
690
+ :param params: Asset opt-out parameters
691
+ :param send_params: Send parameters
692
+ :param ensure_zero_balance: Check if account has zero balance before opt-out, defaults to True
693
+ :raises ValueError: If account has non-zero balance or is not opted in
694
+ :return: Result of the opt-out transaction
695
+
696
+ :example:
697
+ >>> result = algorand.send.asset_opt_out(AssetOptOutParams(
698
+ >>> sender="SENDERADDRESS",
699
+ >>> creator="CREATORADDRESS",
700
+ >>> asset_id=123456,
701
+ >>> ensure_zero_balance=True,
702
+ >>> ))
703
+
704
+ >>> # Advanced example
705
+ >>> result = algorand.send.asset_opt_out(AssetOptOutParams(
706
+ >>> sender="SENDERADDRESS",
707
+ >>> asset_id=123456,
708
+ >>> creator="CREATORADDRESS",
709
+ >>> ensure_zero_balance=True,
710
+ >>> lease="lease",
711
+ >>> note="note",
712
+ >>> # You wouldn't normally set this field
713
+ >>> first_valid_round=1000,
714
+ >>> validity_window=10,
715
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
716
+ >>> static_fee=AlgoAmount(micro_algo=1000),
717
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
718
+ >>> # already specified, but here for completeness
719
+ >>> max_fee=AlgoAmount(micro_algo=3000),
720
+ >>> # Signer only needed if you want to provide one,
721
+ >>> # generally you'd register it with AlgorandClient
722
+ >>> # against the sender and not need to pass it in
723
+ >>> signer=transactionSigner
724
+ >>> ), send_params=SendParams(
725
+ >>> max_rounds_to_wait_for_confirmation=5,
726
+ >>> suppress_log=True,
727
+ >>> ))
728
+ """
729
+ if ensure_zero_balance:
730
+ try:
731
+ account_asset_info = self._asset_manager.get_account_information(params.sender, params.asset_id)
732
+ balance = account_asset_info.balance
733
+ if balance != 0:
734
+ raise ValueError(
735
+ f"Account {params.sender} does not have a zero balance for Asset "
736
+ f"{params.asset_id}; can't opt-out."
737
+ )
738
+ except Exception as e:
739
+ raise ValueError(
740
+ f"Account {params.sender} is not opted-in to Asset {params.asset_id}; can't opt-out."
741
+ ) from e
742
+
743
+ if not hasattr(params, "creator"):
744
+ asset_info = self._asset_manager.get_by_id(params.asset_id)
745
+ params = AssetOptOutParams(
746
+ **params.__dict__,
747
+ creator=asset_info.creator,
748
+ )
749
+
750
+ creator = params.__dict__.get("creator")
751
+ return self._send(
752
+ lambda c: c.add_asset_opt_out,
753
+ pre_log=lambda params, transaction: (
754
+ f"Opting {params.sender} out of asset with ID {params.asset_id} to creator "
755
+ f"{creator} via transaction {transaction.tx_id()}"
756
+ ),
757
+ )(params, send_params)
758
+
759
+ def app_create(
760
+ self, params: AppCreateParams, send_params: SendParams | None = None
761
+ ) -> SendAppCreateTransactionResult[ABIReturn]:
762
+ """Create a new application.
763
+
764
+ :param params: Application creation parameters
765
+ :param send_params: Send parameters
766
+ :return: Result containing the new application ID and address
767
+
768
+ :example:
769
+ >>> result = algorand.send.app_create(AppCreateParams(
770
+ >>> sender="CREATORADDRESS",
771
+ >>> approval_program="TEALCODE",
772
+ >>> clear_state_program="TEALCODE",
773
+ >>> ))
774
+
775
+ >>> # Advanced example
776
+ >>> result = algorand.send.app_create(AppCreateParams(
777
+ >>> sender="CREATORADDRESS",
778
+ >>> approval_program="TEALCODE",
779
+ >>> clear_state_program="TEALCODE",
780
+ >>> ))
781
+ >>> # algorand.send.appCreate(AppCreateParams(
782
+ >>> # sender='CREATORADDRESS',
783
+ >>> # approval_program="TEALCODE",
784
+ >>> # clear_state_program="TEALCODE",
785
+ >>> # schema={
786
+ >>> # "global_ints": 1,
787
+ >>> # "global_byte_slices": 2,
788
+ >>> # "local_ints": 3,
789
+ >>> # "local_byte_slices": 4
790
+ >>> # },
791
+ >>> # extra_program_pages: 1,
792
+ >>> # on_complete: algosdk.transaction.OnApplicationComplete.OptInOC,
793
+ >>> # args: [b'some_bytes']
794
+ >>> # account_references: ["ACCOUNT_1"]
795
+ >>> # app_references: [123, 1234]
796
+ >>> # asset_references: [12345]
797
+ >>> # box_references: ["box1", {app_id: 1234, name: "box2"}]
798
+ >>> # lease: 'lease',
799
+ >>> # note: 'note',
800
+ >>> # # You wouldn't normally set this field
801
+ >>> # first_valid_round: 1000,
802
+ >>> # validity_window: 10,
803
+ >>> # extra_fee: AlgoAmount(micro_algo=1000),
804
+ >>> # static_fee: AlgoAmount(micro_algo=1000),
805
+ >>> # # Max fee doesn't make sense with extraFee AND staticFee
806
+ >>> # # already specified, but here for completeness
807
+ >>> # max_fee: AlgoAmount(micro_algo=3000),
808
+ >>> # # Signer only needed if you want to provide one,
809
+ >>> # # generally you'd register it with AlgorandClient
810
+ >>> # # against the sender and not need to pass it in
811
+ >>> # signer: transactionSigner
812
+ >>> #}, send_params=SendParams(
813
+ >>> # max_rounds_to_wait_for_confirmation=5,
814
+ >>> # suppress_log=True,
815
+ >>> #))
816
+ """
817
+ return self._send_app_create_call(lambda c: c.add_app_create)(params, send_params)
818
+
819
+ def app_update(
820
+ self, params: AppUpdateParams, send_params: SendParams | None = None
821
+ ) -> SendAppUpdateTransactionResult[ABIReturn]:
822
+ """Update an application.
823
+
824
+ :param params: Application update parameters
825
+ :param send_params: Send parameters
826
+ :return: Result containing the compiled programs
827
+
828
+ :example:
829
+ >>> # Basic example
830
+ >>> algorand.send.app_update(AppUpdateParams(
831
+ >>> sender="CREATORADDRESS",
832
+ >>> approval_program="TEALCODE",
833
+ >>> clear_state_program="TEALCODE",
834
+ >>> ))
835
+ >>> # Advanced example
836
+ >>> algorand.send.app_update(AppUpdateParams(
837
+ >>> sender="CREATORADDRESS",
838
+ >>> approval_program="TEALCODE",
839
+ >>> clear_state_program="TEALCODE",
840
+ >>> on_complete=OnApplicationComplete.UpdateApplication,
841
+ >>> args=[b'some_bytes'],
842
+ >>> account_references=["ACCOUNT_1"],
843
+ >>> app_references=[123, 1234],
844
+ >>> asset_references=[12345],
845
+ >>> box_references=[...],
846
+ >>> lease="lease",
847
+ >>> note="note",
848
+ >>> # You wouldn't normally set this field
849
+ >>> first_valid_round=1000,
850
+ >>> validity_window=10,
851
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
852
+ >>> static_fee=AlgoAmount(micro_algo=1000),
853
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
854
+ >>> # already specified, but here for completeness
855
+ >>> max_fee=AlgoAmount(micro_algo=3000),
856
+ >>> # Signer only needed if you want to provide one,
857
+ >>> # generally you'd register it with AlgorandClient
858
+ >>> # against the sender and not need to pass it in
859
+ >>> signer=transactionSigner
860
+ >>> ), send_params=SendParams(
861
+ >>> max_rounds_to_wait_for_confirmation=5,
862
+ >>> suppress_log=True,
863
+ >>> ))
864
+ """
865
+ return self._send_app_update_call(lambda c: c.add_app_update)(params, send_params)
866
+
867
+ def app_delete(
868
+ self, params: AppDeleteParams, send_params: SendParams | None = None
869
+ ) -> SendAppTransactionResult[ABIReturn]:
870
+ """Delete an application.
871
+
872
+ :param params: Application deletion parameters
873
+ :param send_params: Send parameters
874
+ :return: Result of the deletion transaction
875
+
876
+ :example:
877
+ >>> # Basic example
878
+ >>> algorand.send.app_delete(AppDeleteParams(
879
+ >>> sender="CREATORADDRESS",
880
+ >>> app_id=123456,
881
+ >>> ))
882
+ >>> # Advanced example
883
+ >>> algorand.send.app_delete(AppDeleteParams(
884
+ >>> sender="CREATORADDRESS",
885
+ >>> on_complete=OnApplicationComplete.DeleteApplication,
886
+ >>> args=[b'some_bytes'],
887
+ >>> account_references=["ACCOUNT_1"],
888
+ >>> app_references=[123, 1234],
889
+ >>> asset_references=[12345],
890
+ >>> box_references=[...],
891
+ >>> lease="lease",
892
+ >>> note="note",
893
+ >>> # You wouldn't normally set this field
894
+ >>> first_valid_round=1000,
895
+ >>> validity_window=10,
896
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
897
+ >>> static_fee=AlgoAmount(micro_algo=1000),
898
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
899
+ >>> # already specified, but here for completeness
900
+ >>> max_fee=AlgoAmount(micro_algo=3000),
901
+ >>> # Signer only needed if you want to provide one,
902
+ >>> # generally you'd register it with AlgorandClient
903
+ >>> # against the sender and not need to pass it in
904
+ >>> signer=transactionSigner,
905
+ >>> ), send_params=SendParams(
906
+ >>> max_rounds_to_wait_for_confirmation=5,
907
+ >>> suppress_log=True,
908
+ >>> ))
909
+ """
910
+ return self._send_app_call(lambda c: c.add_app_delete)(params, send_params)
911
+
912
+ def app_call(
913
+ self, params: AppCallParams, send_params: SendParams | None = None
914
+ ) -> SendAppTransactionResult[ABIReturn]:
915
+ """Call an application.
916
+
917
+ :param params: Application call parameters
918
+ :param send_params: Send parameters
919
+ :return: Result containing any ABI return value
920
+
921
+ :example:
922
+ >>> # Basic example
923
+ >>> algorand.send.app_call(AppCallParams(
924
+ >>> sender="CREATORADDRESS",
925
+ >>> app_id=123456,
926
+ >>> ))
927
+ >>> # Advanced example
928
+ >>> algorand.send.app_call(AppCallParams(
929
+ >>> sender="CREATORADDRESS",
930
+ >>> on_complete=OnApplicationComplete.OptInOC,
931
+ >>> args=[b'some_bytes'],
932
+ >>> account_references=["ACCOUNT_1"],
933
+ >>> app_references=[123, 1234],
934
+ >>> asset_references=[12345],
935
+ >>> box_references=[...],
936
+ >>> lease="lease",
937
+ >>> note="note",
938
+ >>> # You wouldn't normally set this field
939
+ >>> first_valid_round=1000,
940
+ >>> validity_window=10,
941
+ >>> extra_fee=AlgoAmount(micro_algo=1000),
942
+ >>> static_fee=AlgoAmount(micro_algo=1000),
943
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
944
+ >>> # already specified, but here for completeness
945
+ >>> max_fee=AlgoAmount(micro_algo=3000),
946
+ >>> # Signer only needed if you want to provide one,
947
+ >>> # generally you'd register it with AlgorandClient
948
+ >>> # against the sender and not need to pass it in
949
+ >>> signer=transactionSigner,
950
+ >>> ), send_params=SendParams(
951
+ >>> max_rounds_to_wait_for_confirmation=5,
952
+ >>> suppress_log=True,
953
+ >>> ))
954
+ """
955
+ return self._send_app_call(lambda c: c.add_app_call)(params, send_params)
956
+
957
+ def app_create_method_call(
958
+ self, params: AppCreateMethodCallParams, send_params: SendParams | None = None
959
+ ) -> SendAppCreateTransactionResult[ABIReturn]:
960
+ """Call an application's create method.
961
+
962
+ :param params: Method call parameters for application creation
963
+ :param send_params: Send parameters
964
+ :return: Result containing the new application ID and address
965
+
966
+ :example:
967
+ >>> # Note: you may prefer to use `algorand.client` to get an app client for more advanced functionality.
968
+ >>> #
969
+ >>> # @param params The parameters for the app creation transaction
970
+ >>> # Basic example
971
+ >>> method = algorand.abi.Method(
972
+ >>> name='method',
973
+ >>> args=[b'arg1'],
974
+ >>> returns='string'
975
+ >>> )
976
+ >>> result = algorand.send.app_create_method_call({ sender: 'CREATORADDRESS',
977
+ >>> approval_program: 'TEALCODE',
978
+ >>> clear_state_program: 'TEALCODE',
979
+ >>> method: method,
980
+ >>> args: ["arg1_value"] })
981
+ >>> created_app_id = result.app_id
982
+ >>> ...
983
+ >>> # Advanced example
984
+ >>> method = algorand.abi.Method(
985
+ >>> name='method',
986
+ >>> args=[b'arg1'],
987
+ >>> returns='string'
988
+ >>> )
989
+ >>> result = algorand.send.app_create_method_call({
990
+ >>> sender: 'CREATORADDRESS',
991
+ >>> method: method,
992
+ >>> args: ["arg1_value"],
993
+ >>> approval_program: "TEALCODE",
994
+ >>> clear_state_program: "TEALCODE",
995
+ >>> schema: {
996
+ >>> "global_ints": 1,
997
+ >>> "global_byte_slices": 2,
998
+ >>> "local_ints": 3,
999
+ >>> "local_byte_slices": 4
1000
+ >>> },
1001
+ >>> extra_program_pages: 1,
1002
+ >>> on_complete: algosdk.transaction.OnApplicationComplete.OptInOC,
1003
+ >>> args: [new Uint8Array(1, 2, 3, 4)],
1004
+ >>> account_references: ["ACCOUNT_1"],
1005
+ >>> app_references: [123, 1234],
1006
+ >>> asset_references: [12345],
1007
+ >>> box_references: [...],
1008
+ >>> lease: 'lease',
1009
+ >>> note: 'note',
1010
+ >>> # You wouldn't normally set this field
1011
+ >>> first_valid_round: 1000,
1012
+ >>> validity_window: 10,
1013
+ >>> extra_fee: AlgoAmount(micro_algo=1000),
1014
+ >>> static_fee: AlgoAmount(micro_algo=1000),
1015
+ >>> # Max fee doesn't make sense with extraFee AND staticFee
1016
+ >>> # already specified, but here for completeness
1017
+ >>> max_fee: AlgoAmount(micro_algo=3000),
1018
+ >>> # Signer only needed if you want to provide one,
1019
+ >>> # generally you'd register it with AlgorandClient
1020
+ >>> # against the sender and not need to pass it in
1021
+ >>> signer: transactionSigner,
1022
+ >>> }, send_params=SendParams(
1023
+ >>> max_rounds_to_wait_for_confirmation=5,
1024
+ >>> suppress_log=True,
1025
+ >>> ))
1026
+ """
1027
+ return self._send_app_create_call(lambda c: c.add_app_create_method_call)(params, send_params)
1028
+
1029
+ def app_update_method_call(
1030
+ self, params: AppUpdateMethodCallParams, send_params: SendParams | None = None
1031
+ ) -> SendAppUpdateTransactionResult[ABIReturn]:
1032
+ """Call an application's update method.
1033
+
1034
+ :param params: Method call parameters for application update
1035
+ :param send_params: Send parameters
1036
+ :return: Result containing the compiled programs
1037
+
1038
+ :example:
1039
+ # Basic example:
1040
+ >>> method = algorand.abi.Method(
1041
+ ... name="updateMethod",
1042
+ ... args=[{"type": "string", "name": "arg1"}],
1043
+ ... returns="string"
1044
+ ... )
1045
+ >>> params = AppUpdateMethodCallParams(
1046
+ ... sender="CREATORADDRESS",
1047
+ ... app_id=123,
1048
+ ... method=method,
1049
+ ... args=["new_value"],
1050
+ ... approval_program="TEALCODE",
1051
+ ... clear_state_program="TEALCODE"
1052
+ ... )
1053
+ >>> result = algorand.send.app_update_method_call(params)
1054
+ >>> print(result.compiled_approval, result.compiled_clear)
1055
+
1056
+ # Advanced example:
1057
+ >>> method = algorand.abi.Method(
1058
+ ... name="updateMethod",
1059
+ ... args=[{"type": "string", "name": "arg1"}, {"type": "uint64", "name": "arg2"}],
1060
+ ... returns="string"
1061
+ ... )
1062
+ >>> params = AppUpdateMethodCallParams(
1063
+ ... sender="CREATORADDRESS",
1064
+ ... app_id=456,
1065
+ ... method=method,
1066
+ ... args=["new_value", 42],
1067
+ ... approval_program="TEALCODE_ADVANCED",
1068
+ ... clear_state_program="TEALCLEAR_ADVANCED",
1069
+ ... account_references=["ACCOUNT1", "ACCOUNT2"],
1070
+ ... app_references=[789],
1071
+ ... asset_references=[101112]
1072
+ ... )
1073
+ >>> result = algorand.send.app_update_method_call(params)
1074
+ >>> print(result.compiled_approval, result.compiled_clear)
1075
+ """
1076
+ return self._send_app_update_call(lambda c: c.add_app_update_method_call)(params, send_params)
1077
+
1078
+ def app_delete_method_call(
1079
+ self, params: AppDeleteMethodCallParams, send_params: SendParams | None = None
1080
+ ) -> SendAppTransactionResult[ABIReturn]:
1081
+ """Call an application's delete method.
1082
+
1083
+ :param params: Method call parameters for application deletion
1084
+ :param send_params: Send parameters
1085
+ :return: Result of the deletion transaction
1086
+
1087
+ :example:
1088
+ # Basic example:
1089
+ >>> method = algorand.abi.Method(
1090
+ ... name="deleteMethod",
1091
+ ... args=[],
1092
+ ... returns="void"
1093
+ ... )
1094
+ >>> params = AppDeleteMethodCallParams(
1095
+ ... sender="CREATORADDRESS",
1096
+ ... app_id=123,
1097
+ ... method=method
1098
+ ... )
1099
+ >>> result = algorand.send.app_delete_method_call(params)
1100
+ >>> print(result.tx_id)
1101
+
1102
+ # Advanced example:
1103
+ >>> method = algorand.abi.Method(
1104
+ ... name="deleteMethod",
1105
+ ... args=[{"type": "uint64", "name": "confirmation"}],
1106
+ ... returns="void"
1107
+ ... )
1108
+ >>> params = AppDeleteMethodCallParams(
1109
+ ... sender="CREATORADDRESS",
1110
+ ... app_id=123,
1111
+ ... method=method,
1112
+ ... args=[1],
1113
+ ... account_references=["ACCOUNT1"],
1114
+ ... app_references=[456]
1115
+ ... )
1116
+ >>> result = algorand.send.app_delete_method_call(params)
1117
+ >>> print(result.tx_id)
1118
+ """
1119
+ return self._send_app_call(lambda c: c.add_app_delete_method_call)(params, send_params)
1120
+
1121
+ def app_call_method_call(
1122
+ self, params: AppCallMethodCallParams, send_params: SendParams | None = None
1123
+ ) -> SendAppTransactionResult[ABIReturn]:
1124
+ """Call an application's call method.
1125
+
1126
+ :param params: Method call parameters
1127
+ :param send_params: Send parameters
1128
+ :return: Result containing any ABI return value
1129
+
1130
+ :example:
1131
+ # Basic example:
1132
+ >>> method = algorand.abi.Method(
1133
+ ... name="callMethod",
1134
+ ... args=[{"type": "uint64", "name": "arg1"}],
1135
+ ... returns="uint64"
1136
+ ... )
1137
+ >>> params = AppCallMethodCallParams(
1138
+ ... sender="CALLERADDRESS",
1139
+ ... app_id=123,
1140
+ ... method=method,
1141
+ ... args=[12345]
1142
+ ... )
1143
+ >>> result = algorand.send.app_call_method_call(params)
1144
+ >>> print(result.abi_return)
1145
+
1146
+ # Advanced example:
1147
+ >>> method = algorand.abi.Method(
1148
+ ... name="callMethod",
1149
+ ... args=[{"type": "uint64", "name": "arg1"}, {"type": "string", "name": "arg2"}],
1150
+ ... returns="uint64"
1151
+ ... )
1152
+ >>> params = AppCallMethodCallParams(
1153
+ ... sender="CALLERADDRESS",
1154
+ ... app_id=123,
1155
+ ... method=method,
1156
+ ... args=[12345, "extra"],
1157
+ ... account_references=["ACCOUNT1"],
1158
+ ... asset_references=[101112],
1159
+ ... app_references=[789]
1160
+ ... )
1161
+ >>> result = algorand.send.app_call_method_call(params)
1162
+ >>> print(result.abi_return)
1163
+ """
1164
+ return self._send_app_call(lambda c: c.add_app_call_method_call)(params, send_params)
1165
+
1166
+ def online_key_registration(
1167
+ self, params: OnlineKeyRegistrationParams, send_params: SendParams | None = None
1168
+ ) -> SendSingleTransactionResult:
1169
+ """Register an online key.
1170
+
1171
+ :param params: Key registration parameters
1172
+ :param send_params: Send parameters
1173
+ :return: Result of the registration transaction
1174
+
1175
+ :example:
1176
+ # Basic example:
1177
+ >>> params = OnlineKeyRegistrationParams(
1178
+ ... sender="ACCOUNTADDRESS",
1179
+ ... vote_key="VOTEKEY",
1180
+ ... selection_key="SELECTIONKEY",
1181
+ ... vote_first=1000,
1182
+ ... vote_last=2000,
1183
+ ... vote_key_dilution=10
1184
+ ... )
1185
+ >>> result = algorand.send.online_key_registration(params)
1186
+ >>> print(result.tx_id)
1187
+
1188
+ # Advanced example:
1189
+ >>> params = OnlineKeyRegistrationParams(
1190
+ ... sender="ACCOUNTADDRESS",
1191
+ ... vote_key="VOTEKEY",
1192
+ ... selection_key="SELECTIONKEY",
1193
+ ... vote_first=1000,
1194
+ ... vote_last=2100,
1195
+ ... vote_key_dilution=10,
1196
+ ... state_proof_key=b'\x01' * 64
1197
+ ... )
1198
+ >>> result = algorand.send.online_key_registration(params)
1199
+ >>> print(result.tx_id)
1200
+ """
1201
+ return self._send(
1202
+ lambda c: c.add_online_key_registration,
1203
+ pre_log=lambda params, transaction: (
1204
+ f"Registering online key for {params.sender} via transaction {transaction.tx_id()}"
1205
+ ),
1206
+ )(params, send_params)
1207
+
1208
+ def offline_key_registration(
1209
+ self, params: OfflineKeyRegistrationParams, send_params: SendParams | None = None
1210
+ ) -> SendSingleTransactionResult:
1211
+ """Register an offline key.
1212
+
1213
+ :param params: Key registration parameters
1214
+ :param send_params: Send parameters
1215
+ :return: Result of the registration transaction
1216
+
1217
+ :example:
1218
+ # Basic example:
1219
+ >>> params = OfflineKeyRegistrationParams(
1220
+ ... sender="ACCOUNTADDRESS",
1221
+ ... prevent_account_from_ever_participating_again=True
1222
+ ... )
1223
+ >>> result = algorand.send.offline_key_registration(params)
1224
+ >>> print(result.tx_id)
1225
+
1226
+ # Advanced example:
1227
+ >>> params = OfflineKeyRegistrationParams(
1228
+ ... sender="ACCOUNTADDRESS",
1229
+ ... prevent_account_from_ever_participating_again=True,
1230
+ ... note=b'Offline registration'
1231
+ ... )
1232
+ >>> result = algorand.send.offline_key_registration(params)
1233
+ >>> print(result.tx_id)
1234
+ """
1235
+ return self._send(
1236
+ lambda c: c.add_offline_key_registration,
1237
+ pre_log=lambda params, transaction: (
1238
+ f"Registering offline key for {params.sender} via transaction {transaction.tx_id()}"
1239
+ ),
1240
+ )(params, send_params)