algokit-utils 3.0.0b3__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.
- algokit_utils/_legacy_v2/account.py +4 -4
- algokit_utils/accounts/account_manager.py +98 -98
- algokit_utils/accounts/kmd_account_manager.py +2 -0
- algokit_utils/applications/app_client.py +122 -161
- algokit_utils/applications/app_factory.py +2 -8
- algokit_utils/assets/asset_manager.py +5 -5
- algokit_utils/clients/client_manager.py +17 -12
- algokit_utils/clients/dispenser_api_client.py +3 -0
- algokit_utils/models/amount.py +71 -69
- algokit_utils/models/network.py +6 -2
- algokit_utils/transactions/transaction_composer.py +19 -15
- {algokit_utils-3.0.0b3.dist-info → algokit_utils-3.0.0b5.dist-info}/METADATA +1 -1
- {algokit_utils-3.0.0b3.dist-info → algokit_utils-3.0.0b5.dist-info}/RECORD +15 -15
- {algokit_utils-3.0.0b3.dist-info → algokit_utils-3.0.0b5.dist-info}/LICENSE +0 -0
- {algokit_utils-3.0.0b3.dist-info → algokit_utils-3.0.0b5.dist-info}/WHEEL +0 -0
|
@@ -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
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
|
|
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
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
-
|
|
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
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
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
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
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
|
-
|
|
283
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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
|
-
|
|
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
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
497
|
-
|
|
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
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
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
|
-
|
|
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
|
-
|
|
640
|
+
or None if no funds were needed
|
|
641
641
|
|
|
642
642
|
:example:
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
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")
|