algokit-utils 3.0.0b1__py3-none-any.whl → 3.0.0b2__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 +2056 -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 +193 -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 +2293 -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.0b2.dist-info}/METADATA +12 -7
  67. algokit_utils-3.0.0b2.dist-info/RECORD +70 -0
  68. {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b2.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.0b2.dist-info}/LICENSE +0 -0
@@ -0,0 +1,21 @@
1
+ from algokit_utils.applications.app_spec.arc32 import (
2
+ AppSpecStateDict,
3
+ CallConfig,
4
+ DefaultArgumentDict,
5
+ DefaultArgumentType,
6
+ MethodConfigDict,
7
+ MethodHints,
8
+ OnCompleteActionName,
9
+ )
10
+ from algokit_utils.applications.app_spec.arc32 import Arc32Contract as ApplicationSpecification
11
+
12
+ __all__ = [
13
+ "AppSpecStateDict",
14
+ "ApplicationSpecification",
15
+ "CallConfig",
16
+ "DefaultArgumentDict",
17
+ "DefaultArgumentType",
18
+ "MethodConfigDict",
19
+ "MethodHints",
20
+ "OnCompleteActionName",
21
+ ]
@@ -0,0 +1,168 @@
1
+ import logging
2
+ from enum import Enum, auto
3
+
4
+ from algosdk.atomic_transaction_composer import AtomicTransactionComposer, TransactionWithSigner
5
+ from algosdk.constants import TX_GROUP_LIMIT
6
+ from algosdk.transaction import AssetTransferTxn
7
+ from algosdk.v2client.algod import AlgodClient
8
+ from typing_extensions import deprecated
9
+
10
+ from algokit_utils._legacy_v2.models import Account
11
+
12
+ __all__ = ["opt_in", "opt_out"]
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class ValidationType(Enum):
17
+ OPTIN = auto()
18
+ OPTOUT = auto()
19
+
20
+
21
+ def _ensure_account_is_valid(algod_client: "AlgodClient", account: Account) -> None:
22
+ try:
23
+ algod_client.account_info(account.address)
24
+ except Exception as err:
25
+ error_message = f"Account address{account.address} does not exist"
26
+ logger.debug(error_message)
27
+ raise err
28
+
29
+
30
+ def _ensure_asset_balance_conditions(
31
+ algod_client: "AlgodClient", account: Account, asset_ids: list, validation_type: ValidationType
32
+ ) -> None:
33
+ invalid_asset_ids = []
34
+ account_info = algod_client.account_info(account.address)
35
+ account_assets = account_info.get("assets", []) # type: ignore # noqa: PGH003
36
+ for asset_id in asset_ids:
37
+ asset_exists_in_account_info = any(asset["asset-id"] == asset_id for asset in account_assets)
38
+ if validation_type == ValidationType.OPTIN:
39
+ if asset_exists_in_account_info:
40
+ logger.debug(f"Asset {asset_id} is already opted in for account {account.address}")
41
+ invalid_asset_ids.append(asset_id)
42
+
43
+ elif validation_type == ValidationType.OPTOUT:
44
+ if not account_assets or not asset_exists_in_account_info:
45
+ logger.debug(f"Account {account.address} does not have asset {asset_id}")
46
+ invalid_asset_ids.append(asset_id)
47
+ else:
48
+ asset_balance = next((asset["amount"] for asset in account_assets if asset["asset-id"] == asset_id), 0)
49
+ if asset_balance != 0:
50
+ logger.debug(f"Asset {asset_id} balance is not zero")
51
+ invalid_asset_ids.append(asset_id)
52
+
53
+ if len(invalid_asset_ids) > 0:
54
+ action = "opted out" if validation_type == ValidationType.OPTOUT else "opted in"
55
+ condition_message = (
56
+ "their amount is zero and that the account has"
57
+ if validation_type == ValidationType.OPTOUT
58
+ else "they are valid and that the account has not"
59
+ )
60
+
61
+ error_message = (
62
+ f"Assets {invalid_asset_ids} cannot be {action}. Ensure that "
63
+ f"{condition_message} previously opted into them."
64
+ )
65
+ raise ValueError(error_message)
66
+
67
+
68
+ @deprecated(
69
+ "Use TransactionComposer.add_asset_opt_in() or AlgorandClient.asset.bulk_opt_in() instead. "
70
+ "Example: composer.add_asset_opt_in(AssetOptInParams(sender=account.address, asset_id=123))"
71
+ )
72
+ def opt_in(algod_client: "AlgodClient", account: Account, asset_ids: list[int]) -> dict[int, str]:
73
+ """
74
+ Opt-in to a list of assets on the Algorand blockchain. Before an account can receive a specific asset,
75
+ it must `opt-in` to receive it. An opt-in transaction places an asset holding of 0 into the account and increases
76
+ its minimum balance by [100,000 microAlgos](https://developer.algorand.org/docs/get-details/asa/#assets-overview).
77
+
78
+ :param algod_client: An instance of the AlgodClient class from the algosdk library.
79
+ :param account: An instance of the Account class representing the account that wants to opt-in to the assets.
80
+ :param asset_ids: A list of integers representing the asset IDs to opt-in to.
81
+ :return: A dictionary where the keys are the asset IDs and the values are the transaction IDs for opting-in to each asset.
82
+ :rtype: dict[int, str]
83
+ """
84
+ _ensure_account_is_valid(algod_client, account)
85
+ _ensure_asset_balance_conditions(algod_client, account, asset_ids, ValidationType.OPTIN)
86
+ suggested_params = algod_client.suggested_params()
87
+ result = {}
88
+ for i in range(0, len(asset_ids), TX_GROUP_LIMIT):
89
+ atc = AtomicTransactionComposer()
90
+ chunk = asset_ids[i : i + TX_GROUP_LIMIT]
91
+ for asset_id in chunk:
92
+ asset = algod_client.asset_info(asset_id)
93
+ xfer_txn = AssetTransferTxn(
94
+ sp=suggested_params,
95
+ sender=account.address,
96
+ receiver=account.address,
97
+ close_assets_to=None,
98
+ revocation_target=None,
99
+ amt=0,
100
+ note=f"opt in asset id ${asset_id}",
101
+ index=asset["index"], # type: ignore # noqa: PGH003
102
+ rekey_to=None,
103
+ )
104
+
105
+ transaction_with_signer = TransactionWithSigner(
106
+ txn=xfer_txn,
107
+ signer=account.signer,
108
+ )
109
+ atc.add_transaction(transaction_with_signer)
110
+ atc.execute(algod_client, 4)
111
+
112
+ for index, asset_id in enumerate(chunk):
113
+ result[asset_id] = atc.tx_ids[index]
114
+
115
+ return result
116
+
117
+
118
+ @deprecated(
119
+ "Use TransactionComposer.add_asset_opt_out() or AlgorandClient.asset.bulk_opt_out() instead. "
120
+ "Example: composer.add_asset_opt_out(AssetOptOutParams(sender=account.address, asset_id=123, creator=creator_address))"
121
+ )
122
+ def opt_out(algod_client: "AlgodClient", account: Account, asset_ids: list[int]) -> dict[int, str]:
123
+ """
124
+ Opt out from a list of Algorand Standard Assets (ASAs) by transferring them back to their creators.
125
+ The account also recovers the Minimum Balance Requirement for the asset (100,000 microAlgos)
126
+ The `optOut` function manages the opt-out process, permitting the account to discontinue holding a group of assets.
127
+
128
+ It's essential to note that an account can only opt_out of an asset if its balance of that asset is zero.
129
+
130
+ :param AlgodClient algod_client: An instance of the AlgodClient class from the algosdk library.
131
+ :param Account account: An instance of the Account class representing the account that wants to opt-out from the assets.
132
+ :param list[int] asset_ids: A list of integers representing the asset IDs to opt-out from.
133
+ :return dict[int, str]: A dictionary where the keys are the asset IDs and the values are the transaction IDs of
134
+ the executed transactions.
135
+ """
136
+ _ensure_account_is_valid(algod_client, account)
137
+ _ensure_asset_balance_conditions(algod_client, account, asset_ids, ValidationType.OPTOUT)
138
+ suggested_params = algod_client.suggested_params()
139
+ result = {}
140
+ for i in range(0, len(asset_ids), TX_GROUP_LIMIT):
141
+ atc = AtomicTransactionComposer()
142
+ chunk = asset_ids[i : i + TX_GROUP_LIMIT]
143
+ for asset_id in chunk:
144
+ asset = algod_client.asset_info(asset_id)
145
+ asset_creator = asset["params"]["creator"] # type: ignore # noqa: PGH003
146
+ xfer_txn = AssetTransferTxn(
147
+ sp=suggested_params,
148
+ sender=account.address,
149
+ receiver=account.address,
150
+ close_assets_to=asset_creator,
151
+ revocation_target=None,
152
+ amt=0,
153
+ note=f"opt out asset id ${asset_id}",
154
+ index=asset["index"], # type: ignore # noqa: PGH003
155
+ rekey_to=None,
156
+ )
157
+
158
+ transaction_with_signer = TransactionWithSigner(
159
+ txn=xfer_txn,
160
+ signer=account.signer,
161
+ )
162
+ atc.add_transaction(transaction_with_signer)
163
+ atc.execute(algod_client, 4)
164
+
165
+ for index, asset_id in enumerate(chunk):
166
+ result[asset_id] = atc.tx_ids[index]
167
+
168
+ return result
@@ -0,0 +1,28 @@
1
+ """
2
+ This module contains common classes and methods that are reused in more than one file.
3
+ """
4
+
5
+ import base64
6
+ import typing
7
+
8
+ from algosdk.source_map import SourceMap
9
+
10
+ from algokit_utils._legacy_v2.deploy import strip_comments
11
+
12
+ if typing.TYPE_CHECKING:
13
+ from algosdk.v2client.algod import AlgodClient
14
+
15
+
16
+ class Program:
17
+ """A compiled TEAL program
18
+
19
+ :param program: The TEAL program source code
20
+ :param client: The AlgodClient instance to use for compiling the program
21
+ """
22
+
23
+ def __init__(self, program: str, client: "AlgodClient"):
24
+ self.teal = program
25
+ result: dict = client.compile(strip_comments(self.teal), source_map=True)
26
+ self.raw_binary = base64.b64decode(result["result"])
27
+ self.binary_hash: str = result["hash"]
28
+ self.source_map = SourceMap(result["sourcemap"])