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.
- algokit_utils/__init__.py +23 -183
- algokit_utils/_debugging.py +123 -97
- algokit_utils/_legacy_v2/__init__.py +177 -0
- algokit_utils/{_ensure_funded.py → _legacy_v2/_ensure_funded.py} +19 -18
- algokit_utils/{_transfer.py → _legacy_v2/_transfer.py} +24 -23
- algokit_utils/_legacy_v2/account.py +203 -0
- algokit_utils/_legacy_v2/application_client.py +1471 -0
- algokit_utils/_legacy_v2/application_specification.py +21 -0
- algokit_utils/_legacy_v2/asset.py +168 -0
- algokit_utils/_legacy_v2/common.py +28 -0
- algokit_utils/_legacy_v2/deploy.py +822 -0
- algokit_utils/_legacy_v2/logic_error.py +14 -0
- algokit_utils/{models.py → _legacy_v2/models.py} +19 -142
- algokit_utils/_legacy_v2/network_clients.py +140 -0
- algokit_utils/account.py +12 -183
- algokit_utils/accounts/__init__.py +2 -0
- algokit_utils/accounts/account_manager.py +909 -0
- algokit_utils/accounts/kmd_account_manager.py +159 -0
- algokit_utils/algorand.py +265 -0
- algokit_utils/application_client.py +9 -1453
- algokit_utils/application_specification.py +39 -197
- algokit_utils/applications/__init__.py +7 -0
- algokit_utils/applications/abi.py +276 -0
- algokit_utils/applications/app_client.py +2054 -0
- algokit_utils/applications/app_deployer.py +600 -0
- algokit_utils/applications/app_factory.py +826 -0
- algokit_utils/applications/app_manager.py +470 -0
- algokit_utils/applications/app_spec/__init__.py +2 -0
- algokit_utils/applications/app_spec/arc32.py +207 -0
- algokit_utils/applications/app_spec/arc56.py +1023 -0
- algokit_utils/applications/enums.py +40 -0
- algokit_utils/asset.py +32 -168
- algokit_utils/assets/__init__.py +1 -0
- algokit_utils/assets/asset_manager.py +320 -0
- algokit_utils/beta/_utils.py +36 -0
- algokit_utils/beta/account_manager.py +4 -195
- algokit_utils/beta/algorand_client.py +4 -314
- algokit_utils/beta/client_manager.py +5 -74
- algokit_utils/beta/composer.py +5 -712
- algokit_utils/clients/__init__.py +2 -0
- algokit_utils/clients/client_manager.py +656 -0
- algokit_utils/clients/dispenser_api_client.py +192 -0
- algokit_utils/common.py +8 -26
- algokit_utils/config.py +71 -18
- algokit_utils/deploy.py +7 -892
- algokit_utils/dispenser_api.py +8 -176
- algokit_utils/errors/__init__.py +1 -0
- algokit_utils/errors/logic_error.py +121 -0
- algokit_utils/logic_error.py +7 -80
- algokit_utils/models/__init__.py +8 -0
- algokit_utils/models/account.py +197 -0
- algokit_utils/models/amount.py +198 -0
- algokit_utils/models/application.py +61 -0
- algokit_utils/models/network.py +25 -0
- algokit_utils/models/simulate.py +11 -0
- algokit_utils/models/state.py +59 -0
- algokit_utils/models/transaction.py +100 -0
- algokit_utils/network_clients.py +7 -152
- algokit_utils/protocols/__init__.py +2 -0
- algokit_utils/protocols/account.py +22 -0
- algokit_utils/protocols/typed_clients.py +108 -0
- algokit_utils/transactions/__init__.py +3 -0
- algokit_utils/transactions/transaction_composer.py +2287 -0
- algokit_utils/transactions/transaction_creator.py +156 -0
- algokit_utils/transactions/transaction_sender.py +574 -0
- {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/METADATA +13 -8
- algokit_utils-3.0.0b3.dist-info/RECORD +70 -0
- {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/WHEEL +1 -1
- algokit_utils-3.0.0b1.dist-info/RECORD +0 -24
- {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,574 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Any, Generic, TypeVar
|
|
4
|
+
|
|
5
|
+
import algosdk
|
|
6
|
+
import algosdk.atomic_transaction_composer
|
|
7
|
+
from algosdk.transaction import Transaction
|
|
8
|
+
from typing_extensions import Self
|
|
9
|
+
|
|
10
|
+
from algokit_utils.applications.abi import ABIReturn
|
|
11
|
+
from algokit_utils.applications.app_manager import AppManager
|
|
12
|
+
from algokit_utils.assets.asset_manager import AssetManager
|
|
13
|
+
from algokit_utils.config import config
|
|
14
|
+
from algokit_utils.models.transaction import SendParams, TransactionWrapper
|
|
15
|
+
from algokit_utils.transactions.transaction_composer import (
|
|
16
|
+
AppCallMethodCallParams,
|
|
17
|
+
AppCallParams,
|
|
18
|
+
AppCreateMethodCallParams,
|
|
19
|
+
AppCreateParams,
|
|
20
|
+
AppDeleteMethodCallParams,
|
|
21
|
+
AppDeleteParams,
|
|
22
|
+
AppUpdateMethodCallParams,
|
|
23
|
+
AppUpdateParams,
|
|
24
|
+
AssetConfigParams,
|
|
25
|
+
AssetCreateParams,
|
|
26
|
+
AssetDestroyParams,
|
|
27
|
+
AssetFreezeParams,
|
|
28
|
+
AssetOptInParams,
|
|
29
|
+
AssetOptOutParams,
|
|
30
|
+
AssetTransferParams,
|
|
31
|
+
OfflineKeyRegistrationParams,
|
|
32
|
+
OnlineKeyRegistrationParams,
|
|
33
|
+
PaymentParams,
|
|
34
|
+
SendAtomicTransactionComposerResults,
|
|
35
|
+
TransactionComposer,
|
|
36
|
+
TxnParams,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
__all__ = [
|
|
40
|
+
"AlgorandClientTransactionSender",
|
|
41
|
+
"SendAppCreateTransactionResult",
|
|
42
|
+
"SendAppTransactionResult",
|
|
43
|
+
"SendAppUpdateTransactionResult",
|
|
44
|
+
"SendSingleAssetCreateTransactionResult",
|
|
45
|
+
"SendSingleTransactionResult",
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
logger = config.logger
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
TxnParamsT = TypeVar("TxnParamsT", bound=TxnParams)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True, kw_only=True)
|
|
55
|
+
class SendSingleTransactionResult:
|
|
56
|
+
"""Base class for transaction results.
|
|
57
|
+
|
|
58
|
+
Represents the result of sending a single transaction.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
transaction: TransactionWrapper # Last transaction
|
|
62
|
+
confirmation: algosdk.v2client.algod.AlgodResponseType # Last confirmation
|
|
63
|
+
|
|
64
|
+
# Fields from SendAtomicTransactionComposerResults
|
|
65
|
+
group_id: str
|
|
66
|
+
tx_id: str | None = None
|
|
67
|
+
tx_ids: list[str] # Full array of transaction IDs
|
|
68
|
+
transactions: list[TransactionWrapper]
|
|
69
|
+
confirmations: list[algosdk.v2client.algod.AlgodResponseType]
|
|
70
|
+
returns: list[ABIReturn] | None = None
|
|
71
|
+
|
|
72
|
+
@classmethod
|
|
73
|
+
def from_composer_result(cls, result: SendAtomicTransactionComposerResults, index: int = -1) -> Self:
|
|
74
|
+
# Get base parameters
|
|
75
|
+
base_params = {
|
|
76
|
+
"transaction": result.transactions[index],
|
|
77
|
+
"confirmation": result.confirmations[index],
|
|
78
|
+
"group_id": result.group_id,
|
|
79
|
+
"tx_id": result.tx_ids[index],
|
|
80
|
+
"tx_ids": result.tx_ids,
|
|
81
|
+
"transactions": [result.transactions[index]],
|
|
82
|
+
"confirmations": result.confirmations,
|
|
83
|
+
"returns": result.returns,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# For asset creation, extract asset_id from confirmation
|
|
87
|
+
if cls is SendSingleAssetCreateTransactionResult:
|
|
88
|
+
base_params["asset_id"] = result.confirmations[index]["asset-index"] # type: ignore[call-overload]
|
|
89
|
+
# For app creation, extract app_id and calculate app_address
|
|
90
|
+
elif cls is SendAppCreateTransactionResult:
|
|
91
|
+
app_id = result.confirmations[index]["application-index"] # type: ignore[call-overload]
|
|
92
|
+
base_params.update(
|
|
93
|
+
{
|
|
94
|
+
"app_id": app_id,
|
|
95
|
+
"app_address": algosdk.logic.get_application_address(app_id),
|
|
96
|
+
"abi_return": result.returns[index] if result.returns else None, # type: ignore[dict-item]
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
# For regular app transactions, just add abi_return
|
|
100
|
+
elif cls is SendAppTransactionResult:
|
|
101
|
+
base_params["abi_return"] = result.returns[index] if result.returns else None # type: ignore[assignment]
|
|
102
|
+
|
|
103
|
+
return cls(**base_params) # type: ignore[arg-type]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True, kw_only=True)
|
|
107
|
+
class SendSingleAssetCreateTransactionResult(SendSingleTransactionResult):
|
|
108
|
+
"""Result of creating a new ASA (Algorand Standard Asset).
|
|
109
|
+
|
|
110
|
+
Contains the asset ID of the newly created asset.
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
asset_id: int
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
ABIReturnT = TypeVar("ABIReturnT")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass(frozen=True)
|
|
120
|
+
class SendAppTransactionResult(SendSingleTransactionResult, Generic[ABIReturnT]):
|
|
121
|
+
"""Result of an application transaction.
|
|
122
|
+
|
|
123
|
+
Contains the ABI return value if applicable.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
abi_return: ABIReturnT | None = None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class SendAppUpdateTransactionResult(SendAppTransactionResult[ABIReturnT]):
|
|
131
|
+
"""Result of updating an application.
|
|
132
|
+
|
|
133
|
+
Contains the compiled approval and clear programs.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
compiled_approval: Any | None = None
|
|
137
|
+
compiled_clear: Any | None = None
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@dataclass(frozen=True, kw_only=True)
|
|
141
|
+
class SendAppCreateTransactionResult(SendAppUpdateTransactionResult[ABIReturnT]):
|
|
142
|
+
"""Result of creating a new application.
|
|
143
|
+
|
|
144
|
+
Contains the app ID and address of the newly created application.
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
app_id: int
|
|
148
|
+
app_address: str
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class AlgorandClientTransactionSender:
|
|
152
|
+
"""Orchestrates sending transactions for AlgorandClient.
|
|
153
|
+
|
|
154
|
+
Provides methods to send various types of transactions including payments,
|
|
155
|
+
asset operations, and application calls.
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
def __init__(
|
|
159
|
+
self,
|
|
160
|
+
new_group: Callable[[], TransactionComposer],
|
|
161
|
+
asset_manager: AssetManager,
|
|
162
|
+
app_manager: AppManager,
|
|
163
|
+
algod_client: algosdk.v2client.algod.AlgodClient,
|
|
164
|
+
) -> None:
|
|
165
|
+
self._new_group = new_group
|
|
166
|
+
self._asset_manager = asset_manager
|
|
167
|
+
self._app_manager = app_manager
|
|
168
|
+
self._algod = algod_client
|
|
169
|
+
|
|
170
|
+
def new_group(self) -> TransactionComposer:
|
|
171
|
+
"""Create a new transaction group.
|
|
172
|
+
|
|
173
|
+
:return: A new TransactionComposer instance
|
|
174
|
+
"""
|
|
175
|
+
return self._new_group()
|
|
176
|
+
|
|
177
|
+
def _send(
|
|
178
|
+
self,
|
|
179
|
+
c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
|
|
180
|
+
pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
|
|
181
|
+
post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
|
|
182
|
+
) -> Callable[[TxnParamsT, SendParams | None], SendSingleTransactionResult]:
|
|
183
|
+
def send_transaction(params: TxnParamsT, send_params: SendParams | None = None) -> SendSingleTransactionResult:
|
|
184
|
+
composer = self.new_group()
|
|
185
|
+
c(composer)(params)
|
|
186
|
+
|
|
187
|
+
if pre_log:
|
|
188
|
+
transaction = composer.build().transactions[-1].txn
|
|
189
|
+
logger.debug(pre_log(params, transaction))
|
|
190
|
+
|
|
191
|
+
raw_result = composer.send(
|
|
192
|
+
send_params,
|
|
193
|
+
)
|
|
194
|
+
raw_result_dict = raw_result.__dict__.copy()
|
|
195
|
+
raw_result_dict["transactions"] = raw_result.transactions
|
|
196
|
+
del raw_result_dict["simulate_response"]
|
|
197
|
+
|
|
198
|
+
result = SendSingleTransactionResult(
|
|
199
|
+
**raw_result_dict,
|
|
200
|
+
confirmation=raw_result.confirmations[-1],
|
|
201
|
+
transaction=raw_result_dict["transactions"][-1],
|
|
202
|
+
tx_id=raw_result.tx_ids[-1],
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if post_log:
|
|
206
|
+
logger.debug(post_log(params, result))
|
|
207
|
+
|
|
208
|
+
return result
|
|
209
|
+
|
|
210
|
+
return send_transaction
|
|
211
|
+
|
|
212
|
+
def _send_app_call(
|
|
213
|
+
self,
|
|
214
|
+
c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
|
|
215
|
+
pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
|
|
216
|
+
post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
|
|
217
|
+
) -> Callable[[TxnParamsT, SendParams | None], SendAppTransactionResult[ABIReturn]]:
|
|
218
|
+
def send_app_call(
|
|
219
|
+
params: TxnParamsT, send_params: SendParams | None = None
|
|
220
|
+
) -> SendAppTransactionResult[ABIReturn]:
|
|
221
|
+
result = self._send(c, pre_log, post_log)(params, send_params)
|
|
222
|
+
return SendAppTransactionResult[ABIReturn](
|
|
223
|
+
**result.__dict__,
|
|
224
|
+
abi_return=AppManager.get_abi_return(result.confirmation, getattr(params, "method", None)),
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
return send_app_call
|
|
228
|
+
|
|
229
|
+
def _send_app_update_call(
|
|
230
|
+
self,
|
|
231
|
+
c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
|
|
232
|
+
pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
|
|
233
|
+
post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
|
|
234
|
+
) -> Callable[[TxnParamsT, SendParams | None], SendAppUpdateTransactionResult[ABIReturn]]:
|
|
235
|
+
def send_app_update_call(
|
|
236
|
+
params: TxnParamsT, send_params: SendParams | None = None
|
|
237
|
+
) -> SendAppUpdateTransactionResult[ABIReturn]:
|
|
238
|
+
result = self._send_app_call(c, pre_log, post_log)(params, send_params)
|
|
239
|
+
|
|
240
|
+
if not isinstance(
|
|
241
|
+
params, AppCreateParams | AppUpdateParams | AppCreateMethodCallParams | AppUpdateMethodCallParams
|
|
242
|
+
):
|
|
243
|
+
raise TypeError("Invalid parameter type")
|
|
244
|
+
|
|
245
|
+
compiled_approval = (
|
|
246
|
+
self._app_manager.get_compilation_result(params.approval_program)
|
|
247
|
+
if isinstance(params.approval_program, str)
|
|
248
|
+
else params.approval_program
|
|
249
|
+
)
|
|
250
|
+
compiled_clear = (
|
|
251
|
+
self._app_manager.get_compilation_result(params.clear_state_program)
|
|
252
|
+
if isinstance(params.clear_state_program, str)
|
|
253
|
+
else params.clear_state_program
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
return SendAppUpdateTransactionResult[ABIReturn](
|
|
257
|
+
**result.__dict__,
|
|
258
|
+
compiled_approval=compiled_approval,
|
|
259
|
+
compiled_clear=compiled_clear,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
return send_app_update_call
|
|
263
|
+
|
|
264
|
+
def _send_app_create_call(
|
|
265
|
+
self,
|
|
266
|
+
c: Callable[[TransactionComposer], Callable[[TxnParamsT], TransactionComposer]],
|
|
267
|
+
pre_log: Callable[[TxnParamsT, Transaction], str] | None = None,
|
|
268
|
+
post_log: Callable[[TxnParamsT, SendSingleTransactionResult], str] | None = None,
|
|
269
|
+
) -> Callable[[TxnParamsT, SendParams | None], SendAppCreateTransactionResult[ABIReturn]]:
|
|
270
|
+
def send_app_create_call(
|
|
271
|
+
params: TxnParamsT, send_params: SendParams | None = None
|
|
272
|
+
) -> SendAppCreateTransactionResult[ABIReturn]:
|
|
273
|
+
result = self._send_app_update_call(c, pre_log, post_log)(params, send_params)
|
|
274
|
+
app_id = int(result.confirmation["application-index"]) # type: ignore[call-overload]
|
|
275
|
+
|
|
276
|
+
return SendAppCreateTransactionResult[ABIReturn](
|
|
277
|
+
**result.__dict__,
|
|
278
|
+
app_id=app_id,
|
|
279
|
+
app_address=algosdk.logic.get_application_address(app_id),
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
return send_app_create_call
|
|
283
|
+
|
|
284
|
+
def _get_method_call_for_log(self, method: algosdk.abi.Method, args: list[Any]) -> str:
|
|
285
|
+
"""Helper function to format method call logs similar to TypeScript version"""
|
|
286
|
+
args_str = str([str(a) if not isinstance(a, bytes | bytearray) else a.hex() for a in args])
|
|
287
|
+
return f"{method.name}({args_str})"
|
|
288
|
+
|
|
289
|
+
def payment(self, params: PaymentParams, send_params: SendParams | None = None) -> SendSingleTransactionResult:
|
|
290
|
+
"""Send a payment transaction to transfer Algo between accounts.
|
|
291
|
+
|
|
292
|
+
:param params: Payment transaction parameters
|
|
293
|
+
:param send_params: Send parameters
|
|
294
|
+
:return: Result of the payment transaction
|
|
295
|
+
"""
|
|
296
|
+
return self._send(
|
|
297
|
+
lambda c: c.add_payment,
|
|
298
|
+
pre_log=lambda params, transaction: (
|
|
299
|
+
f"Sending {params.amount} from {params.sender} to {params.receiver} "
|
|
300
|
+
f"via transaction {transaction.get_txid()}"
|
|
301
|
+
),
|
|
302
|
+
)(params, send_params)
|
|
303
|
+
|
|
304
|
+
def asset_create(
|
|
305
|
+
self, params: AssetCreateParams, send_params: SendParams | None = None
|
|
306
|
+
) -> SendSingleAssetCreateTransactionResult:
|
|
307
|
+
"""Create a new Algorand Standard Asset.
|
|
308
|
+
|
|
309
|
+
:param params: Asset creation parameters
|
|
310
|
+
:param send_params: Send parameters
|
|
311
|
+
:return: Result containing the new asset ID
|
|
312
|
+
"""
|
|
313
|
+
result = self._send(
|
|
314
|
+
lambda c: c.add_asset_create,
|
|
315
|
+
post_log=lambda params, result: (
|
|
316
|
+
f"Created asset{f' {params.asset_name}' if hasattr(params, 'asset_name') else ''}"
|
|
317
|
+
f"{f' ({params.unit_name})' if hasattr(params, 'unit_name') else ''} with "
|
|
318
|
+
f"{params.total} units and {getattr(params, 'decimals', 0)} decimals created by "
|
|
319
|
+
f"{params.sender} with ID {result.confirmation['asset-index']} via transaction " # type: ignore[call-overload]
|
|
320
|
+
f"{result.tx_ids[-1]}"
|
|
321
|
+
),
|
|
322
|
+
)(params, send_params)
|
|
323
|
+
|
|
324
|
+
return SendSingleAssetCreateTransactionResult(
|
|
325
|
+
**result.__dict__,
|
|
326
|
+
asset_id=int(result.confirmation["asset-index"]), # type: ignore[call-overload]
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
def asset_config(
|
|
330
|
+
self, params: AssetConfigParams, send_params: SendParams | None = None
|
|
331
|
+
) -> SendSingleTransactionResult:
|
|
332
|
+
"""Configure an existing Algorand Standard Asset.
|
|
333
|
+
|
|
334
|
+
:param params: Asset configuration parameters
|
|
335
|
+
:param send_params: Send parameters
|
|
336
|
+
:return: Result of the configuration transaction
|
|
337
|
+
"""
|
|
338
|
+
return self._send(
|
|
339
|
+
lambda c: c.add_asset_config,
|
|
340
|
+
pre_log=lambda params, transaction: (
|
|
341
|
+
f"Configuring asset with ID {params.asset_id} via transaction {transaction.get_txid()}"
|
|
342
|
+
),
|
|
343
|
+
)(params, send_params)
|
|
344
|
+
|
|
345
|
+
def asset_freeze(
|
|
346
|
+
self, params: AssetFreezeParams, send_params: SendParams | None = None
|
|
347
|
+
) -> SendSingleTransactionResult:
|
|
348
|
+
"""Freeze or unfreeze an Algorand Standard Asset for an account.
|
|
349
|
+
|
|
350
|
+
:param params: Asset freeze parameters
|
|
351
|
+
:param send_params: Send parameters
|
|
352
|
+
:return: Result of the freeze transaction
|
|
353
|
+
"""
|
|
354
|
+
return self._send(
|
|
355
|
+
lambda c: c.add_asset_freeze,
|
|
356
|
+
pre_log=lambda params, transaction: (
|
|
357
|
+
f"Freezing asset with ID {params.asset_id} via transaction {transaction.get_txid()}"
|
|
358
|
+
),
|
|
359
|
+
)(params, send_params)
|
|
360
|
+
|
|
361
|
+
def asset_destroy(
|
|
362
|
+
self, params: AssetDestroyParams, send_params: SendParams | None = None
|
|
363
|
+
) -> SendSingleTransactionResult:
|
|
364
|
+
"""Destroys an Algorand Standard Asset.
|
|
365
|
+
|
|
366
|
+
:param params: Asset destruction parameters
|
|
367
|
+
:param send_params: Send parameters
|
|
368
|
+
:return: Result of the destroy transaction
|
|
369
|
+
"""
|
|
370
|
+
return self._send(
|
|
371
|
+
lambda c: c.add_asset_destroy,
|
|
372
|
+
pre_log=lambda params, transaction: (
|
|
373
|
+
f"Destroying asset with ID {params.asset_id} via transaction {transaction.get_txid()}"
|
|
374
|
+
),
|
|
375
|
+
)(params, send_params)
|
|
376
|
+
|
|
377
|
+
def asset_transfer(
|
|
378
|
+
self, params: AssetTransferParams, send_params: SendParams | None = None
|
|
379
|
+
) -> SendSingleTransactionResult:
|
|
380
|
+
"""Transfer an Algorand Standard Asset.
|
|
381
|
+
|
|
382
|
+
:param params: Asset transfer parameters
|
|
383
|
+
:param send_params: Send parameters
|
|
384
|
+
:return: Result of the transfer transaction
|
|
385
|
+
"""
|
|
386
|
+
return self._send(
|
|
387
|
+
lambda c: c.add_asset_transfer,
|
|
388
|
+
pre_log=lambda params, transaction: (
|
|
389
|
+
f"Transferring {params.amount} units of asset with ID {params.asset_id} from "
|
|
390
|
+
f"{params.sender} to {params.receiver} via transaction {transaction.get_txid()}"
|
|
391
|
+
),
|
|
392
|
+
)(params, send_params)
|
|
393
|
+
|
|
394
|
+
def asset_opt_in(
|
|
395
|
+
self, params: AssetOptInParams, send_params: SendParams | None = None
|
|
396
|
+
) -> SendSingleTransactionResult:
|
|
397
|
+
"""Opt an account into an Algorand Standard Asset.
|
|
398
|
+
|
|
399
|
+
:param params: Asset opt-in parameters
|
|
400
|
+
:param send_params: Send parameters
|
|
401
|
+
:return: Result of the opt-in transaction
|
|
402
|
+
"""
|
|
403
|
+
return self._send(
|
|
404
|
+
lambda c: c.add_asset_opt_in,
|
|
405
|
+
pre_log=lambda params, transaction: (
|
|
406
|
+
f"Opting in {params.sender} to asset with ID {params.asset_id} via transaction "
|
|
407
|
+
f"{transaction.get_txid()}"
|
|
408
|
+
),
|
|
409
|
+
)(params, send_params)
|
|
410
|
+
|
|
411
|
+
def asset_opt_out(
|
|
412
|
+
self,
|
|
413
|
+
*,
|
|
414
|
+
params: AssetOptOutParams,
|
|
415
|
+
send_params: SendParams | None = None,
|
|
416
|
+
ensure_zero_balance: bool = True,
|
|
417
|
+
) -> SendSingleTransactionResult:
|
|
418
|
+
"""Opt an account out of an Algorand Standard Asset.
|
|
419
|
+
|
|
420
|
+
:param params: Asset opt-out parameters
|
|
421
|
+
:param send_params: Send parameters
|
|
422
|
+
:param ensure_zero_balance: Check if account has zero balance before opt-out, defaults to True
|
|
423
|
+
:raises ValueError: If account has non-zero balance or is not opted in
|
|
424
|
+
:return: Result of the opt-out transaction
|
|
425
|
+
"""
|
|
426
|
+
if ensure_zero_balance:
|
|
427
|
+
try:
|
|
428
|
+
account_asset_info = self._asset_manager.get_account_information(params.sender, params.asset_id)
|
|
429
|
+
balance = account_asset_info.balance
|
|
430
|
+
if balance != 0:
|
|
431
|
+
raise ValueError(
|
|
432
|
+
f"Account {params.sender} does not have a zero balance for Asset "
|
|
433
|
+
f"{params.asset_id}; can't opt-out."
|
|
434
|
+
)
|
|
435
|
+
except Exception as e:
|
|
436
|
+
raise ValueError(
|
|
437
|
+
f"Account {params.sender} is not opted-in to Asset {params.asset_id}; " "can't opt-out."
|
|
438
|
+
) from e
|
|
439
|
+
|
|
440
|
+
if not hasattr(params, "creator"):
|
|
441
|
+
asset_info = self._asset_manager.get_by_id(params.asset_id)
|
|
442
|
+
params = AssetOptOutParams(
|
|
443
|
+
**params.__dict__,
|
|
444
|
+
creator=asset_info.creator,
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
creator = params.__dict__.get("creator")
|
|
448
|
+
return self._send(
|
|
449
|
+
lambda c: c.add_asset_opt_out,
|
|
450
|
+
pre_log=lambda params, transaction: (
|
|
451
|
+
f"Opting {params.sender} out of asset with ID {params.asset_id} to creator "
|
|
452
|
+
f"{creator} via transaction {transaction.get_txid()}"
|
|
453
|
+
),
|
|
454
|
+
)(params, send_params)
|
|
455
|
+
|
|
456
|
+
def app_create(
|
|
457
|
+
self, params: AppCreateParams, send_params: SendParams | None = None
|
|
458
|
+
) -> SendAppCreateTransactionResult[ABIReturn]:
|
|
459
|
+
"""Create a new application.
|
|
460
|
+
|
|
461
|
+
:param params: Application creation parameters
|
|
462
|
+
:param send_params: Send parameters
|
|
463
|
+
:return: Result containing the new application ID and address
|
|
464
|
+
"""
|
|
465
|
+
return self._send_app_create_call(lambda c: c.add_app_create)(params, send_params)
|
|
466
|
+
|
|
467
|
+
def app_update(
|
|
468
|
+
self, params: AppUpdateParams, send_params: SendParams | None = None
|
|
469
|
+
) -> SendAppUpdateTransactionResult[ABIReturn]:
|
|
470
|
+
"""Update an application.
|
|
471
|
+
|
|
472
|
+
:param params: Application update parameters
|
|
473
|
+
:param send_params: Send parameters
|
|
474
|
+
:return: Result containing the compiled programs
|
|
475
|
+
"""
|
|
476
|
+
return self._send_app_update_call(lambda c: c.add_app_update)(params, send_params)
|
|
477
|
+
|
|
478
|
+
def app_delete(
|
|
479
|
+
self, params: AppDeleteParams, send_params: SendParams | None = None
|
|
480
|
+
) -> SendAppTransactionResult[ABIReturn]:
|
|
481
|
+
"""Delete an application.
|
|
482
|
+
|
|
483
|
+
:param params: Application deletion parameters
|
|
484
|
+
:param send_params: Send parameters
|
|
485
|
+
:return: Result of the deletion transaction
|
|
486
|
+
"""
|
|
487
|
+
return self._send_app_call(lambda c: c.add_app_delete)(params, send_params)
|
|
488
|
+
|
|
489
|
+
def app_call(
|
|
490
|
+
self, params: AppCallParams, send_params: SendParams | None = None
|
|
491
|
+
) -> SendAppTransactionResult[ABIReturn]:
|
|
492
|
+
"""Call an application.
|
|
493
|
+
|
|
494
|
+
:param params: Application call parameters
|
|
495
|
+
:param send_params: Send parameters
|
|
496
|
+
:return: Result containing any ABI return value
|
|
497
|
+
"""
|
|
498
|
+
return self._send_app_call(lambda c: c.add_app_call)(params, send_params)
|
|
499
|
+
|
|
500
|
+
def app_create_method_call(
|
|
501
|
+
self, params: AppCreateMethodCallParams, send_params: SendParams | None = None
|
|
502
|
+
) -> SendAppCreateTransactionResult[ABIReturn]:
|
|
503
|
+
"""Call an application's create method.
|
|
504
|
+
|
|
505
|
+
:param params: Method call parameters for application creation
|
|
506
|
+
:param send_params: Send parameters
|
|
507
|
+
:return: Result containing the new application ID and address
|
|
508
|
+
"""
|
|
509
|
+
return self._send_app_create_call(lambda c: c.add_app_create_method_call)(params, send_params)
|
|
510
|
+
|
|
511
|
+
def app_update_method_call(
|
|
512
|
+
self, params: AppUpdateMethodCallParams, send_params: SendParams | None = None
|
|
513
|
+
) -> SendAppUpdateTransactionResult[ABIReturn]:
|
|
514
|
+
"""Call an application's update method.
|
|
515
|
+
|
|
516
|
+
:param params: Method call parameters for application update
|
|
517
|
+
:param send_params: Send parameters
|
|
518
|
+
:return: Result containing the compiled programs
|
|
519
|
+
"""
|
|
520
|
+
return self._send_app_update_call(lambda c: c.add_app_update_method_call)(params, send_params)
|
|
521
|
+
|
|
522
|
+
def app_delete_method_call(
|
|
523
|
+
self, params: AppDeleteMethodCallParams, send_params: SendParams | None = None
|
|
524
|
+
) -> SendAppTransactionResult[ABIReturn]:
|
|
525
|
+
"""Call an application's delete method.
|
|
526
|
+
|
|
527
|
+
:param params: Method call parameters for application deletion
|
|
528
|
+
:param send_params: Send parameters
|
|
529
|
+
:return: Result of the deletion transaction
|
|
530
|
+
"""
|
|
531
|
+
return self._send_app_call(lambda c: c.add_app_delete_method_call)(params, send_params)
|
|
532
|
+
|
|
533
|
+
def app_call_method_call(
|
|
534
|
+
self, params: AppCallMethodCallParams, send_params: SendParams | None = None
|
|
535
|
+
) -> SendAppTransactionResult[ABIReturn]:
|
|
536
|
+
"""Call an application's call method.
|
|
537
|
+
|
|
538
|
+
:param params: Method call parameters
|
|
539
|
+
:param send_params: Send parameters
|
|
540
|
+
:return: Result containing any ABI return value
|
|
541
|
+
"""
|
|
542
|
+
return self._send_app_call(lambda c: c.add_app_call_method_call)(params, send_params)
|
|
543
|
+
|
|
544
|
+
def online_key_registration(
|
|
545
|
+
self, params: OnlineKeyRegistrationParams, send_params: SendParams | None = None
|
|
546
|
+
) -> SendSingleTransactionResult:
|
|
547
|
+
"""Register an online key.
|
|
548
|
+
|
|
549
|
+
:param params: Key registration parameters
|
|
550
|
+
:param send_params: Send parameters
|
|
551
|
+
:return: Result of the registration transaction
|
|
552
|
+
"""
|
|
553
|
+
return self._send(
|
|
554
|
+
lambda c: c.add_online_key_registration,
|
|
555
|
+
pre_log=lambda params, transaction: (
|
|
556
|
+
f"Registering online key for {params.sender} via transaction {transaction.get_txid()}"
|
|
557
|
+
),
|
|
558
|
+
)(params, send_params)
|
|
559
|
+
|
|
560
|
+
def offline_key_registration(
|
|
561
|
+
self, params: OfflineKeyRegistrationParams, send_params: SendParams | None = None
|
|
562
|
+
) -> SendSingleTransactionResult:
|
|
563
|
+
"""Register an offline key.
|
|
564
|
+
|
|
565
|
+
:param params: Key registration parameters
|
|
566
|
+
:param send_params: Send parameters
|
|
567
|
+
:return: Result of the registration transaction
|
|
568
|
+
"""
|
|
569
|
+
return self._send(
|
|
570
|
+
lambda c: c.add_offline_key_registration,
|
|
571
|
+
pre_log=lambda params, transaction: (
|
|
572
|
+
f"Registering offline key for {params.sender} via transaction {transaction.get_txid()}"
|
|
573
|
+
),
|
|
574
|
+
)(params, send_params)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: algokit-utils
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0b3
|
|
4
4
|
Summary: Utilities for Algorand development for use by AlgoKit
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Algorand Foundation
|
|
@@ -11,23 +11,24 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
-
|
|
15
|
-
Requires-Dist: httpx (>=0.
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Requires-Dist: httpx (>=0.28,<0.29)
|
|
16
16
|
Requires-Dist: py-algorand-sdk (>=2.4.0,<3.0.0)
|
|
17
|
+
Requires-Dist: typing-extensions (>=4.6.0)
|
|
17
18
|
Description-Content-Type: text/markdown
|
|
18
19
|
|
|
19
20
|
# AlgoKit Python Utilities
|
|
20
21
|
|
|
21
|
-
A set of core Algorand utilities written in Python and released via PyPi that make it easier to build solutions on Algorand.
|
|
22
|
+
A set of core Algorand utilities written in Python and released via PyPi that make it easier to build solutions on Algorand.
|
|
22
23
|
This project is part of [AlgoKit](https://github.com/algorandfoundation/algokit-cli).
|
|
23
24
|
|
|
24
|
-
The goal of this library is to provide intuitive, productive utility functions that make it easier, quicker and safer to build applications on Algorand.
|
|
25
|
+
The goal of this library is to provide intuitive, productive utility functions that make it easier, quicker and safer to build applications on Algorand.
|
|
25
26
|
Largely these functions wrap the underlying Algorand SDK, but provide a higher level interface with sensible defaults and capabilities for common tasks.
|
|
26
27
|
|
|
27
28
|
> **Note**
|
|
28
29
|
> If you prefer TypeScript there's an equivalent [TypeScript utility library](https://github.com/algorandfoundation/algokit-utils-ts).
|
|
29
30
|
|
|
30
|
-
[Install](https://github.com/algorandfoundation/algokit-utils-py#install) | [Documentation](https://algorandfoundation.github.io/algokit-utils-py
|
|
31
|
+
[Install](https://github.com/algorandfoundation/algokit-utils-py#install) | [Documentation](https://algorandfoundation.github.io/algokit-utils-py)
|
|
31
32
|
|
|
32
33
|
## Install
|
|
33
34
|
|
|
@@ -37,13 +38,17 @@ This library can be installed using pip, e.g.:
|
|
|
37
38
|
pip install algokit-utils
|
|
38
39
|
```
|
|
39
40
|
|
|
41
|
+
## Migration from `v2.x` to `v3.x`
|
|
42
|
+
|
|
43
|
+
Refer to the [v3 migration](./docs/source/v3-migration-guide.md) for more information on how to migrate to latest version of `algokit-utils-py`.
|
|
44
|
+
|
|
40
45
|
## Guiding principles
|
|
41
46
|
|
|
42
47
|
This library follows the [Guiding Principles of AlgoKit](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/algokit.md#guiding-principles).
|
|
43
48
|
|
|
44
49
|
## Contributing
|
|
45
50
|
|
|
46
|
-
This is an open source project managed by the Algorand Foundation.
|
|
51
|
+
This is an open source project managed by the Algorand Foundation.
|
|
47
52
|
See the [AlgoKit contributing page](https://github.com/algorandfoundation/algokit-cli/blob/main/CONTRIBUTING.MD) to learn about making improvements.
|
|
48
53
|
|
|
49
54
|
To successfully run the tests in this repository you need to be running LocalNet via [AlgoKit](https://github.com/algorandfoundation/algokit-cli):
|