algokit-utils 3.0.0b4__py3-none-any.whl → 3.0.0b6__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/_legacy_v2/application_client.py +1 -0
- algokit_utils/accounts/account_manager.py +98 -98
- algokit_utils/accounts/kmd_account_manager.py +2 -0
- algokit_utils/applications/app_client.py +38 -14
- algokit_utils/applications/app_deployer.py +40 -6
- algokit_utils/assets/asset_manager.py +5 -5
- algokit_utils/clients/client_manager.py +17 -12
- algokit_utils/config.py +62 -59
- algokit_utils/models/amount.py +25 -81
- algokit_utils/models/network.py +6 -2
- algokit_utils/models/transaction.py +1 -1
- algokit_utils/transactions/transaction_composer.py +33 -25
- {algokit_utils-3.0.0b4.dist-info → algokit_utils-3.0.0b6.dist-info}/METADATA +1 -1
- {algokit_utils-3.0.0b4.dist-info → algokit_utils-3.0.0b6.dist-info}/RECORD +17 -17
- {algokit_utils-3.0.0b4.dist-info → algokit_utils-3.0.0b6.dist-info}/LICENSE +0 -0
- {algokit_utils-3.0.0b4.dist-info → algokit_utils-3.0.0b6.dist-info}/WHEEL +0 -0
|
@@ -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}
|
|
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
|
|
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(
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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=
|
|
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:
|
algokit_utils/config.py
CHANGED
|
@@ -2,71 +2,67 @@ import logging
|
|
|
2
2
|
import os
|
|
3
3
|
from collections.abc import Callable
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any
|
|
6
5
|
|
|
7
6
|
# Environment variable to override the project root
|
|
8
7
|
ALGOKIT_PROJECT_ROOT = os.getenv("ALGOKIT_PROJECT_ROOT")
|
|
9
8
|
ALGOKIT_CONFIG_FILENAME = ".algokit.toml"
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
class AlgoKitLogger:
|
|
13
|
-
def __init__(self
|
|
14
|
-
|
|
15
|
-
self.
|
|
16
|
-
|
|
17
|
-
def _setup_logger(self) -> None:
|
|
18
|
-
formatter = logging.Formatter("%(levelname)s: %(message)s")
|
|
19
|
-
handler = logging.StreamHandler()
|
|
20
|
-
handler.setFormatter(formatter)
|
|
21
|
-
self._logger.addHandler(handler)
|
|
22
|
-
self._logger.setLevel(logging.INFO)
|
|
23
|
-
|
|
24
|
-
def _get_logger(self, *, suppress_log: bool = False) -> logging.Logger:
|
|
25
|
-
if suppress_log:
|
|
26
|
-
null_logger = logging.getLogger("null")
|
|
27
|
-
null_logger.addHandler(logging.NullHandler())
|
|
28
|
-
return null_logger
|
|
29
|
-
return self._logger
|
|
11
|
+
class AlgoKitLogger(logging.Logger):
|
|
12
|
+
def __init__(self, name: str = "algokit-utils-py", level: int = logging.NOTSET):
|
|
13
|
+
super().__init__(name, level)
|
|
14
|
+
self._setup_handler()
|
|
30
15
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
self.
|
|
16
|
+
def _setup_handler(self) -> None:
|
|
17
|
+
# Only add the handler if no handlers are already set.
|
|
18
|
+
if not self.handlers:
|
|
19
|
+
formatter = logging.Formatter("%(levelname)s: %(message)s")
|
|
20
|
+
handler = logging.StreamHandler()
|
|
21
|
+
handler.setFormatter(formatter)
|
|
22
|
+
self.addHandler(handler)
|
|
34
23
|
|
|
35
|
-
def
|
|
36
|
-
"""
|
|
37
|
-
|
|
24
|
+
def _log(self, level: int, msg: object, args, exc_info=None, extra=None, stack_info=False, stacklevel=1) -> None: # type: ignore[no-untyped-def] # noqa: FBT002, ANN001
|
|
25
|
+
"""
|
|
26
|
+
Overrides the base _log method to allow suppressing individual log calls.
|
|
27
|
+
When a caller passes suppress_log=True in the extra keyword, the log call is ignored.
|
|
28
|
+
"""
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
# Check if the 'suppress_log' flag is provided in the extra dictionary.
|
|
31
|
+
if extra and extra.get("suppress_log", False):
|
|
32
|
+
return
|
|
33
|
+
# Call the parent _log
|
|
34
|
+
super()._log(level, msg, args, exc_info, extra, stack_info, stacklevel)
|
|
42
35
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
@classmethod
|
|
37
|
+
def get_null_logger(cls) -> logging.Logger:
|
|
38
|
+
"""Return a logger that does nothing (a null logger)."""
|
|
39
|
+
null_logger = logging.getLogger("null")
|
|
40
|
+
null_logger.handlers.clear()
|
|
41
|
+
null_logger.addHandler(logging.NullHandler())
|
|
42
|
+
null_logger.propagate = False
|
|
43
|
+
return null_logger
|
|
46
44
|
|
|
47
|
-
def debug(self, message: str, *args: Any, suppress_log: bool = False, **kwargs: Any) -> None:
|
|
48
|
-
"""Log a debug message, optionally suppressing output"""
|
|
49
|
-
self._get_logger(suppress_log=suppress_log).debug(message, *args, **kwargs)
|
|
50
45
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
self._get_logger(suppress_log=suppress_log).debug(message, *args, **kwargs)
|
|
46
|
+
# Set our custom logger class as the default.
|
|
47
|
+
logging.setLoggerClass(AlgoKitLogger)
|
|
54
48
|
|
|
55
49
|
|
|
56
50
|
class UpdatableConfig:
|
|
57
|
-
"""
|
|
51
|
+
"""
|
|
52
|
+
Class to manage and update configuration settings for the AlgoKit project.
|
|
58
53
|
|
|
59
54
|
Attributes:
|
|
60
55
|
debug (bool): Indicates whether debug mode is enabled.
|
|
61
56
|
project_root (Path | None): The path to the project root directory.
|
|
62
57
|
trace_all (bool): Indicates whether to trace all operations.
|
|
63
|
-
trace_buffer_size_mb (int): The size of the trace buffer in megabytes.
|
|
58
|
+
trace_buffer_size_mb (int | float): The size of the trace buffer in megabytes.
|
|
64
59
|
max_search_depth (int): The maximum depth to search for a specific file.
|
|
65
|
-
populate_app_call_resources (bool):
|
|
60
|
+
populate_app_call_resources (bool): Whether to populate app call resources.
|
|
61
|
+
logger (logging.Logger): The logger instance to use. Defaults to an AlgoKitLogger instance.
|
|
66
62
|
"""
|
|
67
63
|
|
|
68
64
|
def __init__(self) -> None:
|
|
69
|
-
self._logger = AlgoKitLogger()
|
|
65
|
+
self._logger: logging.Logger = AlgoKitLogger()
|
|
70
66
|
self._debug: bool = False
|
|
71
67
|
self._project_root: Path | None = None
|
|
72
68
|
self._trace_all: bool = False
|
|
@@ -76,17 +72,20 @@ class UpdatableConfig:
|
|
|
76
72
|
self._configure_project_root()
|
|
77
73
|
|
|
78
74
|
def _configure_project_root(self) -> None:
|
|
79
|
-
"""
|
|
75
|
+
"""
|
|
76
|
+
Configures the project root by searching for a specific file within a depth limit.
|
|
77
|
+
"""
|
|
80
78
|
current_path = Path(__file__).resolve()
|
|
81
79
|
for _ in range(self._max_search_depth):
|
|
82
|
-
self.
|
|
80
|
+
self._logger.debug(f"Searching in: {current_path}")
|
|
83
81
|
if (current_path / ALGOKIT_CONFIG_FILENAME).exists():
|
|
84
82
|
self._project_root = current_path
|
|
85
83
|
break
|
|
86
84
|
current_path = current_path.parent
|
|
87
85
|
|
|
88
86
|
@property
|
|
89
|
-
def logger(self) ->
|
|
87
|
+
def logger(self) -> logging.Logger:
|
|
88
|
+
"""Returns the logger instance."""
|
|
90
89
|
return self._logger
|
|
91
90
|
|
|
92
91
|
@property
|
|
@@ -101,7 +100,7 @@ class UpdatableConfig:
|
|
|
101
100
|
|
|
102
101
|
@property
|
|
103
102
|
def trace_all(self) -> bool:
|
|
104
|
-
"""Indicates whether
|
|
103
|
+
"""Indicates whether simulation traces for all operations should be stored."""
|
|
105
104
|
return self._trace_all
|
|
106
105
|
|
|
107
106
|
@property
|
|
@@ -111,10 +110,13 @@ class UpdatableConfig:
|
|
|
111
110
|
|
|
112
111
|
@property
|
|
113
112
|
def populate_app_call_resource(self) -> bool:
|
|
113
|
+
"""Indicates whether or not to populate app call resources."""
|
|
114
114
|
return self._populate_app_call_resources
|
|
115
115
|
|
|
116
116
|
def with_debug(self, func: Callable[[], str | None]) -> None:
|
|
117
|
-
"""
|
|
117
|
+
"""
|
|
118
|
+
Executes a function with debug mode temporarily enabled.
|
|
119
|
+
"""
|
|
118
120
|
original_debug = self._debug
|
|
119
121
|
try:
|
|
120
122
|
self._debug = True
|
|
@@ -131,26 +133,27 @@ class UpdatableConfig:
|
|
|
131
133
|
trace_buffer_size_mb: float = 256,
|
|
132
134
|
max_search_depth: int = 10,
|
|
133
135
|
populate_app_call_resources: bool = False,
|
|
136
|
+
logger: logging.Logger | None = None,
|
|
134
137
|
) -> None:
|
|
135
138
|
"""
|
|
136
139
|
Configures various settings for the application.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
:param
|
|
144
|
-
:param
|
|
145
|
-
:param trace_all: Indicates whether to trace all operations. Defaults to False. Which implies that
|
|
146
|
-
only the operations that are failed will be traced by default.
|
|
147
|
-
:param trace_buffer_size_mb: The size of the trace buffer in megabytes. Defaults to 256
|
|
148
|
-
:param max_search_depth: The maximum depth to search for a specific file. Defaults to 10
|
|
149
|
-
:param populate_app_call_resources: Indicates whether to populate app call resources. Defaults to False
|
|
140
|
+
|
|
141
|
+
:param debug: Whether debug mode is enabled.
|
|
142
|
+
:param project_root: The path to the project root directory.
|
|
143
|
+
:param trace_all: Whether to trace all operations. Defaults to False.
|
|
144
|
+
:param trace_buffer_size_mb: The trace buffer size in megabytes. Defaults to 256.
|
|
145
|
+
:param max_search_depth: The maximum depth to search for a specific file. Defaults to 10.
|
|
146
|
+
:param populate_app_call_resources: Whether to populate app call resources. Defaults to False.
|
|
147
|
+
:param logger: A custom logger to use. Defaults to AlgoKitLogger instance.
|
|
150
148
|
"""
|
|
149
|
+
if logger is not None:
|
|
150
|
+
self._logger = logger
|
|
151
151
|
|
|
152
152
|
if debug is not None:
|
|
153
153
|
self._debug = debug
|
|
154
|
+
# Update logger's level so debug messages are processed only when debug is True.
|
|
155
|
+
self._logger.setLevel(logging.DEBUG)
|
|
156
|
+
|
|
154
157
|
if project_root is not None:
|
|
155
158
|
self._project_root = project_root.resolve(strict=True)
|
|
156
159
|
elif debug is not None and ALGOKIT_PROJECT_ROOT:
|
algokit_utils/models/amount.py
CHANGED
|
@@ -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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
34
|
+
if micro_algo is None and algo is None:
|
|
47
35
|
raise ValueError("No amount provided")
|
|
48
36
|
|
|
49
|
-
if
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
215
|
-
return AlgoAmount.
|
|
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.
|
|
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(
|
|
171
|
+
def algo(algo: int) -> AlgoAmount:
|
|
228
172
|
"""Create an AlgoAmount object representing the given number of Algo.
|
|
229
173
|
|
|
230
|
-
:param
|
|
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.
|
|
177
|
+
return AlgoAmount.from_algo(algo)
|
|
234
178
|
|
|
235
179
|
|
|
236
|
-
def micro_algo(
|
|
180
|
+
def micro_algo(micro_algo: int) -> AlgoAmount:
|
|
237
181
|
"""Create an AlgoAmount object representing the given number of µAlgo.
|
|
238
182
|
|
|
239
|
-
:param
|
|
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.
|
|
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.
|
|
256
|
-
return
|
|
199
|
+
total_micro_algos = number_of_transactions * ALGORAND_MIN_TX_FEE.micro_algo
|
|
200
|
+
return AlgoAmount.from_micro_algo(total_micro_algos)
|
algokit_utils/models/network.py
CHANGED
|
@@ -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
|
|
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:
|
|
@@ -45,7 +45,7 @@ TransactionNote = bytes | TransactionNoteData | Arc2TransactionNote
|
|
|
45
45
|
TxnTypeT = TypeVar("TxnTypeT", bound=algosdk.transaction.Transaction)
|
|
46
46
|
|
|
47
47
|
|
|
48
|
-
class TransactionWrapper
|
|
48
|
+
class TransactionWrapper:
|
|
49
49
|
"""Wrapper around algosdk.transaction.Transaction with optional property validators"""
|
|
50
50
|
|
|
51
51
|
def __init__(self, transaction: algosdk.transaction.Transaction) -> None:
|