algokit-utils 2.4.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 -181
  2. algokit_utils/_debugging.py +89 -45
  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} +16 -45
  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 -1447
  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 -894
  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 -82
  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 -128
  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-2.4.0b1.dist-info → algokit_utils-3.0.0b2.dist-info}/METADATA +11 -7
  67. algokit_utils-3.0.0b2.dist-info/RECORD +70 -0
  68. {algokit_utils-2.4.0b1.dist-info → algokit_utils-3.0.0b2.dist-info}/WHEEL +1 -1
  69. algokit_utils-2.4.0b1.dist-info/RECORD +0 -24
  70. {algokit_utils-2.4.0b1.dist-info → algokit_utils-3.0.0b2.dist-info}/LICENSE +0 -0
@@ -1,716 +1,9 @@
1
- from collections.abc import Callable
2
- from dataclasses import dataclass
3
- from typing import Union
1
+ from typing import Any
4
2
 
5
- import algosdk
6
- from algosdk.abi import Method
7
- from algosdk.atomic_transaction_composer import (
8
- AtomicTransactionComposer,
9
- AtomicTransactionResponse,
10
- TransactionSigner,
11
- TransactionWithSigner,
12
- )
13
- from algosdk.box_reference import BoxReference
14
- from algosdk.transaction import OnComplete
15
- from algosdk.v2client.algod import AlgodClient
3
+ from algokit_utils.beta._utils import handle_getattr
16
4
 
17
5
 
18
- @dataclass(frozen=True)
19
- class SenderParam:
20
- sender: str
6
+ def __getattr__(name: str) -> Any: # noqa: ANN401
7
+ """Handle deprecated imports of parameter classes"""
21
8
 
