algokit-utils 3.0.0b1__py3-none-any.whl → 3.0.0b3__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.

Potentially problematic release.


This version of algokit-utils might be problematic. Click here for more details.

Files changed (70) hide show
  1. algokit_utils/__init__.py +23 -183
  2. algokit_utils/_debugging.py +123 -97
  3. algokit_utils/_legacy_v2/__init__.py +177 -0
  4. algokit_utils/{_ensure_funded.py → _legacy_v2/_ensure_funded.py} +19 -18
  5. algokit_utils/{_transfer.py → _legacy_v2/_transfer.py} +24 -23
  6. algokit_utils/_legacy_v2/account.py +203 -0
  7. algokit_utils/_legacy_v2/application_client.py +1471 -0
  8. algokit_utils/_legacy_v2/application_specification.py +21 -0
  9. algokit_utils/_legacy_v2/asset.py +168 -0
  10. algokit_utils/_legacy_v2/common.py +28 -0
  11. algokit_utils/_legacy_v2/deploy.py +822 -0
  12. algokit_utils/_legacy_v2/logic_error.py +14 -0
  13. algokit_utils/{models.py → _legacy_v2/models.py} +19 -142
  14. algokit_utils/_legacy_v2/network_clients.py +140 -0
  15. algokit_utils/account.py +12 -183
  16. algokit_utils/accounts/__init__.py +2 -0
  17. algokit_utils/accounts/account_manager.py +909 -0
  18. algokit_utils/accounts/kmd_account_manager.py +159 -0
  19. algokit_utils/algorand.py +265 -0
  20. algokit_utils/application_client.py +9 -1453
  21. algokit_utils/application_specification.py +39 -197
  22. algokit_utils/applications/__init__.py +7 -0
  23. algokit_utils/applications/abi.py +276 -0
  24. algokit_utils/applications/app_client.py +2054 -0
  25. algokit_utils/applications/app_deployer.py +600 -0
  26. algokit_utils/applications/app_factory.py +826 -0
  27. algokit_utils/applications/app_manager.py +470 -0
  28. algokit_utils/applications/app_spec/__init__.py +2 -0
  29. algokit_utils/applications/app_spec/arc32.py +207 -0
  30. algokit_utils/applications/app_spec/arc56.py +1023 -0
  31. algokit_utils/applications/enums.py +40 -0
  32. algokit_utils/asset.py +32 -168
  33. algokit_utils/assets/__init__.py +1 -0
  34. algokit_utils/assets/asset_manager.py +320 -0
  35. algokit_utils/beta/_utils.py +36 -0
  36. algokit_utils/beta/account_manager.py +4 -195
  37. algokit_utils/beta/algorand_client.py +4 -314
  38. algokit_utils/beta/client_manager.py +5 -74
  39. algokit_utils/beta/composer.py +5 -712
  40. algokit_utils/clients/__init__.py +2 -0
  41. algokit_utils/clients/client_manager.py +656 -0
  42. algokit_utils/clients/dispenser_api_client.py +192 -0
  43. algokit_utils/common.py +8 -26
  44. algokit_utils/config.py +71 -18
  45. algokit_utils/deploy.py +7 -892
  46. algokit_utils/dispenser_api.py +8 -176
  47. algokit_utils/errors/__init__.py +1 -0
  48. algokit_utils/errors/logic_error.py +121 -0
  49. algokit_utils/logic_error.py +7 -80
  50. algokit_utils/models/__init__.py +8 -0
  51. algokit_utils/models/account.py +197 -0
  52. algokit_utils/models/amount.py +198 -0
  53. algokit_utils/models/application.py +61 -0
  54. algokit_utils/models/network.py +25 -0
  55. algokit_utils/models/simulate.py +11 -0
  56. algokit_utils/models/state.py +59 -0
  57. algokit_utils/models/transaction.py +100 -0
  58. algokit_utils/network_clients.py +7 -152
  59. algokit_utils/protocols/__init__.py +2 -0
  60. algokit_utils/protocols/account.py +22 -0
  61. algokit_utils/protocols/typed_clients.py +108 -0
  62. algokit_utils/transactions/__init__.py +3 -0
  63. algokit_utils/transactions/transaction_composer.py +2287 -0
  64. algokit_utils/transactions/transaction_creator.py +156 -0
  65. algokit_utils/transactions/transaction_sender.py +574 -0
  66. {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/METADATA +13 -8
  67. algokit_utils-3.0.0b3.dist-info/RECORD +70 -0
  68. {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/WHEEL +1 -1
  69. algokit_utils-3.0.0b1.dist-info/RECORD +0 -24
  70. {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/LICENSE +0 -0
@@ -1,200 +1,9 @@
1
- from collections.abc import Callable
2
- from dataclasses import dataclass
3
1
  from typing import Any
4
2
 
5
- from algokit_utils.account import get_dispenser_account, get_kmd_wallet_account, get_localnet_default_account
6
- from algosdk.account import generate_account
7
- from algosdk.atomic_transaction_composer import AccountTransactionSigner, TransactionSigner
8
- from typing_extensions import Self
3
+ from algokit_utils.beta._utils import handle_getattr
9
4
 
10
- from .client_manager import ClientManager
11
5
 
6
+ def __getattr__(name: str) -> Any: # noqa: ANN401
7
+ """Handle deprecated imports of parameter classes"""
12
8
 
13
- @dataclass
14
- class AddressAndSigner:
15
- address: str
16
- signer: TransactionSigner
17
-
18
-
19
- class AccountManager:
20
- """Creates and keeps track of addresses and signers"""
21
-
22
- def __init__(self, client_manager: ClientManager):
23
- """
24
- Create a new account manager.
25
-
26
- :param client_manager: The ClientManager client to use for algod and kmd clients
27
- """
28
- self._client_manager = client_manager
29
- self._accounts = dict[str, TransactionSigner]()
30
- self._default_signer: TransactionSigner | None = None
31
-
32
- def set_default_signer(self, signer: TransactionSigner) -> Self:
33
- """
34
- Sets the default signer to use if no other signer is specified.
35
-
36
- :param signer: The signer to use, either a `TransactionSigner` or a `TransactionSignerAccount`
37
- :return: The `AccountManager` so method calls can be chained
38
- """
39
- self._default_signer = signer
40
- return self
41
-
42
- def set_signer(self, sender: str, signer: TransactionSigner) -> Self:
43
- """
44
- Tracks the given account for later signing.
45
-
46
- :param sender: The sender address to use this signer for
47
- :param signer: The signer to sign transactions with for the given sender
48
- :return: The AccountCreator instance for method chaining
49
- """
50
- self._accounts[sender] = signer
51
- return self
52
-
53
- def get_signer(self, sender: str) -> TransactionSigner:
54
- """
55
- Returns the `TransactionSigner` for the given sender address.
56
-
57
- If no signer has been registered for that address then the default signer is used if registered.
58
-
59
- :param sender: The sender address
60
- :return: The `TransactionSigner` or throws an error if not found
61
- """
62
- signer = self._accounts.get(sender, None) or self._default_signer
63
- if not signer:
64
- raise ValueError(f"No signer found for address {sender}")
65
- return signer
66
-
67
- def get_information(self, sender: str) -> dict[str, Any]:
68
- """
69
- Returns the given sender account's current status, balance and spendable amounts.
70
-
71
- Example:
72
- address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA"
73
- account_info = account.get_information(address)
74
-
75
- `Response data schema details <https://developer.algorand.org/docs/rest-apis/algod/#get-v2accountsaddress>`_
76
-
77
- :param sender: The address of the sender/account to look up
78
- :return: The account information
79
- """
80
- info = self._client_manager.algod.account_info(sender)
81
- assert isinstance(info, dict)
82
- return info
83
-
84
- def get_asset_information(self, sender: str, asset_id: int) -> dict[str, Any]:
85
- info = self._client_manager.algod.account_asset_info(sender, asset_id)
86
- assert isinstance(info, dict)
87
- return info
88
-
89
- # TODO
90
- # def from_mnemonic(self, mnemonic_secret: str, sender: Optional[str] = None) -> AddrAndSigner:
91
- # """
92
- # Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.
93
-
94
- # Example:
95
- # account = account.from_mnemonic("mnemonic secret ...")
96
- # rekeyed_account = account.from_mnemonic("mnemonic secret ...", "SENDERADDRESS...")
97
-
98
- # :param mnemonic_secret: The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,
99
- # never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.
100
- # :param sender: The optional sender address to use this signer for (aka a rekeyed account)
101
- # :return: The account
102
- # """
103
- # account = mnemonic_account(mnemonic_secret)
104
- # return self.signer_account(rekeyed_account(account, sender) if sender else account)
105
-
106
- def from_kmd(
107
- self,
108
- name: str,
109
- predicate: Callable[[dict[str, Any]], bool] | None = None,
110
- ) -> AddressAndSigner:
111
- """
112
- Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).
113
-
114
- Example (Get default funded account in a LocalNet):
115
- default_dispenser_account = account.from_kmd('unencrypted-default-wallet',
116
- lambda a: a['status'] != 'Offline' and a['amount'] > 1_000_000_000
117
- )
118
-
119
- :param name: The name of the wallet to retrieve an account from
120
- :param predicate: An optional filter to use to find the account (otherwise it will return a random account from the wallet)
121
- :return: The account
122
- """
123
- account = get_kmd_wallet_account(
124
- name=name, predicate=predicate, client=self._client_manager.algod, kmd_client=self._client_manager.kmd
125
- )
126
- if not account:
127
- raise ValueError(f"Unable to find KMD account {name}{' with predicate' if predicate else ''}")
128
-
129
- self.set_signer(account.address, account.signer)
130
- return AddressAndSigner(address=account.address, signer=account.signer)
131
-
132
- # TODO
133
- # def multisig(
134
- # self, multisig_params: algosdk.MultisigMetadata, signing_accounts: Union[algosdk.Account, SigningAccount]
135
- # ) -> TransactionSignerAccount:
136
- # """
137
- # Tracks and returns an account that supports partial or full multisig signing.
138
-
139
- # Example:
140
- # account = account.multisig(
141
- # {
142
- # "version": 1,
143
- # "threshold": 1,
144
- # "addrs": ["ADDRESS1...", "ADDRESS2..."]
145
- # },
146
- # account.from_environment('ACCOUNT1')
147
- # )
148
-
149
- # :param multisig_params: The parameters that define the multisig account
150
- # :param signing_accounts: The signers that are currently present
151
- # :return: A multisig account wrapper
152
- # """
153
- # return self.signer_account(multisig_account(multisig_params, signing_accounts))
154
-
155
- def random(self) -> AddressAndSigner:
156
- """
157
- Tracks and returns a new, random Algorand account with secret key loaded.
158
-
159
- Example:
160
- account = account.random()
161
-
162
- :return: The account
163
- """
164
- (sk, addr) = generate_account() # type: ignore[no-untyped-call]
165
- signer = AccountTransactionSigner(sk)
166
-
167
- self.set_signer(addr, signer)
168
-
169
- return AddressAndSigner(address=addr, signer=signer)
170
-
171
- def dispenser(self) -> AddressAndSigner:
172
- """
173
- Returns an account (with private key loaded) that can act as a dispenser.
174
-
175
- Example:
176
- account = account.dispenser()
177
-
178
- If running on LocalNet then it will return the default dispenser account automatically,
179
- otherwise it will load the account mnemonic stored in os.environ['DISPENSER_MNEMONIC'].
180
-
181
- :return: The account
182
- """
183
- acct = get_dispenser_account(self._client_manager.algod)
184
-
185
- self.set_signer(acct.address, acct.signer)
186
-
187
- return AddressAndSigner(address=acct.address, signer=acct.signer)
188
-
189
- def localnet_dispenser(self) -> AddressAndSigner:
190
- """
191
- Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).
192
-
193
- Example:
194
- account = account.localnet_dispenser()
195
-
196
- :return: The account
197
- """
198
- acct = get_localnet_default_account(self._client_manager.algod)
199
- self.set_signer(acct.address, acct.signer)
200
- return AddressAndSigner(address=acct.address, signer=acct.signer)
9
+ handle_getattr(name)
@@ -1,319 +1,9 @@
1
- import copy
2
- import time
3
- from collections.abc import Callable
4
- from dataclasses import dataclass
5
1
  from typing import Any
6
2
 
7
- from algokit_utils.beta.account_manager import AccountManager
8
- from algokit_utils.beta.client_manager import AlgoSdkClients, ClientManager
9
- from algokit_utils.beta.composer import (
10
- AlgokitComposer,
11
- AppCallParams,
12
- AssetConfigParams,
13
- AssetCreateParams,
14
- AssetDestroyParams,
15
- AssetFreezeParams,
16
- AssetOptInParams,
17
- AssetTransferParams,
18
- MethodCallParams,
19
- OnlineKeyRegParams,
20
- PayParams,
21
- )
22
- from algokit_utils.network_clients import (
23
- AlgoClientConfigs,
24
- get_algod_client,
25
- get_algonode_config,
26
- get_default_localnet_config,
27
- get_indexer_client,
28
- get_kmd_client,
29
- )
30
- from algosdk.atomic_transaction_composer import AtomicTransactionResponse, TransactionSigner
31
- from algosdk.transaction import SuggestedParams, Transaction, wait_for_confirmation
32
- from typing_extensions import Self
3
+ from algokit_utils.beta._utils import handle_getattr
33
4
 
34
- __all__ = [
35
- "AlgorandClient",
36
- "AssetCreateParams",
37
- "AssetOptInParams",
38
- "MethodCallParams",
39
- "PayParams",
40
- "AssetFreezeParams",
41
- "AssetConfigParams",
42
- "AssetDestroyParams",
43
- "AppCallParams",
44
- "OnlineKeyRegParams",
45
- "AssetTransferParams",
46
- ]
47
5
 
6
+ def __getattr__(name: str) -> Any: # noqa: ANN401
7
+ """Handle deprecated imports of parameter classes"""
48
8
 
49
- @dataclass
50
- class AlgorandClientSendMethods:
51
- """
52
- Methods used to send a transaction to the network and wait for confirmation
53
- """
54
-
55
- payment: Callable[[PayParams], dict[str, Any]]
56
- asset_create: Callable[[AssetCreateParams], dict[str, Any]]
57
- asset_config: Callable[[AssetConfigParams], dict[str, Any]]
58
- asset_freeze: Callable[[AssetFreezeParams], dict[str, Any]]
59
- asset_destroy: Callable[[AssetDestroyParams], dict[str, Any]]
60
- asset_transfer: Callable[[AssetTransferParams], dict[str, Any]]
61
- app_call: Callable[[AppCallParams], dict[str, Any]]
62
- online_key_reg: Callable[[OnlineKeyRegParams], dict[str, Any]]
63
- method_call: Callable[[MethodCallParams], dict[str, Any]]
64
- asset_opt_in: Callable[[AssetOptInParams], dict[str, Any]]
65
-
66
-
67
- @dataclass
68
- class AlgorandClientTransactionMethods:
69
- """
70
- Methods used to form a transaction without signing or sending to the network
71
- """
72
-
73
- payment: Callable[[PayParams], Transaction]
74
- asset_create: Callable[[AssetCreateParams], Transaction]
75
- asset_config: Callable[[AssetConfigParams], Transaction]
76
- asset_freeze: Callable[[AssetFreezeParams], Transaction]
77
- asset_destroy: Callable[[AssetDestroyParams], Transaction]
78
- asset_transfer: Callable[[AssetTransferParams], Transaction]
79
- app_call: Callable[[AppCallParams], Transaction]
80
- online_key_reg: Callable[[OnlineKeyRegParams], Transaction]
81
- method_call: Callable[[MethodCallParams], list[Transaction]]
82
- asset_opt_in: Callable[[AssetOptInParams], Transaction]
83
-
84
-
85
- class AlgorandClient:
86
- """A client that brokers easy access to Algorand functionality."""
87
-
88
- def __init__(self, config: AlgoClientConfigs | AlgoSdkClients):
89
- self._client_manager: ClientManager = ClientManager(config)
90
- self._account_manager: AccountManager = AccountManager(self._client_manager)
91
-
92
- self._cached_suggested_params: SuggestedParams | None = None
93
- self._cached_suggested_params_expiry: float | None = None
94
- self._cached_suggested_params_timeout: int = 3_000 # three seconds
95
-
96
- self._default_validity_window: int = 10
97
-
98
- def _unwrap_single_send_result(self, results: AtomicTransactionResponse) -> dict[str, Any]:
99
- return {
100
- "confirmation": wait_for_confirmation(self._client_manager.algod, results.tx_ids[0]),
101
- "tx_id": results.tx_ids[0],
102
- }
103
-
104
- def set_default_validity_window(self, validity_window: int) -> Self:
105
- """
106
- Sets the default validity window for transactions.
107
-
108
- :param validity_window: The number of rounds between the first and last valid rounds
109
- :return: The `AlgorandClient` so method calls can be chained
110
- """
111
- self._default_validity_window = validity_window
112
- return self
113
-
114
- def set_default_signer(self, signer: TransactionSigner) -> Self:
115
- """
116
- Sets the default signer to use if no other signer is specified.
117
-
118
- :param signer: The signer to use, either a `TransactionSigner` or a `TransactionSignerAccount`
119
- :return: The `AlgorandClient` so method calls can be chained
120
- """
121
- self._account_manager.set_default_signer(signer)
122
- return self
123
-
124
- def set_signer(self, sender: str, signer: TransactionSigner) -> Self:
125
- """
126
- Tracks the given account for later signing.
127
-
128
- :param sender: The sender address to use this signer for
129
- :param signer: The signer to sign transactions with for the given sender
130
- :return: The `AlgorandClient` so method calls can be chained
131
- """
132
- self._account_manager.set_signer(sender, signer)
133
- return self
134
-
135
- def set_suggested_params(self, suggested_params: SuggestedParams, until: float | None = None) -> Self:
136
- """
137
- Sets a cache value to use for suggested params.
138
-
139
- :param suggested_params: The suggested params to use
140
- :param until: A timestamp until which to cache, or if not specified then the timeout is used
141
- :return: The `AlgorandClient` so method calls can be chained
142
- """
143
- self._cached_suggested_params = suggested_params
144
- self._cached_suggested_params_expiry = until or time.time() + self._cached_suggested_params_timeout
145
- return self
146
-
147
- def set_suggested_params_timeout(self, timeout: int) -> Self:
148
- """
149
- Sets the timeout for caching suggested params.
150
-
151
- :param timeout: The timeout in milliseconds
152
- :return: The `AlgorandClient` so method calls can be chained
153
- """
154
- self._cached_suggested_params_timeout = timeout
155
- return self
156
-
157
- def get_suggested_params(self) -> SuggestedParams:
158
- """Get suggested params for a transaction (either cached or from algod if the cache is stale or empty)"""
159
- if self._cached_suggested_params and (
160
- self._cached_suggested_params_expiry is None or self._cached_suggested_params_expiry > time.time()
161
- ):
162
- return copy.deepcopy(self._cached_suggested_params)
163
-
164
- self._cached_suggested_params = self._client_manager.algod.suggested_params()
165
- self._cached_suggested_params_expiry = time.time() + self._cached_suggested_params_timeout
166
-
167
- return copy.deepcopy(self._cached_suggested_params)
168
-
169
- @property
170
- def client(self) -> ClientManager:
171
- """Get clients, including algosdk clients and app clients."""
172
- return self._client_manager
173
-
174
- @property
175
- def account(self) -> AccountManager:
176
- """Get or create accounts that can sign transactions."""
177
- return self._account_manager
178
-
179
- def new_group(self) -> AlgokitComposer:
180
- """Start a new `AlgokitComposer` transaction group"""
181
- return AlgokitComposer(
182
- algod=self.client.algod,
183
- get_signer=lambda addr: self.account.get_signer(addr),
184
- get_suggested_params=self.get_suggested_params,
185
- default_validity_window=self._default_validity_window,
186
- )
187
-
188
- @property
189
- def send(self) -> AlgorandClientSendMethods:
190
- """Methods for sending a transaction and waiting for confirmation"""
191
- return AlgorandClientSendMethods(
192
- payment=lambda params: self._unwrap_single_send_result(self.new_group().add_payment(params).execute()),
193
- asset_create=lambda params: self._unwrap_single_send_result(
194
- self.new_group().add_asset_create(params).execute()
195
- ),
196
- asset_config=lambda params: self._unwrap_single_send_result(
197
- self.new_group().add_asset_config(params).execute()
198
- ),
199
- asset_freeze=lambda params: self._unwrap_single_send_result(
200
- self.new_group().add_asset_freeze(params).execute()
201
- ),
202
- asset_destroy=lambda params: self._unwrap_single_send_result(
203
- self.new_group().add_asset_destroy(params).execute()
204
- ),
205
- asset_transfer=lambda params: self._unwrap_single_send_result(
206
- self.new_group().add_asset_transfer(params).execute()
207
- ),
208
- app_call=lambda params: self._unwrap_single_send_result(self.new_group().add_app_call(params).execute()),
209
- online_key_reg=lambda params: self._unwrap_single_send_result(
210
- self.new_group().add_online_key_reg(params).execute()
211
- ),
212
- method_call=lambda params: self._unwrap_single_send_result(
213
- self.new_group().add_method_call(params).execute()
214
- ),
215
- asset_opt_in=lambda params: self._unwrap_single_send_result(
216
- self.new_group().add_asset_opt_in(params).execute()
217
- ),
218
- )
219
-
220
- @property
221
- def transactions(self) -> AlgorandClientTransactionMethods:
222
- """Methods for building transactions"""
223
-
224
- return AlgorandClientTransactionMethods(
225
- payment=lambda params: self.new_group().add_payment(params).build_group()[0].txn,
226
- asset_create=lambda params: self.new_group().add_asset_create(params).build_group()[0].txn,
227
- asset_config=lambda params: self.new_group().add_asset_config(params).build_group()[0].txn,
228
- asset_freeze=lambda params: self.new_group().add_asset_freeze(params).build_group()[0].txn,
229
- asset_destroy=lambda params: self.new_group().add_asset_destroy(params).build_group()[0].txn,
230
- asset_transfer=lambda params: self.new_group().add_asset_transfer(params).build_group()[0].txn,
231
- app_call=lambda params: self.new_group().add_app_call(params).build_group()[0].txn,
232
- online_key_reg=lambda params: self.new_group().add_online_key_reg(params).build_group()[0].txn,
233
- method_call=lambda params: [txn.txn for txn in self.new_group().add_method_call(params).build_group()],
234
- asset_opt_in=lambda params: self.new_group().add_asset_opt_in(params).build_group()[0].txn,
235
- )
236
-
237
- @staticmethod
238
- def default_local_net() -> "AlgorandClient":
239
- """
240
- Returns an `AlgorandClient` pointing at default LocalNet ports and API token.
241
-
242
- :return: The `AlgorandClient`
243
- """
244
- return AlgorandClient(
245
- AlgoClientConfigs(
246
- algod_config=get_default_localnet_config("algod"),
247
- indexer_config=get_default_localnet_config("indexer"),
248
- kmd_config=get_default_localnet_config("kmd"),
249
- )
250
- )
251
-
252
- @staticmethod
253
- def test_net() -> "AlgorandClient":
254
- """
255
- Returns an `AlgorandClient` pointing at TestNet using AlgoNode.
256
-
257
- :return: The `AlgorandClient`
258
- """
259
- return AlgorandClient(
260
- AlgoClientConfigs(
261
- algod_config=get_algonode_config("testnet", "algod", ""),
262
- indexer_config=get_algonode_config("testnet", "indexer", ""),
263
- kmd_config=None,
264
- )
265
- )
266
-
267
- @staticmethod
268
- def main_net() -> "AlgorandClient":
269
- """
270
- Returns an `AlgorandClient` pointing at MainNet using AlgoNode.
271
-
272
- :return: The `AlgorandClient`
273
- """
274
- return AlgorandClient(
275
- AlgoClientConfigs(
276
- algod_config=get_algonode_config("mainnet", "algod", ""),
277
- indexer_config=get_algonode_config("mainnet", "indexer", ""),
278
- kmd_config=None,
279
- )
280
- )
281
-
282
- @staticmethod
283
- def from_clients(clients: AlgoSdkClients) -> "AlgorandClient":
284
- """
285
- Returns an `AlgorandClient` pointing to the given client(s).
286
-
287
- :param clients: The clients to use
288
- :return: The `AlgorandClient`
289
- """
290
- return AlgorandClient(clients)
291
-
292
- @staticmethod
293
- def from_environment() -> "AlgorandClient":
294
- """
295
- Returns an `AlgorandClient` loading the configuration from environment variables.
296
-
297
- Retrieve configurations from environment variables when defined or get defaults.
298
-
299
- Expects to be called from a Python environment.
300
-
301
- :return: The `AlgorandClient`
302
- """
303
- return AlgorandClient(
304
- AlgoSdkClients(
305
- algod=get_algod_client(),
306
- kmd=get_kmd_client(),
307
- indexer=get_indexer_client(),
308
- )
309
- )
310
-
311
- @staticmethod
312
- def from_config(config: AlgoClientConfigs) -> "AlgorandClient":
313
- """
314
- Returns an `AlgorandClient` from the given config.
315
-
316
- :param config: The config to use
317
- :return: The `AlgorandClient`
318
- """
319
- return AlgorandClient(config)
9
+ handle_getattr(name)
@@ -1,78 +1,9 @@
1
- import algosdk
2
- from algokit_utils.dispenser_api import TestNetDispenserApiClient
3
- from algokit_utils.network_clients import AlgoClientConfigs, get_algod_client, get_indexer_client, get_kmd_client
4
- from algosdk.kmd import KMDClient
5
- from algosdk.v2client.algod import AlgodClient
6
- from algosdk.v2client.indexer import IndexerClient
1
+ from typing import Any
7
2
 
3
+ from algokit_utils.beta._utils import handle_getattr
8
4
 
9
- class AlgoSdkClients:
10
- """
11
- Clients from algosdk that interact with the official Algorand APIs.
12
5
 
13
- Attributes:
14
- algod (AlgodClient): Algod client, see https://developer.algorand.org/docs/rest-apis/algod/
15
- indexer (Optional[IndexerClient]): Optional indexer client, see https://developer.algorand.org/docs/rest-apis/indexer/
16
- kmd (Optional[KMDClient]): Optional KMD client, see https://developer.algorand.org/docs/rest-apis/kmd/
17
- """
6
+ def __getattr__(name: str) -> Any: # noqa: ANN401
7
+ """Handle deprecated imports of parameter classes"""
18
8
 
19
- def __init__(
20
- self,
21
- algod: algosdk.v2client.algod.AlgodClient,
22
- indexer: IndexerClient | None = None,
23
- kmd: KMDClient | None = None,
24
- ):
25
- self.algod = algod
26
- self.indexer = indexer
27
- self.kmd = kmd
28
-
29
-
30
- class ClientManager:
31
- """
32
- Exposes access to various API clients.
33
-
34
- Args:
35
- clients_or_config (Union[AlgoConfig, AlgoSdkClients]): algosdk clients or config for interacting with the official Algorand APIs.
36
- """
37
-
38
- def __init__(self, clients_or_configs: AlgoClientConfigs | AlgoSdkClients):
39
- if isinstance(clients_or_configs, AlgoSdkClients):
40
- _clients = clients_or_configs
41
- elif isinstance(clients_or_configs, AlgoClientConfigs):
42
- _clients = AlgoSdkClients(
43
- algod=get_algod_client(clients_or_configs.algod_config),
44
- indexer=get_indexer_client(clients_or_configs.indexer_config)
45
- if clients_or_configs.indexer_config
46
- else None,
47
- kmd=get_kmd_client(clients_or_configs.kmd_config) if clients_or_configs.kmd_config else None,
48
- )
49
- self._algod = _clients.algod
50
- self._indexer = _clients.indexer
51
- self._kmd = _clients.kmd
52
-
53
- @property
54
- def algod(self) -> AlgodClient:
55
- """Returns an algosdk Algod API client."""
56
- return self._algod
57
-
58
- @property
59
- def indexer(self) -> IndexerClient:
60
- """Returns an algosdk Indexer API client or raises an error if it's not been provided."""
61
- if not self._indexer:
62
- raise ValueError("Attempt to use Indexer client in AlgoKit instance with no Indexer configured")
63
- return self._indexer
64
-
65
- @property
66
- def kmd(self) -> KMDClient:
67
- """Returns an algosdk KMD API client or raises an error if it's not been provided."""
68
- if not self._kmd:
69
- raise ValueError("Attempt to use Kmd client in AlgoKit instance with no Kmd configured")
70
- return self._kmd
71
-
72
- def get_testnet_dispenser(
73
- self, auth_token: str | None = None, request_timeout: int | None = None
74
- ) -> TestNetDispenserApiClient:
75
- if request_timeout:
76
- return TestNetDispenserApiClient(auth_token=auth_token, request_timeout=request_timeout)
77
-
78
- return TestNetDispenserApiClient(auth_token=auth_token)
9
+ handle_getattr(name)