algokit-utils 3.0.0b1__py3-none-any.whl → 3.0.0b3__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 -183
- algokit_utils/_debugging.py +123 -97
- algokit_utils/_legacy_v2/__init__.py +177 -0
- algokit_utils/{_ensure_funded.py → _legacy_v2/_ensure_funded.py} +19 -18
- algokit_utils/{_transfer.py → _legacy_v2/_transfer.py} +24 -23
- algokit_utils/_legacy_v2/account.py +203 -0
- algokit_utils/_legacy_v2/application_client.py +1471 -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} +19 -142
- algokit_utils/_legacy_v2/network_clients.py +140 -0
- algokit_utils/account.py +12 -183
- algokit_utils/accounts/__init__.py +2 -0
- algokit_utils/accounts/account_manager.py +909 -0
- algokit_utils/accounts/kmd_account_manager.py +159 -0
- algokit_utils/algorand.py +265 -0
- algokit_utils/application_client.py +9 -1453
- algokit_utils/application_specification.py +39 -197
- algokit_utils/applications/__init__.py +7 -0
- algokit_utils/applications/abi.py +276 -0
- algokit_utils/applications/app_client.py +2054 -0
- algokit_utils/applications/app_deployer.py +600 -0
- algokit_utils/applications/app_factory.py +826 -0
- algokit_utils/applications/app_manager.py +470 -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 +1023 -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 +320 -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 +656 -0
- algokit_utils/clients/dispenser_api_client.py +192 -0
- algokit_utils/common.py +8 -26
- algokit_utils/config.py +71 -18
- algokit_utils/deploy.py +7 -892
- 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 -80
- algokit_utils/models/__init__.py +8 -0
- algokit_utils/models/account.py +197 -0
- algokit_utils/models/amount.py +198 -0
- algokit_utils/models/application.py +61 -0
- algokit_utils/models/network.py +25 -0
- algokit_utils/models/simulate.py +11 -0
- algokit_utils/models/state.py +59 -0
- algokit_utils/models/transaction.py +100 -0
- algokit_utils/network_clients.py +7 -152
- 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 +2287 -0
- algokit_utils/transactions/transaction_creator.py +156 -0
- algokit_utils/transactions/transaction_sender.py +574 -0
- {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/METADATA +13 -8
- algokit_utils-3.0.0b3.dist-info/RECORD +70 -0
- {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/WHEEL +1 -1
- algokit_utils-3.0.0b1.dist-info/RECORD +0 -24
- {algokit_utils-3.0.0b1.dist-info → algokit_utils-3.0.0b3.dist-info}/LICENSE +0 -0
algokit_utils/__init__.py
CHANGED
|
@@ -1,184 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
from algokit_utils._ensure_funded import EnsureBalanceParameters, EnsureFundedResponse, ensure_funded
|
|
3
|
-
from algokit_utils._transfer import TransferAssetParameters, TransferParameters, transfer, transfer_asset
|
|
4
|
-
from algokit_utils.account import (
|
|
5
|
-
create_kmd_wallet_account,
|
|
6
|
-
get_account,
|
|
7
|
-
get_account_from_mnemonic,
|
|
8
|
-
get_dispenser_account,
|
|
9
|
-
get_kmd_wallet_account,
|
|
10
|
-
get_localnet_default_account,
|
|
11
|
-
get_or_create_kmd_wallet_account,
|
|
12
|
-
)
|
|
13
|
-
from algokit_utils.application_client import (
|
|
14
|
-
ApplicationClient,
|
|
15
|
-
execute_atc_with_logic_error,
|
|
16
|
-
get_next_version,
|
|
17
|
-
get_sender_from_signer,
|
|
18
|
-
num_extra_program_pages,
|
|
19
|
-
)
|
|
20
|
-
from algokit_utils.application_specification import (
|
|
21
|
-
ApplicationSpecification,
|
|
22
|
-
AppSpecStateDict,
|
|
23
|
-
CallConfig,
|
|
24
|
-
DefaultArgumentDict,
|
|
25
|
-
DefaultArgumentType,
|
|
26
|
-
MethodConfigDict,
|
|
27
|
-
MethodHints,
|
|
28
|
-
OnCompleteActionName,
|
|
29
|
-
)
|
|
30
|
-
from algokit_utils.asset import opt_in, opt_out
|
|
31
|
-
from algokit_utils.common import Program
|
|
32
|
-
from algokit_utils.deploy import (
|
|
33
|
-
DELETABLE_TEMPLATE_NAME,
|
|
34
|
-
NOTE_PREFIX,
|
|
35
|
-
UPDATABLE_TEMPLATE_NAME,
|
|
36
|
-
ABICallArgs,
|
|
37
|
-
ABICallArgsDict,
|
|
38
|
-
ABICreateCallArgs,
|
|
39
|
-
ABICreateCallArgsDict,
|
|
40
|
-
AppDeployMetaData,
|
|
41
|
-
AppLookup,
|
|
42
|
-
AppMetaData,
|
|
43
|
-
AppReference,
|
|
44
|
-
DeployCallArgs,
|
|
45
|
-
DeployCallArgsDict,
|
|
46
|
-
DeployCreateCallArgs,
|
|
47
|
-
DeployCreateCallArgsDict,
|
|
48
|
-
DeploymentFailedError,
|
|
49
|
-
DeployResponse,
|
|
50
|
-
OnSchemaBreak,
|
|
51
|
-
OnUpdate,
|
|
52
|
-
OperationPerformed,
|
|
53
|
-
TemplateValueDict,
|
|
54
|
-
TemplateValueMapping,
|
|
55
|
-
get_app_id_from_tx_id,
|
|
56
|
-
get_creator_apps,
|
|
57
|
-
replace_template_variables,
|
|
58
|
-
)
|
|
59
|
-
from algokit_utils.dispenser_api import (
|
|
60
|
-
DISPENSER_ACCESS_TOKEN_KEY,
|
|
61
|
-
DISPENSER_REQUEST_TIMEOUT,
|
|
62
|
-
DispenserFundResponse,
|
|
63
|
-
DispenserLimitResponse,
|
|
64
|
-
TestNetDispenserApiClient,
|
|
65
|
-
)
|
|
66
|
-
from algokit_utils.logic_error import LogicError
|
|
67
|
-
from algokit_utils.models import (
|
|
68
|
-
ABIArgsDict,
|
|
69
|
-
ABIMethod,
|
|
70
|
-
ABITransactionResponse,
|
|
71
|
-
Account,
|
|
72
|
-
CommonCallParameters, # noqa: F401
|
|
73
|
-
CommonCallParametersDict, # noqa: F401
|
|
74
|
-
CreateCallParameters,
|
|
75
|
-
CreateCallParametersDict,
|
|
76
|
-
CreateTransactionParameters,
|
|
77
|
-
OnCompleteCallParameters,
|
|
78
|
-
OnCompleteCallParametersDict,
|
|
79
|
-
RawTransactionParameters, # noqa: F401
|
|
80
|
-
TransactionParameters,
|
|
81
|
-
TransactionParametersDict,
|
|
82
|
-
TransactionResponse,
|
|
83
|
-
)
|
|
84
|
-
from algokit_utils.network_clients import (
|
|
85
|
-
AlgoClientConfig,
|
|
86
|
-
get_algod_client,
|
|
87
|
-
get_algonode_config,
|
|
88
|
-
get_default_localnet_config,
|
|
89
|
-
get_indexer_client,
|
|
90
|
-
get_kmd_client_from_algod_client,
|
|
91
|
-
get_purestake_config,
|
|
92
|
-
is_localnet,
|
|
93
|
-
is_mainnet,
|
|
94
|
-
is_testnet,
|
|
95
|
-
)
|
|
1
|
+
"""AlgoKit Python Utilities - a set of utilities for building solutions on Algorand
|
|
96
2
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"ABICreateCallArgsDict",
|
|
120
|
-
"ABIMethod",
|
|
121
|
-
"CreateCallParameters",
|
|
122
|
-
"CreateCallParametersDict",
|
|
123
|
-
"CreateTransactionParameters",
|
|
124
|
-
"DeployCallArgs",
|
|
125
|
-
"DeployCreateCallArgs",
|
|
126
|
-
"DeployCallArgsDict",
|
|
127
|
-
"DeployCreateCallArgsDict",
|
|
128
|
-
"OnCompleteCallParameters",
|
|
129
|
-
"OnCompleteCallParametersDict",
|
|
130
|
-
"TransactionParameters",
|
|
131
|
-
"TransactionParametersDict",
|
|
132
|
-
"ApplicationClient",
|
|
133
|
-
"DeployResponse",
|
|
134
|
-
"OnUpdate",
|
|
135
|
-
"OnSchemaBreak",
|
|
136
|
-
"OperationPerformed",
|
|
137
|
-
"TemplateValueDict",
|
|
138
|
-
"TemplateValueMapping",
|
|
139
|
-
"Program",
|
|
140
|
-
"execute_atc_with_logic_error",
|
|
141
|
-
"get_app_id_from_tx_id",
|
|
142
|
-
"get_next_version",
|
|
143
|
-
"get_sender_from_signer",
|
|
144
|
-
"num_extra_program_pages",
|
|
145
|
-
"AppSpecStateDict",
|
|
146
|
-
"ApplicationSpecification",
|
|
147
|
-
"CallConfig",
|
|
148
|
-
"DefaultArgumentDict",
|
|
149
|
-
"DefaultArgumentType",
|
|
150
|
-
"MethodConfigDict",
|
|
151
|
-
"OnCompleteActionName",
|
|
152
|
-
"MethodHints",
|
|
153
|
-
"LogicError",
|
|
154
|
-
"ABITransactionResponse",
|
|
155
|
-
"Account",
|
|
156
|
-
"TransactionResponse",
|
|
157
|
-
"AlgoClientConfig",
|
|
158
|
-
"get_algod_client",
|
|
159
|
-
"get_algonode_config",
|
|
160
|
-
"get_default_localnet_config",
|
|
161
|
-
"get_indexer_client",
|
|
162
|
-
"get_kmd_client_from_algod_client",
|
|
163
|
-
"get_purestake_config",
|
|
164
|
-
"is_localnet",
|
|
165
|
-
"is_mainnet",
|
|
166
|
-
"is_testnet",
|
|
167
|
-
"TestNetDispenserApiClient",
|
|
168
|
-
"DispenserFundResponse",
|
|
169
|
-
"DispenserLimitResponse",
|
|
170
|
-
"DISPENSER_ACCESS_TOKEN_KEY",
|
|
171
|
-
"DISPENSER_REQUEST_TIMEOUT",
|
|
172
|
-
"EnsureBalanceParameters",
|
|
173
|
-
"EnsureFundedResponse",
|
|
174
|
-
"TransferParameters",
|
|
175
|
-
"ensure_funded",
|
|
176
|
-
"transfer",
|
|
177
|
-
"TransferAssetParameters",
|
|
178
|
-
"transfer_asset",
|
|
179
|
-
"opt_in",
|
|
180
|
-
"opt_out",
|
|
181
|
-
"persist_sourcemaps",
|
|
182
|
-
"PersistSourceMapInput",
|
|
183
|
-
"simulate_and_persist_response",
|
|
184
|
-
]
|
|
3
|
+
This module provides commonly used utilities and types at the root level for convenience.
|
|
4
|
+
For more specific functionality, import directly from the relevant submodules:
|
|
5
|
+
|
|
6
|
+
from algokit_utils.accounts import KmdAccountManager
|
|
7
|
+
from algokit_utils.applications import AppClient
|
|
8
|
+
from algokit_utils.applications.app_spec import Arc52Contract
|
|
9
|
+
etc.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
# Core types and utilities that are commonly used
|
|
13
|
+
from algokit_utils.applications import * # noqa: F403
|
|
14
|
+
from algokit_utils.assets import * # noqa: F403
|
|
15
|
+
from algokit_utils.protocols import * # noqa: F403
|
|
16
|
+
from algokit_utils.models import * # noqa: F403
|
|
17
|
+
from algokit_utils.accounts import * # noqa: F403
|
|
18
|
+
from algokit_utils.clients import * # noqa: F403
|
|
19
|
+
from algokit_utils.transactions import * # noqa: F403
|
|
20
|
+
from algokit_utils.errors import * # noqa: F403
|
|
21
|
+
from algokit_utils.algorand import * # noqa: F403
|
|
22
|
+
|
|
23
|
+
# Legacy types and utilities
|
|
24
|
+
from algokit_utils._legacy_v2 import * # noqa: F403
|
algokit_utils/_debugging.py
CHANGED
|
@@ -14,7 +14,8 @@ from algosdk.atomic_transaction_composer import (
|
|
|
14
14
|
from algosdk.encoding import checksum
|
|
15
15
|
from algosdk.v2client.models import SimulateRequest, SimulateRequestTransactionGroup, SimulateTraceConfig
|
|
16
16
|
|
|
17
|
-
from algokit_utils.common import Program
|
|
17
|
+
from algokit_utils._legacy_v2.common import Program
|
|
18
|
+
from algokit_utils.models.application import CompiledTeal
|
|
18
19
|
|
|
19
20
|
if typing.TYPE_CHECKING:
|
|
20
21
|
from algosdk.v2client.algod import AlgodClient
|
|
@@ -27,7 +28,7 @@ SOURCES_FILE = "sources.avm.json"
|
|
|
27
28
|
TRACES_FILE_EXT = ".trace.avm.json"
|
|
28
29
|
DEBUG_TRACES_DIR = "debug_traces"
|
|
29
30
|
TEAL_FILE_EXT = ".teal"
|
|
30
|
-
TEAL_SOURCEMAP_EXT = ".teal.
|
|
31
|
+
TEAL_SOURCEMAP_EXT = ".teal.map"
|
|
31
32
|
|
|
32
33
|
|
|
33
34
|
@dataclass
|
|
@@ -64,7 +65,11 @@ class AVMDebuggerSourceMap:
|
|
|
64
65
|
@dataclass
|
|
65
66
|
class PersistSourceMapInput:
|
|
66
67
|
def __init__(
|
|
67
|
-
self,
|
|
68
|
+
self,
|
|
69
|
+
app_name: str,
|
|
70
|
+
file_name: str,
|
|
71
|
+
raw_teal: str | None = None,
|
|
72
|
+
compiled_teal: CompiledTeal | Program | None = None,
|
|
68
73
|
):
|
|
69
74
|
self.compiled_teal = compiled_teal
|
|
70
75
|
self.app_name = app_name
|
|
@@ -76,7 +81,9 @@ class PersistSourceMapInput:
|
|
|
76
81
|
return cls(app_name, file_name, raw_teal=raw_teal)
|
|
77
82
|
|
|
78
83
|
@classmethod
|
|
79
|
-
def from_compiled_teal(
|
|
84
|
+
def from_compiled_teal(
|
|
85
|
+
cls, compiled_teal: CompiledTeal | Program, app_name: str, file_name: str
|
|
86
|
+
) -> "PersistSourceMapInput":
|
|
80
87
|
return cls(app_name, file_name, compiled_teal=compiled_teal)
|
|
81
88
|
|
|
82
89
|
@property
|
|
@@ -107,60 +114,40 @@ def _load_or_create_sources(sources_path: Path) -> AVMDebuggerSourceMap:
|
|
|
107
114
|
return AVMDebuggerSourceMap.from_dict(json.load(f))
|
|
108
115
|
|
|
109
116
|
|
|
110
|
-
def _upsert_debug_sourcemaps(sourcemaps: list[AVMDebuggerSourceMapEntry], project_root: Path) -> None:
|
|
111
|
-
"""
|
|
112
|
-
This function updates or inserts debug sourcemaps. If path in the sourcemap during iteration leads to non
|
|
113
|
-
existing file, removes it. Otherwise upserts.
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
sourcemaps (list[AVMDebuggerSourceMapEntry]): A list of AVMDebuggerSourceMapEntry objects.
|
|
117
|
-
project_root (Path): The root directory of the project.
|
|
118
|
-
|
|
119
|
-
Returns:
|
|
120
|
-
None
|
|
121
|
-
"""
|
|
122
|
-
|
|
123
|
-
sources_path = project_root / ALGOKIT_DIR / SOURCES_DIR / SOURCES_FILE
|
|
124
|
-
sources = _load_or_create_sources(sources_path)
|
|
125
|
-
|
|
126
|
-
for sourcemap in sourcemaps:
|
|
127
|
-
source_file_path = Path(sourcemap.location)
|
|
128
|
-
if not source_file_path.exists() and sourcemap in sources.txn_group_sources:
|
|
129
|
-
sources.txn_group_sources.remove(sourcemap)
|
|
130
|
-
elif source_file_path.exists():
|
|
131
|
-
if sourcemap not in sources.txn_group_sources:
|
|
132
|
-
sources.txn_group_sources.append(sourcemap)
|
|
133
|
-
else:
|
|
134
|
-
index = sources.txn_group_sources.index(sourcemap)
|
|
135
|
-
sources.txn_group_sources[index] = sourcemap
|
|
136
|
-
|
|
137
|
-
with sources_path.open("w") as f:
|
|
138
|
-
json.dump(sources.to_dict(), f)
|
|
139
|
-
|
|
140
|
-
|
|
141
117
|
def _write_to_file(path: Path, content: str) -> None:
|
|
142
118
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
143
119
|
path.write_text(content)
|
|
144
120
|
|
|
145
121
|
|
|
146
|
-
def _build_avm_sourcemap(
|
|
122
|
+
def _build_avm_sourcemap(
|
|
147
123
|
*,
|
|
148
124
|
app_name: str,
|
|
149
125
|
file_name: str,
|
|
150
126
|
output_path: Path,
|
|
151
127
|
client: "AlgodClient",
|
|
152
128
|
raw_teal: str | None = None,
|
|
153
|
-
compiled_teal: Program | None = None,
|
|
129
|
+
compiled_teal: CompiledTeal | Program | None = None,
|
|
154
130
|
with_sources: bool = True,
|
|
155
131
|
) -> AVMDebuggerSourceMapEntry:
|
|
156
132
|
if not raw_teal and not compiled_teal:
|
|
157
133
|
raise ValueError("Either raw teal or compiled teal must be provided")
|
|
158
134
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
checksum(
|
|
162
|
-
|
|
163
|
-
|
|
135
|
+
# Handle both legacy Program and new CompiledTeal
|
|
136
|
+
if isinstance(compiled_teal, Program):
|
|
137
|
+
program_hash = base64.b64encode(checksum(compiled_teal.raw_binary)).decode()
|
|
138
|
+
source_map = compiled_teal.source_map.__dict__
|
|
139
|
+
teal_content = compiled_teal.teal
|
|
140
|
+
elif isinstance(compiled_teal, CompiledTeal):
|
|
141
|
+
program_hash = base64.b64encode(checksum(compiled_teal.compiled_base64_to_bytes)).decode()
|
|
142
|
+
source_map = compiled_teal.source_map.__dict__ if compiled_teal.source_map else {}
|
|
143
|
+
teal_content = compiled_teal.teal
|
|
144
|
+
else:
|
|
145
|
+
# Handle raw TEAL case
|
|
146
|
+
result = Program(str(raw_teal), client=client)
|
|
147
|
+
program_hash = base64.b64encode(checksum(result.raw_binary)).decode()
|
|
148
|
+
source_map = result.source_map.__dict__
|
|
149
|
+
teal_content = result.teal
|
|
150
|
+
|
|
164
151
|
source_map["sources"] = [f"{file_name}{TEAL_FILE_EXT}"] if with_sources else []
|
|
165
152
|
|
|
166
153
|
output_dir_path = output_path / ALGOKIT_DIR / SOURCES_DIR / app_name
|
|
@@ -169,25 +156,45 @@ def _build_avm_sourcemap( # noqa: PLR0913
|
|
|
169
156
|
_write_to_file(source_map_output_path, json.dumps(source_map))
|
|
170
157
|
|
|
171
158
|
if with_sources:
|
|
172
|
-
_write_to_file(teal_output_path,
|
|
159
|
+
_write_to_file(teal_output_path, teal_content)
|
|
173
160
|
|
|
174
161
|
return AVMDebuggerSourceMapEntry(str(source_map_output_path), program_hash)
|
|
175
162
|
|
|
176
163
|
|
|
164
|
+
def cleanup_old_trace_files(output_dir: Path, buffer_size_mb: float) -> None:
|
|
165
|
+
"""
|
|
166
|
+
Cleanup old trace files if total size exceeds buffer size limit.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
output_dir (Path): Directory containing trace files
|
|
170
|
+
buffer_size_mb (float): Maximum allowed size in megabytes
|
|
171
|
+
"""
|
|
172
|
+
total_size = sum(f.stat().st_size for f in output_dir.glob("*") if f.is_file())
|
|
173
|
+
if total_size > buffer_size_mb * 1024 * 1024:
|
|
174
|
+
sorted_files = sorted(output_dir.glob("*"), key=lambda p: p.stat().st_mtime)
|
|
175
|
+
while total_size > buffer_size_mb * 1024 * 1024 and sorted_files:
|
|
176
|
+
oldest_file = sorted_files.pop(0)
|
|
177
|
+
total_size -= oldest_file.stat().st_size
|
|
178
|
+
oldest_file.unlink()
|
|
179
|
+
|
|
180
|
+
|
|
177
181
|
def persist_sourcemaps(
|
|
178
|
-
*,
|
|
182
|
+
*,
|
|
183
|
+
sources: list[PersistSourceMapInput],
|
|
184
|
+
project_root: Path,
|
|
185
|
+
client: "AlgodClient",
|
|
186
|
+
with_sources: bool = True,
|
|
179
187
|
) -> None:
|
|
180
188
|
"""
|
|
181
189
|
Persist the sourcemaps for the given sources as an AlgoKit AVM Debugger compliant artifacts.
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
Default is True, as needed by an AlgoKit AVM debugger.
|
|
190
|
+
|
|
191
|
+
:param sources: A list of PersistSourceMapInput objects.
|
|
192
|
+
:param project_root: The root directory of the project.
|
|
193
|
+
:param client: An AlgodClient object for interacting with the Algorand blockchain.
|
|
194
|
+
:param with_sources: If True, it will dump teal source files along with sourcemaps.
|
|
188
195
|
"""
|
|
189
196
|
|
|
190
|
-
|
|
197
|
+
for source in sources:
|
|
191
198
|
_build_avm_sourcemap(
|
|
192
199
|
raw_teal=source.raw_teal,
|
|
193
200
|
compiled_teal=source.compiled_teal,
|
|
@@ -197,54 +204,68 @@ def persist_sourcemaps(
|
|
|
197
204
|
client=client,
|
|
198
205
|
with_sources=with_sources,
|
|
199
206
|
)
|
|
200
|
-
for source in sources
|
|
201
|
-
]
|
|
202
|
-
|
|
203
|
-
_upsert_debug_sourcemaps(sourcemaps, project_root)
|
|
204
207
|
|
|
205
208
|
|
|
206
|
-
def simulate_response(
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
"""
|
|
209
|
+
def simulate_response(
|
|
210
|
+
atc: AtomicTransactionComposer,
|
|
211
|
+
algod_client: "AlgodClient",
|
|
212
|
+
allow_more_logs: bool | None = None,
|
|
213
|
+
allow_empty_signatures: bool | None = None,
|
|
214
|
+
allow_unnamed_resources: bool | None = None,
|
|
215
|
+
extra_opcode_budget: int | None = None,
|
|
216
|
+
exec_trace_config: SimulateTraceConfig | None = None,
|
|
217
|
+
simulation_round: int | None = None,
|
|
218
|
+
) -> SimulateAtomicTransactionResponse:
|
|
219
|
+
"""Simulate atomic transaction group execution"""
|
|
217
220
|
|
|
218
221
|
unsigned_txn_groups = atc.build_group()
|
|
219
222
|
empty_signer = EmptySigner()
|
|
220
223
|
txn_list = [txn_group.txn for txn_group in unsigned_txn_groups]
|
|
221
224
|
fake_signed_transactions = empty_signer.sign_transactions(txn_list, [])
|
|
222
225
|
txn_group = [SimulateRequestTransactionGroup(txns=fake_signed_transactions)]
|
|
223
|
-
trace_config = SimulateTraceConfig(enable=True, stack_change=True, scratch_change=True)
|
|
226
|
+
trace_config = SimulateTraceConfig(enable=True, stack_change=True, scratch_change=True, state_change=True)
|
|
224
227
|
|
|
225
228
|
simulate_request = SimulateRequest(
|
|
226
|
-
txn_groups=txn_group,
|
|
229
|
+
txn_groups=txn_group,
|
|
230
|
+
allow_more_logs=allow_more_logs if allow_more_logs is not None else True,
|
|
231
|
+
round=simulation_round,
|
|
232
|
+
extra_opcode_budget=extra_opcode_budget if extra_opcode_budget is not None else 0,
|
|
233
|
+
allow_unnamed_resources=allow_unnamed_resources if allow_unnamed_resources is not None else True,
|
|
234
|
+
allow_empty_signatures=allow_empty_signatures if allow_empty_signatures is not None else True,
|
|
235
|
+
exec_trace_config=exec_trace_config if exec_trace_config is not None else trace_config,
|
|
227
236
|
)
|
|
237
|
+
|
|
228
238
|
return atc.simulate(algod_client, simulate_request)
|
|
229
239
|
|
|
230
240
|
|
|
231
241
|
def simulate_and_persist_response(
|
|
232
|
-
atc: AtomicTransactionComposer,
|
|
242
|
+
atc: AtomicTransactionComposer,
|
|
243
|
+
project_root: Path,
|
|
244
|
+
algod_client: "AlgodClient",
|
|
245
|
+
buffer_size_mb: float = 256,
|
|
246
|
+
allow_more_logs: bool | None = None,
|
|
247
|
+
allow_empty_signatures: bool | None = None,
|
|
248
|
+
allow_unnamed_resources: bool | None = None,
|
|
249
|
+
extra_opcode_budget: int | None = None,
|
|
250
|
+
exec_trace_config: SimulateTraceConfig | None = None,
|
|
251
|
+
simulation_round: int | None = None,
|
|
233
252
|
) -> SimulateAtomicTransactionResponse:
|
|
234
|
-
"""
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
:param project_root:
|
|
241
|
-
:param algod_client:
|
|
242
|
-
:param buffer_size_mb:
|
|
243
|
-
:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
253
|
+
"""Simulates atomic transactions and persists simulation response to a JSON file.
|
|
254
|
+
|
|
255
|
+
Simulates the atomic transactions using the provided AtomicTransactionComposer and AlgodClient,
|
|
256
|
+
then persists the simulation response to an AlgoKit AVM Debugger compliant JSON file.
|
|
257
|
+
|
|
258
|
+
:param atc: AtomicTransactionComposer containing transactions to simulate and persist
|
|
259
|
+
:param project_root: Root directory path of the project
|
|
260
|
+
:param algod_client: Algorand client instance
|
|
261
|
+
:param buffer_size_mb: Size of trace buffer in megabytes, defaults to 256
|
|
262
|
+
:param allow_more_logs: Flag to allow additional logs, defaults to None
|
|
263
|
+
:param allow_empty_signatures: Flag to allow empty signatures, defaults to None
|
|
264
|
+
:param allow_unnamed_resources: Flag to allow unnamed resources, defaults to None
|
|
265
|
+
:param extra_opcode_budget: Additional opcode budget, defaults to None
|
|
266
|
+
:param exec_trace_config: Execution trace configuration, defaults to None
|
|
267
|
+
:param simulation_round: Round number for simulation, defa ults to None
|
|
268
|
+
:return: Simulated response after persisting for AlgoKit AVM Debugger consumption
|
|
248
269
|
"""
|
|
249
270
|
atc_to_simulate = atc.clone()
|
|
250
271
|
sp = algod_client.suggested_params()
|
|
@@ -254,27 +275,32 @@ def simulate_and_persist_response(
|
|
|
254
275
|
txn_with_sign.txn.last_valid_round = sp.last
|
|
255
276
|
txn_with_sign.txn.genesis_hash = sp.gh
|
|
256
277
|
|
|
257
|
-
response = simulate_response(
|
|
278
|
+
response = simulate_response(
|
|
279
|
+
atc_to_simulate,
|
|
280
|
+
algod_client,
|
|
281
|
+
allow_more_logs,
|
|
282
|
+
allow_empty_signatures,
|
|
283
|
+
allow_unnamed_resources,
|
|
284
|
+
extra_opcode_budget,
|
|
285
|
+
exec_trace_config,
|
|
286
|
+
simulation_round,
|
|
287
|
+
)
|
|
258
288
|
txn_results = response.simulate_response["txn-groups"]
|
|
259
289
|
|
|
260
|
-
txn_types = [
|
|
261
|
-
|
|
262
|
-
|
|
290
|
+
txn_types = [
|
|
291
|
+
txn["txn-result"]["txn"]["txn"]["type"] for txn_result in txn_results for txn in txn_result["txn-results"]
|
|
292
|
+
]
|
|
293
|
+
txn_types_count = {}
|
|
294
|
+
for txn_type in txn_types:
|
|
295
|
+
if txn_type not in txn_types_count:
|
|
296
|
+
txn_types_count[txn_type] = txn_types.count(txn_type)
|
|
297
|
+
txn_types_str = "_".join([f"{count}{txn_type}" for txn_type, count in txn_types_count.items()])
|
|
263
298
|
|
|
264
299
|
last_round = response.simulate_response["last-round"]
|
|
265
300
|
timestamp = datetime.now(tz=timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
266
301
|
output_file = project_root / DEBUG_TRACES_DIR / f"{timestamp}_lr{last_round}_{txn_types_str}{TRACES_FILE_EXT}"
|
|
267
302
|
|
|
268
303
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
|
269
|
-
|
|
270
|
-
# cleanup old files if buffer size is exceeded
|
|
271
|
-
total_size = sum(f.stat().st_size for f in output_file.parent.glob("*") if f.is_file())
|
|
272
|
-
if total_size > buffer_size_mb * 1024 * 1024:
|
|
273
|
-
sorted_files = sorted(output_file.parent.glob("*"), key=lambda p: p.stat().st_mtime)
|
|
274
|
-
while total_size > buffer_size_mb * 1024 * 1024:
|
|
275
|
-
oldest_file = sorted_files.pop(0)
|
|
276
|
-
total_size -= oldest_file.stat().st_size
|
|
277
|
-
oldest_file.unlink()
|
|
278
|
-
|
|
304
|
+
cleanup_old_trace_files(output_file.parent, buffer_size_mb)
|
|
279
305
|
output_file.write_text(json.dumps(response.simulate_response, indent=2))
|
|
280
306
|
return response
|