22
-
23
- @dataclass(frozen=True)
24
- class CommonTxnParams:
25
- """
26
- Common transaction parameters.
27
-
28
- :param signer: The function used to sign transactions.
29
- :param rekey_to: Change the signing key of the sender to the given address.
30
- :param note: Note to attach to the transaction.
31
- :param lease: Prevent multiple transactions with the same lease being included within the validity window.
32
- :param static_fee: The transaction fee. In most cases you want to use `extra_fee` unless setting the fee to 0 to be covered by another transaction.
33
- :param extra_fee: The fee to pay IN ADDITION to the suggested fee. Useful for covering inner transaction fees.
34
- :param max_fee: Throw an error if the fee for the transaction is more than this amount.
35
- :param validity_window: How many rounds the transaction should be valid for.
36
- :param first_valid_round: Set the first round this transaction is valid. If left undefined, the value from algod will be used. Only set this when you intentionally want this to be some time in the future.
37
- :param last_valid_round: The last round this transaction is valid. It is recommended to use validity_window instead.
38
- """
39
-
40
- signer: TransactionSigner | None = None
41
- rekey_to: str | None = None
42
- note: bytes | None = None
43
- lease: bytes | None = None
44
- static_fee: int | None = None
45
- extra_fee: int | None = None
46
- max_fee: int | None = None
47
- validity_window: int | None = None
48
- first_valid_round: int | None = None
49
- last_valid_round: int | None = None
50
-
51
-
52
- @dataclass(frozen=True)
53
- class _RequiredPayTxnParams(SenderParam):
54
- receiver: str
55
- amount: int
56
-
57
-
58
- @dataclass(frozen=True)
59
- class PayParams(CommonTxnParams, _RequiredPayTxnParams):
60
- """
61
- Payment transaction parameters.
62
-
63
- :param receiver: The account that will receive the ALGO.
64
- :param amount: Amount to send.
65
- :param close_remainder_to: If given, close the sender account and send the remaining balance to this address.
66
- """
67
-
68
- close_remainder_to: str | None = None
69
-
70
-
71
- @dataclass(frozen=True)
72
- class _RequiredAssetCreateParams(SenderParam):
73
- total: int
74
-
75
-
76
- @dataclass(frozen=True)
77
- class AssetCreateParams(CommonTxnParams, _RequiredAssetCreateParams):
78
- """
79
- Asset creation parameters.
80
-
81
- :param total: The total amount of the smallest divisible unit to create.
82
- :param decimals: The amount of decimal places the asset should have.
83
- :param default_frozen: Whether the asset is frozen by default in the creator address.
84
- :param manager: The address that can change the manager, reserve, clawback, and freeze addresses. There will permanently be no manager if undefined or an empty string.
85
- :param reserve: The address that holds the uncirculated supply.
86
- :param freeze: The address that can freeze the asset in any account. Freezing will be permanently disabled if undefined or an empty string.
87
- :param clawback: The address that can clawback the asset from any account. Clawback will be permanently disabled if undefined or an empty string.
88
- :param unit_name: The short ticker name for the asset.
89
- :param asset_name: The full name of the asset.
90
- :param url: The metadata URL for the asset.
91
- :param metadata_hash: Hash of the metadata contained in the metadata URL.
92
- """
93
-
94
- decimals: int | None = None
95
- default_frozen: bool | None = None
96
- manager: str | None = None
97
- reserve: str | None = None
98
- freeze: str | None = None
99
- clawback: str | None = None
100
- unit_name: str | None = None
101
- asset_name: str | None = None
102
- url: str | None = None
103
- metadata_hash: bytes | None = None
104
-
105
-
106
- @dataclass(frozen=True)
107
- class _RequiredAssetConfigParams(SenderParam):
108
- asset_id: int
109
-
110
-
111
- @dataclass(frozen=True)
112
- class AssetConfigParams(CommonTxnParams, _RequiredAssetConfigParams):
113
- """
114
- Asset configuration parameters.
115
-
116
- :param asset_id: ID of the asset.
117
- :param manager: The address that can change the manager, reserve, clawback, and freeze addresses. There will permanently be no manager if undefined or an empty string.
118
- :param reserve: The address that holds the uncirculated supply.
119
- :param freeze: The address that can freeze the asset in any account. Freezing will be permanently disabled if undefined or an empty string.
120
- :param clawback: The address that can clawback the asset from any account. Clawback will be permanently disabled if undefined or an empty string.
121
- """
122
-
123
- manager: str | None = None
124
- reserve: str | None = None
125
- freeze: str | None = None
126
- clawback: str | None = None
127
-
128
-
129
- @dataclass(frozen=True)
130
- class _RequiredAssetFreezeParams(SenderParam):
131
- asset_id: int
132
- account: str
133
- frozen: bool
134
-
135
-
136
- @dataclass(frozen=True)
137
- class AssetFreezeParams(CommonTxnParams, _RequiredAssetFreezeParams):
138
- """
139
- Asset freeze parameters.
140
-
141
- :param asset_id: The ID of the asset.
142
- :param account: The account to freeze or unfreeze.
143
- :param frozen: Whether the assets in the account should be frozen.
144
- """
145
-
146
-
147
- @dataclass(frozen=True)
148
- class _RequiredAssetDestroyParams(SenderParam):
149
- asset_id: int
150
-
151
-
152
- @dataclass(frozen=True)
153
- class AssetDestroyParams(CommonTxnParams, _RequiredAssetDestroyParams):
154
- """
155
- Asset destruction parameters.
156
-
157
- :param asset_id: ID of the asset.
158
- """
159
-
160
-
161
- @dataclass(frozen=True)
162
- class _RequiredOnlineKeyRegParams(SenderParam):
163
- vote_key: str
164
- selection_key: str
165
- vote_first: int
166
- vote_last: int
167
- vote_key_dilution: int
168
-
169
-
170
- @dataclass(frozen=True)
171
- class OnlineKeyRegParams(CommonTxnParams, _RequiredOnlineKeyRegParams):
172
- """
173
- Online key registration parameters.
174
-
175
- :param vote_key: The root participation public key.
176
- :param selection_key: The VRF public key.
177
- :param vote_first: The first round that the participation key is valid. Not to be confused with the `first_valid` round of the keyreg transaction.
178
- :param vote_last: The last round that the participation key is valid. Not to be confused with the `last_valid` round of the keyreg transaction.
179
- :param vote_key_dilution: This is the dilution for the 2-level participation key. It determines the interval (number of rounds) for generating new ephemeral keys.
180
- :param state_proof_key: The 64 byte state proof public key commitment.
181
- """
182
-
183
- state_proof_key: bytes | None = None
184
-
185
-
186
- @dataclass(frozen=True)
187
- class _RequiredAssetTransferParams(SenderParam):
188
- asset_id: int
189
- amount: int
190
- receiver: str
191
-
192
-
193
- @dataclass(frozen=True)
194
- class AssetTransferParams(CommonTxnParams, _RequiredAssetTransferParams):
195
- """
196
- Asset transfer parameters.
197
-
198
- :param asset_id: ID of the asset.
199
- :param amount: Amount of the asset to transfer (smallest divisible unit).
200
- :param receiver: The account to send the asset to.
201
- :param clawback_target: The account to take the asset from.
202
- :param close_asset_to: The account to close the asset to.
203
- """
204
-
205
- clawback_target: str | None = None
206
- close_asset_to: str | None = None
207
-
208
-
209
- @dataclass(frozen=True)
210
- class _RequiredAssetOptInParams(SenderParam):
211
- asset_id: int
212
-
213
-
214
- @dataclass(frozen=True)
215
- class AssetOptInParams(CommonTxnParams, _RequiredAssetOptInParams):
216
- """
217
- Asset opt-in parameters.
218
-
219
- :param asset_id: ID of the asset.
220
- """
221
-
222
-
223
- @dataclass(frozen=True)
224
- class AppCallParams(CommonTxnParams, SenderParam):
225
- """
226
- Application call parameters.
227
-
228
- :param on_complete: The OnComplete action.
229
- :param app_id: ID of the application.
230
- :param approval_program: The program to execute for all OnCompletes other than ClearState.
231
- :param clear_program: The program to execute for ClearState OnComplete.
232
- :param schema: The state schema for the app. This is immutable.
233
- :param args: Application arguments.
234
- :param account_references: Account references.
235
- :param app_references: App references.
236
- :param asset_references: Asset references.
237
- :param extra_pages: Number of extra pages required for the programs.
238
- :param box_references: Box references.
239
- """
240
-
241
- on_complete: OnComplete | None = None
242
- app_id: int | None = None
243
- approval_program: bytes | None = None
244
- clear_program: bytes | None = None
245
- schema: dict[str, int] | None = None
246
- args: list[bytes] | None = None
247
- account_references: list[str] | None = None
248
- app_references: list[int] | None = None
249
- asset_references: list[int] | None = None
250
- extra_pages: int | None = None
251
- box_references: list[BoxReference] | None = None
252
-
253
-
254
- @dataclass(frozen=True)
255
- class _RequiredMethodCallParams(SenderParam):
256
- app_id: int
257
- method: Method
258
-
259
-
260
- @dataclass(frozen=True)
261
- class MethodCallParams(CommonTxnParams, _RequiredMethodCallParams):
262
- """
263
- Method call parameters.
264
-
265
- :param app_id: ID of the application.
266
- :param method: The ABI method to call.
267
- :param args: Arguments to the ABI method.
268
- """
269
-
270
- args: list | None = None
271
-
272
-
273
- TxnParams = Union[ # noqa: UP007
274
- PayParams,
275
- AssetCreateParams,
276
- AssetConfigParams,
277
- AssetFreezeParams,
278
- AssetDestroyParams,
279
- OnlineKeyRegParams,
280
- AssetTransferParams,
281
- AssetOptInParams,
282
- AppCallParams,
283
- MethodCallParams,
284
- ]
285
-
286
-
287
- class AlgokitComposer:
288
- """
289
- A class for composing and managing Algorand transactions using the Algosdk library.
290
-
291
- Attributes:
292
- txn_method_map (dict[str, algosdk.abi.Method]): A dictionary that maps transaction IDs to their corresponding ABI methods.
293
- txns (List[Union[TransactionWithSigner, TxnParams, AtomicTransactionComposer]]): A list of transactions that have not yet been composed.
294
- atc (AtomicTransactionComposer): An instance of AtomicTransactionComposer used to compose transactions.
295
- algod (AlgodClient): The AlgodClient instance used by the composer for suggested params.
296
- get_suggested_params (Callable[[], algosdk.future.transaction.SuggestedParams]): A function that returns suggested parameters for transactions.
297
- get_signer (Callable[[str], TransactionSigner]): A function that takes an address as input and returns a TransactionSigner for that address.
298
- default_validity_window (int): The default validity window for transactions.
299
- """
300
-
301
- def __init__(
302
- self,
303
- algod: AlgodClient,
304
- get_signer: Callable[[str], TransactionSigner],
305
- get_suggested_params: Callable[[], algosdk.transaction.SuggestedParams] | None = None,
306
- default_validity_window: int | None = None,
307
- ):
308
- """
309
- Initialize an instance of the AlgokitComposer class.
310
-
311
- Args:
312
- algod (AlgodClient): An instance of AlgodClient used to get suggested params and send transactions.
313
- get_signer (Callable[[str], TransactionSigner]): A function that takes an address as input and returns a TransactionSigner for that address.
314
- get_suggested_params (Optional[Callable[[], algosdk.future.transaction.SuggestedParams]], optional): A function that returns suggested parameters for transactions. If not provided, it defaults to using algod.suggested_params(). Defaults to None.
315
- default_validity_window (Optional[int], optional): The default validity window for transactions. If not provided, it defaults to 10. Defaults to None.
316
- """
317
- self.txn_method_map: dict[str, algosdk.abi.Method] = {}
318
- self.txns: list[TransactionWithSigner | TxnParams | AtomicTransactionComposer] = []
319
- self.atc: AtomicTransactionComposer = AtomicTransactionComposer()
320
- self.algod: AlgodClient = algod
321
- self.default_get_send_params = lambda: self.algod.suggested_params()
322
- self.get_suggested_params = get_suggested_params or self.default_get_send_params
323
- self.get_signer: Callable[[str], TransactionSigner] = get_signer
324
- self.default_validity_window: int = default_validity_window or 10
325
-
326
- def add_payment(self, params: PayParams) -> "AlgokitComposer":
327
- self.txns.append(params)
328
- return self
329
-
330
- def add_asset_create(self, params: AssetCreateParams) -> "AlgokitComposer":
331
- self.txns.append(params)
332
- return self
333
-
334
- def add_asset_config(self, params: AssetConfigParams) -> "AlgokitComposer":
335
- self.txns.append(params)
336
- return self
337
-
338
- def add_asset_freeze(self, params: AssetFreezeParams) -> "AlgokitComposer":
339
- self.txns.append(params)
340
- return self
341
-
342
- def add_asset_destroy(self, params: AssetDestroyParams) -> "AlgokitComposer":
343
- self.txns.append(params)
344
- return self
345
-
346
- def add_asset_transfer(self, params: AssetTransferParams) -> "AlgokitComposer":
347
- self.txns.append(params)
348
- return self
349
-
350
- def add_asset_opt_in(self, params: AssetOptInParams) -> "AlgokitComposer":
351
- self.txns.append(params)
352
- return self
353
-
354
- def add_app_call(self, params: AppCallParams) -> "AlgokitComposer":
355
- self.txns.append(params)
356
- return self
357
-
358
- def add_online_key_reg(self, params: OnlineKeyRegParams) -> "AlgokitComposer":
359
- self.txns.append(params)
360
- return self
361
-
362
- def add_atc(self, atc: AtomicTransactionComposer) -> "AlgokitComposer":
363
- self.txns.append(atc)
364
- return self
365
-
366
- def add_method_call(self, params: MethodCallParams) -> "AlgokitComposer":
367
- self.txns.append(params)
368
- return self
369
-
370
- def _build_atc(self, atc: AtomicTransactionComposer) -> list[TransactionWithSigner]:
371
- group = atc.build_group()
372
-
373
- for ts in group:
374
- ts.txn.group = None
375
-
376
- method = atc.method_dict.get(len(group) - 1)
377
- if method:
378
- self.txn_method_map[group[-1].txn.get_txid()] = method # type: ignore[no-untyped-call]
379
-
380
- return group
381
-
382
- def _common_txn_build_step(
383
- self,
384
- params: CommonTxnParams,
385
- txn: algosdk.transaction.Transaction,
386
- suggested_params: algosdk.transaction.SuggestedParams,
387
- ) -> algosdk.transaction.Transaction:
388
- if params.lease:
389
- txn.lease = params.lease
390
- if params.rekey_to:
391
- txn.rekey_to = params.rekey_to
392
- if params.note:
393
- txn.note = params.note
394
-
395
- if params.first_valid_round:
396
- txn.first_valid_round = params.first_valid_round
397
-
398
- if params.last_valid_round:
399
- txn.last_valid_round = params.last_valid_round
400
- else:
401
- txn.last_valid_round = txn.first_valid_round + (params.validity_window or self.default_validity_window)
402
-
403
- if params.static_fee is not None and params.extra_fee is not None:
404
- raise ValueError("Cannot set both static_fee and extra_fee")
405
-
406
- if params.static_fee is not None:
407
- txn.fee = params.static_fee
408
- else:
409
- txn.fee = txn.estimate_size() * suggested_params.fee or algosdk.constants.min_txn_fee # type: ignore[no-untyped-call]
410
- if params.extra_fee:
411
- txn.fee += params.extra_fee
412
-
413
- if params.max_fee is not None and txn.fee > params.max_fee:
414
- raise ValueError(f"Transaction fee {txn.fee} is greater than max_fee {params.max_fee}")
415
-
416
- return txn
417
-
418
- def _build_payment(
419
- self, params: PayParams, suggested_params: algosdk.transaction.SuggestedParams
420
- ) -> algosdk.transaction.Transaction:
421
- txn = algosdk.transaction.PaymentTxn(
422
- sender=params.sender,
423
- sp=suggested_params,
424
- receiver=params.receiver,
425
- amt=params.amount,
426
- close_remainder_to=params.close_remainder_to,
427
- ) # type: ignore[no-untyped-call]
428
-
429
- return self._common_txn_build_step(params, txn, suggested_params)
430
-
431
- def _build_asset_create(
432
- self, params: AssetCreateParams, suggested_params: algosdk.transaction.SuggestedParams
433
- ) -> algosdk.transaction.Transaction:
434
- txn = algosdk.transaction.AssetConfigTxn(
435
- sender=params.sender,
436
- sp=suggested_params,
437
- total=params.total,
438
- default_frozen=params.default_frozen or False,
439
- unit_name=params.unit_name,
440
- asset_name=params.asset_name,
441
- manager=params.manager,
442
- reserve=params.reserve,
443
- freeze=params.freeze,
444
- clawback=params.clawback,
445
- url=params.url,
446
- metadata_hash=params.metadata_hash,
447
- decimals=params.decimals or 0,
448
- strict_empty_address_check=False,
449
- ) # type: ignore[no-untyped-call]
450
-
451
- return self._common_txn_build_step(params, txn, suggested_params)
452
-
453
- def _build_app_call(
454
- self, params: AppCallParams, suggested_params: algosdk.transaction.SuggestedParams
455
- ) -> algosdk.transaction.Transaction:
456
- sdk_params = {
457
- "sender": params.sender,
458
- "sp": suggested_params,
459
- "on_complete": params.on_complete or algosdk.transaction.OnComplete.NoOpOC,
460
- "approval_program": params.approval_program,
461
- "clear_program": params.clear_program,
462
- "app_args": params.args,
463
- "accounts": params.account_references,
464
- "foreign_apps": params.app_references,
465
- "foreign_assets": params.asset_references,
466
- "extra_pages": params.extra_pages,
467
- "local_schema": algosdk.transaction.StateSchema(
468
- num_uints=params.schema.get("local_uints", 0), num_byte_slices=params.schema.get("local_byte_slices", 0)
469
- ) # type: ignore[no-untyped-call]
470
- if params.schema
471
- else None,
472
- "global_schema": algosdk.transaction.StateSchema(
473
- num_uints=params.schema.get("global_uints", 0),
474
- num_byte_slices=params.schema.get("global_byte_slices", 0),
475
- ) # type: ignore[no-untyped-call]
476
- if params.schema
477
- else None,
478
- }
479
-
480
- if not params.app_id:
481
- if params.approval_program is None or params.clear_program is None:
482
- raise ValueError("approval_program and clear_program are required for application creation")
483
-
484
- txn = algosdk.transaction.ApplicationCreateTxn(**sdk_params) # type: ignore[no-untyped-call]
485
- else:
486
- sdk_params["index"] = params.app_id
487
- txn = algosdk.transaction.ApplicationCallTxn(**sdk_params) # type: ignore[assignment,no-untyped-call]
488
-
489
- return self._common_txn_build_step(params, txn, suggested_params)
490
-
491
- def _build_asset_config(
492
- self, params: AssetConfigParams, suggested_params: algosdk.transaction.SuggestedParams
493
- ) -> algosdk.transaction.Transaction:
494
- txn = algosdk.transaction.AssetConfigTxn(
495
- sender=params.sender,
496
- sp=suggested_params,
497
- index=params.asset_id,
498
- manager=params.manager,
499
- reserve=params.reserve,
500
- freeze=params.freeze,
501
- clawback=params.clawback,
502
- strict_empty_address_check=False,
503
- ) # type: ignore[no-untyped-call]
504
-
505
- return self._common_txn_build_step(params, txn, suggested_params)
506
-
507
- def _build_asset_destroy(
508
- self, params: AssetDestroyParams, suggested_params: algosdk.transaction.SuggestedParams
509
- ) -> algosdk.transaction.Transaction:
510
- txn = algosdk.transaction.AssetDestroyTxn(
511
- sender=params.sender,
512
- sp=suggested_params,
513
- index=params.asset_id,
514
- ) # type: ignore[no-untyped-call]
515
-
516
- return self._common_txn_build_step(params, txn, suggested_params)
517
-
518
- def _build_asset_freeze(
519
- self, params: AssetFreezeParams, suggested_params: algosdk.transaction.SuggestedParams
520
- ) -> algosdk.transaction.Transaction:
521
- txn = algosdk.transaction.AssetFreezeTxn(
522
- sender=params.sender,
523
- sp=suggested_params,
524
- index=params.asset_id,
525
- target=params.account,
526
- new_freeze_state=params.frozen,
527
- ) # type: ignore[no-untyped-call]
528
-
529
- return self._common_txn_build_step(params, txn, suggested_params)
530
-
531
- def _build_asset_transfer(
532
- self, params: AssetTransferParams, suggested_params: algosdk.transaction.SuggestedParams
533
- ) -> algosdk.transaction.Transaction:
534
- txn = algosdk.transaction.AssetTransferTxn(
535
- sender=params.sender,
536
- sp=suggested_params,
537
- receiver=params.receiver,
538
- amt=params.amount,
539
- index=params.asset_id,
540
- close_assets_to=params.close_asset_to,
541
- revocation_target=params.clawback_target,
542
- ) # type: ignore[no-untyped-call]
543
-
544
- return self._common_txn_build_step(params, txn, suggested_params)
545
-
546
- def _build_key_reg(
547
- self, params: OnlineKeyRegParams, suggested_params: algosdk.transaction.SuggestedParams
548
- ) -> algosdk.transaction.Transaction:
549
- txn = algosdk.transaction.KeyregTxn(
550
- sender=params.sender,
551
- sp=suggested_params,
552
- votekey=params.vote_key,
553
- selkey=params.selection_key,
554
- votefst=params.vote_first,
555
- votelst=params.vote_last,
556
- votekd=params.vote_key_dilution,
557
- rekey_to=params.rekey_to,
558
- nonpart=False,
559
- sprfkey=params.state_proof_key,
560
- ) # type: ignore[no-untyped-call]
561
-
562
- return self._common_txn_build_step(params, txn, suggested_params)
563
-
564
- def _is_abi_value(self, x: bool | float | str | bytes | list | TxnParams) -> bool:
565
- if isinstance(x, list):
566
- return len(x) == 0 or all(self._is_abi_value(item) for item in x)
567
-
568
- return isinstance(x, bool | int | float | str | bytes)
569
-
570
- def _build_method_call( # noqa: C901, PLR0912
571
- self, params: MethodCallParams, suggested_params: algosdk.transaction.SuggestedParams
572
- ) -> list[TransactionWithSigner]:
573
- method_args = []
574
- arg_offset = 0
575
-
576
- if params.args:
577
- for i, arg in enumerate(params.args):
578
- if self._is_abi_value(arg):
579
- method_args.append(arg)
580
- continue
581
-
582
- if algosdk.abi.is_abi_transaction_type(params.method.args[i + arg_offset].type):
583
- match arg:
584
- case MethodCallParams():
585
- temp_txn_with_signers = self._build_method_call(arg, suggested_params)
586
- method_args.extend(temp_txn_with_signers)
587
- arg_offset += len(temp_txn_with_signers) - 1
588
- continue
589
- case AppCallParams():
590
- txn = self._build_app_call(arg, suggested_params)
591
- case PayParams():
592
- txn = self._build_payment(arg, suggested_params)
593
- case AssetOptInParams():
594
- txn = self._build_asset_transfer(
595
- AssetTransferParams(**arg.__dict__, receiver=arg.sender, amount=0), suggested_params
596
- )
597
- case AssetCreateParams():
598
- txn = self._build_asset_create(arg, suggested_params)
599
- case AssetConfigParams():
600
- txn = self._build_asset_config(arg, suggested_params)
601
- case AssetDestroyParams():
602
- txn = self._build_asset_destroy(arg, suggested_params)
603
- case AssetFreezeParams():
604
- txn = self._build_asset_freeze(arg, suggested_params)
605
- case AssetTransferParams():
606
- txn = self._build_asset_transfer(arg, suggested_params)
607
- case OnlineKeyRegParams():
608
- txn = self._build_key_reg(arg, suggested_params)
609
- case _:
610
- raise ValueError(f"Unsupported method arg transaction type: {arg}")
611
-
612
- method_args.append(
613
- TransactionWithSigner(txn=txn, signer=params.signer or self.get_signer(params.sender))
614
- )
615
-
616
- continue
617
-
618
- raise ValueError(f"Unsupported method arg: {arg}")
619
-
620
- method_atc = AtomicTransactionComposer()
621
-
622
- method_atc.add_method_call(
623
- app_id=params.app_id or 0,
624
- method=params.method,
625
- sender=params.sender,
626
- sp=suggested_params,
627
- signer=params.signer or self.get_signer(params.sender),
628
- method_args=method_args,
629
- on_complete=algosdk.transaction.OnComplete.NoOpOC,
630
- note=params.note,
631
- lease=params.lease,
632
- )
633
-
634
- return self._build_atc(method_atc)
635
-
636
- def _build_txn( # noqa: C901, PLR0912
637
- self,
638
- txn: TransactionWithSigner | TxnParams | AtomicTransactionComposer,
639
- suggested_params: algosdk.transaction.SuggestedParams,
640
- ) -> list[TransactionWithSigner]:
641
- match txn:
642
- case TransactionWithSigner():
643
- return [txn]
644
- case AtomicTransactionComposer():
645
- return self._build_atc(txn)
646
- case MethodCallParams():
647
- return self._build_method_call(txn, suggested_params)
648
-
649
- signer = txn.signer or self.get_signer(txn.sender)
650
-
651
- match txn:
652
- case PayParams():
653
- payment = self._build_payment(txn, suggested_params)
654
- return [TransactionWithSigner(txn=payment, signer=signer)]
655
- case AssetCreateParams():
656
- asset_create = self._build_asset_create(txn, suggested_params)
657
- return [TransactionWithSigner(txn=asset_create, signer=signer)]
658
- case AppCallParams():
659
- app_call = self._build_app_call(txn, suggested_params)
660
- return [TransactionWithSigner(txn=app_call, signer=signer)]
661
- case AssetConfigParams():
662
- asset_config = self._build_asset_config(txn, suggested_params)
663
- return [TransactionWithSigner(txn=asset_config, signer=signer)]
664
- case AssetDestroyParams():
665
- asset_destroy = self._build_asset_destroy(txn, suggested_params)
666
- return [TransactionWithSigner(txn=asset_destroy, signer=signer)]
667
- case AssetFreezeParams():
668
- asset_freeze = self._build_asset_freeze(txn, suggested_params)
669
- return [TransactionWithSigner(txn=asset_freeze, signer=signer)]
670
- case AssetTransferParams():
671
- asset_transfer = self._build_asset_transfer(txn, suggested_params)
672
- return [TransactionWithSigner(txn=asset_transfer, signer=signer)]
673
- case AssetOptInParams():
674
- asset_transfer = self._build_asset_transfer(
675
- AssetTransferParams(**txn.__dict__, receiver=txn.sender, amount=0), suggested_params
676
- )
677
- return [TransactionWithSigner(txn=asset_transfer, signer=signer)]
678
- case OnlineKeyRegParams():
679
- key_reg = self._build_key_reg(txn, suggested_params)
680
- return [TransactionWithSigner(txn=key_reg, signer=signer)]
681
- case _:
682
- raise ValueError(f"Unsupported txn: {txn}")
683
-
684
- def build_group(self) -> list[TransactionWithSigner]:
685
- suggested_params = self.get_suggested_params()
686
-
687
- txn_with_signers: list[TransactionWithSigner] = []
688
-
689
- for txn in self.txns:
690
- txn_with_signers.extend(self._build_txn(txn, suggested_params))
691
-
692
- for ts in txn_with_signers:
693
- self.atc.add_transaction(ts)
694
-
695
- method_calls = {}
696
-
697
- for i, ts in enumerate(txn_with_signers):
698
- method = self.txn_method_map.get(ts.txn.get_txid()) # type: ignore[no-untyped-call]
699
- if method:
700
- method_calls[i] = method
701
-
702
- self.atc.method_dict = method_calls
703
-
704
- return self.atc.build_group()
705
-
706
- def execute(self, *, max_rounds_to_wait: int | None = None) -> AtomicTransactionResponse:
707
- group = self.build_group()
708
-
709
- wait_rounds = max_rounds_to_wait
710
-
711
- if wait_rounds is None:
712
- last_round = max(txn.txn.last_valid_round for txn in group)
713
- first_round = self.get_suggested_params().first
714
- wait_rounds = last_round - first_round
715
-
716
- return self.atc.execute(client=self.algod, wait_rounds=wait_rounds)
9
+ handle_getattr(name)