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,756 @@
1
+ import os
2
+ from dataclasses import dataclass
3
+ from typing import TYPE_CHECKING, Literal, Optional, TypeVar
4
+ from urllib import parse
5
+
6
+ from algokit_abi import arc56
7
+ from algokit_algod_client import AlgodClient
8
+ from algokit_algod_client import ClientConfig as AlgodClientConfig
9
+ from algokit_algod_client import models as algod_models
10
+ from algokit_common import ProgramSourceMap
11
+ from algokit_indexer_client import ClientConfig as IndexerClientConfig
12
+ from algokit_indexer_client import IndexerClient
13
+ from algokit_kmd_client import ClientConfig as KmdClientConfig
14
+ from algokit_kmd_client import KmdClient
15
+ from algokit_utils.clients.dispenser_api_client import TestNetDispenserApiClient
16
+ from algokit_utils.models.network import AlgoClientConfigs, AlgoClientNetworkConfig
17
+ from algokit_utils.protocols.signer import TransactionSigner
18
+ from algokit_utils.protocols.typed_clients import TypedAppClientProtocol, TypedAppFactoryProtocol
19
+
20
+ if TYPE_CHECKING:
21
+ from algokit_utils.algorand import AlgorandClient
22
+ from algokit_utils.applications.app_client import AppClient, AppClientCompilationParams
23
+ from algokit_utils.applications.app_deployer import ApplicationLookup
24
+ from algokit_utils.applications.app_factory import AppFactory
25
+
26
+ __all__ = [
27
+ "AlgoSdkClients",
28
+ "ClientManager",
29
+ "NetworkDetail",
30
+ ]
31
+
32
+ TypedFactoryT = TypeVar("TypedFactoryT", bound=TypedAppFactoryProtocol)
33
+ TypedAppClientT = TypeVar("TypedAppClientT", bound=TypedAppClientProtocol)
34
+
35
+
36
+ class AlgoSdkClients:
37
+ """Container for Algorand SDK client instances.
38
+
39
+ Holds references to Algod, Indexer and KMD clients.
40
+
41
+ :param algod: Algod client instance (protocol-compatible typed client)
42
+ :param indexer: Optional Indexer client instance
43
+ :param kmd: Optional KMD client instance
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ algod: AlgodClient,
49
+ indexer: IndexerClient | None = None,
50
+ kmd: KmdClient | None = None,
51
+ ):
52
+ self.algod = algod
53
+ self.indexer = indexer
54
+ self.kmd = kmd
55
+
56
+
57
+ @dataclass(kw_only=True, frozen=True)
58
+ class NetworkDetail:
59
+ """Details about an Algorand network.
60
+
61
+ Contains network type flags and genesis information.
62
+ """
63
+
64
+ is_testnet: bool
65
+ """Whether the network is a testnet"""
66
+ is_mainnet: bool
67
+ """Whether the network is a mainnet"""
68
+ is_localnet: bool
69
+ """Whether the network is a localnet"""
70
+ genesis_id: str
71
+ """The genesis ID of the network"""
72
+ genesis_hash: str
73
+ """The genesis hash of the network"""
74
+
75
+
76
+ def _get_config_from_environment(environment_prefix: str) -> AlgoClientNetworkConfig:
77
+ server = os.getenv(f"{environment_prefix}_SERVER")
78
+ if server is None:
79
+ raise Exception(f"Server environment variable not set: {environment_prefix}_SERVER")
80
+ port = os.getenv(f"{environment_prefix}_PORT")
81
+ if port:
82
+ parsed = parse.urlparse(server)
83
+ server = parsed._replace(netloc=f"{parsed.hostname}").geturl()
84
+ return AlgoClientNetworkConfig(server, os.getenv(f"{environment_prefix}_TOKEN", ""), port=port)
85
+
86
+
87
+ class ClientManager:
88
+ """Manager for Algorand SDK clients.
89
+
90
+ Provides access to Algod, Indexer and KMD clients and helper methods for working with them.
91
+
92
+ :param clients_or_configs: Either client instances or client configurations
93
+ :param algorand_client: "AlgorandClient" instance
94
+
95
+ :example:
96
+ >>> # Algod only
97
+ >>> client_manager = ClientManager(algod_client)
98
+ >>> # Algod and Indexer
99
+ >>> client_manager = ClientManager(algod_client, indexer_client)
100
+ >>> # Algod config only
101
+ >>> client_manager = ClientManager(ClientManager.get_algod_config_from_environment())
102
+ >>> # Algod and Indexer config
103
+ >>> client_manager = ClientManager(ClientManager.get_algod_config_from_environment(),
104
+ ... ClientManager.get_indexer_config_from_environment())
105
+ """
106
+
107
+ def __init__(self, clients_or_configs: AlgoClientConfigs | AlgoSdkClients, algorand_client: "AlgorandClient"):
108
+ if isinstance(clients_or_configs, AlgoSdkClients):
109
+ _clients = clients_or_configs
110
+ elif isinstance(clients_or_configs, AlgoClientConfigs):
111
+ _clients = AlgoSdkClients(
112
+ algod=ClientManager.get_algod_client(clients_or_configs.algod_config),
113
+ indexer=ClientManager.get_indexer_client(clients_or_configs.indexer_config)
114
+ if clients_or_configs.indexer_config
115
+ else None,
116
+ kmd=ClientManager.get_kmd_client(clients_or_configs.kmd_config)
117
+ if clients_or_configs.kmd_config
118
+ else None,
119
+ )
120
+ self._algod = _clients.algod
121
+ self._indexer = _clients.indexer
122
+ self._kmd = _clients.kmd
123
+ self._algorand = algorand_client
124
+ self._suggested_params: algod_models.SuggestedParams | None = None
125
+
126
+ @property
127
+ def algod(self) -> AlgodClient:
128
+ """Returns the typed Algod API client instance.
129
+
130
+ :return: Algod client instance
131
+ """
132
+ return self._algod
133
+
134
+ @property
135
+ def indexer(self) -> IndexerClient:
136
+ """Returns an Indexer API client.
137
+
138
+ :raises ValueError: If no Indexer client is configured
139
+ :return: Indexer client instance
140
+ """
141
+ if not self._indexer:
142
+ raise ValueError("Attempt to use Indexer client in AlgoKit instance with no Indexer configured")
143
+ return self._indexer
144
+
145
+ @property
146
+ def indexer_if_present(self) -> IndexerClient | None:
147
+ """Returns the Indexer client if configured, otherwise None.
148
+
149
+ :return: Indexer client instance or None
150
+ """
151
+ return self._indexer
152
+
153
+ @property
154
+ def kmd(self) -> KmdClient:
155
+ """Returns a KMD-compatible API client.
156
+
157
+ :raises ValueError: If no KMD client is configured
158
+ :return: KMD client instance
159
+ """
160
+ if not self._kmd:
161
+ raise ValueError("Attempt to use Kmd client in AlgoKit instance with no Kmd configured")
162
+ return self._kmd
163
+
164
+ def network(self) -> NetworkDetail:
165
+ """Get details about the connected Algorand network.
166
+
167
+ :return: Network details including type and genesis information
168
+
169
+ :example:
170
+ >>> client_manager = ClientManager(algod_client)
171
+ >>> network_detail = client_manager.network()
172
+ """
173
+ import base64
174
+
175
+ if self._suggested_params is None:
176
+ self._suggested_params = self._algod.suggested_params()
177
+ sp = self._suggested_params
178
+ return NetworkDetail(
179
+ is_testnet=sp.genesis_id in ["testnet-v1.0", "testnet-v1", "testnet"],
180
+ is_mainnet=sp.genesis_id in ["mainnet-v1.0", "mainnet-v1", "mainnet"],
181
+ is_localnet=ClientManager.genesis_id_is_localnet(str(sp.genesis_id)),
182
+ genesis_id=str(sp.genesis_id),
183
+ genesis_hash=base64.b64encode(sp.genesis_hash).decode("utf-8")
184
+ if isinstance(sp.genesis_hash, bytes)
185
+ else sp.genesis_hash,
186
+ )
187
+
188
+ def is_localnet(self) -> bool:
189
+ """Check if connected to a local network.
190
+
191
+ :return: True if connected to a local network
192
+ """
193
+ return self.network().is_localnet
194
+
195
+ def is_testnet(self) -> bool:
196
+ """Check if connected to TestNet.
197
+
198
+ :return: True if connected to TestNet
199
+ """
200
+ return self.network().is_testnet
201
+
202
+ def is_mainnet(self) -> bool:
203
+ """Check if connected to MainNet.
204
+
205
+ :return: True if connected to MainNet
206
+ """
207
+ return self.network().is_mainnet
208
+
209
+ def close(self) -> None:
210
+ """Close the underlying HTTP client connections.
211
+
212
+ This method should be called when the ClientManager is no longer needed
213
+ to properly clean up resources.
214
+
215
+ :example:
216
+ >>> client_manager = ClientManager(algod_client)
217
+ >>> # ... use client_manager ...
218
+ >>> client_manager.close()
219
+ """
220
+ if isinstance(self._algod, AlgodClient):
221
+ self._algod.close()
222
+
223
+ def get_testnet_dispenser(
224
+ self, auth_token: str | None = None, request_timeout: int | None = None
225
+ ) -> TestNetDispenserApiClient:
226
+ """Get a TestNet dispenser API client.
227
+
228
+ :param auth_token: Optional authentication token
229
+ :param request_timeout: Optional request timeout in seconds
230
+ :return: TestNet dispenser client instance
231
+ """
232
+ if request_timeout:
233
+ return TestNetDispenserApiClient(auth_token=auth_token, request_timeout=request_timeout)
234
+
235
+ return TestNetDispenserApiClient(auth_token=auth_token)
236
+
237
+ def get_app_factory(
238
+ self,
239
+ app_spec: arc56.Arc56Contract | str,
240
+ app_name: str | None = None,
241
+ default_sender: str | None = None,
242
+ default_signer: TransactionSigner | None = None,
243
+ version: str | None = None,
244
+ compilation_params: Optional["AppClientCompilationParams"] = None,
245
+ ) -> "AppFactory":
246
+ """Get an application factory for deploying smart contracts.
247
+
248
+ :param app_spec: Application specification
249
+ :param app_name: Optional application name
250
+ :param default_sender: Optional default sender address
251
+ :param default_signer: Optional default transaction signer
252
+ :param version: Optional version string
253
+ :param compilation_params: Optional compilation parameters
254
+ :raises ValueError: If no Algorand client is configured
255
+ :return: Application factory instance
256
+ """
257
+ from algokit_utils.applications.app_factory import AppFactory, AppFactoryParams
258
+
259
+ if not self._algorand:
260
+ raise ValueError("Attempt to get app factory from a ClientManager without an Algorand client")
261
+
262
+ return AppFactory(
263
+ AppFactoryParams(
264
+ algorand=self._algorand,
265
+ app_spec=app_spec,
266
+ app_name=app_name,
267
+ default_sender=default_sender,
268
+ default_signer=default_signer,
269
+ version=version,
270
+ compilation_params=compilation_params,
271
+ )
272
+ )
273
+
274
+ def get_app_client_by_id(
275
+ self,
276
+ app_spec: arc56.Arc56Contract | str,
277
+ app_id: int,
278
+ app_name: str | None = None,
279
+ default_sender: str | None = None,
280
+ default_signer: TransactionSigner | None = None,
281
+ approval_source_map: ProgramSourceMap | None = None,
282
+ clear_source_map: ProgramSourceMap | None = None,
283
+ ) -> "AppClient":
284
+ """Get an application client for an existing application by ID.
285
+
286
+ :param app_spec: Application specification
287
+ :param app_id: Application ID
288
+ :param app_name: Optional application name
289
+ :param default_sender: Optional default sender address
290
+ :param default_signer: Optional default transaction signer
291
+ :param approval_source_map: Optional approval program source map
292
+ :param clear_source_map: Optional clear program source map
293
+ :raises ValueError: If no Algorand client is configured
294
+ :return: Application client instance
295
+ """
296
+ from algokit_utils.applications.app_client import AppClient, AppClientParams
297
+
298
+ if not self._algorand:
299
+ raise ValueError("Attempt to get app client from a ClientManager without an Algorand client")
300
+
301
+ return AppClient(
302
+ AppClientParams(
303
+ app_spec=app_spec,
304
+ algorand=self._algorand,
305
+ app_id=app_id,
306
+ app_name=app_name,
307
+ default_sender=default_sender,
308
+ default_signer=default_signer,
309
+ approval_source_map=approval_source_map,
310
+ clear_source_map=clear_source_map,
311
+ )
312
+ )
313
+
314
+ def get_app_client_by_network(
315
+ self,
316
+ app_spec: (arc56.Arc56Contract | str),
317
+ app_name: str | None = None,
318
+ default_sender: str | None = None,
319
+ default_signer: TransactionSigner | None = None,
320
+ approval_source_map: ProgramSourceMap | None = None,
321
+ clear_source_map: ProgramSourceMap | None = None,
322
+ ) -> "AppClient":
323
+ """Get an application client for an existing application by network.
324
+
325
+ :param app_spec: Application specification
326
+ :param app_name: Optional application name
327
+ :param default_sender: Optional default sender address
328
+ :param default_signer: Optional default transaction signer
329
+ :param approval_source_map: Optional approval program source map
330
+ :param clear_source_map: Optional clear program source map
331
+ :raises ValueError: If no Algorand client is configured
332
+ :return: Application client instance
333
+ """
334
+ from algokit_utils.applications.app_client import AppClient
335
+
336
+ if not self._algorand:
337
+ raise ValueError("Attempt to get app client from a ClientManager without an Algorand client")
338
+
339
+ return AppClient.from_network(
340
+ app_spec=app_spec,
341
+ app_name=app_name,
342
+ default_sender=default_sender,
343
+ default_signer=default_signer,
344
+ approval_source_map=approval_source_map,
345
+ clear_source_map=clear_source_map,
346
+ algorand=self._algorand,
347
+ )
348
+
349
+ def get_app_client_by_creator_and_name(
350
+ self,
351
+ creator_address: str,
352
+ app_name: str,
353
+ app_spec: arc56.Arc56Contract | str,
354
+ default_sender: str | None = None,
355
+ default_signer: TransactionSigner | None = None,
356
+ ignore_cache: bool | None = None,
357
+ app_lookup_cache: Optional["ApplicationLookup"] = None,
358
+ approval_source_map: ProgramSourceMap | None = None,
359
+ clear_source_map: ProgramSourceMap | None = None,
360
+ ) -> "AppClient":
361
+ """Get an application client by creator address and name.
362
+
363
+ :param creator_address: Creator address
364
+ :param app_name: Application name
365
+ :param app_spec: Application specification
366
+ :param default_sender: Optional default sender address
367
+ :param default_signer: Optional default transaction signer
368
+ :param ignore_cache: Optional flag to ignore cache
369
+ :param app_lookup_cache: Optional app lookup cache
370
+ :param approval_source_map: Optional approval program source map
371
+ :param clear_source_map: Optional clear program source map
372
+ :return: Application client instance
373
+ """
374
+ from algokit_utils.applications.app_client import AppClient
375
+
376
+ return AppClient.from_creator_and_name(
377
+ creator_address=creator_address,
378
+ app_name=app_name,
379
+ default_sender=default_sender,
380
+ default_signer=default_signer,
381
+ ignore_cache=ignore_cache,
382
+ app_lookup_cache=app_lookup_cache,
383
+ app_spec=app_spec,
384
+ approval_source_map=approval_source_map,
385
+ clear_source_map=clear_source_map,
386
+ algorand=self._algorand,
387
+ )
388
+
389
+ @staticmethod
390
+ def get_algod_client(config: AlgoClientNetworkConfig) -> AlgodClient:
391
+ """Get a typed Algod client from config.
392
+
393
+ :param config: Client configuration
394
+ :return: Typed Algod client instance
395
+ """
396
+ client_config = AlgodClientConfig(
397
+ base_url=config.full_url(),
398
+ token=config.token or None,
399
+ )
400
+ return AlgodClient(client_config)
401
+
402
+ @staticmethod
403
+ def get_algod_client_from_environment() -> AlgodClient:
404
+ """Get an Algod client from environment variables.
405
+
406
+ :return: Algod client instance
407
+ """
408
+ return ClientManager.get_algod_client(ClientManager.get_algod_config_from_environment())
409
+
410
+ @staticmethod
411
+ def get_kmd_client(config: AlgoClientNetworkConfig) -> KmdClient:
412
+ """Get a KMD client from config or environment.
413
+
414
+ :param config: Optional client configuration
415
+ :return: KMD client instance
416
+ """
417
+ client_config = KmdClientConfig(
418
+ base_url=config.full_url(),
419
+ token=config.token or None,
420
+ )
421
+ return KmdClient(client_config)
422
+
423
+ @staticmethod
424
+ def get_kmd_client_from_environment() -> KmdClient:
425
+ """Get a KMD client from environment variables.
426
+
427
+ :return: KMD client instance
428
+ """
429
+ return ClientManager.get_kmd_client(ClientManager.get_kmd_config_from_environment())
430
+
431
+ @staticmethod
432
+ def get_indexer_client(config: AlgoClientNetworkConfig) -> IndexerClient:
433
+ """Get an Indexer client from config or environment.
434
+
435
+ :param config: Optional client configuration
436
+ :return: Indexer client instance
437
+ """
438
+ client_config = IndexerClientConfig(
439
+ base_url=config.full_url(),
440
+ token=config.token or None,
441
+ )
442
+ return IndexerClient(client_config)
443
+
444
+ @staticmethod
445
+ def get_indexer_client_from_environment() -> IndexerClient:
446
+ """Get an Indexer client from environment variables.
447
+
448
+ :return: Indexer client instance
449
+ """
450
+ return ClientManager.get_indexer_client(ClientManager.get_indexer_config_from_environment())
451
+
452
+ @staticmethod
453
+ def genesis_id_is_localnet(genesis_id: str | None) -> bool:
454
+ """Check if a genesis ID indicates a local network.
455
+
456
+ :param genesis_id: Genesis ID to check
457
+ :return: True if genesis ID indicates a local network
458
+
459
+ :example:
460
+ >>> ClientManager.genesis_id_is_localnet("devnet-v1")
461
+ """
462
+ return genesis_id in ["devnet-v1", "sandnet-v1", "dockernet-v1"]
463
+
464
+ def get_typed_app_client_by_creator_and_name(
465
+ self,
466
+ typed_client: type[TypedAppClientT],
467
+ *,
468
+ creator_address: str,
469
+ app_name: str,
470
+ default_sender: str | None = None,
471
+ default_signer: TransactionSigner | None = None,
472
+ ignore_cache: bool | None = None,
473
+ app_lookup_cache: Optional["ApplicationLookup"] = None,
474
+ ) -> TypedAppClientT:
475
+ """Get a typed application client by creator address and name.
476
+
477
+ :param typed_client: Typed client class
478
+ :param creator_address: Creator address
479
+ :param app_name: Application name
480
+ :param default_sender: Optional default sender address
481
+ :param default_signer: Optional default transaction signer
482
+ :param ignore_cache: Optional flag to ignore cache
483
+ :param app_lookup_cache: Optional app lookup cache
484
+ :raises ValueError: If no Algorand client is configured
485
+ :return: Typed application client instance
486
+
487
+ :example:
488
+ >>> client_manager = ClientManager(algod_client)
489
+ >>> typed_app_client = client_manager.get_typed_app_client_by_creator_and_name(
490
+ ... typed_client=MyAppClient,
491
+ ... creator_address="creator_address",
492
+ ... app_name="app_name",
493
+ ... )
494
+ """
495
+ if not self._algorand:
496
+ raise ValueError("Attempt to get app client from a ClientManager without an Algorand client")
497
+
498
+ return typed_client.from_creator_and_name(
499
+ creator_address=creator_address,
500
+ app_name=app_name,
501
+ default_sender=default_sender,
502
+ default_signer=default_signer,
503
+ ignore_cache=ignore_cache,
504
+ app_lookup_cache=app_lookup_cache,
505
+ algorand=self._algorand,
506
+ )
507
+
508
+ def get_typed_app_client_by_id(
509
+ self,
510
+ typed_client: type[TypedAppClientT],
511
+ *,
512
+ app_id: int,
513
+ app_name: str | None = None,
514
+ default_sender: str | None = None,
515
+ default_signer: TransactionSigner | None = None,
516
+ approval_source_map: ProgramSourceMap | None = None,
517
+ clear_source_map: ProgramSourceMap | None = None,
518
+ ) -> TypedAppClientT:
519
+ """Get a typed application client by ID.
520
+
521
+ :param typed_client: Typed client class
522
+ :param app_id: Application ID
523
+ :param app_name: Optional application name
524
+ :param default_sender: Optional default sender address
525
+ :param default_signer: Optional default transaction signer
526
+ :param approval_source_map: Optional approval program source map
527
+ :param clear_source_map: Optional clear program source map
528
+ :raises ValueError: If no Algorand client is configured
529
+ :return: Typed application client instance
530
+
531
+ :example:
532
+ >>> client_manager = ClientManager(algod_client)
533
+ >>> typed_app_client = client_manager.get_typed_app_client_by_id(
534
+ ... typed_client=MyAppClient,
535
+ ... app_id=1234567890,
536
+ ... )
537
+ """
538
+ if not self._algorand:
539
+ raise ValueError("Attempt to get app client from a ClientManager without an Algorand client")
540
+
541
+ return typed_client(
542
+ app_id=app_id,
543
+ app_name=app_name,
544
+ default_sender=default_sender,
545
+ default_signer=default_signer,
546
+ approval_source_map=approval_source_map,
547
+ clear_source_map=clear_source_map,
548
+ algorand=self._algorand,
549
+ )
550
+
551
+ def get_typed_app_client_by_network(
552
+ self,
553
+ typed_client: type[TypedAppClientT],
554
+ *,
555
+ app_name: str | None = None,
556
+ default_sender: str | None = None,
557
+ default_signer: TransactionSigner | None = None,
558
+ approval_source_map: ProgramSourceMap | None = None,
559
+ clear_source_map: ProgramSourceMap | None = None,
560
+ ) -> TypedAppClientT:
561
+ """Returns a new typed client, resolves the app ID for the current network.
562
+
563
+ Uses pre-determined network-specific app IDs specified in the ARC-56 app spec.
564
+ If no IDs are in the app spec or the network isn't recognised, an error is thrown.
565
+
566
+ :param typed_client: The typed client class to instantiate
567
+ :param app_name: Optional application name
568
+ :param default_sender: Optional default sender address
569
+ :param default_signer: Optional default transaction signer
570
+ :param approval_source_map: Optional approval program source map
571
+ :param clear_source_map: Optional clear program source map
572
+ :raises ValueError: If no Algorand client is configured
573
+ :return: The typed client instance
574
+
575
+ :example:
576
+ >>> client_manager = ClientManager(algod_client)
577
+ >>> typed_app_client = client_manager.get_typed_app_client_by_network(
578
+ ... typed_client=MyAppClient,
579
+ ... app_name="app_name",
580
+ ... )
581
+ """
582
+ if not self._algorand:
583
+ raise ValueError("Attempt to get app client from a ClientManager without an Algorand client")
584
+
585
+ return typed_client.from_network(
586
+ app_name=app_name,
587
+ default_sender=default_sender,
588
+ default_signer=default_signer,
589
+ approval_source_map=approval_source_map,
590
+ clear_source_map=clear_source_map,
591
+ algorand=self._algorand,
592
+ )
593
+
594
+ def get_typed_app_factory(
595
+ self,
596
+ typed_factory: type[TypedFactoryT],
597
+ *,
598
+ app_name: str | None = None,
599
+ default_sender: str | None = None,
600
+ default_signer: TransactionSigner | None = None,
601
+ version: str | None = None,
602
+ compilation_params: Optional["AppClientCompilationParams"] = None,
603
+ ) -> TypedFactoryT:
604
+ """Get a typed application factory.
605
+
606
+ :param typed_factory: Typed factory class
607
+ :param app_name: Optional application name
608
+ :param default_sender: Optional default sender address
609
+ :param default_signer: Optional default transaction signer
610
+ :param version: Optional version string
611
+ :param compilation_params: Optional compilation parameters
612
+ :raises ValueError: If no Algorand client is configured
613
+ :return: Typed application factory instance
614
+
615
+ :example:
616
+ >>> client_manager = ClientManager(algod_client)
617
+ >>> typed_app_factory = client_manager.get_typed_app_factory(
618
+ ... typed_factory=MyAppFactory,
619
+ ... app_name="app_name",
620
+ ... )
621
+ """
622
+ if not self._algorand:
623
+ raise ValueError("Attempt to get app factory from a ClientManager without an Algorand client")
624
+
625
+ return typed_factory(
626
+ algorand=self._algorand,
627
+ app_name=app_name,
628
+ default_sender=default_sender,
629
+ default_signer=default_signer,
630
+ version=version,
631
+ compilation_params=compilation_params,
632
+ )
633
+
634
+ @staticmethod
635
+ def get_config_from_environment_or_localnet() -> AlgoClientConfigs:
636
+ """Retrieve client configuration from environment variables or fallback to localnet defaults.
637
+
638
+ If ALGOD_SERVER is set in environment variables, it will use environment configuration,
639
+ otherwise it will use default localnet configuration.
640
+
641
+ :return: Configuration for algod, indexer, and optionally kmd
642
+
643
+ :example:
644
+ >>> client_manager = ClientManager(algod_client)
645
+ >>> config = client_manager.get_config_from_environment_or_localnet()
646
+ """
647
+ algod_server = os.getenv("ALGOD_SERVER")
648
+
649
+ if algod_server:
650
+ # Use environment configuration
651
+ algod_config = ClientManager.get_algod_config_from_environment()
652
+
653
+ # Only include indexer if INDEXER_SERVER is set
654
+ indexer_config = (
655
+ ClientManager.get_indexer_config_from_environment() if os.getenv("INDEXER_SERVER") else None
656
+ )
657
+
658
+ # Include KMD config only for local networks (not mainnet/testnet)
659
+ kmd_config = (
660
+ AlgoClientNetworkConfig(
661
+ server=algod_config.server, token=algod_config.token, port=os.getenv("KMD_PORT", "4002")
662
+ )
663
+ if not any(net in algod_server.lower() for net in ["mainnet", "testnet"])
664
+ else None
665
+ )
666
+ else:
667
+ # Use localnet defaults
668
+ algod_config = ClientManager.get_default_localnet_config("algod")
669
+ indexer_config = ClientManager.get_default_localnet_config("indexer")
670
+ kmd_config = ClientManager.get_default_localnet_config("kmd")
671
+
672
+ return AlgoClientConfigs(
673
+ algod_config=algod_config,
674
+ indexer_config=indexer_config,
675
+ kmd_config=kmd_config,
676
+ )
677
+
678
+ @staticmethod
679
+ def get_default_localnet_config(
680
+ config_or_port: Literal["algod", "indexer", "kmd"] | int,
681
+ ) -> AlgoClientNetworkConfig:
682
+ """Get default configuration for local network services.
683
+
684
+ :param config_or_port: Service name or port number
685
+ :return: Client configuration for local network
686
+
687
+ :example:
688
+ >>> client_manager = ClientManager(algod_client)
689
+ >>> config = client_manager.get_default_localnet_config("algod")
690
+ """
691
+ port = (
692
+ config_or_port
693
+ if isinstance(config_or_port, int)
694
+ else {"algod": 4001, "indexer": 8980, "kmd": 4002}[config_or_port]
695
+ )
696
+
697
+ return AlgoClientNetworkConfig(server="http://localhost", token="a" * 64, port=port)
698
+
699
+ @staticmethod
700
+ def get_algod_config_from_environment() -> AlgoClientNetworkConfig:
701
+ """Retrieve the algod configuration from environment variables.
702
+ Will raise an error if ALGOD_SERVER environment variable is not set
703
+
704
+ :return: Algod client configuration
705
+
706
+ :example:
707
+ >>> client_manager = ClientManager(algod_client)
708
+ >>> config = client_manager.get_algod_config_from_environment()
709
+ """
710
+ return _get_config_from_environment("ALGOD")
711
+
712
+ @staticmethod
713
+ def get_indexer_config_from_environment() -> AlgoClientNetworkConfig:
714
+ """Retrieve the indexer configuration from environment variables.
715
+ Will raise an error if INDEXER_SERVER environment variable is not set
716
+
717
+ :return: Indexer client configuration
718
+
719
+ :example:
720
+ >>> client_manager = ClientManager(algod_client)
721
+ >>> config = client_manager.get_indexer_config_from_environment()
722
+ """
723
+ return _get_config_from_environment("INDEXER")
724
+
725
+ @staticmethod
726
+ def get_kmd_config_from_environment() -> AlgoClientNetworkConfig:
727
+ """Retrieve the kmd configuration from environment variables.
728
+
729
+ :return: KMD client configuration
730
+
731
+ :example:
732
+ >>> client_manager = ClientManager(algod_client)
733
+ >>> config = client_manager.get_kmd_config_from_environment()
734
+ """
735
+ return _get_config_from_environment("KMD")
736
+
737
+ @staticmethod
738
+ def get_algonode_config(
739
+ network: Literal["testnet", "mainnet"], config: Literal["algod", "indexer"]
740
+ ) -> AlgoClientNetworkConfig:
741
+ """Returns the Algorand configuration to point to the free tier of the AlgoNode service.
742
+
743
+ :param network: Which network to connect to - TestNet or MainNet
744
+ :param config: Which algod config to return - Algod or Indexer
745
+ :return: Configuration for the specified network and service
746
+
747
+ :example:
748
+ >>> client_manager = ClientManager(algod_client)
749
+ >>> config = client_manager.get_algonode_config("testnet", "algod")
750
+ """
751
+ service_type = "api" if config == "algod" else "idx"
752
+ return AlgoClientNetworkConfig(
753
+ server=f"https://{network}-{service_type}.algonode.cloud",
754
+ port=443,
755
+ token="",
756
+ )