algokit-utils 2.4.0b1__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of algokit-utils might be problematic. Click here for more details.
- algokit_utils/__init__.py +23 -181
- algokit_utils/_debugging.py +89 -45
- algokit_utils/_legacy_v2/__init__.py +177 -0
- algokit_utils/{_ensure_funded.py → _legacy_v2/_ensure_funded.py} +21 -24
- algokit_utils/{_transfer.py → _legacy_v2/_transfer.py} +26 -23
- algokit_utils/_legacy_v2/account.py +203 -0
- algokit_utils/_legacy_v2/application_client.py +1472 -0
- algokit_utils/_legacy_v2/application_specification.py +21 -0
- algokit_utils/_legacy_v2/asset.py +168 -0
- algokit_utils/_legacy_v2/common.py +28 -0
- algokit_utils/_legacy_v2/deploy.py +822 -0
- algokit_utils/_legacy_v2/logic_error.py +14 -0
- algokit_utils/{models.py → _legacy_v2/models.py} +16 -45
- algokit_utils/_legacy_v2/network_clients.py +144 -0
- algokit_utils/account.py +12 -183
- algokit_utils/accounts/__init__.py +2 -0
- algokit_utils/accounts/account_manager.py +912 -0
- algokit_utils/accounts/kmd_account_manager.py +161 -0
- algokit_utils/algorand.py +359 -0
- algokit_utils/application_client.py +9 -1447
- algokit_utils/application_specification.py +39 -197
- algokit_utils/applications/__init__.py +7 -0
- algokit_utils/applications/abi.py +275 -0
- algokit_utils/applications/app_client.py +2108 -0
- algokit_utils/applications/app_deployer.py +725 -0
- algokit_utils/applications/app_factory.py +1134 -0
- algokit_utils/applications/app_manager.py +578 -0
- algokit_utils/applications/app_spec/__init__.py +2 -0
- algokit_utils/applications/app_spec/arc32.py +207 -0
- algokit_utils/applications/app_spec/arc56.py +989 -0
- algokit_utils/applications/enums.py +40 -0
- algokit_utils/asset.py +32 -168
- algokit_utils/assets/__init__.py +1 -0
- algokit_utils/assets/asset_manager.py +336 -0
- algokit_utils/beta/_utils.py +36 -0
- algokit_utils/beta/account_manager.py +4 -195
- algokit_utils/beta/algorand_client.py +4 -314
- algokit_utils/beta/client_manager.py +5 -74
- algokit_utils/beta/composer.py +5 -712
- algokit_utils/clients/__init__.py +2 -0
- algokit_utils/clients/client_manager.py +738 -0
- algokit_utils/clients/dispenser_api_client.py +224 -0
- algokit_utils/common.py +8 -26
- algokit_utils/config.py +76 -29
- algokit_utils/deploy.py +7 -894
- algokit_utils/dispenser_api.py +8 -176
- algokit_utils/errors/__init__.py +1 -0
- algokit_utils/errors/logic_error.py +121 -0
- algokit_utils/logic_error.py +7 -82
- algokit_utils/models/__init__.py +8 -0
- algokit_utils/models/account.py +217 -0
- algokit_utils/models/amount.py +200 -0
- algokit_utils/models/application.py +91 -0
- algokit_utils/models/network.py +29 -0
- algokit_utils/models/simulate.py +11 -0
- algokit_utils/models/state.py +68 -0
- algokit_utils/models/transaction.py +100 -0
- algokit_utils/network_clients.py +7 -128
- algokit_utils/protocols/__init__.py +2 -0
- algokit_utils/protocols/account.py +22 -0
- algokit_utils/protocols/typed_clients.py +108 -0
- algokit_utils/transactions/__init__.py +3 -0
- algokit_utils/transactions/transaction_composer.py +2499 -0
- algokit_utils/transactions/transaction_creator.py +688 -0
- algokit_utils/transactions/transaction_sender.py +1219 -0
- {algokit_utils-2.4.0b1.dist-info → algokit_utils-3.0.0.dist-info}/METADATA +11 -7
- algokit_utils-3.0.0.dist-info/RECORD +70 -0
- {algokit_utils-2.4.0b1.dist-info → algokit_utils-3.0.0.dist-info}/WHEEL +1 -1
- algokit_utils-2.4.0b1.dist-info/RECORD +0 -24
- {algokit_utils-2.4.0b1.dist-info → algokit_utils-3.0.0.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any, cast
|
|
3
|
+
|
|
4
|
+
from algosdk.kmd import KMDClient
|
|
5
|
+
|
|
6
|
+
from algokit_utils.clients.client_manager import ClientManager
|
|
7
|
+
from algokit_utils.config import config
|
|
8
|
+
from algokit_utils.models.account import SigningAccount
|
|
9
|
+
from algokit_utils.models.amount import AlgoAmount
|
|
10
|
+
from algokit_utils.transactions.transaction_composer import PaymentParams, TransactionComposer
|
|
11
|
+
|
|
12
|
+
__all__ = ["KmdAccount", "KmdAccountManager"]
|
|
13
|
+
|
|
14
|
+
logger = config.logger
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class KmdAccount(SigningAccount):
|
|
18
|
+
"""Account retrieved from KMD with signing capabilities, extending base Account.
|
|
19
|
+
|
|
20
|
+
Provides an account implementation that can be used to sign transactions using keys stored in KMD.
|
|
21
|
+
|
|
22
|
+
:param private_key: Base64 encoded private key
|
|
23
|
+
:param address: Optional address override for rekeyed accounts, defaults to None
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, private_key: str, address: str | None = None) -> None:
|
|
27
|
+
super().__init__(private_key=private_key, address=address or "")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class KmdAccountManager:
|
|
31
|
+
"""Provides abstractions over KMD that makes it easier to get and manage accounts."""
|
|
32
|
+
|
|
33
|
+
_kmd: KMDClient | None
|
|
34
|
+
|
|
35
|
+
def __init__(self, client_manager: ClientManager) -> None:
|
|
36
|
+
self._client_manager = client_manager
|
|
37
|
+
try:
|
|
38
|
+
self._kmd = client_manager.kmd
|
|
39
|
+
except ValueError:
|
|
40
|
+
self._kmd = None
|
|
41
|
+
|
|
42
|
+
def kmd(self) -> KMDClient:
|
|
43
|
+
"""Returns the KMD client, initializing it if needed.
|
|
44
|
+
|
|
45
|
+
:raises Exception: If KMD client is not configured and not running against LocalNet
|
|
46
|
+
:return: The KMD client
|
|
47
|
+
"""
|
|
48
|
+
if self._kmd is None:
|
|
49
|
+
if self._client_manager.is_localnet():
|
|
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")
|
|
53
|
+
self._kmd = ClientManager.get_kmd_client(kmd_config.kmd_config)
|
|
54
|
+
return self._kmd
|
|
55
|
+
raise Exception("Attempt to use KMD client with no KMD configured")
|
|
56
|
+
return self._kmd
|
|
57
|
+
|
|
58
|
+
def get_wallet_account(
|
|
59
|
+
self,
|
|
60
|
+
wallet_name: str,
|
|
61
|
+
predicate: Callable[[dict[str, Any]], bool] | None = None,
|
|
62
|
+
sender: str | None = None,
|
|
63
|
+
) -> KmdAccount | None:
|
|
64
|
+
"""Returns an Algorand signing account with private key loaded from the given KMD wallet.
|
|
65
|
+
|
|
66
|
+
Retrieves an account from a KMD wallet that matches the given predicate, or a random account
|
|
67
|
+
if no predicate is provided.
|
|
68
|
+
|
|
69
|
+
:param wallet_name: The name of the wallet to retrieve an account from
|
|
70
|
+
:param predicate: Optional filter to use to find the account (otherwise gets a random account from the wallet)
|
|
71
|
+
:param sender: Optional sender address to use this signer for (aka a rekeyed account)
|
|
72
|
+
:return: The signing account or None if no matching wallet or account was found
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
kmd_client = self.kmd()
|
|
76
|
+
wallets = kmd_client.list_wallets()
|
|
77
|
+
wallet = next((w for w in wallets if w["name"] == wallet_name), None)
|
|
78
|
+
if not wallet:
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
wallet_id = wallet["id"]
|
|
82
|
+
wallet_handle = kmd_client.init_wallet_handle(wallet_id, "")
|
|
83
|
+
addresses = kmd_client.list_keys(wallet_handle)
|
|
84
|
+
|
|
85
|
+
matched_address = None
|
|
86
|
+
if predicate:
|
|
87
|
+
for address in addresses:
|
|
88
|
+
account_info = self._client_manager.algod.account_info(address)
|
|
89
|
+
if predicate(cast(dict[str, Any], account_info)):
|
|
90
|
+
matched_address = address
|
|
91
|
+
break
|
|
92
|
+
else:
|
|
93
|
+
matched_address = next(iter(addresses), None)
|
|
94
|
+
|
|
95
|
+
if not matched_address:
|
|
96
|
+
return None
|
|
97
|
+
|
|
98
|
+
private_key = kmd_client.export_key(wallet_handle, "", matched_address)
|
|
99
|
+
return KmdAccount(private_key=private_key, address=sender)
|
|
100
|
+
|
|
101
|
+
def get_or_create_wallet_account(self, name: str, fund_with: AlgoAmount | None = None) -> KmdAccount:
|
|
102
|
+
"""Gets or creates a funded account in a KMD wallet of the given name.
|
|
103
|
+
|
|
104
|
+
Provides idempotent access to accounts from LocalNet without specifying the private key.
|
|
105
|
+
|
|
106
|
+
:param name: The name of the wallet to retrieve / create
|
|
107
|
+
:param fund_with: The number of Algos to fund the account with when created
|
|
108
|
+
:return: An Algorand account with private key loaded
|
|
109
|
+
"""
|
|
110
|
+
fund_with = fund_with or AlgoAmount.from_algo(1000)
|
|
111
|
+
|
|
112
|
+
existing = self.get_wallet_account(name)
|
|
113
|
+
if existing:
|
|
114
|
+
return existing
|
|
115
|
+
|
|
116
|
+
kmd_client = self.kmd()
|
|
117
|
+
wallet_id = kmd_client.create_wallet(name, "")["id"]
|
|
118
|
+
wallet_handle = kmd_client.init_wallet_handle(wallet_id, "")
|
|
119
|
+
kmd_client.generate_key(wallet_handle)
|
|
120
|
+
|
|
121
|
+
account = self.get_wallet_account(name)
|
|
122
|
+
assert account is not None
|
|
123
|
+
|
|
124
|
+
logger.info(
|
|
125
|
+
f"LocalNet account '{name}' doesn't yet exist; created account {account.address} "
|
|
126
|
+
f"with keys stored in KMD and funding with {fund_with} ALGO"
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
dispenser = self.get_localnet_dispenser_account()
|
|
130
|
+
TransactionComposer(
|
|
131
|
+
algod=self._client_manager.algod,
|
|
132
|
+
get_signer=lambda _: dispenser.signer,
|
|
133
|
+
get_suggested_params=self._client_manager.algod.suggested_params,
|
|
134
|
+
).add_payment(
|
|
135
|
+
PaymentParams(
|
|
136
|
+
sender=dispenser.address,
|
|
137
|
+
receiver=account.address,
|
|
138
|
+
amount=fund_with,
|
|
139
|
+
)
|
|
140
|
+
).send()
|
|
141
|
+
return account
|
|
142
|
+
|
|
143
|
+
def get_localnet_dispenser_account(self) -> KmdAccount:
|
|
144
|
+
"""Returns an Algorand account with private key loaded for the default LocalNet dispenser account.
|
|
145
|
+
|
|
146
|
+
Retrieves the default funded account from LocalNet that can be used to fund other accounts.
|
|
147
|
+
|
|
148
|
+
:raises Exception: If not running against LocalNet or dispenser account not found
|
|
149
|
+
:return: The default LocalNet dispenser account
|
|
150
|
+
"""
|
|
151
|
+
if not self._client_manager.is_localnet():
|
|
152
|
+
raise Exception("Can't get LocalNet dispenser account from non LocalNet network")
|
|
153
|
+
|
|
154
|
+
dispenser = self.get_wallet_account(
|
|
155
|
+
"unencrypted-default-wallet",
|
|
156
|
+
lambda a: a["status"] != "Offline" and a["amount"] > 1_000_000_000, # noqa: PLR2004
|
|
157
|
+
)
|
|
158
|
+
if not dispenser:
|
|
159
|
+
raise Exception("Error retrieving LocalNet dispenser account; couldn't find the default account in KMD")
|
|
160
|
+
|
|
161
|
+
return dispenser
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import copy
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import typing_extensions
|
|
5
|
+
from algosdk.atomic_transaction_composer import TransactionSigner
|
|
6
|
+
from algosdk.kmd import KMDClient
|
|
7
|
+
from algosdk.transaction import SuggestedParams
|
|
8
|
+
from algosdk.v2client.algod import AlgodClient
|
|
9
|
+
from algosdk.v2client.indexer import IndexerClient
|
|
10
|
+
|
|
11
|
+
from algokit_utils.accounts.account_manager import AccountManager
|
|
12
|
+
from algokit_utils.applications.app_deployer import AppDeployer
|
|
13
|
+
from algokit_utils.applications.app_manager import AppManager
|
|
14
|
+
from algokit_utils.assets.asset_manager import AssetManager
|
|
15
|
+
from algokit_utils.clients.client_manager import AlgoSdkClients, ClientManager
|
|
16
|
+
from algokit_utils.models.network import AlgoClientConfigs, AlgoClientNetworkConfig
|
|
17
|
+
from algokit_utils.protocols.account import TransactionSignerAccountProtocol
|
|
18
|
+
from algokit_utils.transactions.transaction_composer import (
|
|
19
|
+
TransactionComposer,
|
|
20
|
+
)
|
|
21
|
+
from algokit_utils.transactions.transaction_creator import AlgorandClientTransactionCreator
|
|
22
|
+
from algokit_utils.transactions.transaction_sender import AlgorandClientTransactionSender
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"AlgorandClient",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class AlgorandClient:
|
|
30
|
+
"""A client that brokers easy access to Algorand functionality."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, config: AlgoClientConfigs | AlgoSdkClients):
|
|
33
|
+
self._client_manager: ClientManager = ClientManager(clients_or_configs=config, algorand_client=self)
|
|
34
|
+
self._account_manager: AccountManager = AccountManager(self._client_manager)
|
|
35
|
+
self._asset_manager: AssetManager = AssetManager(self._client_manager.algod, lambda: self.new_group())
|
|
36
|
+
self._app_manager: AppManager = AppManager(self._client_manager.algod)
|
|
37
|
+
self._transaction_sender = AlgorandClientTransactionSender(
|
|
38
|
+
new_group=lambda: self.new_group(),
|
|
39
|
+
asset_manager=self._asset_manager,
|
|
40
|
+
app_manager=self._app_manager,
|
|
41
|
+
algod_client=self._client_manager.algod,
|
|
42
|
+
)
|
|
43
|
+
self._app_deployer: AppDeployer = AppDeployer(
|
|
44
|
+
self._app_manager, self._transaction_sender, self._client_manager.indexer_if_present
|
|
45
|
+
)
|
|
46
|
+
self._transaction_creator = AlgorandClientTransactionCreator(
|
|
47
|
+
new_group=lambda: self.new_group(),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
self._cached_suggested_params: SuggestedParams | None = None
|
|
51
|
+
self._cached_suggested_params_expiry: float | None = None
|
|
52
|
+
self._cached_suggested_params_timeout: int = 3_000 # three seconds
|
|
53
|
+
self._default_validity_window: int | None = None
|
|
54
|
+
|
|
55
|
+
def set_default_validity_window(self, validity_window: int) -> typing_extensions.Self:
|
|
56
|
+
"""
|
|
57
|
+
Sets the default validity window for transactions.
|
|
58
|
+
|
|
59
|
+
:param validity_window: The number of rounds between the first and last valid rounds
|
|
60
|
+
:return: The `AlgorandClient` so method calls can be chained
|
|
61
|
+
:example:
|
|
62
|
+
>>> algorand = AlgorandClient.mainnet().set_default_validity_window(1000);
|
|
63
|
+
"""
|
|
64
|
+
self._default_validity_window = validity_window
|
|
65
|
+
return self
|
|
66
|
+
|
|
67
|
+
def set_default_signer(
|
|
68
|
+
self, signer: TransactionSigner | TransactionSignerAccountProtocol
|
|
69
|
+
) -> typing_extensions.Self:
|
|
70
|
+
"""
|
|
71
|
+
Sets the default signer to use if no other signer is specified.
|
|
72
|
+
|
|
73
|
+
:param signer: The signer to use, either a `TransactionSigner` or a `TransactionSignerAccountProtocol`
|
|
74
|
+
:return: The `AlgorandClient` so method calls can be chained
|
|
75
|
+
:example:
|
|
76
|
+
>>> signer = SigningAccount(private_key=..., address=...)
|
|
77
|
+
>>> algorand = AlgorandClient.mainnet().set_default_signer(signer)
|
|
78
|
+
"""
|
|
79
|
+
self._account_manager.set_default_signer(signer)
|
|
80
|
+
return self
|
|
81
|
+
|
|
82
|
+
def set_signer(self, sender: str, signer: TransactionSigner) -> typing_extensions.Self:
|
|
83
|
+
"""
|
|
84
|
+
Tracks the given account for later signing.
|
|
85
|
+
|
|
86
|
+
:param sender: The sender address to use this signer for
|
|
87
|
+
:param signer: The signer to sign transactions with for the given sender
|
|
88
|
+
:return: The `AlgorandClient` so method calls can be chained
|
|
89
|
+
:example:
|
|
90
|
+
>>> signer = SigningAccount(private_key=..., address=...)
|
|
91
|
+
>>> algorand = AlgorandClient.mainnet().set_signer(signer.addr, signer.signer)
|
|
92
|
+
"""
|
|
93
|
+
self._account_manager.set_signer(sender, signer)
|
|
94
|
+
return self
|
|
95
|
+
|
|
96
|
+
def set_signer_from_account(self, signer: TransactionSignerAccountProtocol) -> typing_extensions.Self:
|
|
97
|
+
"""
|
|
98
|
+
Sets the default signer to use if no other signer is specified.
|
|
99
|
+
|
|
100
|
+
:param signer: The signer to use, either a `TransactionSigner` or a `TransactionSignerAccountProtocol`
|
|
101
|
+
:return: The `AlgorandClient` so method calls can be chained
|
|
102
|
+
:example:
|
|
103
|
+
>>> accountManager = AlgorandClient.mainnet()
|
|
104
|
+
>>> accountManager.set_signer_from_account(TransactionSignerAccount(address=..., signer=...))
|
|
105
|
+
>>> accountManager.set_signer_from_account(algosdk.LogicSigAccount(program, args))
|
|
106
|
+
>>> accountManager.set_signer_from_account(SigningAccount(private_key=..., address=...))
|
|
107
|
+
>>> accountManager.set_signer_from_account(MultisigAccount(metadata, signing_accounts))
|
|
108
|
+
>>> accountManager.set_signer_from_account(account)
|
|
109
|
+
"""
|
|
110
|
+
self._account_manager.set_default_signer(signer)
|
|
111
|
+
return self
|
|
112
|
+
|
|
113
|
+
def set_suggested_params_cache(
|
|
114
|
+
self, suggested_params: SuggestedParams, until: float | None = None
|
|
115
|
+
) -> typing_extensions.Self:
|
|
116
|
+
"""
|
|
117
|
+
Sets a cache value to use for suggested params.
|
|
118
|
+
|
|
119
|
+
:param suggested_params: The suggested params to use
|
|
120
|
+
:param until: A timestamp until which to cache, or if not specified then the timeout is used
|
|
121
|
+
:return: The `AlgorandClient` so method calls can be chained
|
|
122
|
+
:example:
|
|
123
|
+
>>> algorand = AlgorandClient.mainnet().set_suggested_params_cache(suggested_params, time.time() + 3.6e6)
|
|
124
|
+
"""
|
|
125
|
+
self._cached_suggested_params = suggested_params
|
|
126
|
+
self._cached_suggested_params_expiry = until or time.time() + self._cached_suggested_params_timeout
|
|
127
|
+
return self
|
|
128
|
+
|
|
129
|
+
def set_suggested_params_cache_timeout(self, timeout: int) -> typing_extensions.Self:
|
|
130
|
+
"""
|
|
131
|
+
Sets the timeout for caching suggested params.
|
|
132
|
+
|
|
133
|
+
:param timeout: The timeout in milliseconds
|
|
134
|
+
:return: The `AlgorandClient` so method calls can be chained
|
|
135
|
+
:example:
|
|
136
|
+
>>> algorand = AlgorandClient.mainnet().set_suggested_params_cache_timeout(10_000)
|
|
137
|
+
"""
|
|
138
|
+
self._cached_suggested_params_timeout = timeout
|
|
139
|
+
return self
|
|
140
|
+
|
|
141
|
+
def get_suggested_params(self) -> SuggestedParams:
|
|
142
|
+
"""
|
|
143
|
+
Get suggested params for a transaction (either cached or from algod if the cache is stale or empty)
|
|
144
|
+
|
|
145
|
+
:example:
|
|
146
|
+
>>> algorand = AlgorandClient.mainnet().get_suggested_params()
|
|
147
|
+
"""
|
|
148
|
+
if self._cached_suggested_params and (
|
|
149
|
+
self._cached_suggested_params_expiry is None or self._cached_suggested_params_expiry > time.time()
|
|
150
|
+
):
|
|
151
|
+
return copy.deepcopy(self._cached_suggested_params)
|
|
152
|
+
|
|
153
|
+
self._cached_suggested_params = self._client_manager.algod.suggested_params()
|
|
154
|
+
self._cached_suggested_params_expiry = time.time() + self._cached_suggested_params_timeout
|
|
155
|
+
|
|
156
|
+
return copy.deepcopy(self._cached_suggested_params)
|
|
157
|
+
|
|
158
|
+
def new_group(self) -> TransactionComposer:
|
|
159
|
+
"""
|
|
160
|
+
Start a new `TransactionComposer` transaction group
|
|
161
|
+
|
|
162
|
+
:example:
|
|
163
|
+
>>> composer = AlgorandClient.mainnet().new_group()
|
|
164
|
+
>>> result = await composer.add_transaction(payment).send()
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
return TransactionComposer(
|
|
168
|
+
algod=self.client.algod,
|
|
169
|
+
get_signer=lambda addr: self.account.get_signer(addr),
|
|
170
|
+
get_suggested_params=self.get_suggested_params,
|
|
171
|
+
default_validity_window=self._default_validity_window,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def client(self) -> ClientManager:
|
|
176
|
+
"""
|
|
177
|
+
Get clients, including algosdk clients and app clients.
|
|
178
|
+
|
|
179
|
+
:example:
|
|
180
|
+
>>> clientManager = AlgorandClient.mainnet().client
|
|
181
|
+
"""
|
|
182
|
+
return self._client_manager
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def account(self) -> AccountManager:
|
|
186
|
+
"""Get or create accounts that can sign transactions.
|
|
187
|
+
|
|
188
|
+
:example:
|
|
189
|
+
>>> accountManager = AlgorandClient.mainnet().account
|
|
190
|
+
"""
|
|
191
|
+
return self._account_manager
|
|
192
|
+
|
|
193
|
+
@property
|
|
194
|
+
def asset(self) -> AssetManager:
|
|
195
|
+
"""
|
|
196
|
+
Get or create assets.
|
|
197
|
+
|
|
198
|
+
:example:
|
|
199
|
+
>>> assetManager = AlgorandClient.mainnet().asset
|
|
200
|
+
"""
|
|
201
|
+
return self._asset_manager
|
|
202
|
+
|
|
203
|
+
@property
|
|
204
|
+
def app(self) -> AppManager:
|
|
205
|
+
"""
|
|
206
|
+
Get or create applications.
|
|
207
|
+
|
|
208
|
+
:example:
|
|
209
|
+
>>> appManager = AlgorandClient.mainnet().app
|
|
210
|
+
"""
|
|
211
|
+
return self._app_manager
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def app_deployer(self) -> AppDeployer:
|
|
215
|
+
"""
|
|
216
|
+
Get or create applications.
|
|
217
|
+
|
|
218
|
+
:example:
|
|
219
|
+
>>> appDeployer = AlgorandClient.mainnet().app_deployer
|
|
220
|
+
"""
|
|
221
|
+
return self._app_deployer
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def send(self) -> AlgorandClientTransactionSender:
|
|
225
|
+
"""
|
|
226
|
+
Methods for sending a transaction and waiting for confirmation
|
|
227
|
+
|
|
228
|
+
:example:
|
|
229
|
+
>>> result = await AlgorandClient.mainnet().send.payment(
|
|
230
|
+
>>> PaymentParams(
|
|
231
|
+
>>> sender="SENDERADDRESS",
|
|
232
|
+
>>> receiver="RECEIVERADDRESS",
|
|
233
|
+
>>> amount=AlgoAmount(algo-1)
|
|
234
|
+
>>> ))
|
|
235
|
+
"""
|
|
236
|
+
return self._transaction_sender
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def create_transaction(self) -> AlgorandClientTransactionCreator:
|
|
240
|
+
"""
|
|
241
|
+
Methods for building transactions
|
|
242
|
+
|
|
243
|
+
:example:
|
|
244
|
+
>>> transaction = AlgorandClient.mainnet().create_transaction.payment(
|
|
245
|
+
>>> PaymentParams(
|
|
246
|
+
>>> sender="SENDERADDRESS",
|
|
247
|
+
>>> receiver="RECEIVERADDRESS",
|
|
248
|
+
>>> amount=AlgoAmount(algo=1)
|
|
249
|
+
>>> ))
|
|
250
|
+
"""
|
|
251
|
+
return self._transaction_creator
|
|
252
|
+
|
|
253
|
+
@staticmethod
|
|
254
|
+
def default_localnet() -> "AlgorandClient":
|
|
255
|
+
"""
|
|
256
|
+
Returns an `AlgorandClient` pointing at default LocalNet ports and API token.
|
|
257
|
+
|
|
258
|
+
:return: The `AlgorandClient`
|
|
259
|
+
|
|
260
|
+
:example:
|
|
261
|
+
>>> algorand = AlgorandClient.default_localnet()
|
|
262
|
+
"""
|
|
263
|
+
return AlgorandClient(
|
|
264
|
+
AlgoClientConfigs(
|
|
265
|
+
algod_config=ClientManager.get_default_localnet_config("algod"),
|
|
266
|
+
indexer_config=ClientManager.get_default_localnet_config("indexer"),
|
|
267
|
+
kmd_config=ClientManager.get_default_localnet_config("kmd"),
|
|
268
|
+
)
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
@staticmethod
|
|
272
|
+
def testnet() -> "AlgorandClient":
|
|
273
|
+
"""
|
|
274
|
+
Returns an `AlgorandClient` pointing at TestNet using AlgoNode.
|
|
275
|
+
|
|
276
|
+
:return: The `AlgorandClient`
|
|
277
|
+
|
|
278
|
+
:example:
|
|
279
|
+
>>> algorand = AlgorandClient.testnet()
|
|
280
|
+
"""
|
|
281
|
+
return AlgorandClient(
|
|
282
|
+
AlgoClientConfigs(
|
|
283
|
+
algod_config=ClientManager.get_algonode_config("testnet", "algod"),
|
|
284
|
+
indexer_config=ClientManager.get_algonode_config("testnet", "indexer"),
|
|
285
|
+
kmd_config=None,
|
|
286
|
+
)
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
@staticmethod
|
|
290
|
+
def mainnet() -> "AlgorandClient":
|
|
291
|
+
"""
|
|
292
|
+
Returns an `AlgorandClient` pointing at MainNet using AlgoNode.
|
|
293
|
+
|
|
294
|
+
:return: The `AlgorandClient`
|
|
295
|
+
|
|
296
|
+
:example:
|
|
297
|
+
>>> algorand = AlgorandClient.mainnet()
|
|
298
|
+
"""
|
|
299
|
+
return AlgorandClient(
|
|
300
|
+
AlgoClientConfigs(
|
|
301
|
+
algod_config=ClientManager.get_algonode_config("mainnet", "algod"),
|
|
302
|
+
indexer_config=ClientManager.get_algonode_config("mainnet", "indexer"),
|
|
303
|
+
kmd_config=None,
|
|
304
|
+
)
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
@staticmethod
|
|
308
|
+
def from_clients(
|
|
309
|
+
algod: AlgodClient, indexer: IndexerClient | None = None, kmd: KMDClient | None = None
|
|
310
|
+
) -> "AlgorandClient":
|
|
311
|
+
"""
|
|
312
|
+
Returns an `AlgorandClient` pointing to the given client(s).
|
|
313
|
+
|
|
314
|
+
:param algod: The algod client to use
|
|
315
|
+
:param indexer: The indexer client to use
|
|
316
|
+
:param kmd: The kmd client to use
|
|
317
|
+
:return: The `AlgorandClient`
|
|
318
|
+
|
|
319
|
+
:example:
|
|
320
|
+
>>> algorand = AlgorandClient.from_clients(algod, indexer, kmd)
|
|
321
|
+
"""
|
|
322
|
+
return AlgorandClient(AlgoSdkClients(algod=algod, indexer=indexer, kmd=kmd))
|
|
323
|
+
|
|
324
|
+
@staticmethod
|
|
325
|
+
def from_environment() -> "AlgorandClient":
|
|
326
|
+
"""
|
|
327
|
+
Returns an `AlgorandClient` loading the configuration from environment variables.
|
|
328
|
+
|
|
329
|
+
Retrieve configurations from environment variables when defined or get defaults.
|
|
330
|
+
|
|
331
|
+
Expects to be called from a Python environment.
|
|
332
|
+
|
|
333
|
+
:return: The `AlgorandClient`
|
|
334
|
+
|
|
335
|
+
:example:
|
|
336
|
+
>>> algorand = AlgorandClient.from_environment()
|
|
337
|
+
"""
|
|
338
|
+
return AlgorandClient(ClientManager.get_config_from_environment_or_localnet())
|
|
339
|
+
|
|
340
|
+
@staticmethod
|
|
341
|
+
def from_config(
|
|
342
|
+
algod_config: AlgoClientNetworkConfig,
|
|
343
|
+
indexer_config: AlgoClientNetworkConfig | None = None,
|
|
344
|
+
kmd_config: AlgoClientNetworkConfig | None = None,
|
|
345
|
+
) -> "AlgorandClient":
|
|
346
|
+
"""
|
|
347
|
+
Returns an `AlgorandClient` from the given config.
|
|
348
|
+
|
|
349
|
+
:param algod_config: The config to use for the algod client
|
|
350
|
+
:param indexer_config: The config to use for the indexer client
|
|
351
|
+
:param kmd_config: The config to use for the kmd client
|
|
352
|
+
:return: The `AlgorandClient`
|
|
353
|
+
|
|
354
|
+
:example:
|
|
355
|
+
>>> algorand = AlgorandClient.from_config(algod_config, indexer_config, kmd_config)
|
|
356
|
+
"""
|
|
357
|
+
return AlgorandClient(
|
|
358
|
+
AlgoClientConfigs(algod_config=algod_config, indexer_config=indexer_config, kmd_config=kmd_config)
|
|
359
|
+
)
|