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

@@ -177,10 +177,10 @@ def get_account(
177
177
  For LocalNet environments, loads or creates an account from a KMD wallet named {name}.
178
178
 
179
179
  :example:
180
- >>> # If you have a mnemonic secret loaded into `os.environ["ACCOUNT_MNEMONIC"]` then you can call:
181
- >>> account = get_account('ACCOUNT', algod)
182
- >>> # If that code runs against LocalNet then a wallet called 'ACCOUNT' will automatically be created
183
- >>> # with an account that is automatically funded with 1000 (default) ALGOs from the default LocalNet dispenser.
180
+ >>> # If you have a mnemonic secret loaded into `os.environ["ACCOUNT_MNEMONIC"]` then you can call:
181
+ >>> account = get_account('ACCOUNT', algod)
182
+ >>> # If that code runs against LocalNet then a wallet called 'ACCOUNT' will automatically be created
183
+ >>> # with an account that is automatically funded with 1000 (default) ALGOs from the default LocalNet dispenser.
184
184
 
185
185
  :param client: The Algorand client to use
186
186
  :param name: The name identifier to use for loading/creating the account
@@ -148,7 +148,7 @@ class AccountManager:
148
148
  :param client_manager: The ClientManager client to use for algod and kmd clients
149
149
 
150
150
  :example:
151
- >>> account_manager = AccountManager(client_manager)
151
+ >>> account_manager = AccountManager(client_manager)
152
152
  """
153
153
 
154
154
  def __init__(self, client_manager: ClientManager):
@@ -172,11 +172,11 @@ class AccountManager:
172
172
  :returns: The `AccountManager` so method calls can be chained
173
173
 
174
174
  :example:
175
- >>> signer_account = account_manager.random()
176
- >>> account_manager.set_default_signer(signer_account.signer)
177
- >>> # When signing a transaction, if there is no signer registered for the sender
178
- >>> # then the default signer will be used
179
- >>> signer = account_manager.get_signer("{SENDERADDRESS}")
175
+ >>> signer_account = account_manager.random()
176
+ >>> account_manager.set_default_signer(signer_account.signer)
177
+ >>> # When signing a transaction, if there is no signer registered for the sender
178
+ >>> # then the default signer will be used
179
+ >>> signer = account_manager.get_signer("{SENDERADDRESS}")
180
180
  """
181
181
  self._default_signer = signer if isinstance(signer, TransactionSigner) else signer.signer
182
182
  return self
@@ -190,7 +190,7 @@ class AccountManager:
190
190
  :returns: The `AccountManager` instance for method chaining
191
191
 
192
192
  :example:
193
- >>> account_manager.set_signer("SENDERADDRESS", transaction_signer)
193
+ >>> account_manager.set_signer("SENDERADDRESS", transaction_signer)
194
194
  """
195
195
  self._accounts[sender] = TransactionSignerAccount(address=sender, signer=signer)
196
196
  return self
@@ -221,11 +221,11 @@ class AccountManager:
221
221
  :returns: The `AccountManager` instance for method chaining
222
222
 
223
223
  :example:
224
- >>> account_manager = AccountManager(client_manager)
225
- >>> account_manager.set_signer_from_account(SigningAccount(private_key=algosdk.account.generate_account()[0]))
226
- >>> account_manager.set_signer_from_account(LogicSigAccount(AlgosdkLogicSigAccount(program, args)))
227
- >>> account_manager.set_signer_from_account(MultiSigAccount(multisig_params, [account1, account2]))
228
- """
224
+ >>> account_manager = AccountManager(client_manager)
225
+ >>> account_manager.set_signer_from_account(SigningAccount(private_key=algosdk.account.generate_account()[0]))
226
+ >>> account_manager.set_signer_from_account(LogicSigAccount(AlgosdkLogicSigAccount(program, args)))
227
+ >>> account_manager.set_signer_from_account(MultiSigAccount(multisig_params, [account1, account2]))
228
+ """ # noqa: E501
229
229
  self._accounts[account.address] = account
230
230
  return self
231
231
 
@@ -240,7 +240,7 @@ class AccountManager:
240
240
  :raises ValueError: If no signer is found and no default signer is set
241
241
 
242
242
  :example:
243
- >>> signer = account_manager.get_signer("SENDERADDRESS")
243
+ >>> signer = account_manager.get_signer("SENDERADDRESS")
244
244
  """
245
245
  signer = self._accounts.get(self._get_address(sender)) or self._default_signer
246
246
  if not signer:
@@ -256,10 +256,10 @@ class AccountManager:
256
256
  :raises ValueError: If no account is found or if the account is not a regular account
257
257
 
258
258
  :example:
259
- >>> sender = account_manager.random().address
260
- >>> # ...
261
- >>> # Returns the `TransactionSignerAccountProtocol` for `sender` that has previously been registered
262
- >>> account = account_manager.get_account(sender)
259
+ >>> sender = account_manager.random().address
260
+ >>> # ...
261
+ >>> # Returns the `TransactionSignerAccountProtocol` for `sender` that has previously been registered
262
+ >>> account = account_manager.get_account(sender)
263
263
  """
264
264
  account = self._accounts.get(sender)
265
265
  if not account:
@@ -279,8 +279,8 @@ class AccountManager:
279
279
  :returns: The account information
280
280
 
281
281
  :example:
282
- >>> address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA"
283
- >>> account_info = account_manager.get_information(address)
282
+ >>> address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA"
283
+ >>> account_info = account_manager.get_information(address)
284
284
  """
285
285
  info = self._client_manager.algod.account_info(self._get_address(sender))
286
286
  assert isinstance(info, dict)
@@ -342,7 +342,7 @@ class AccountManager:
342
342
  from the environment (ideally via a secret storage service) rather than the file system.
343
343
 
344
344
  :example:
345
- >>> account = account_manager.from_mnemonic("mnemonic secret ...")
345
+ >>> account = account_manager.from_mnemonic("mnemonic secret ...")
346
346
  """
347
347
  return self._register_account(to_private_key(mnemonic), sender)
348
348
 
@@ -355,7 +355,7 @@ class AccountManager:
355
355
 
356
356
  :param name: The name identifier of the account
357
357
  :param fund_with: Optional amount to fund the account with when it gets created
358
- (when targeting LocalNet)
358
+ (when targeting LocalNet)
359
359
  :returns: The account
360
360
  :raises ValueError: If environment variable {NAME}_MNEMONIC is missing when looking for account {NAME}
361
361
 
@@ -368,10 +368,10 @@ class AccountManager:
368
368
  it will create it and fund the account for you
369
369
 
370
370
  :example:
371
- >>> # If you have a mnemonic secret loaded into `MY_ACCOUNT_MNEMONIC` then you can call:
372
- >>> account = account_manager.from_environment('MY_ACCOUNT')
373
- >>> # If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created
374
- >>> # with an account that is automatically funded with the specified amount from the default LocalNet dispenser
371
+ >>> # If you have a mnemonic secret loaded into `MY_ACCOUNT_MNEMONIC` then you can call:
372
+ >>> account = account_manager.from_environment('MY_ACCOUNT')
373
+ >>> # If that code runs against LocalNet then a wallet called `MY_ACCOUNT` will automatically be created
374
+ >>> # with an account that is automatically funded with the specified amount from the LocalNet dispenser
375
375
  """
376
376
  account_mnemonic = os.getenv(f"{name.upper()}_MNEMONIC")
377
377
 
@@ -398,10 +398,10 @@ class AccountManager:
398
398
  :raises ValueError: If unable to find KMD account with given name and predicate
399
399
 
400
400
  :example:
401
- >>> # Get default funded account in a LocalNet:
402
- >>> defaultDispenserAccount = account.from_kmd('unencrypted-default-wallet',
403
- ... lambda a: a.status != 'Offline' and a.amount > 1_000_000_000
404
- ... )
401
+ >>> # Get default funded account in a LocalNet:
402
+ >>> defaultDispenserAccount = account.from_kmd('unencrypted-default-wallet',
403
+ ... lambda a: a.status != 'Offline' and a.amount > 1_000_000_000
404
+ ... )
405
405
  """
406
406
  kmd_account = self._kmd_account_manager.get_wallet_account(name, predicate, sender)
407
407
  if not kmd_account:
@@ -418,7 +418,7 @@ class AccountManager:
418
418
  :returns: A logic signature account wrapper
419
419
 
420
420
  :example:
421
- >>> account = account.logic_sig(program, [new Uint8Array(3, ...)])
421
+ >>> account = account.logic_sig(program, [new Uint8Array(3, ...)])
422
422
  """
423
423
  return self._register_logicsig(program, args)
424
424
 
@@ -431,12 +431,12 @@ class AccountManager:
431
431
  :returns: A multisig account wrapper
432
432
 
433
433
  :example:
434
- >>> account = account_manager.multi_sig(
435
- ... version=1,
436
- ... threshold=1,
437
- ... addrs=["ADDRESS1...", "ADDRESS2..."],
438
- ... signing_accounts=[account1, account2]
439
- ... )
434
+ >>> account = account_manager.multi_sig(
435
+ ... version=1,
436
+ ... threshold=1,
437
+ ... addrs=["ADDRESS1...", "ADDRESS2..."],
438
+ ... signing_accounts=[account1, account2]
439
+ ... )
440
440
  """
441
441
  return self._register_multisig(metadata, signing_accounts)
442
442
 
@@ -447,7 +447,7 @@ class AccountManager:
447
447
  :returns: The account
448
448
 
449
449
  :example:
450
- >>> account = account_manager.random()
450
+ >>> account = account_manager.random()
451
451
  """
452
452
  private_key, _ = algosdk.account.generate_account()
453
453
  return self._register_account(private_key)
@@ -461,7 +461,7 @@ class AccountManager:
461
461
  :returns: The account
462
462
 
463
463
  :example:
464
- >>> account = account_manager.localnet_dispenser()
464
+ >>> account = account_manager.localnet_dispenser()
465
465
  """
466
466
  kmd_account = self._kmd_account_manager.get_localnet_dispenser_account()
467
467
  return self._register_account(kmd_account.private_key)
@@ -475,7 +475,7 @@ class AccountManager:
475
475
  :returns: The account
476
476
 
477
477
  :example:
478
- >>> account = account_manager.dispenser_from_environment()
478
+ >>> account = account_manager.dispenser_from_environment()
479
479
  """
480
480
  name = os.getenv(f"{DISPENSER_ACCOUNT_NAME}_MNEMONIC")
481
481
  if name:
@@ -493,8 +493,8 @@ class AccountManager:
493
493
  :returns: The rekeyed account
494
494
 
495
495
  :example:
496
- >>> account = account.from_mnemonic("mnemonic secret ...")
497
- >>> rekeyed_account = account_manager.rekeyed(account, "SENDERADDRESS...")
496
+ >>> account = account.from_mnemonic("mnemonic secret ...")
497
+ >>> rekeyed_account = account_manager.rekeyed(account, "SENDERADDRESS...")
498
498
  """
499
499
  sender_address = sender.address if isinstance(sender, SigningAccount) else sender
500
500
  self._accounts[sender_address] = TransactionSignerAccount(address=sender_address, signer=account.signer)
@@ -540,23 +540,23 @@ class AccountManager:
540
540
  `official rekey guidance <https://developer.algorand.org/docs/get-details/accounts/rekey/>`_.
541
541
 
542
542
  :example:
543
- >>> # Basic example (with string addresses):
544
- >>> algorand.account.rekey_account({account: "ACCOUNTADDRESS", rekey_to: "NEWADDRESS"})
545
- >>> # Basic example (with signer accounts):
546
- >>> algorand.account.rekey_account({account: account1, rekey_to: newSignerAccount})
547
- >>> # Advanced example:
548
- >>> algorand.account.rekey_account({
549
- ... account: "ACCOUNTADDRESS",
550
- ... rekey_to: "NEWADDRESS",
551
- ... lease: 'lease',
552
- ... note: 'note',
553
- ... first_valid_round: 1000,
554
- ... validity_window: 10,
555
- ... extra_fee: AlgoAmount.from_micro_algo(1000),
556
- ... static_fee: AlgoAmount.from_micro_algo(1000),
557
- ... max_fee: AlgoAmount.from_micro_algo(3000),
558
- ... suppress_log: True,
559
- ... })
543
+ >>> # Basic example (with string addresses):
544
+ >>> algorand.account.rekey_account({account: "ACCOUNTADDRESS", rekey_to: "NEWADDRESS"})
545
+ >>> # Basic example (with signer accounts):
546
+ >>> algorand.account.rekey_account({account: account1, rekey_to: newSignerAccount})
547
+ >>> # Advanced example:
548
+ >>> algorand.account.rekey_account({
549
+ ... account: "ACCOUNTADDRESS",
550
+ ... rekey_to: "NEWADDRESS",
551
+ ... lease: 'lease',
552
+ ... note: 'note',
553
+ ... first_valid_round: 1000,
554
+ ... validity_window: 10,
555
+ ... extra_fee: AlgoAmount.from_micro_algo(1000),
556
+ ... static_fee: AlgoAmount.from_micro_algo(1000),
557
+ ... max_fee: AlgoAmount.from_micro_algo(3000),
558
+ ... suppress_log: True,
559
+ ... })
560
560
  """
561
561
  sender_address = self._get_address(account)
562
562
  rekey_address = self._get_address(rekey_to)
@@ -623,7 +623,7 @@ class AccountManager:
623
623
  :param account_to_fund: The account to fund
624
624
  :param dispenser_account: The account to use as a dispenser funding source
625
625
  :param min_spending_balance: The minimum balance of Algo that the account
626
- should have available to spend
626
+ should have available to spend
627
627
  :param min_funding_increment: Optional minimum funding increment
628
628
  :param send_params: Parameters for the send operation, defaults to None
629
629
  :param signer: Optional transaction signer
@@ -637,20 +637,20 @@ class AccountManager:
637
637
  :param first_valid_round: Optional first valid round
638
638
  :param last_valid_round: Optional last valid round
639
639
  :returns: The result of executing the dispensing transaction and the `amountFunded` if funds were needed,
640
- or None if no funds were needed
640
+ or None if no funds were needed
641
641
 
642
642
  :example:
643
- >>> # Basic example:
644
- >>> algorand.account.ensure_funded("ACCOUNTADDRESS", "DISPENSERADDRESS", algokit.algo(1))
645
- >>> # With configuration:
646
- >>> algorand.account.ensure_funded(
647
- ... "ACCOUNTADDRESS",
648
- ... "DISPENSERADDRESS",
649
- ... algokit.algo(1),
650
- ... min_funding_increment=algokit.algo(2),
651
- ... fee=AlgoAmount.from_micro_algo(1000),
652
- ... suppress_log=True
653
- ... )
643
+ >>> # Basic example:
644
+ >>> algorand.account.ensure_funded("ACCOUNTADDRESS", "DISPENSERADDRESS", algokit.algo(1))
645
+ >>> # With configuration:
646
+ >>> algorand.account.ensure_funded(
647
+ ... "ACCOUNTADDRESS",
648
+ ... "DISPENSERADDRESS",
649
+ ... algokit.algo(1),
650
+ ... min_funding_increment=algokit.algo(2),
651
+ ... fee=AlgoAmount.from_micro_algo(1000),
652
+ ... suppress_log=True
653
+ ... )
654
654
  """
655
655
  account_to_fund = self._get_address(account_to_fund)
656
656
  dispenser_account = self._get_address(dispenser_account)
@@ -724,7 +724,7 @@ class AccountManager:
724
724
 
725
725
  :param account_to_fund: The account to fund
726
726
  :param min_spending_balance: The minimum balance of Algo that the account should have available to
727
- spend
727
+ spend
728
728
  :param min_funding_increment: Optional minimum funding increment
729
729
  :param send_params: Parameters for the send operation, defaults to None
730
730
  :param signer: Optional transaction signer
@@ -738,7 +738,7 @@ class AccountManager:
738
738
  :param first_valid_round: Optional first valid round
739
739
  :param last_valid_round: Optional last valid round
740
740
  :returns: The result of executing the dispensing transaction and the `amountFunded` if funds were needed, or
741
- None if no funds were needed
741
+ None if no funds were needed
742
742
 
743
743
  .. note::
744
744
  The dispenser account is retrieved from the account mnemonic stored in
@@ -746,16 +746,16 @@ class AccountManager:
746
746
  if it's a rekeyed account, or against default LocalNet if no environment variables present.
747
747
 
748
748
  :example:
749
- >>> # Basic example:
750
- >>> algorand.account.ensure_funded_from_environment("ACCOUNTADDRESS", algokit.algo(1))
751
- >>> # With configuration:
752
- >>> algorand.account.ensure_funded_from_environment(
753
- ... "ACCOUNTADDRESS",
754
- ... algokit.algo(1),
755
- ... min_funding_increment=algokit.algo(2),
756
- ... fee=AlgoAmount.from_micro_algo(1000),
757
- ... suppress_log=True
758
- ... )
749
+ >>> # Basic example:
750
+ >>> algorand.account.ensure_funded_from_environment("ACCOUNTADDRESS", algokit.algo(1))
751
+ >>> # With configuration:
752
+ >>> algorand.account.ensure_funded_from_environment(
753
+ ... "ACCOUNTADDRESS",
754
+ ... algokit.algo(1),
755
+ ... min_funding_increment=algokit.algo(2),
756
+ ... fee=AlgoAmount.from_micro_algo(1000),
757
+ ... suppress_log=True
758
+ ... )
759
759
  """
760
760
  account_to_fund = self._get_address(account_to_fund)
761
761
  dispenser_account = self.dispenser_from_environment()
@@ -818,26 +818,26 @@ class AccountManager:
818
818
  :param account_to_fund: The account to fund
819
819
  :param dispenser_client: The TestNet dispenser funding client
820
820
  :param min_spending_balance: The minimum balance of Algo that the account should have
821
- available to spend
821
+ available to spend
822
822
  :param min_funding_increment: Optional minimum funding increment
823
823
  :returns: The result of executing the dispensing transaction and the `amountFunded` if funds were needed, or
824
- None if no funds were needed
824
+ None if no funds were needed
825
825
  :raises ValueError: If attempting to fund on non-TestNet network
826
826
 
827
827
  :example:
828
- >>> # Basic example:
829
- >>> algorand.account.ensure_funded_from_testnet_dispenser_api(
830
- ... "ACCOUNTADDRESS",
831
- ... algorand.client.get_testnet_dispenser_from_environment(),
832
- ... algokit.algo(1)
833
- ... )
834
- >>> # With configuration:
835
- >>> algorand.account.ensure_funded_from_testnet_dispenser_api(
836
- ... "ACCOUNTADDRESS",
837
- ... algorand.client.get_testnet_dispenser_from_environment(),
838
- ... algokit.algo(1),
839
- ... min_funding_increment=algokit.algo(2)
840
- ... )
828
+ >>> # Basic example:
829
+ >>> algorand.account.ensure_funded_from_testnet_dispenser_api(
830
+ ... "ACCOUNTADDRESS",
831
+ ... algorand.client.get_testnet_dispenser_from_environment(),
832
+ ... algokit.algo(1)
833
+ ... )
834
+ >>> # With configuration:
835
+ >>> algorand.account.ensure_funded_from_testnet_dispenser_api(
836
+ ... "ACCOUNTADDRESS",
837
+ ... algorand.client.get_testnet_dispenser_from_environment(),
838
+ ... algokit.algo(1),
839
+ ... min_funding_increment=algokit.algo(2)
840
+ ... )
841
841
  """
842
842
  account_to_fund = self._get_address(account_to_fund)
843
843
 
@@ -48,6 +48,8 @@ class KmdAccountManager:
48
48
  if self._kmd is None:
49
49
  if self._client_manager.is_localnet():
50
50
  kmd_config = ClientManager.get_config_from_environment_or_localnet()
51
+ if not kmd_config.kmd_config:
52
+ raise Exception("Attempt to use KMD client with no KMD configured")
51
53
  self._kmd = ClientManager.get_kmd_client(kmd_config.kmd_config)
52
54
  return self._kmd
53
55
  raise Exception("Attempt to use KMD client with no KMD configured")
@@ -5,7 +5,7 @@ import copy
5
5
  import json
6
6
  import os
7
7
  from collections.abc import Sequence
8
- from dataclasses import asdict, dataclass, fields
8
+ from dataclasses import asdict, dataclass, fields, replace
9
9
  from typing import TYPE_CHECKING, Any, Generic, Literal, TypedDict, TypeVar
10
10
 
11
11
  import algosdk
@@ -54,6 +54,7 @@ from algokit_utils.transactions.transaction_composer import (
54
54
  AppUpdateParams,
55
55
  BuiltTransactions,
56
56
  PaymentParams,
57
+ SendAtomicTransactionComposerResults,
57
58
  )
58
59
  from algokit_utils.transactions.transaction_sender import (
59
60
  SendAppTransactionResult,
@@ -1189,28 +1190,51 @@ class _TransactionSender:
1189
1190
  :param params: Parameters for the application call including method and transaction options
1190
1191
  :param send_params: Send parameters
1191
1192
  :return: The result of sending or simulating the transaction, including ABI return value if applicable
1193
+ :raises ValueError: If the transaction is read-only and `max_fee` is not provided
1192
1194
  """
1193
1195
  is_read_only_call = (
1194
1196
  params.on_complete == algosdk.transaction.OnComplete.NoOpOC or params.on_complete is None
1195
1197
  ) and self._app_spec.get_arc56_method(params.method).readonly
1196
1198
 
1197
1199
  if is_read_only_call:
1200
+ readonly_params = params
1201
+ readonly_send_params = send_params or SendParams()
1202
+
1203
+ # Read-only calls do not require fees to be paid, as they are only simulated on the network.
1204
+ # Therefore there is no value in calculating the minimum fee needed for a successful app call with inners.
1205
+ # As a a result we only need to send a single simulate call,
1206
+ # however to do this successfully we need to ensure fees for the transaction are fully covered using maxFee.
1207
+ if readonly_send_params.get("cover_app_call_inner_transaction_fees"):
1208
+ if params.max_fee is None:
1209
+ raise ValueError(
1210
+ "Please provide a `max_fee` for the transaction when `cover_app_call_inner_transaction_fees` is enabled." # noqa: E501
1211
+ )
1212
+ readonly_params = replace(readonly_params, static_fee=params.max_fee, extra_fee=None)
1213
+
1198
1214
  method_call_to_simulate = self._algorand.new_group().add_app_call_method_call(
1199
- self._client.params.call(params)
1200
- )
1201
- send_params = send_params or SendParams()
1202
- simulate_response = self._client._handle_call_errors(
1203
- lambda: method_call_to_simulate.simulate(
1204
- allow_unnamed_resources=send_params.get("populate_app_call_resources") or True,
1205
- skip_signatures=True,
1206
- allow_more_logs=True,
1207
- allow_empty_signatures=True,
1208
- extra_opcode_budget=None,
1209
- exec_trace_config=None,
1210
- simulation_round=None,
1211
- )
1215
+ self._client.params.call(readonly_params)
1212
1216
  )
1213
1217
 
1218
+ def run_simulate() -> SendAtomicTransactionComposerResults:
1219
+ try:
1220
+ return method_call_to_simulate.simulate(
1221
+ allow_unnamed_resources=readonly_send_params.get("populate_app_call_resources") or True,
1222
+ skip_signatures=True,
1223
+ allow_more_logs=True,
1224
+ allow_empty_signatures=True,
1225
+ extra_opcode_budget=None,
1226
+ exec_trace_config=None,
1227
+ simulation_round=None,
1228
+ )
1229
+ except Exception as e:
1230
+ if readonly_send_params.get("cover_app_call_inner_transaction_fees") and "fee too small" in str(e):
1231
+ raise ValueError(
1232
+ "Fees were too small. You may need to increase the transaction `maxFee`."
1233
+ ) from e
1234
+ raise
1235
+
1236
+ simulate_response = self._client._handle_call_errors(run_simulate)
1237
+
1214
1238
  return SendAppTransactionResult[Arc56ReturnValueType](
1215
1239
  tx_ids=simulate_response.tx_ids,
1216
1240
  transactions=simulate_response.transactions,
@@ -43,13 +43,13 @@ class AssetInformation:
43
43
  :ivar decimals: The amount of decimal places the asset was created with
44
44
  :ivar default_frozen: Whether the asset was frozen by default for all accounts, defaults to None
45
45
  :ivar manager: The address of the optional account that can manage the configuration of the asset and destroy it,
46
- defaults to None
46
+ defaults to None
47
47
  :ivar reserve: The address of the optional account that holds the reserve (uncirculated supply) units of the asset,
48
- defaults to None
48
+ defaults to None
49
49
  :ivar freeze: The address of the optional account that can be used to freeze or unfreeze holdings of this asset,
50
- defaults to None
50
+ defaults to None
51
51
  :ivar clawback: The address of the optional account that can clawback holdings of this asset from any account,
52
- defaults to None
52
+ defaults to None
53
53
  :ivar unit_name: The optional name of the unit of this asset (e.g. ticker name), defaults to None
54
54
  :ivar unit_name_b64: The optional name of the unit of this asset as bytes, defaults to None
55
55
  :ivar asset_name: The optional name of the asset, defaults to None
@@ -57,7 +57,7 @@ class AssetInformation:
57
57
  :ivar url: Optional URL where more information about the asset can be retrieved, defaults to None
58
58
  :ivar url_b64: Optional URL where more information about the asset can be retrieved as bytes, defaults to None
59
59
  :ivar metadata_hash: 32-byte hash of some metadata that is relevant to the asset and/or asset holders,
60
- defaults to None
60
+ defaults to None
61
61
  """
62
62
 
63
63
  asset_id: int
@@ -77,8 +77,8 @@ def _get_config_from_environment(environment_prefix: str) -> AlgoClientNetworkCo
77
77
  port = os.getenv(f"{environment_prefix}_PORT")
78
78
  if port:
79
79
  parsed = parse.urlparse(server)
80
- server = parsed._replace(netloc=f"{parsed.hostname}:{port}").geturl()
81
- return AlgoClientNetworkConfig(server, os.getenv(f"{environment_prefix}_TOKEN", ""))
80
+ server = parsed._replace(netloc=f"{parsed.hostname}").geturl()
81
+ return AlgoClientNetworkConfig(server, os.getenv(f"{environment_prefix}_TOKEN", ""), port=port)
82
82
 
83
83
 
84
84
  class ClientManager:
@@ -351,15 +351,18 @@ class ClientManager:
351
351
  )
352
352
 
353
353
  @staticmethod
354
- def get_algod_client(config: AlgoClientNetworkConfig | None = None) -> AlgodClient:
354
+ def get_algod_client(config: AlgoClientNetworkConfig) -> AlgodClient:
355
355
  """Get an Algod client from config or environment.
356
356
 
357
357
  :param config: Optional client configuration
358
358
  :return: Algod client instance
359
359
  """
360
- config = config or _get_config_from_environment("ALGOD")
361
360
  headers = {"X-Algo-API-Token": config.token or ""}
362
- return AlgodClient(algod_token=config.token or "", algod_address=config.server, headers=headers)
361
+ return AlgodClient(
362
+ algod_token=config.token or "",
363
+ algod_address=config.full_url(),
364
+ headers=headers,
365
+ )
363
366
 
364
367
  @staticmethod
365
368
  def get_algod_client_from_environment() -> AlgodClient:
@@ -370,14 +373,13 @@ class ClientManager:
370
373
  return ClientManager.get_algod_client(ClientManager.get_algod_config_from_environment())
371
374
 
372
375
  @staticmethod
373
- def get_kmd_client(config: AlgoClientNetworkConfig | None = None) -> KMDClient:
376
+ def get_kmd_client(config: AlgoClientNetworkConfig) -> KMDClient:
374
377
  """Get a KMD client from config or environment.
375
378
 
376
379
  :param config: Optional client configuration
377
380
  :return: KMD client instance
378
381
  """
379
- config = config or _get_config_from_environment("KMD")
380
- return KMDClient(config.token, config.server)
382
+ return KMDClient(config.token, config.full_url())
381
383
 
382
384
  @staticmethod
383
385
  def get_kmd_client_from_environment() -> KMDClient:
@@ -388,15 +390,18 @@ class ClientManager:
388
390
  return ClientManager.get_kmd_client(ClientManager.get_kmd_config_from_environment())
389
391
 
390
392
  @staticmethod
391
- def get_indexer_client(config: AlgoClientNetworkConfig | None = None) -> IndexerClient:
393
+ def get_indexer_client(config: AlgoClientNetworkConfig) -> IndexerClient:
392
394
  """Get an Indexer client from config or environment.
393
395
 
394
396
  :param config: Optional client configuration
395
397
  :return: Indexer client instance
396
398
  """
397
- config = config or _get_config_from_environment("INDEXER")
398
399
  headers = {"X-Indexer-API-Token": config.token}
399
- return IndexerClient(indexer_token=config.token, indexer_address=config.server, headers=headers)
400
+ return IndexerClient(
401
+ indexer_token=config.token,
402
+ indexer_address=config.full_url(),
403
+ headers=headers,
404
+ )
400
405
 
401
406
  @staticmethod
402
407
  def get_indexer_client_from_environment() -> IndexerClient:
@@ -611,7 +616,7 @@ class ClientManager:
611
616
  else {"algod": 4001, "indexer": 8980, "kmd": 4002}[config_or_port]
612
617
  )
613
618
 
614
- return AlgoClientNetworkConfig(server=f"http://localhost:{port}", token="a" * 64)
619
+ return AlgoClientNetworkConfig(server="http://localhost", token="a" * 64, port=port)
615
620
 
616
621
  @staticmethod
617
622
  def get_algod_config_from_environment() -> AlgoClientNetworkConfig:
@@ -13,58 +13,34 @@ class AlgoAmount:
13
13
  """Wrapper class to ensure safe, explicit conversion between µAlgo, Algo and numbers.
14
14
 
15
15
  :example:
16
- >>> amount = AlgoAmount(algos=1)
17
- >>> amount = AlgoAmount(algo=1)
18
- >>> amount = AlgoAmount.from_algos(1)
19
- >>> amount = AlgoAmount.from_algo(1)
20
- >>> amount = AlgoAmount(micro_algos=1_000_000)
21
- >>> amount = AlgoAmount(micro_algo=1_000_000)
22
- >>> amount = AlgoAmount.from_micro_algos(1_000_000)
23
- >>> amount = AlgoAmount.from_micro_algo(1_000_000)
16
+ >>> amount = AlgoAmount(algo=1)
17
+ >>> amount = AlgoAmount.from_algo(1)
18
+ >>> amount = AlgoAmount(micro_algo=1_000_000)
19
+ >>> amount = AlgoAmount.from_micro_algo(1_000_000)
24
20
  """
25
21
 
26
- @overload
27
- def __init__(self, *, micro_algos: int) -> None: ...
28
-
29
22
  @overload
30
23
  def __init__(self, *, micro_algo: int) -> None: ...
31
24
 
32
- @overload
33
- def __init__(self, *, algos: int | Decimal) -> None: ...
34
-
35
25
  @overload
36
26
  def __init__(self, *, algo: int | Decimal) -> None: ...
37
27
 
38
28
  def __init__(
39
29
  self,
40
30
  *,
41
- micro_algos: int | None = None,
42
31
  micro_algo: int | None = None,
43
- algos: int | Decimal | None = None,
44
32
  algo: int | Decimal | None = None,
45
33
  ):
46
- if micro_algos is None and micro_algo is None and algos is None and algo is None:
34
+ if micro_algo is None and algo is None:
47
35
  raise ValueError("No amount provided")
48
36
 
49
- if micro_algos is not None:
50
- self.amount_in_micro_algo = int(micro_algos)
51
- elif micro_algo is not None:
37
+ if micro_algo is not None:
52
38
  self.amount_in_micro_algo = int(micro_algo)
53
- elif algos is not None:
54
- self.amount_in_micro_algo = int(algos * algosdk.constants.MICROALGOS_TO_ALGOS_RATIO)
55
39
  elif algo is not None:
56
40
  self.amount_in_micro_algo = int(algo * algosdk.constants.MICROALGOS_TO_ALGOS_RATIO)
57
41
  else:
58
42
  raise ValueError("Invalid amount provided")
59
43
 
60
- @property
61
- def micro_algos(self) -> int:
62
- """Return the amount as a number in µAlgo.
63
-
64
- :returns: The amount in µAlgo.
65
- """
66
- return self.amount_in_micro_algo
67
-
68
44
  @property
69
45
  def micro_algo(self) -> int:
70
46
  """Return the amount as a number in µAlgo.
@@ -73,14 +49,6 @@ class AlgoAmount:
73
49
  """
74
50
  return self.amount_in_micro_algo
75
51
 
76
- @property
77
- def algos(self) -> Decimal:
78
- """Return the amount as a number in Algo.
79
-
80
- :returns: The amount in Algo.
81
- """
82
- return algosdk.util.microalgos_to_algos(self.amount_in_micro_algo) # type: ignore[no-any-return]
83
-
84
52
  @property
85
53
  def algo(self) -> Decimal:
86
54
  """Return the amount as a number in Algo.
@@ -89,18 +57,6 @@ class AlgoAmount:
89
57
  """
90
58
  return algosdk.util.microalgos_to_algos(self.amount_in_micro_algo) # type: ignore[no-any-return]
91
59
 
92
- @staticmethod
93
- def from_algos(amount: int | Decimal) -> AlgoAmount:
94
- """Create an AlgoAmount object representing the given number of Algo.
95
-
96
- :param amount: The amount in Algo.
97
- :returns: An AlgoAmount instance.
98
-
99
- :example:
100
- >>> amount = AlgoAmount.from_algos(1)
101
- """
102
- return AlgoAmount(algos=amount)
103
-
104
60
  @staticmethod
105
61
  def from_algo(amount: int | Decimal) -> AlgoAmount:
106
62
  """Create an AlgoAmount object representing the given number of Algo.
@@ -109,22 +65,10 @@ class AlgoAmount:
109
65
  :returns: An AlgoAmount instance.
110
66
 
111
67
  :example:
112
- >>> amount = AlgoAmount.from_algo(1)
68
+ >>> amount = AlgoAmount.from_algo(1)
113
69
  """
114
70
  return AlgoAmount(algo=amount)
115
71
 
116
- @staticmethod
117
- def from_micro_algos(amount: int) -> AlgoAmount:
118
- """Create an AlgoAmount object representing the given number of µAlgo.
119
-
120
- :param amount: The amount in µAlgo.
121
- :returns: An AlgoAmount instance.
122
-
123
- :example:
124
- >>> amount = AlgoAmount.from_micro_algos(1_000_000)
125
- """
126
- return AlgoAmount(micro_algos=amount)
127
-
128
72
  @staticmethod
129
73
  def from_micro_algo(amount: int) -> AlgoAmount:
130
74
  """Create an AlgoAmount object representing the given number of µAlgo.
@@ -133,7 +77,7 @@ class AlgoAmount:
133
77
  :returns: An AlgoAmount instance.
134
78
 
135
79
  :example:
136
- >>> amount = AlgoAmount.from_micro_algo(1_000_000)
80
+ >>> amount = AlgoAmount.from_micro_algo(1_000_000)
137
81
  """
138
82
  return AlgoAmount(micro_algo=amount)
139
83
 
@@ -141,21 +85,21 @@ class AlgoAmount:
141
85
  return f"{self.micro_algo:,} µALGO"
142
86
 
143
87
  def __int__(self) -> int:
144
- return self.micro_algos
88
+ return self.micro_algo
145
89
 
146
90
  def __add__(self, other: AlgoAmount) -> AlgoAmount:
147
91
  if isinstance(other, AlgoAmount):
148
- total_micro_algos = self.micro_algos + other.micro_algos
92
+ total_micro_algos = self.micro_algo + other.micro_algo
149
93
  else:
150
94
  raise TypeError(f"Unsupported operand type(s) for +: 'AlgoAmount' and '{type(other).__name__}'")
151
- return AlgoAmount.from_micro_algos(total_micro_algos)
95
+ return AlgoAmount.from_micro_algo(total_micro_algos)
152
96
 
153
97
  def __radd__(self, other: AlgoAmount) -> AlgoAmount:
154
98
  return self.__add__(other)
155
99
 
156
100
  def __iadd__(self, other: AlgoAmount) -> Self:
157
101
  if isinstance(other, AlgoAmount):
158
- self.amount_in_micro_algo += other.micro_algos
102
+ self.amount_in_micro_algo += other.micro_algo
159
103
  else:
160
104
  raise TypeError(f"Unsupported operand type(s) for +: 'AlgoAmount' and '{type(other).__name__}'")
161
105
  return self
@@ -204,42 +148,42 @@ class AlgoAmount:
204
148
 
205
149
  def __sub__(self, other: AlgoAmount) -> AlgoAmount:
206
150
  if isinstance(other, AlgoAmount):
207
- total_micro_algos = self.micro_algos - other.micro_algos
151
+ total_micro_algos = self.micro_algo - other.micro_algo
208
152
  else:
209
153
  raise TypeError(f"Unsupported operand type(s) for -: 'AlgoAmount' and '{type(other).__name__}'")
210
- return AlgoAmount.from_micro_algos(total_micro_algos)
154
+ return AlgoAmount.from_micro_algo(total_micro_algos)
211
155
 
212
156
  def __rsub__(self, other: int) -> AlgoAmount:
213
157
  if isinstance(other, (int)):
214
- total_micro_algos = int(other) - self.micro_algos
215
- return AlgoAmount.from_micro_algos(total_micro_algos)
158
+ total_micro_algos = int(other) - self.micro_algo
159
+ return AlgoAmount.from_micro_algo(total_micro_algos)
216
160
  raise TypeError(f"Unsupported operand type(s) for -: '{type(other).__name__}' and 'AlgoAmount'")
217
161
 
218
162
  def __isub__(self, other: AlgoAmount) -> Self:
219
163
  if isinstance(other, AlgoAmount):
220
- self.amount_in_micro_algo -= other.micro_algos
164
+ self.amount_in_micro_algo -= other.micro_algo
221
165
  else:
222
166
  raise TypeError(f"Unsupported operand type(s) for -: 'AlgoAmount' and '{type(other).__name__}'")
223
167
  return self
224
168
 
225
169
 
226
170
  # Helper functions
227
- def algo(algos: int) -> AlgoAmount:
171
+ def algo(algo: int) -> AlgoAmount:
228
172
  """Create an AlgoAmount object representing the given number of Algo.
229
173
 
230
- :param algos: The number of Algo to create an AlgoAmount object for.
174
+ :param algo: The number of Algo to create an AlgoAmount object for.
231
175
  :return: An AlgoAmount object representing the given number of Algo.
232
176
  """
233
- return AlgoAmount.from_algos(algos)
177
+ return AlgoAmount.from_algo(algo)
234
178
 
235
179
 
236
- def micro_algo(microalgos: int) -> AlgoAmount:
180
+ def micro_algo(micro_algo: int) -> AlgoAmount:
237
181
  """Create an AlgoAmount object representing the given number of µAlgo.
238
182
 
239
- :param microalgos: The number of µAlgo to create an AlgoAmount object for.
183
+ :param micro_algo: The number of µAlgo to create an AlgoAmount object for.
240
184
  :return: An AlgoAmount object representing the given number of µAlgo.
241
185
  """
242
- return AlgoAmount.from_micro_algos(microalgos)
186
+ return AlgoAmount.from_micro_algo(micro_algo)
243
187
 
244
188
 
245
189
  ALGORAND_MIN_TX_FEE = micro_algo(1_000)
@@ -252,5 +196,5 @@ def transaction_fees(number_of_transactions: int) -> AlgoAmount:
252
196
  :return: The total transaction fees.
253
197
  """
254
198
 
255
- total_micro_algos = number_of_transactions * ALGORAND_MIN_TX_FEE.micro_algos
256
- return micro_algo(total_micro_algos)
199
+ total_micro_algos = number_of_transactions * ALGORAND_MIN_TX_FEE.micro_algo
200
+ return AlgoAmount.from_micro_algo(total_micro_algos)
@@ -12,11 +12,15 @@ class AlgoClientNetworkConfig:
12
12
  {py:class}`algosdk.v2client.indexer.IndexerClient`"""
13
13
 
14
14
  server: str
15
- """URL for the service e.g. `http://localhost:4001` or `https://testnet-api.algonode.cloud`"""
15
+ """URL for the service e.g. `http://localhost` or `https://testnet-api.algonode.cloud`"""
16
16
  token: str | None = None
17
- """API Token to authenticate with the service"""
17
+ """API Token to authenticate with the service e.g '4001' or '8980'"""
18
18
  port: str | int | None = None
19
19
 
20
+ def full_url(self) -> str:
21
+ """Returns the full URL for the service"""
22
+ return f"{self.server.rstrip('/')}{f':{self.port}' if self.port else ''}"
23
+
20
24
 
21
25
  @dataclasses.dataclass
22
26
  class AlgoClientConfigs:
@@ -68,6 +68,8 @@ __all__ = [
68
68
  "TransactionComposer",
69
69
  "TransactionComposerBuildResult",
70
70
  "TxnParams",
71
+ "populate_app_call_resources",
72
+ "prepare_group_for_sending",
71
73
  "send_atomic_transaction_composer",
72
74
  ]
73
75
 
@@ -107,7 +109,7 @@ class PaymentParams(_CommonTxnParams):
107
109
  :ivar receiver: The account that will receive the ALGO
108
110
  :ivar amount: Amount to send
109
111
  :ivar close_remainder_to: If given, close the sender account and send the remaining balance to this address,
110
- defaults to None
112
+ defaults to None
111
113
  """
112
114
 
113
115
  receiver: str
@@ -299,9 +301,9 @@ class AppCreateParams(_CommonTxnParams):
299
301
  """Parameters for creating an application.
300
302
 
301
303
  :ivar approval_program: The program to execute for all OnCompletes other than ClearState as raw teal (string)
302
- or compiled teal (bytes)
304
+ or compiled teal (bytes)
303
305
  :ivar clear_state_program: The program to execute for ClearState OnComplete as raw teal (string)
304
- or compiled teal (bytes)
306
+ or compiled teal (bytes)
305
307
  :ivar schema: The state schema for the app. This is immutable, defaults to None
306
308
  :ivar on_complete: The OnComplete action (cannot be ClearState), defaults to None
307
309
  :ivar args: Application arguments, defaults to None
@@ -330,9 +332,9 @@ class AppUpdateParams(_CommonTxnParams):
330
332
 
331
333
  :ivar app_id: ID of the application
332
334
  :ivar approval_program: The program to execute for all OnCompletes other than ClearState as raw teal (string)
333
- or compiled teal (bytes)
335
+ or compiled teal (bytes)
334
336
  :ivar clear_state_program: The program to execute for ClearState OnComplete as raw teal (string)
335
- or compiled teal (bytes)
337
+ or compiled teal (bytes)
336
338
  :ivar args: Application arguments, defaults to None
337
339
  :ivar account_references: Account references, defaults to None
338
340
  :ivar app_references: App references, defaults to None
@@ -417,7 +419,7 @@ class AppCallMethodCallParams(_BaseAppMethodCall):
417
419
  :ivar app_id: ID of the application
418
420
  :ivar method: The ABI method to call
419
421
  :ivar args: Arguments to the ABI method, either an ABI value, transaction with explicit signer,
420
- transaction, another method call, or None
422
+ transaction, another method call, or None
421
423
  :ivar on_complete: The OnComplete action (cannot be UpdateApplication or ClearState), defaults to None
422
424
  """
423
425
 
@@ -673,7 +675,7 @@ def _get_group_execution_info( # noqa: C901, PLR0912
673
675
  if not suggested_params:
674
676
  raise ValueError("suggested_params required when cover_app_call_inner_transaction_fees enabled")
675
677
 
676
- max_fee = max_fees.get(i).micro_algos if max_fees and i in max_fees else None # type: ignore[union-attr]
678
+ max_fee = max_fees.get(i).micro_algo if max_fees and i in max_fees else None # type: ignore[union-attr]
677
679
  if max_fee is None:
678
680
  app_call_indexes_without_max_fees.append(i)
679
681
  else:
@@ -843,7 +845,7 @@ def prepare_group_for_sending( # noqa: C901, PLR0912, PLR0915
843
845
  if not txn_info:
844
846
  continue
845
847
  txn = group[i].txn
846
- max_fee = max_fees.get(i).micro_algos if max_fees and i in max_fees else None # type: ignore[union-attr]
848
+ max_fee = max_fees.get(i).micro_algo if max_fees and i in max_fees else None # type: ignore[union-attr]
847
849
  immutable_fee = max_fee is not None and max_fee == txn.fee
848
850
  priority_multiplier = (
849
851
  1000
@@ -1096,7 +1098,7 @@ def prepare_group_for_sending( # noqa: C901, PLR0912, PLR0915
1096
1098
  )
1097
1099
 
1098
1100
  transaction_fee = cur_txn.fee + additional_fee
1099
- max_fee = max_fees.get(i).micro_algos if max_fees and i in max_fees else None # type: ignore[union-attr]
1101
+ max_fee = max_fees.get(i).micro_algo if max_fees and i in max_fees else None # type: ignore[union-attr]
1100
1102
 
1101
1103
  if max_fee is None or transaction_fee > max_fee:
1102
1104
  raise ValueError(
@@ -1324,7 +1326,7 @@ class TransactionComposer:
1324
1326
  :param algod: An instance of AlgodClient used to get suggested params and send transactions
1325
1327
  :param get_signer: A function that takes an address and returns a TransactionSigner for that address
1326
1328
  :param get_suggested_params: Optional function to get suggested transaction parameters,
1327
- defaults to using algod.suggested_params()
1329
+ defaults to using algod.suggested_params()
1328
1330
  :param default_validity_window: Optional default validity window for transactions in rounds, defaults to 10
1329
1331
  :param app_manager: Optional AppManager instance for compiling TEAL programs, defaults to None
1330
1332
  """
@@ -1600,6 +1602,8 @@ class TransactionComposer:
1600
1602
  signers[idx] = ts.signer
1601
1603
  if isinstance(ts, TransactionWithSignerAndContext) and ts.context.abi_method:
1602
1604
  method_calls[idx] = ts.context.abi_method
1605
+ if ts.context.max_fee:
1606
+ self._txn_max_fees[idx] = ts.context.max_fee
1603
1607
  idx += 1
1604
1608
 
1605
1609
  return BuiltTransactions(transactions=transactions, method_calls=method_calls, signers=signers)
@@ -1681,7 +1685,7 @@ class TransactionComposer:
1681
1685
 
1682
1686
  :param allow_more_logs: Whether to allow more logs than the standard limit
1683
1687
  :param allow_empty_signatures: Whether to allow transactions with empty signatures
1684
- :param allow_unnamed_resources: Whether to allow unnamed resources
1688
+ :param allow_unnamed_resources: Whether to allow unnamed resources.
1685
1689
  :param extra_opcode_budget: Additional opcode budget to allocate
1686
1690
  :param exec_trace_config: Configuration for execution tracing
1687
1691
  :param simulation_round: Round number to simulate at
@@ -1839,7 +1843,7 @@ class TransactionComposer:
1839
1843
  txn_params["sp"].last = txn_params["sp"].first + window
1840
1844
 
1841
1845
  if params.static_fee is not None and txn_params["sp"]:
1842
- txn_params["sp"].fee = params.static_fee.micro_algos
1846
+ txn_params["sp"].fee = params.static_fee.micro_algo
1843
1847
  txn_params["sp"].flat_fee = True
1844
1848
 
1845
1849
  if isinstance(txn_params.get("method"), Arc56Method):
@@ -1848,9 +1852,9 @@ class TransactionComposer:
1848
1852
  txn = build_txn(txn_params)
1849
1853
 
1850
1854
  if params.extra_fee:
1851
- txn.fee += params.extra_fee.micro_algos
1855
+ txn.fee += params.extra_fee.micro_algo
1852
1856
 
1853
- if params.max_fee and txn.fee > params.max_fee.micro_algos:
1857
+ if params.max_fee and txn.fee > params.max_fee.micro_algo:
1854
1858
  raise ValueError(f"Transaction fee {txn.fee} is greater than max_fee {params.max_fee}")
1855
1859
  use_max_fee = params.max_fee and params.max_fee.micro_algo > (
1856
1860
  params.static_fee.micro_algo if params.static_fee else 0
@@ -2037,7 +2041,7 @@ class TransactionComposer:
2037
2041
  "sender": params.sender,
2038
2042
  "sp": suggested_params,
2039
2043
  "receiver": params.receiver,
2040
- "amt": params.amount.micro_algos,
2044
+ "amt": params.amount.micro_algo,
2041
2045
  "close_remainder_to": params.close_remainder_to,
2042
2046
  }
2043
2047
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: algokit-utils
3
- Version: 3.0.0b4
3
+ Version: 3.0.0b5
4
4
  Summary: Utilities for Algorand development for use by AlgoKit
5
5
  License: MIT
6
6
  Author: Algorand Foundation
@@ -3,7 +3,7 @@ algokit_utils/_debugging.py,sha256=nAiC10WXiZsvc0RPWOrMLpjJQZT_ItgcMl7D9Z4DfYc,1
3
3
  algokit_utils/_legacy_v2/__init__.py,sha256=WcRE30axWjGnBB09bJCeTw9NT-2_jDN_CVJITFcIDc8,4689
4
4
  algokit_utils/_legacy_v2/_ensure_funded.py,sha256=tw4ZEcqsKBHbSCH9gPz3V2onGaj1kyv6BM9V59fLgCU,6931
5
5
  algokit_utils/_legacy_v2/_transfer.py,sha256=FRut71CU8kDn4-FqMepwZGjFPhPtQg5Wv5_kdtVqK-8,6256
6
- algokit_utils/_legacy_v2/account.py,sha256=yP3t7qB-fAXfLf8G5buYgsdknwrdigzrWsTu08XJWuE,8224
6
+ algokit_utils/_legacy_v2/account.py,sha256=_4pxTKO6y9XK4CkUb1M9Du_XVXKeU1MWXHx54KPVbMk,8240
7
7
  algokit_utils/_legacy_v2/application_client.py,sha256=ScUalY2h2Wj_TAPYdxuucAmdwRwvO-xZ0yOMXDb9OgE,59536
8
8
  algokit_utils/_legacy_v2/application_specification.py,sha256=wp2Y9ou2_F-bSFbDnm6AEhFexybmD7-fAT0CuWtO26g,521
9
9
  algokit_utils/_legacy_v2/asset.py,sha256=b4GEzsPuHAbb330ZjoyY3lol0SisQGwJiOpnXvuXvJI,7594
@@ -14,14 +14,14 @@ algokit_utils/_legacy_v2/models.py,sha256=hH7aO50E4po4EgxXI9zdX5HTthn1HLfSLvkuPf
14
14
  algokit_utils/_legacy_v2/network_clients.py,sha256=5nqC-47hreWvMxR-PQWs_QP44wJDAGhtS1MQv8JQ82o,5660
15
15
  algokit_utils/account.py,sha256=gyGrBSoafUh8WV677IzYGkYoxtzzElsgxGMp4SgA4pk,410
16
16
  algokit_utils/accounts/__init__.py,sha256=_LyY0se6TaQOes7vAcmbpt6pmG4VKlzfTt37-IjwimA,138
17
- algokit_utils/accounts/account_manager.py,sha256=pQjfdDeoi5694QYD-EmvlVpuSvIYdFH_e0LKXkcwzRA,39369
18
- algokit_utils/accounts/kmd_account_manager.py,sha256=7HF2eKYULu6TAXSSXrSGZG7i6VuIEMyf6Ppmo5hE3EI,6342
17
+ algokit_utils/accounts/account_manager.py,sha256=zr8NV6k9L8xESzsmbFK06T-DOmVEvHWcoHgIIX5SDcQ,39763
18
+ algokit_utils/accounts/kmd_account_manager.py,sha256=0flsU5T11JciyL0YvOKDHPVSm-ghV0RjJAbtm8JwrhU,6476
19
19
  algokit_utils/algorand.py,sha256=Gtx3vspZmSxUrNWmh09NFQB24G4v4CEogYuRX_9o5Xw,10554
20
20
  algokit_utils/application_client.py,sha256=5UIxXIBjukjRyjZPCeXmaNlAftbb3TziV7EfBolW79k,337
21
21
  algokit_utils/application_specification.py,sha256=-ZM13Qv-AcLmwudJCq8xGPoWLvAvKBICgAdHeFozKbY,1416
22
22
  algokit_utils/applications/__init__.py,sha256=NGjhpBeExsQZOAYCT2QUFag1xuKoFiX-Ux5SR2GNzd8,452
23
23
  algokit_utils/applications/abi.py,sha256=ZwiLuFXx2EwWJ_cOEvNWCzt5onoasm-QmQPv9N7d49g,10087
24
- algokit_utils/applications/app_client.py,sha256=xHpcZhp6l1PO6OeY009rJ-T3rOyRAS7xrA3evAKI1Jk,83432
24
+ algokit_utils/applications/app_client.py,sha256=oAwe9_6-ETWJIdXNScDvUiVYN8JNP4kplSnr3qCQPVY,84979
25
25
  algokit_utils/applications/app_deployer.py,sha256=RrSmIsbN84z0lNtGD8JP2FwkDmsAD_HvF8b4kHnCSmo,23099
26
26
  algokit_utils/applications/app_factory.py,sha256=wljyXuXWaMc3KJkDeACJ5XVEfIsVxeSXqdGTJ9p3tJQ,33425
27
27
  algokit_utils/applications/app_manager.py,sha256=EA1uRtmvPVAdKi1I5HSCpHjIDgLN7eZcEPT0Cj3C7fU,17661
@@ -31,14 +31,14 @@ algokit_utils/applications/app_spec/arc56.py,sha256=8GyQ_gDBSkHLzTL35D1r7dce5owh
31
31
  algokit_utils/applications/enums.py,sha256=1MUBrPW9v0-OZk6jsa5rqSEEpC-z-6QAQIs9G7pLn1I,1257
32
32
  algokit_utils/asset.py,sha256=ZnNo_MsDGPb8UTPxi7cmIZpbrT0x0xZjblHP01pDAC0,874
33
33
  algokit_utils/assets/__init__.py,sha256=6igogt0eo0TEae6-rO9qPsmlrKkbnkq3aV8wtePX3yk,63
34
- algokit_utils/assets/asset_manager.py,sha256=S4-ob-JO31aCq3N9tqI2JREtq2R7eJ8F6WTXbQczvg4,14132
34
+ algokit_utils/assets/asset_manager.py,sha256=0vs02dbXarAkVxehM4XJp_AHveZCujIPfnQVXiwhZiw,14152
35
35
  algokit_utils/beta/_utils.py,sha256=eGgrSH5dA7Lhe7Z_9rudU7O6azZHMH0U7A3in4GpFOg,1839
36
36
  algokit_utils/beta/account_manager.py,sha256=xDFvsMSha0Ki42BGvKvfScQWT_W9y4GeP_RWXjc3vnE,213
37
37
  algokit_utils/beta/algorand_client.py,sha256=xDFvsMSha0Ki42BGvKvfScQWT_W9y4GeP_RWXjc3vnE,213
38
38
  algokit_utils/beta/client_manager.py,sha256=xDFvsMSha0Ki42BGvKvfScQWT_W9y4GeP_RWXjc3vnE,213
39
39
  algokit_utils/beta/composer.py,sha256=xDFvsMSha0Ki42BGvKvfScQWT_W9y4GeP_RWXjc3vnE,213
40
40
  algokit_utils/clients/__init__.py,sha256=qUuKBvfLnw4z6ZU9x7mc-mLjfnnXC9UcvtoeU33ZLJ8,136
41
- algokit_utils/clients/client_manager.py,sha256=DzJMf_jdQoZYNcy0sK34Uv-IenqJmfAupkqzo_Asp-A,25683
41
+ algokit_utils/clients/client_manager.py,sha256=Yl5k7LwlUaoHh76tNK1UxFl8xoFdaTejrhrr488E0Ww,25559
42
42
  algokit_utils/clients/dispenser_api_client.py,sha256=lx6II3beCt7YiKO2TrW6UbsRVirf3NoWMJi8HD_W5nI,6045
43
43
  algokit_utils/common.py,sha256=5wl83vWw91RYdEC4hTTufqaptKiFtgjKLIyONDmRSH0,300
44
44
  algokit_utils/config.py,sha256=Fd466a33pyqmblKn3YUEoSqMSGbKDmZeaS5Uu7_CNHw,7029
@@ -49,9 +49,9 @@ algokit_utils/errors/logic_error.py,sha256=uxqUOU9-D1R5TrKturCbmmWRVlB024Ca4CfVi
49
49
  algokit_utils/logic_error.py,sha256=3duw-l6tBr-DeapO0e0tYHoa9rOxP-QZZ6QWmN8L9tc,305
50
50
  algokit_utils/models/__init__.py,sha256=0aB_c5pnkqKl1Z0hkxM9qbKn2qVdizZE2DvziN9ObqM,465
51
51
  algokit_utils/models/account.py,sha256=TdeKjhYkppD8g0DYRGbnCsi8zfPz3zU74DaZte_CYJw,6014
52
- algokit_utils/models/amount.py,sha256=2Eb5W9IduM4hqvWz0bpD8-8htKhhmUonaLCuz9c2_1w,9411
52
+ algokit_utils/models/amount.py,sha256=PcjzqRY5ThcUuSYHk1yeYgUooos1j2-54hBIJJcipd4,7567
53
53
  algokit_utils/models/application.py,sha256=lM2_g5kZ18k_zyVzcbGvkvqHzksfb2sgRqowJ3pvUgo,1288
54
- algokit_utils/models/network.py,sha256=Qe631nHpLgjtGcwqWTc6D4Gk_5Fc_dutxD-bCTsb-xw,723
54
+ algokit_utils/models/network.py,sha256=3QNcZ9jVmckv3CCxrD2Y1jiwBdBGdaaziiRgOpsqhwI,904
55
55
  algokit_utils/models/simulate.py,sha256=F9OSEfA9QGFGe5po24h8IGLor5z1ogu5Cwm3l6cHnAs,236
56
56
  algokit_utils/models/state.py,sha256=N6jsjZiZsz-Rn1ZDnBRvVv1En-lUrh97JuaaDRZtCkg,1478
57
57
  algokit_utils/models/transaction.py,sha256=Am0-rmfiANVq9_Zbd1zMTtaV91ZcPqtEfpp2ScQ2Ji8,3052
@@ -61,10 +61,10 @@ algokit_utils/protocols/account.py,sha256=CowaVY7ErBP84TWBHNvBjkZy18whPb8HIlMZtJ
61
61
  algokit_utils/protocols/typed_clients.py,sha256=UrQrHbN2SvS8pEFJ8JQodvouoWeBrQOQGZGyBQx1KLM,3322
62
62
  algokit_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  algokit_utils/transactions/__init__.py,sha256=7fYF3m6DyOGzbV36MT5svo0wSkj9AIz496kWgIWSAlk,225
64
- algokit_utils/transactions/transaction_composer.py,sha256=yGLFgJk51BKgnwbGYmmuDIE7WPpZZmHqVAVZ7IWcRDQ,94794
64
+ algokit_utils/transactions/transaction_composer.py,sha256=AZ4xVHH1IFSKSoxdHpvGVfa2v-e9MkZGiXilCHnjfqE,94996
65
65
  algokit_utils/transactions/transaction_creator.py,sha256=A1YHeGC2EkR2V0HPYJiXVOAEIrfjBW2KVyYgi3exm4E,6167
66
66
  algokit_utils/transactions/transaction_sender.py,sha256=uQmHElJgUIxLXfdklMNoabjQQzUku8CFP82wwhfr44E,22769
67
- algokit_utils-3.0.0b4.dist-info/LICENSE,sha256=J5i7U1Q9Q2c7saUzlvFRmrCCFhQyXb5Juz_LO5omNUw,1076
68
- algokit_utils-3.0.0b4.dist-info/METADATA,sha256=-QVF-0xUq7DMn6ZLnL4uBA5M0pnI5yh2UrjuDOBFCOk,2416
69
- algokit_utils-3.0.0b4.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
70
- algokit_utils-3.0.0b4.dist-info/RECORD,,
67
+ algokit_utils-3.0.0b5.dist-info/LICENSE,sha256=J5i7U1Q9Q2c7saUzlvFRmrCCFhQyXb5Juz_LO5omNUw,1076
68
+ algokit_utils-3.0.0b5.dist-info/METADATA,sha256=agxt079grOlLMzeM0hMFI9g-yl8PfBbVqKUVCMAF1M8,2416
69
+ algokit_utils-3.0.0b5.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
70
+ algokit_utils-3.0.0b5.dist-info/RECORD,,