algokit-utils 2.2.2b5__py3-none-any.whl → 2.3.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.

@@ -86,7 +86,7 @@ def transfer(client: "AlgodClient", parameters: TransferParameters) -> PaymentTx
86
86
  params = parameters
87
87
  params.suggested_params = parameters.suggested_params or client.suggested_params()
88
88
  from_account = params.from_account
89
- sender = address_from_private_key(from_account.private_key) # type: ignore[no-untyped-call]
89
+ sender = _get_address(from_account)
90
90
  transaction = PaymentTxn(
91
91
  sender=sender,
92
92
  receiver=params.to_address,
@@ -105,7 +105,7 @@ def transfer_asset(client: "AlgodClient", parameters: TransferAssetParameters) -
105
105
 
106
106
  params = parameters
107
107
  params.suggested_params = parameters.suggested_params or client.suggested_params()
108
- sender = address_from_private_key(parameters.from_account.private_key) # type: ignore[no-untyped-call]
108
+ sender = _get_address(parameters.from_account)
109
109
  suggested_params = parameters.suggested_params or client.suggested_params()
110
110
  xfer_txn = AssetTransferTxn(
111
111
  sp=suggested_params,
@@ -139,9 +139,14 @@ def _send_transaction(
139
139
  client.send_transaction(signed_transaction)
140
140
 
141
141
  txid = transaction.get_txid() # type: ignore[no-untyped-call]
142
- logger.debug(
143
- f"Sent transaction {txid} type={transaction.type} from "
144
- f"{address_from_private_key(parameters.from_account.private_key)}" # type: ignore[no-untyped-call]
145
- )
142
+ logger.debug(f"Sent transaction {txid} type={transaction.type} from {_get_address(parameters.from_account)}")
146
143
 
147
144
  return transaction
145
+
146
+
147
+ def _get_address(account: Account | AccountTransactionSigner) -> str:
148
+ if type(account) is Account:
149
+ return account.address
150
+ else:
151
+ address = address_from_private_key(account.private_key) # type: ignore[no-untyped-call]
152
+ return str(address)
@@ -1,6 +1,5 @@
1
1
  import base64
2
2
  import copy
3
- import dataclasses
4
3
  import json
5
4
  import logging
6
5
  import re
@@ -59,6 +58,7 @@ if typing.TYPE_CHECKING:
59
58
  from algosdk.v2client.algod import AlgodClient
60
59
  from algosdk.v2client.indexer import IndexerClient
61
60
 
61
+
62
62
  logger = logging.getLogger(__name__)
63
63
 
64
64
 
@@ -375,7 +375,7 @@ class ApplicationClient:
375
375
  ) -> None:
376
376
  """Adds a signed transaction with application id == 0 and the schema and source of client's app_spec to atc"""
377
377
  approval_program, clear_program = self._check_is_compiled()
378
- transaction_parameters = _convert_transaction_parameters(CreateCallParameters, transaction_parameters)
378
+ transaction_parameters = _convert_transaction_parameters(transaction_parameters)
379
379
 
380
380
  extra_pages = transaction_parameters.extra_pages or num_extra_program_pages(
381
381
  approval_program.raw_binary, clear_program.raw_binary
@@ -388,7 +388,7 @@ class ApplicationClient:
388
388
  abi_args=abi_kwargs,
389
389
  on_complete=transaction_parameters.on_complete or transaction.OnComplete.NoOpOC,
390
390
  call_config=au_spec.CallConfig.CREATE,
391
- parameters=_convert_transaction_parameters(TransactionParameters, transaction_parameters),
391
+ parameters=transaction_parameters,
392
392
  approval_program=approval_program.raw_binary,
393
393
  clear_program=clear_program.raw_binary,
394
394
  global_schema=self.app_spec.global_state_schema,
@@ -567,12 +567,12 @@ class ApplicationClient:
567
567
  **abi_kwargs: ABIArgType,
568
568
  ) -> None:
569
569
  """Adds a signed transaction with specified parameters to atc"""
570
- _parameters = _convert_transaction_parameters(OnCompleteCallParameters, transaction_parameters)
570
+ _parameters = _convert_transaction_parameters(transaction_parameters)
571
571
  self.add_method_call(
572
572
  atc,
573
573
  abi_method=call_abi_method,
574
574
  abi_args=abi_kwargs,
575
- parameters=_convert_transaction_parameters(TransactionParameters, transaction_parameters),
575
+ parameters=_parameters,
576
576
  on_complete=_parameters.on_complete or transaction.OnComplete.NoOpOC,
577
577
  )
578
578
 
@@ -607,7 +607,7 @@ class ApplicationClient:
607
607
  ) -> TransactionResponse | ABITransactionResponse:
608
608
  """Submits a signed transaction with specified parameters"""
609
609
  atc = AtomicTransactionComposer()
610
- _parameters = _convert_transaction_parameters(OnCompleteCallParameters, transaction_parameters)
610
+ _parameters = _convert_transaction_parameters(transaction_parameters)
611
611
  self.compose_call(
612
612
  atc,
613
613
  call_abi_method=call_abi_method,
@@ -1003,7 +1003,7 @@ class ApplicationClient:
1003
1003
  if app_id is None:
1004
1004
  self._load_reference_and_check_app_id()
1005
1005
  app_id = self.app_id
1006
- parameters = _convert_transaction_parameters(TransactionParameters, parameters)
1006
+ parameters = _convert_transaction_parameters(parameters)
1007
1007
  method = self._resolve_method(abi_method, abi_args, on_complete, call_config)
1008
1008
  sp = parameters.suggested_params or self.suggested_params or self.algod_client.suggested_params()
1009
1009
  signer, sender = self.resolve_signer_sender(parameters.signer, parameters.sender)
@@ -1317,18 +1317,11 @@ def _create_simulate_traces(simulate: SimulateAtomicTransactionResponse) -> list
1317
1317
  return traces
1318
1318
 
1319
1319
 
1320
- _TParams = typing.TypeVar("_TParams", TransactionParameters, OnCompleteCallParameters, CreateCallParameters)
1321
-
1322
-
1323
1320
  def _convert_transaction_parameters(
1324
- cls: type[_TParams],
1325
- args: object | None,
1326
- ) -> _TParams:
1327
- if args is None:
1328
- return cls()
1329
- args_dict = args.__dict__ if not isinstance(args, dict) else (args or {})
1330
- _args = {f.name: args_dict[f.name] for f in dataclasses.fields(cls) if f.name in args_dict}
1331
- return cls(**_args)
1321
+ args: TransactionParameters | TransactionParametersDict | None,
1322
+ ) -> CreateCallParameters:
1323
+ _args = args.__dict__ if isinstance(args, TransactionParameters) else (args or {})
1324
+ return CreateCallParameters(**_args)
1332
1325
 
1333
1326
 
1334
1327
  def get_sender_from_signer(signer: TransactionSigner | None) -> str | None:
@@ -0,0 +1,200 @@
1
+ from collections.abc import Callable
2
+ from dataclasses import dataclass
3
+ from typing import Any
4
+
5
+ from algokit_utils.account import get_dispenser_account, get_kmd_wallet_account, get_localnet_default_account
6
+ from algosdk.account import generate_account
7
+ from algosdk.atomic_transaction_composer import AccountTransactionSigner, TransactionSigner
8
+ from typing_extensions import Self
9
+
10
+ from .client_manager import ClientManager
11
+
12
+
13
+ @dataclass
14
+ class AddressAndSigner:
15
+ address: str
16
+ signer: TransactionSigner
17
+
18
+
19
+ class AccountManager:
20
+ """Creates and keeps track of addresses and signers"""
21
+
22
+ def __init__(self, client_manager: ClientManager):
23
+ """
24
+ Create a new account manager.
25
+
26
+ :param client_manager: The ClientManager client to use for algod and kmd clients
27
+ """
28
+ self._client_manager = client_manager
29
+ self._accounts = dict[str, TransactionSigner]()
30
+ self._default_signer: TransactionSigner | None = None
31
+
32
+ def set_default_signer(self, signer: TransactionSigner) -> Self:
33
+ """
34
+ Sets the default signer to use if no other signer is specified.
35
+
36
+ :param signer: The signer to use, either a `TransactionSigner` or a `TransactionSignerAccount`
37
+ :return: The `AccountManager` so method calls can be chained
38
+ """
39
+ self._default_signer = signer
40
+ return self
41
+
42
+ def set_signer(self, sender: str, signer: TransactionSigner) -> Self:
43
+ """
44
+ Tracks the given account for later signing.
45
+
46
+ :param sender: The sender address to use this signer for
47
+ :param signer: The signer to sign transactions with for the given sender
48
+ :return: The AccountCreator instance for method chaining
49
+ """
50
+ self._accounts[sender] = signer
51
+ return self
52
+
53
+ def get_signer(self, sender: str) -> TransactionSigner:
54
+ """
55
+ Returns the `TransactionSigner` for the given sender address.
56
+
57
+ If no signer has been registered for that address then the default signer is used if registered.
58
+
59
+ :param sender: The sender address
60
+ :return: The `TransactionSigner` or throws an error if not found
61
+ """
62
+ signer = self._accounts.get(sender, None) or self._default_signer
63
+ if not signer:
64
+ raise ValueError(f"No signer found for address {sender}")
65
+ return signer
66
+
67
+ def get_information(self, sender: str) -> dict[str, Any]:
68
+ """
69
+ Returns the given sender account's current status, balance and spendable amounts.
70
+
71
+ Example:
72
+ address = "XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA"
73
+ account_info = account.get_information(address)
74
+
75
+ `Response data schema details <https://developer.algorand.org/docs/rest-apis/algod/#get-v2accountsaddress>`_
76
+
77
+ :param sender: The address of the sender/account to look up
78
+ :return: The account information
79
+ """
80
+ info = self._client_manager.algod.account_info(sender)
81
+ assert isinstance(info, dict)
82
+ return info
83
+
84
+ def get_asset_information(self, sender: str, asset_id: int) -> dict[str, Any]:
85
+ info = self._client_manager.algod.account_asset_info(sender, asset_id)
86
+ assert isinstance(info, dict)
87
+ return info
88
+
89
+ # TODO
90
+ # def from_mnemonic(self, mnemonic_secret: str, sender: Optional[str] = None) -> AddrAndSigner:
91
+ # """
92
+ # Tracks and returns an Algorand account with secret key loaded (i.e. that can sign transactions) by taking the mnemonic secret.
93
+
94
+ # Example:
95
+ # account = account.from_mnemonic("mnemonic secret ...")
96
+ # rekeyed_account = account.from_mnemonic("mnemonic secret ...", "SENDERADDRESS...")
97
+
98
+ # :param mnemonic_secret: The mnemonic secret representing the private key of an account; **Note: Be careful how the mnemonic is handled**,
99
+ # never commit it into source control and ideally load it from the environment (ideally via a secret storage service) rather than the file system.
100
+ # :param sender: The optional sender address to use this signer for (aka a rekeyed account)
101
+ # :return: The account
102
+ # """
103
+ # account = mnemonic_account(mnemonic_secret)
104
+ # return self.signer_account(rekeyed_account(account, sender) if sender else account)
105
+
106
+ def from_kmd(
107
+ self,
108
+ name: str,
109
+ predicate: Callable[[dict[str, Any]], bool] | None = None,
110
+ ) -> AddressAndSigner:
111
+ """
112
+ Tracks and returns an Algorand account with private key loaded from the given KMD wallet (identified by name).
113
+
114
+ Example (Get default funded account in a LocalNet):
115
+ default_dispenser_account = account.from_kmd('unencrypted-default-wallet',
116
+ lambda a: a['status'] != 'Offline' and a['amount'] > 1_000_000_000
117
+ )
118
+
119
+ :param name: The name of the wallet to retrieve an account from
120
+ :param predicate: An optional filter to use to find the account (otherwise it will return a random account from the wallet)
121
+ :return: The account
122
+ """
123
+ account = get_kmd_wallet_account(
124
+ name=name, predicate=predicate, client=self._client_manager.algod, kmd_client=self._client_manager.kmd
125
+ )
126
+ if not account:
127
+ raise ValueError(f"Unable to find KMD account {name}{' with predicate' if predicate else ''}")
128
+
129
+ self.set_signer(account.address, account.signer)
130
+ return AddressAndSigner(address=account.address, signer=account.signer)
131
+
132
+ # TODO
133
+ # def multisig(
134
+ # self, multisig_params: algosdk.MultisigMetadata, signing_accounts: Union[algosdk.Account, SigningAccount]
135
+ # ) -> TransactionSignerAccount:
136
+ # """
137
+ # Tracks and returns an account that supports partial or full multisig signing.
138
+
139
+ # Example:
140
+ # account = account.multisig(
141
+ # {
142
+ # "version": 1,
143
+ # "threshold": 1,
144
+ # "addrs": ["ADDRESS1...", "ADDRESS2..."]
145
+ # },
146
+ # account.from_environment('ACCOUNT1')
147
+ # )
148
+
149
+ # :param multisig_params: The parameters that define the multisig account
150
+ # :param signing_accounts: The signers that are currently present
151
+ # :return: A multisig account wrapper
152
+ # """
153
+ # return self.signer_account(multisig_account(multisig_params, signing_accounts))
154
+
155
+ def random(self) -> AddressAndSigner:
156
+ """
157
+ Tracks and returns a new, random Algorand account with secret key loaded.
158
+
159
+ Example:
160
+ account = account.random()
161
+
162
+ :return: The account
163
+ """
164
+ (sk, addr) = generate_account() # type: ignore[no-untyped-call]
165
+ signer = AccountTransactionSigner(sk)
166
+
167
+ self.set_signer(addr, signer)
168
+
169
+ return AddressAndSigner(address=addr, signer=signer)
170
+
171
+ def dispenser(self) -> AddressAndSigner:
172
+ """
173
+ Returns an account (with private key loaded) that can act as a dispenser.
174
+
175
+ Example:
176
+ account = account.dispenser()
177
+
178
+ If running on LocalNet then it will return the default dispenser account automatically,
179
+ otherwise it will load the account mnemonic stored in os.environ['DISPENSER_MNEMONIC'].
180
+
181
+ :return: The account
182
+ """
183
+ acct = get_dispenser_account(self._client_manager.algod)
184
+
185
+ self.set_signer(acct.address, acct.signer)
186
+
187
+ return AddressAndSigner(address=acct.address, signer=acct.signer)
188
+
189
+ def localnet_dispenser(self) -> AddressAndSigner:
190
+ """
191
+ Returns an Algorand account with private key loaded for the default LocalNet dispenser account (that can be used to fund other accounts).
192
+
193
+ Example:
194
+ account = account.localnet_dispenser()
195
+
196
+ :return: The account
197
+ """
198
+ acct = get_localnet_default_account(self._client_manager.algod)
199
+ self.set_signer(acct.address, acct.signer)
200
+ return AddressAndSigner(address=acct.address, signer=acct.signer)
@@ -0,0 +1,319 @@
1
+ import copy
2
+ import time
3
+ from collections.abc import Callable
4
+ from dataclasses import dataclass
5
+ from typing import Any
6
+
7
+ from algokit_utils.beta.account_manager import AccountManager
8
+ from algokit_utils.beta.client_manager import AlgoSdkClients, ClientManager
9
+ from algokit_utils.beta.composer import (
10
+ AlgokitComposer,
11
+ AppCallParams,
12
+ AssetConfigParams,
13
+ AssetCreateParams,
14
+ AssetDestroyParams,
15
+ AssetFreezeParams,
16
+ AssetOptInParams,
17
+ AssetTransferParams,
18
+ MethodCallParams,
19
+ OnlineKeyRegParams,
20
+ PayParams,
21
+ )
22
+ from algokit_utils.network_clients import (
23
+ AlgoClientConfigs,
24
+ get_algod_client,
25
+ get_algonode_config,
26
+ get_default_localnet_config,
27
+ get_indexer_client,
28
+ get_kmd_client,
29
+ )
30
+ from algosdk.atomic_transaction_composer import AtomicTransactionResponse, TransactionSigner
31
+ from algosdk.transaction import SuggestedParams, Transaction, wait_for_confirmation
32
+ from typing_extensions import Self
33
+
34
+ __all__ = [
35
+ "AlgorandClient",
36
+ "AssetCreateParams",
37
+ "AssetOptInParams",
38
+ "MethodCallParams",
39
+ "PayParams",
40
+ "AssetFreezeParams",
41
+ "AssetConfigParams",
42
+ "AssetDestroyParams",
43
+ "AppCallParams",
44
+ "OnlineKeyRegParams",
45
+ "AssetTransferParams",
46
+ ]
47
+
48
+
49
+ @dataclass
50
+ class AlgorandClientSendMethods:
51
+ """
52
+ Methods used to send a transaction to the network and wait for confirmation
53
+ """
54
+
55
+ payment: Callable[[PayParams], dict[str, Any]]
56
+ asset_create: Callable[[AssetCreateParams], dict[str, Any]]
57
+ asset_config: Callable[[AssetConfigParams], dict[str, Any]]
58
+ asset_freeze: Callable[[AssetFreezeParams], dict[str, Any]]
59
+ asset_destroy: Callable[[AssetDestroyParams], dict[str, Any]]
60
+ asset_transfer: Callable[[AssetTransferParams], dict[str, Any]]
61
+ app_call: Callable[[AppCallParams], dict[str, Any]]
62
+ online_key_reg: Callable[[OnlineKeyRegParams], dict[str, Any]]
63
+ method_call: Callable[[MethodCallParams], dict[str, Any]]
64
+ asset_opt_in: Callable[[AssetOptInParams], dict[str, Any]]
65
+
66
+
67
+ @dataclass
68
+ class AlgorandClientTransactionMethods:
69
+ """
70
+ Methods used to form a transaction without signing or sending to the network
71
+ """
72
+
73
+ payment: Callable[[PayParams], Transaction]
74
+ asset_create: Callable[[AssetCreateParams], Transaction]
75
+ asset_config: Callable[[AssetConfigParams], Transaction]
76
+ asset_freeze: Callable[[AssetFreezeParams], Transaction]
77
+ asset_destroy: Callable[[AssetDestroyParams], Transaction]
78
+ asset_transfer: Callable[[AssetTransferParams], Transaction]
79
+ app_call: Callable[[AppCallParams], Transaction]
80
+ online_key_reg: Callable[[OnlineKeyRegParams], Transaction]
81
+ method_call: Callable[[MethodCallParams], list[Transaction]]
82
+ asset_opt_in: Callable[[AssetOptInParams], Transaction]
83
+
84
+
85
+ class AlgorandClient:
86
+ """A client that brokers easy access to Algorand functionality."""
87
+
88
+ def __init__(self, config: AlgoClientConfigs | AlgoSdkClients):
89
+ self._client_manager: ClientManager = ClientManager(config)
90
+ self._account_manager: AccountManager = AccountManager(self._client_manager)
91
+
92
+ self._cached_suggested_params: SuggestedParams | None = None
93
+ self._cached_suggested_params_expiry: float | None = None
94
+ self._cached_suggested_params_timeout: int = 3_000 # three seconds
95
+
96
+ self._default_validity_window: int = 10
97
+
98
+ def _unwrap_single_send_result(self, results: AtomicTransactionResponse) -> dict[str, Any]:
99
+ return {
100
+ "confirmation": wait_for_confirmation(self._client_manager.algod, results.tx_ids[0]),
101
+ "tx_id": results.tx_ids[0],
102
+ }
103
+
104
+ def set_default_validity_window(self, validity_window: int) -> Self:
105
+ """
106
+ Sets the default validity window for transactions.
107
+
108
+ :param validity_window: The number of rounds between the first and last valid rounds
109
+ :return: The `AlgorandClient` so method calls can be chained
110
+ """
111
+ self._default_validity_window = validity_window
112
+ return self
113
+
114
+ def set_default_signer(self, signer: TransactionSigner) -> Self:
115
+ """
116
+ Sets the default signer to use if no other signer is specified.
117
+
118
+ :param signer: The signer to use, either a `TransactionSigner` or a `TransactionSignerAccount`
119
+ :return: The `AlgorandClient` so method calls can be chained
120
+ """
121
+ self._account_manager.set_default_signer(signer)
122
+ return self
123
+
124
+ def set_signer(self, sender: str, signer: TransactionSigner) -> Self:
125
+ """
126
+ Tracks the given account for later signing.
127
+
128
+ :param sender: The sender address to use this signer for
129
+ :param signer: The signer to sign transactions with for the given sender
130
+ :return: The `AlgorandClient` so method calls can be chained
131
+ """
132
+ self._account_manager.set_signer(sender, signer)
133
+ return self
134
+
135
+ def set_suggested_params(self, suggested_params: SuggestedParams, until: float | None = None) -> Self:
136
+ """
137
+ Sets a cache value to use for suggested params.
138
+
139
+ :param suggested_params: The suggested params to use
140
+ :param until: A timestamp until which to cache, or if not specified then the timeout is used
141
+ :return: The `AlgorandClient` so method calls can be chained
142
+ """
143
+ self._cached_suggested_params = suggested_params
144
+ self._cached_suggested_params_expiry = until or time.time() + self._cached_suggested_params_timeout
145
+ return self
146
+
147
+ def set_suggested_params_timeout(self, timeout: int) -> Self:
148
+ """
149
+ Sets the timeout for caching suggested params.
150
+
151
+ :param timeout: The timeout in milliseconds
152
+ :return: The `AlgorandClient` so method calls can be chained
153
+ """
154
+ self._cached_suggested_params_timeout = timeout
155
+ return self
156
+
157
+ def get_suggested_params(self) -> SuggestedParams:
158
+ """Get suggested params for a transaction (either cached or from algod if the cache is stale or empty)"""
159
+ if self._cached_suggested_params and (
160
+ self._cached_suggested_params_expiry is None or self._cached_suggested_params_expiry > time.time()
161
+ ):
162
+ return copy.deepcopy(self._cached_suggested_params)
163
+
164
+ self._cached_suggested_params = self._client_manager.algod.suggested_params()
165
+ self._cached_suggested_params_expiry = time.time() + self._cached_suggested_params_timeout
166
+
167
+ return copy.deepcopy(self._cached_suggested_params)
168
+
169
+ @property
170
+ def client(self) -> ClientManager:
171
+ """Get clients, including algosdk clients and app clients."""
172
+ return self._client_manager
173
+
174
+ @property
175
+ def account(self) -> AccountManager:
176
+ """Get or create accounts that can sign transactions."""
177
+ return self._account_manager
178
+
179
+ def new_group(self) -> AlgokitComposer:
180
+ """Start a new `AlgokitComposer` transaction group"""
181
+ return AlgokitComposer(
182
+ algod=self.client.algod,
183
+ get_signer=lambda addr: self.account.get_signer(addr),
184
+ get_suggested_params=self.get_suggested_params,
185
+ default_validity_window=self._default_validity_window,
186
+ )
187
+
188
+ @property
189
+ def send(self) -> AlgorandClientSendMethods:
190
+ """Methods for sending a transaction and waiting for confirmation"""
191
+ return AlgorandClientSendMethods(
192
+ payment=lambda params: self._unwrap_single_send_result(self.new_group().add_payment(params).execute()),
193
+ asset_create=lambda params: self._unwrap_single_send_result(
194
+ self.new_group().add_asset_create(params).execute()
195
+ ),
196
+ asset_config=lambda params: self._unwrap_single_send_result(
197
+ self.new_group().add_asset_config(params).execute()
198
+ ),
199
+ asset_freeze=lambda params: self._unwrap_single_send_result(
200
+ self.new_group().add_asset_freeze(params).execute()
201
+ ),
202
+ asset_destroy=lambda params: self._unwrap_single_send_result(
203
+ self.new_group().add_asset_destroy(params).execute()
204
+ ),
205
+ asset_transfer=lambda params: self._unwrap_single_send_result(
206
+ self.new_group().add_asset_transfer(params).execute()
207
+ ),
208
+ app_call=lambda params: self._unwrap_single_send_result(self.new_group().add_app_call(params).execute()),
209
+ online_key_reg=lambda params: self._unwrap_single_send_result(
210
+ self.new_group().add_online_key_reg(params).execute()
211
+ ),
212
+ method_call=lambda params: self._unwrap_single_send_result(
213
+ self.new_group().add_method_call(params).execute()
214
+ ),
215
+ asset_opt_in=lambda params: self._unwrap_single_send_result(
216
+ self.new_group().add_asset_opt_in(params).execute()
217
+ ),
218
+ )
219
+
220
+ @property
221
+ def transactions(self) -> AlgorandClientTransactionMethods:
222
+ """Methods for building transactions"""
223
+
224
+ return AlgorandClientTransactionMethods(
225
+ payment=lambda params: self.new_group().add_payment(params).build_group()[0].txn,
226
+ asset_create=lambda params: self.new_group().add_asset_create(params).build_group()[0].txn,
227
+ asset_config=lambda params: self.new_group().add_asset_config(params).build_group()[0].txn,
228
+ asset_freeze=lambda params: self.new_group().add_asset_freeze(params).build_group()[0].txn,
229
+ asset_destroy=lambda params: self.new_group().add_asset_destroy(params).build_group()[0].txn,
230
+ asset_transfer=lambda params: self.new_group().add_asset_transfer(params).build_group()[0].txn,
231
+ app_call=lambda params: self.new_group().add_app_call(params).build_group()[0].txn,
232
+ online_key_reg=lambda params: self.new_group().add_online_key_reg(params).build_group()[0].txn,
233
+ method_call=lambda params: [txn.txn for txn in self.new_group().add_method_call(params).build_group()],
234
+ asset_opt_in=lambda params: self.new_group().add_asset_opt_in(params).build_group()[0].txn,
235
+ )
236
+
237
+ @staticmethod
238
+ def default_local_net() -> "AlgorandClient":
239
+ """
240
+ Returns an `AlgorandClient` pointing at default LocalNet ports and API token.
241
+
242
+ :return: The `AlgorandClient`
243
+ """
244
+ return AlgorandClient(
245
+ AlgoClientConfigs(
246
+ algod_config=get_default_localnet_config("algod"),
247
+ indexer_config=get_default_localnet_config("indexer"),
248
+ kmd_config=get_default_localnet_config("kmd"),
249
+ )
250
+ )
251
+
252
+ @staticmethod
253
+ def test_net() -> "AlgorandClient":
254
+ """
255
+ Returns an `AlgorandClient` pointing at TestNet using AlgoNode.
256
+
257
+ :return: The `AlgorandClient`
258
+ """
259
+ return AlgorandClient(
260
+ AlgoClientConfigs(
261
+ algod_config=get_algonode_config("testnet", "algod", ""),
262
+ indexer_config=get_algonode_config("testnet", "indexer", ""),
263
+ kmd_config=None,
264
+ )
265
+ )
266
+
267
+ @staticmethod
268
+ def main_net() -> "AlgorandClient":
269
+ """
270
+ Returns an `AlgorandClient` pointing at MainNet using AlgoNode.
271
+
272
+ :return: The `AlgorandClient`
273
+ """
274
+ return AlgorandClient(
275
+ AlgoClientConfigs(
276
+ algod_config=get_algonode_config("mainnet", "algod", ""),
277
+ indexer_config=get_algonode_config("mainnet", "indexer", ""),
278
+ kmd_config=None,
279
+ )
280
+ )
281
+
282
+ @staticmethod
283
+ def from_clients(clients: AlgoSdkClients) -> "AlgorandClient":
284
+ """
285
+ Returns an `AlgorandClient` pointing to the given client(s).
286
+
287
+ :param clients: The clients to use
288
+ :return: The `AlgorandClient`
289
+ """
290
+ return AlgorandClient(clients)
291
+
292
+ @staticmethod
293
+ def from_environment() -> "AlgorandClient":
294
+ """
295
+ Returns an `AlgorandClient` loading the configuration from environment variables.
296
+
297
+ Retrieve configurations from environment variables when defined or get defaults.
298
+
299
+ Expects to be called from a Python environment.
300
+
301
+ :return: The `AlgorandClient`
302
+ """
303
+ return AlgorandClient(
304
+ AlgoSdkClients(
305
+ algod=get_algod_client(),
306
+ kmd=get_kmd_client(),
307
+ indexer=get_indexer_client(),
308
+ )
309
+ )
310
+
311
+ @staticmethod
312
+ def from_config(config: AlgoClientConfigs) -> "AlgorandClient":
313
+ """
314
+ Returns an `AlgorandClient` from the given config.
315
+
316
+ :param config: The config to use
317
+ :return: The `AlgorandClient`
318
+ """
319
+ return AlgorandClient(config)