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,206 @@
1
+ from collections.abc import Callable
2
+ from typing import Any
3
+
4
+ from nacl.signing import SigningKey
5
+
6
+ from algokit_common.serde import to_wire
7
+ from algokit_kmd_client.client import KmdClient
8
+ from algokit_kmd_client.models._create_wallet_request import CreateWalletRequest
9
+ from algokit_kmd_client.models._export_key_request import ExportKeyRequest
10
+ from algokit_kmd_client.models._generate_key_request import GenerateKeyRequest
11
+ from algokit_kmd_client.models._init_wallet_handle_token_request import InitWalletHandleTokenRequest
12
+ from algokit_kmd_client.models._list_keys_request import ListKeysRequest
13
+ from algokit_transact.signer import AddressWithSigners, generate_address_with_signers
14
+ from algokit_utils.clients.client_manager import ClientManager
15
+ from algokit_utils.config import config
16
+ from algokit_utils.models.amount import AlgoAmount
17
+ from algokit_utils.transactions.transaction_composer import (
18
+ PaymentParams,
19
+ TransactionComposer,
20
+ TransactionComposerParams,
21
+ )
22
+
23
+ __all__ = ["KmdAccountManager"]
24
+
25
+
26
+ class KmdAccountManager:
27
+ """Provides abstractions over KMD that makes it easier to get and manage accounts."""
28
+
29
+ _kmd: KmdClient | None
30
+
31
+ def __init__(self, client_manager: ClientManager) -> None:
32
+ self._client_manager = client_manager
33
+ try:
34
+ self._kmd = client_manager.kmd
35
+ except ValueError:
36
+ self._kmd = None
37
+
38
+ def kmd(self) -> KmdClient:
39
+ """Returns the KMD client, initializing it if needed.
40
+
41
+ :raises Exception: If KMD client is not configured and not running against LocalNet
42
+ :return: The KMD client
43
+ """
44
+ if self._kmd is None:
45
+ if self._client_manager.is_localnet():
46
+ kmd_config = ClientManager.get_config_from_environment_or_localnet()
47
+ if not kmd_config.kmd_config:
48
+ raise Exception("Attempt to use KMD client with no KMD configured")
49
+ self._kmd = ClientManager.get_kmd_client(kmd_config.kmd_config)
50
+ return self._kmd
51
+ raise Exception("Attempt to use KMD client with no KMD configured")
52
+ return self._kmd
53
+
54
+ def get_wallet_account(
55
+ self,
56
+ wallet_name: str,
57
+ predicate: Callable[[dict[str, Any]], bool] | None = None,
58
+ sender: str | None = None,
59
+ ) -> AddressWithSigners | None:
60
+ """Returns an Algorand signing account with private key loaded from the given KMD wallet.
61
+
62
+ Retrieves an account from a KMD wallet that matches the given predicate, or a random account
63
+ if no predicate is provided.
64
+
65
+ :param wallet_name: The name of the wallet to retrieve an account from
66
+ :param predicate: Optional filter to use to find the account (otherwise gets a random account from the wallet)
67
+ :param sender: Optional sender address to use this signer for (aka a rekeyed account)
68
+ :return: The signing account or None if no matching wallet or account was found
69
+ """
70
+ return self._find_wallet_account(
71
+ wallet_name,
72
+ predicate,
73
+ sender,
74
+ )
75
+
76
+ def _find_matching_address(
77
+ self,
78
+ addresses: list[str],
79
+ predicate_or_address: Callable[[dict[str, Any]], bool] | str | None,
80
+ ) -> str | None:
81
+ """Find a matching address from a list based on a predicate, specific address, or return the first one."""
82
+ if not addresses:
83
+ return None
84
+
85
+ if callable(predicate_or_address):
86
+ for address in addresses:
87
+ account_info = self._client_manager.algod.account_information(address)
88
+ if predicate_or_address(to_wire(account_info)):
89
+ return address
90
+ return None
91
+
92
+ if isinstance(predicate_or_address, str):
93
+ return predicate_or_address if predicate_or_address in addresses else None
94
+
95
+ return addresses[0]
96
+
97
+ def _find_wallet_account(
98
+ self,
99
+ wallet_name: str,
100
+ predicate_or_address: Callable[[dict[str, Any]], bool] | str | None = None,
101
+ sender: str | None = None,
102
+ ) -> AddressWithSigners | None:
103
+ kmd_client = self.kmd()
104
+ wallets = kmd_client.list_wallets().wallets or []
105
+ wallet = next((w for w in wallets if w.name == wallet_name), None)
106
+ if not wallet:
107
+ return None
108
+
109
+ wallet_id = wallet.id_
110
+ wallet_handle = kmd_client.init_wallet_handle(InitWalletHandleTokenRequest(wallet_id, "")).wallet_handle_token
111
+ addresses = kmd_client.list_keys_in_wallet(ListKeysRequest(wallet_handle)).addresses or []
112
+
113
+ matched_address = self._find_matching_address(addresses, predicate_or_address)
114
+ if not matched_address:
115
+ return None
116
+
117
+ private_key = kmd_client.export_key(ExportKeyRequest(matched_address, wallet_handle, "")).private_key
118
+ if not private_key:
119
+ raise Exception(f"Error exporting key for address {matched_address} from KMD wallet {wallet_name}")
120
+
121
+ # private_key is 64 bytes from KMD (seed + public key)
122
+ seed = private_key[:32]
123
+ public_key = private_key[32:]
124
+ signing_key = SigningKey(seed)
125
+
126
+ def raw_signer(bytes_to_sign: bytes) -> bytes:
127
+ return signing_key.sign(bytes_to_sign).signature
128
+
129
+ return generate_address_with_signers(
130
+ ed25519_pubkey=public_key,
131
+ raw_ed25519_signer=raw_signer,
132
+ sending_address=sender,
133
+ )
134
+
135
+ def get_or_create_wallet_account(self, name: str, fund_with: AlgoAmount | None = None) -> AddressWithSigners:
136
+ """Gets or creates a funded account in a KMD wallet of the given name.
137
+
138
+ Provides idempotent access to accounts from LocalNet without specifying the private key.
139
+
140
+ :param name: The name of the wallet to retrieve / create
141
+ :param fund_with: The number of Algos to fund the account with when created
142
+ :return: An Algorand account with private key loaded
143
+
144
+ :raises Exception: If error received while creating the wallet or funding the account
145
+ """
146
+ fund_with = fund_with or AlgoAmount.from_algo(1000)
147
+
148
+ existing = self.get_wallet_account(name)
149
+ if existing:
150
+ return existing
151
+
152
+ kmd_client = self.kmd()
153
+ wallet = kmd_client.create_wallet(CreateWalletRequest(wallet_name=name, wallet_password="")).wallet
154
+ if not wallet:
155
+ raise Exception(f"Error creating KMD wallet with name {name}")
156
+ wallet_id = wallet.id_
157
+ wallet_handle = kmd_client.init_wallet_handle(InitWalletHandleTokenRequest(wallet_id, "")).wallet_handle_token
158
+ kmd_client.generate_key(GenerateKeyRequest(wallet_handle_token=wallet_handle))
159
+
160
+ account = self.get_wallet_account(name)
161
+ assert account is not None
162
+
163
+ config.logger.info(
164
+ f"LocalNet account '{name}' doesn't yet exist; created account {account.addr} "
165
+ f"with keys stored in KMD and funding with {fund_with} ALGO"
166
+ )
167
+
168
+ dispenser = self.get_localnet_dispenser_account()
169
+ TransactionComposer(
170
+ TransactionComposerParams(
171
+ algod=self._client_manager.algod,
172
+ get_signer=lambda _: dispenser.signer,
173
+ get_suggested_params=self._client_manager.algod.suggested_params,
174
+ )
175
+ ).add_payment(
176
+ PaymentParams(
177
+ sender=dispenser.addr,
178
+ receiver=account.addr,
179
+ amount=fund_with,
180
+ )
181
+ ).send()
182
+ return account
183
+
184
+ def get_localnet_dispenser_account(self) -> AddressWithSigners:
185
+ """Returns an Algorand account with private key loaded for the default LocalNet dispenser account.
186
+
187
+ Retrieves the default funded account from LocalNet that can be used to fund other accounts.
188
+
189
+ :raises Exception: If not running against LocalNet or dispenser account not found
190
+ :return: The default LocalNet dispenser account
191
+ """
192
+ if not self._client_manager.is_localnet():
193
+ raise Exception("Can't get LocalNet dispenser account from non LocalNet network")
194
+
195
+ genesis_response = self._client_manager.algod.get_genesis()
196
+ dispenser_addresses = [a.addr for a in genesis_response.alloc if a.comment == "Wallet1"]
197
+
198
+ if dispenser_addresses:
199
+ dispenser = self._find_wallet_account(
200
+ "unencrypted-default-wallet",
201
+ dispenser_addresses[0],
202
+ )
203
+ if dispenser:
204
+ return dispenser
205
+
206
+ raise Exception("Error retrieving LocalNet dispenser account; couldn't find the default account in KMD")
@@ -0,0 +1,46 @@
1
+ """Algorand 25-word mnemonic utilities.
2
+
3
+ Re-exports from algokit_algo25 for convenient access via algokit_utils.algo25.
4
+
5
+ Usage:
6
+ from algokit_utils import algo25
7
+ mnemonic = algo25.mnemonic_from_seed(seed)
8
+
9
+ # Or import directly:
10
+ from algokit_utils.algo25 import mnemonic_from_seed, seed_from_mnemonic
11
+ """
12
+
13
+ from algokit_algo25 import (
14
+ FAIL_TO_DECODE_MNEMONIC_ERROR_MSG,
15
+ KEY_LEN_BYTES,
16
+ MNEMONIC_LEN,
17
+ NOT_IN_WORDS_LIST_ERROR_MSG,
18
+ InvalidMnemonicError,
19
+ InvalidSeedLengthError,
20
+ MnemonicError,
21
+ WordNotFoundError,
22
+ master_derivation_key_to_mnemonic,
23
+ mnemonic_from_seed,
24
+ mnemonic_to_master_derivation_key,
25
+ secret_key_to_mnemonic,
26
+ seed_from_mnemonic,
27
+ )
28
+
29
+ __all__ = [
30
+ # Constants
31
+ "FAIL_TO_DECODE_MNEMONIC_ERROR_MSG",
32
+ "KEY_LEN_BYTES",
33
+ "MNEMONIC_LEN",
34
+ "NOT_IN_WORDS_LIST_ERROR_MSG",
35
+ # Exceptions
36
+ "InvalidMnemonicError",
37
+ "InvalidSeedLengthError",
38
+ "MnemonicError",
39
+ "WordNotFoundError",
40
+ # Functions
41
+ "master_derivation_key_to_mnemonic",
42
+ "mnemonic_from_seed",
43
+ "mnemonic_to_master_derivation_key",
44
+ "secret_key_to_mnemonic",
45
+ "seed_from_mnemonic",
46
+ ]
@@ -0,0 +1,383 @@
1
+ import copy
2
+ import time
3
+
4
+ import typing_extensions
5
+
6
+ from algokit_algod_client import AlgodClient
7
+ from algokit_algod_client import models as algod_models
8
+ from algokit_indexer_client import IndexerClient
9
+ from algokit_kmd_client.client import KmdClient
10
+ from algokit_transact.signer import AddressWithTransactionSigner
11
+ from algokit_utils.accounts.account_manager import AccountManager
12
+ from algokit_utils.applications.app_deployer import AppDeployer
13
+ from algokit_utils.applications.app_manager import AppManager
14
+ from algokit_utils.assets.asset_manager import AssetManager
15
+ from algokit_utils.clients.client_manager import AlgoSdkClients, ClientManager
16
+ from algokit_utils.models.network import AlgoClientConfigs, AlgoClientNetworkConfig
17
+ from algokit_utils.protocols.signer import TransactionSigner
18
+ from algokit_utils.transactions.transaction_composer import (
19
+ ErrorTransformer,
20
+ TransactionComposer,
21
+ TransactionComposerParams,
22
+ )
23
+ from algokit_utils.transactions.transaction_creator import AlgorandClientTransactionCreator
24
+ from algokit_utils.transactions.transaction_sender import AlgorandClientTransactionSender
25
+
26
+ __all__ = [
27
+ "AlgorandClient",
28
+ ]
29
+
30
+
31
+ class AlgorandClient:
32
+ """A client that brokers easy access to Algorand functionality."""
33
+
34
+ def __init__(self, config: AlgoClientConfigs | AlgoSdkClients):
35
+ self._client_manager: ClientManager = ClientManager(clients_or_configs=config, algorand_client=self)
36
+ self._account_manager: AccountManager = AccountManager(self._client_manager)
37
+ self._asset_manager: AssetManager = AssetManager(self._client_manager.algod, lambda: self.new_group())
38
+ self._app_manager: AppManager = AppManager(self._client_manager.algod)
39
+ self._transaction_sender = AlgorandClientTransactionSender(
40
+ new_group=lambda: self.new_group(),
41
+ asset_manager=self._asset_manager,
42
+ app_manager=self._app_manager,
43
+ algod_client=self._client_manager.algod,
44
+ )
45
+ self._app_deployer: AppDeployer = AppDeployer(
46
+ self._app_manager, self._transaction_sender, self._client_manager.indexer_if_present
47
+ )
48
+ self._transaction_creator = AlgorandClientTransactionCreator(
49
+ new_group=lambda: self.new_group(),
50
+ )
51
+
52
+ self._cached_suggested_params: algod_models.SuggestedParams | None = None
53
+ self._cached_suggested_params_expiry: float | None = None
54
+ self._cached_suggested_params_timeout: int = 3_000 # three seconds
55
+ self._default_validity_window: int | None = None
56
+ self._error_transformers: set[ErrorTransformer] = set()
57
+
58
+ def set_default_validity_window(self, validity_window: int) -> typing_extensions.Self:
59
+ """
60
+ Sets the default validity window for transactions.
61
+
62
+ :param validity_window: The number of rounds between the first and last valid rounds
63
+ :return: The `AlgorandClient` so method calls can be chained
64
+ :example:
65
+ >>> algorand = AlgorandClient.mainnet().set_default_validity_window(1000);
66
+ """
67
+ self._default_validity_window = validity_window
68
+ return self
69
+
70
+ def set_default_signer(self, signer: TransactionSigner | AddressWithTransactionSigner) -> typing_extensions.Self:
71
+ """
72
+ Sets the default signer to use if no other signer is specified.
73
+
74
+ :param signer: The signer to use, either a `TransactionSigner` or an `AddressWithTransactionSigner`
75
+ :return: The `AlgorandClient` so method calls can be chained
76
+ :example:
77
+ >>> signer = account_manager.random() # Returns AddressWithSigners
78
+ >>> algorand = AlgorandClient.mainnet().set_default_signer(signer)
79
+ """
80
+ self._account_manager.set_default_signer(signer)
81
+ return self
82
+
83
+ def set_signer(self, sender: str, signer: TransactionSigner) -> typing_extensions.Self:
84
+ """
85
+ Tracks the given account for later signing.
86
+
87
+ :param sender: The sender address to use this signer for
88
+ :param signer: The signer to sign transactions with for the given sender
89
+ :return: The `AlgorandClient` so method calls can be chained
90
+ :example:
91
+ >>> account = account_manager.random() # Returns AddressWithSigners
92
+ >>> algorand = AlgorandClient.mainnet().set_signer(account.addr, account.signer)
93
+ """
94
+ self._account_manager.set_signer(sender, signer)
95
+ return self
96
+
97
+ def set_signer_from_account(self, signer: AddressWithTransactionSigner) -> typing_extensions.Self:
98
+ """
99
+ Sets the default signer to use if no other signer is specified.
100
+
101
+ :param signer: The signer to use, either a `TransactionSigner` or an `AddressWithTransactionSigner`
102
+ :return: The `AlgorandClient` so method calls can be chained
103
+ :example:
104
+ >>> accountManager = AlgorandClient.mainnet()
105
+ >>> accountManager.set_signer_from_account(TransactionSignerAccount(address=..., signer=...))
106
+ >>> accountManager.set_signer_from_account(algosdk.LogicSigAccount(program, args))
107
+ >>> accountManager.set_signer_from_account(account_manager.random()) # AddressWithSigners
108
+ >>> accountManager.set_signer_from_account(MultisigAccount(metadata, sub_signers))
109
+ >>> accountManager.set_signer_from_account(account)
110
+ """
111
+ self._account_manager.set_default_signer(signer)
112
+ return self
113
+
114
+ def set_suggested_params_cache(
115
+ self, suggested_params: algod_models.SuggestedParams, until: float | None = None
116
+ ) -> typing_extensions.Self:
117
+ """
118
+ Sets a cache value to use for suggested params.
119
+
120
+ :param suggested_params: The suggested params to use
121
+ :param until: A timestamp until which to cache, or if not specified then the timeout is used
122
+ :return: The `AlgorandClient` so method calls can be chained
123
+ :example:
124
+ >>> algorand = AlgorandClient.mainnet().set_suggested_params_cache(suggested_params, time.time() + 3.6e6)
125
+ """
126
+ self._cached_suggested_params = suggested_params
127
+ self._cached_suggested_params_expiry = until or time.time() + self._cached_suggested_params_timeout
128
+ return self
129
+
130
+ def set_suggested_params_cache_timeout(self, timeout: int) -> typing_extensions.Self:
131
+ """
132
+ Sets the timeout for caching suggested params.
133
+
134
+ :param timeout: The timeout in milliseconds
135
+ :return: The `AlgorandClient` so method calls can be chained
136
+ :example:
137
+ >>> algorand = AlgorandClient.mainnet().set_suggested_params_cache_timeout(10_000)
138
+ """
139
+ self._cached_suggested_params_timeout = timeout
140
+ return self
141
+
142
+ def get_suggested_params(self) -> algod_models.SuggestedParams:
143
+ """
144
+ Get suggested params for a transaction (either cached or from algod if the cache is stale or empty)
145
+
146
+ :example:
147
+ >>> algorand = AlgorandClient.mainnet().get_suggested_params()
148
+ """
149
+ if self._cached_suggested_params and (
150
+ self._cached_suggested_params_expiry is None or self._cached_suggested_params_expiry > time.time()
151
+ ):
152
+ return copy.deepcopy(self._cached_suggested_params)
153
+
154
+ self._cached_suggested_params = self._client_manager.algod.suggested_params()
155
+ self._cached_suggested_params_expiry = time.time() + self._cached_suggested_params_timeout
156
+
157
+ return copy.deepcopy(self._cached_suggested_params)
158
+
159
+ def register_error_transformer(self, transformer: ErrorTransformer) -> typing_extensions.Self:
160
+ """Register a function that will be used to transform an error caught when simulating or executing
161
+ composed transaction groups made from `new_group`
162
+
163
+ :param transformer: The error transformer function
164
+ :return: The AlgorandClient so you can chain method calls
165
+ """
166
+ self._error_transformers.add(transformer)
167
+ return self
168
+
169
+ def unregister_error_transformer(self, transformer: ErrorTransformer) -> typing_extensions.Self:
170
+ """Unregister an error transformer function
171
+
172
+ :param transformer: The error transformer function to remove
173
+ :return: The AlgorandClient so you can chain method calls
174
+ """
175
+ self._error_transformers.discard(transformer)
176
+ return self
177
+
178
+ def new_group(self) -> TransactionComposer:
179
+ """
180
+ Start a new `TransactionComposer` transaction group
181
+
182
+ :example:
183
+ >>> composer = AlgorandClient.mainnet().new_group()
184
+ >>> result = await composer.add_transaction(payment).send()
185
+ """
186
+
187
+ return TransactionComposer(
188
+ TransactionComposerParams(
189
+ algod=self.client.algod,
190
+ get_signer=lambda addr: self.account.get_signer(addr),
191
+ get_suggested_params=self.get_suggested_params,
192
+ default_validity_window=self._default_validity_window,
193
+ app_manager=self._app_manager,
194
+ error_transformers=list(self._error_transformers),
195
+ )
196
+ )
197
+
198
+ @property
199
+ def client(self) -> ClientManager:
200
+ """
201
+ Get clients, including algosdk clients and app clients.
202
+
203
+ :example:
204
+ >>> clientManager = AlgorandClient.mainnet().client
205
+ """
206
+ return self._client_manager
207
+
208
+ @property
209
+ def account(self) -> AccountManager:
210
+ """Get or create accounts that can sign transactions.
211
+
212
+ :example:
213
+ >>> accountManager = AlgorandClient.mainnet().account
214
+ """
215
+ return self._account_manager
216
+
217
+ @property
218
+ def asset(self) -> AssetManager:
219
+ """
220
+ Get or create assets.
221
+
222
+ :example:
223
+ >>> assetManager = AlgorandClient.mainnet().asset
224
+ """
225
+ return self._asset_manager
226
+
227
+ @property
228
+ def app(self) -> AppManager:
229
+ """
230
+ Get or create applications.
231
+
232
+ :example:
233
+ >>> appManager = AlgorandClient.mainnet().app
234
+ """
235
+ return self._app_manager
236
+
237
+ @property
238
+ def app_deployer(self) -> AppDeployer:
239
+ """
240
+ Get or create applications.
241
+
242
+ :example:
243
+ >>> appDeployer = AlgorandClient.mainnet().app_deployer
244
+ """
245
+ return self._app_deployer
246
+
247
+ @property
248
+ def send(self) -> AlgorandClientTransactionSender:
249
+ """
250
+ Methods for sending a transaction and waiting for confirmation
251
+
252
+ :example:
253
+ >>> result = await AlgorandClient.mainnet().send.payment(
254
+ >>> PaymentParams(
255
+ >>> sender="SENDERADDRESS",
256
+ >>> receiver="RECEIVERADDRESS",
257
+ >>> amount=AlgoAmount(algo-1)
258
+ >>> ))
259
+ """
260
+ return self._transaction_sender
261
+
262
+ @property
263
+ def create_transaction(self) -> AlgorandClientTransactionCreator:
264
+ """
265
+ Methods for building transactions
266
+
267
+ :example:
268
+ >>> transaction = AlgorandClient.mainnet().create_transaction.payment(
269
+ >>> PaymentParams(
270
+ >>> sender="SENDERADDRESS",
271
+ >>> receiver="RECEIVERADDRESS",
272
+ >>> amount=AlgoAmount(algo=1)
273
+ >>> ))
274
+ """
275
+ return self._transaction_creator
276
+
277
+ @staticmethod
278
+ def default_localnet() -> "AlgorandClient":
279
+ """
280
+ Returns an `AlgorandClient` pointing at default LocalNet ports and API token.
281
+
282
+ :return: The `AlgorandClient`
283
+
284
+ :example:
285
+ >>> algorand = AlgorandClient.default_localnet()
286
+ """
287
+ return AlgorandClient(
288
+ AlgoClientConfigs(
289
+ algod_config=ClientManager.get_default_localnet_config("algod"),
290
+ indexer_config=ClientManager.get_default_localnet_config("indexer"),
291
+ kmd_config=ClientManager.get_default_localnet_config("kmd"),
292
+ )
293
+ )
294
+
295
+ @staticmethod
296
+ def testnet() -> "AlgorandClient":
297
+ """
298
+ Returns an `AlgorandClient` pointing at TestNet using AlgoNode.
299
+
300
+ :return: The `AlgorandClient`
301
+
302
+ :example:
303
+ >>> algorand = AlgorandClient.testnet()
304
+ """
305
+ return AlgorandClient(
306
+ AlgoClientConfigs(
307
+ algod_config=ClientManager.get_algonode_config("testnet", "algod"),
308
+ indexer_config=ClientManager.get_algonode_config("testnet", "indexer"),
309
+ kmd_config=None,
310
+ )
311
+ )
312
+
313
+ @staticmethod
314
+ def mainnet() -> "AlgorandClient":
315
+ """
316
+ Returns an `AlgorandClient` pointing at MainNet using AlgoNode.
317
+
318
+ :return: The `AlgorandClient`
319
+
320
+ :example:
321
+ >>> algorand = AlgorandClient.mainnet()
322
+ """
323
+ return AlgorandClient(
324
+ AlgoClientConfigs(
325
+ algod_config=ClientManager.get_algonode_config("mainnet", "algod"),
326
+ indexer_config=ClientManager.get_algonode_config("mainnet", "indexer"),
327
+ kmd_config=None,
328
+ )
329
+ )
330
+
331
+ @staticmethod
332
+ def from_clients(
333
+ algod: AlgodClient, indexer: IndexerClient | None = None, kmd: KmdClient | None = None
334
+ ) -> "AlgorandClient":
335
+ """
336
+ Returns an `AlgorandClient` pointing to the given client(s).
337
+
338
+ :param algod: The algod client to use
339
+ :param indexer: The indexer client to use
340
+ :param kmd: The kmd client to use
341
+ :return: The `AlgorandClient`
342
+
343
+ :example:
344
+ >>> algorand = AlgorandClient.from_clients(algod, indexer, kmd)
345
+ """
346
+ return AlgorandClient(AlgoSdkClients(algod=algod, indexer=indexer, kmd=kmd))
347
+
348
+ @staticmethod
349
+ def from_environment() -> "AlgorandClient":
350
+ """
351
+ Returns an `AlgorandClient` loading the configuration from environment variables.
352
+
353
+ Retrieve configurations from environment variables when defined or get defaults.
354
+
355
+ Expects to be called from a Python environment.
356
+
357
+ :return: The `AlgorandClient`
358
+
359
+ :example:
360
+ >>> algorand = AlgorandClient.from_environment()
361
+ """
362
+ return AlgorandClient(ClientManager.get_config_from_environment_or_localnet())
363
+
364
+ @staticmethod
365
+ def from_config(
366
+ algod_config: AlgoClientNetworkConfig,
367
+ indexer_config: AlgoClientNetworkConfig | None = None,
368
+ kmd_config: AlgoClientNetworkConfig | None = None,
369
+ ) -> "AlgorandClient":
370
+ """
371
+ Returns an `AlgorandClient` from the given config.
372
+
373
+ :param algod_config: The config to use for the algod client
374
+ :param indexer_config: The config to use for the indexer client
375
+ :param kmd_config: The config to use for the kmd client
376
+ :return: The `AlgorandClient`
377
+
378
+ :example:
379
+ >>> algorand = AlgorandClient.from_config(algod_config, indexer_config, kmd_config)
380
+ """
381
+ return AlgorandClient(
382
+ AlgoClientConfigs(algod_config=algod_config, indexer_config=indexer_config, kmd_config=kmd_config)
383
+ )
@@ -0,0 +1,7 @@
1
+ from algokit_utils.applications.abi import * # noqa: F403
2
+ from algokit_utils.applications.app_client import * # noqa: F403
3
+ from algokit_utils.applications.app_deployer import * # noqa: F403
4
+ from algokit_utils.applications.app_factory import * # noqa: F403
5
+ from algokit_utils.applications.app_manager import * # noqa: F403
6
+ from algokit_utils.applications.app_spec import * # noqa: F403
7
+ from algokit_utils.applications.enums import * # noqa: F403