algokit-utils 5.0.0a3__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.
- algokit_abi/__init__.py +9 -0
- algokit_abi/_arc32_to_arc56.py +242 -0
- algokit_abi/_arc56_serde.py +161 -0
- algokit_abi/abi.py +667 -0
- algokit_abi/arc32.py +210 -0
- algokit_abi/arc56.py +821 -0
- algokit_abi/py.typed +0 -0
- algokit_algo25/__init__.py +38 -0
- algokit_algo25/_encoding.py +46 -0
- algokit_algo25/_wordlist.py +2065 -0
- algokit_algo25/exceptions.py +29 -0
- algokit_algo25/mnemonic.py +128 -0
- algokit_algo25/py.typed +0 -0
- algokit_algod_client/__init__.py +10 -0
- algokit_algod_client/client.py +1585 -0
- algokit_algod_client/config.py +36 -0
- algokit_algod_client/exceptions.py +59 -0
- algokit_algod_client/models/__init__.py +229 -0
- algokit_algod_client/models/_account.py +150 -0
- algokit_algod_client/models/_account_application_response.py +25 -0
- algokit_algod_client/models/_account_asset_response.py +25 -0
- algokit_algod_client/models/_account_participation.py +53 -0
- algokit_algod_client/models/_account_state_delta.py +30 -0
- algokit_algod_client/models/_allocations_for_genesis_file.py +23 -0
- algokit_algod_client/models/_allocations_for_genesis_file_state_model.py +42 -0
- algokit_algod_client/models/_application.py +23 -0
- algokit_algod_client/models/_application_initial_states.py +37 -0
- algokit_algod_client/models/_application_kvstorage.py +29 -0
- algokit_algod_client/models/_application_local_state.py +33 -0
- algokit_algod_client/models/_application_params.py +63 -0
- algokit_algod_client/models/_application_state_operation.py +41 -0
- algokit_algod_client/models/_application_state_schema.py +22 -0
- algokit_algod_client/models/_asset.py +23 -0
- algokit_algod_client/models/_asset_holding.py +29 -0
- algokit_algod_client/models/_asset_params.py +102 -0
- algokit_algod_client/models/_avm_key_value.py +28 -0
- algokit_algod_client/models/_avm_value.py +32 -0
- algokit_algod_client/models/_block.py +363 -0
- algokit_algod_client/models/_block_hash_response.py +14 -0
- algokit_algod_client/models/_block_txids_response.py +14 -0
- algokit_algod_client/models/_box.py +36 -0
- algokit_algod_client/models/_box_descriptor.py +24 -0
- algokit_algod_client/models/_boxes_response.py +21 -0
- algokit_algod_client/models/_build_version_contains_the_current_algod_build_version_information.py +34 -0
- algokit_algod_client/models/_compile_response.py +24 -0
- algokit_algod_client/models/_disassemble_response.py +14 -0
- algokit_algod_client/models/_error_response.py +22 -0
- algokit_algod_client/models/_eval_delta.py +32 -0
- algokit_algod_client/models/_eval_delta_key_value.py +28 -0
- algokit_algod_client/models/_genesis_file_in_json.py +53 -0
- algokit_algod_client/models/_get_block_time_stamp_offset_response.py +14 -0
- algokit_algod_client/models/_get_sync_round_response.py +14 -0
- algokit_algod_client/models/_ledger_state_delta.py +389 -0
- algokit_algod_client/models/_light_block_header_proof.py +32 -0
- algokit_algod_client/models/_node_status_response.py +118 -0
- algokit_algod_client/models/_pending_transaction_response.py +91 -0
- algokit_algod_client/models/_pending_transactions_response.py +29 -0
- algokit_algod_client/models/_post_transactions_response.py +14 -0
- algokit_algod_client/models/_scratch_change.py +23 -0
- algokit_algod_client/models/_serde_helpers.py +241 -0
- algokit_algod_client/models/_simulate_initial_states.py +25 -0
- algokit_algod_client/models/_simulate_request.py +54 -0
- algokit_algod_client/models/_simulate_request_transaction_group.py +25 -0
- algokit_algod_client/models/_simulate_response.py +44 -0
- algokit_algod_client/models/_simulate_trace_config.py +30 -0
- algokit_algod_client/models/_simulate_transaction_group_result.py +46 -0
- algokit_algod_client/models/_simulate_transaction_result.py +41 -0
- algokit_algod_client/models/_simulate_unnamed_resources_accessed.py +64 -0
- algokit_algod_client/models/_simulation_eval_overrides.py +40 -0
- algokit_algod_client/models/_simulation_opcode_trace_unit.py +55 -0
- algokit_algod_client/models/_simulation_transaction_exec_trace.py +82 -0
- algokit_algod_client/models/_source_map.py +30 -0
- algokit_algod_client/models/_state_delta.py +6 -0
- algokit_algod_client/models/_state_proof.py +28 -0
- algokit_algod_client/models/_state_proof_message.py +44 -0
- algokit_algod_client/models/_supply_response.py +26 -0
- algokit_algod_client/models/_teal_key_value.py +28 -0
- algokit_algod_client/models/_teal_key_value_store.py +6 -0
- algokit_algod_client/models/_teal_value.py +32 -0
- algokit_algod_client/models/_transaction_group_ledger_state_deltas_for_round_response.py +21 -0
- algokit_algod_client/models/_transaction_parameters_response.py +45 -0
- algokit_algod_client/models/_transaction_proof.py +44 -0
- algokit_algod_client/models/_version_contains_the_current_algod_version.py +38 -0
- algokit_algod_client/models/suggested_params.py +42 -0
- algokit_algod_client/py.typed +1 -0
- algokit_algod_client/types.py +7 -0
- algokit_algosdk/__init__.py +38 -0
- algokit_algosdk/account.py +32 -0
- algokit_algosdk/app_access.py +228 -0
- algokit_algosdk/box_reference.py +100 -0
- algokit_algosdk/constants.py +147 -0
- algokit_algosdk/encoding.py +89 -0
- algokit_algosdk/error.py +180 -0
- algokit_algosdk/logic.py +61 -0
- algokit_algosdk/logicsig.py +218 -0
- algokit_algosdk/mnemonic.py +216 -0
- algokit_algosdk/multisig.py +161 -0
- algokit_algosdk/py.typed +0 -0
- algokit_algosdk/transaction.py +596 -0
- algokit_algosdk/wordlist.py +2054 -0
- algokit_common/__init__.py +50 -0
- algokit_common/address.py +34 -0
- algokit_common/constants.py +47 -0
- algokit_common/hashing.py +25 -0
- algokit_common/py.typed +0 -0
- algokit_common/serde/__init__.py +40 -0
- algokit_common/serde/_core.py +610 -0
- algokit_common/serde/_primitives.py +135 -0
- algokit_common/source_map.py +158 -0
- algokit_indexer_client/__init__.py +10 -0
- algokit_indexer_client/client.py +1456 -0
- algokit_indexer_client/config.py +36 -0
- algokit_indexer_client/exceptions.py +59 -0
- algokit_indexer_client/models/__init__.py +148 -0
- algokit_indexer_client/models/_account.py +161 -0
- algokit_indexer_client/models/_account_participation.py +53 -0
- algokit_indexer_client/models/_account_response.py +19 -0
- algokit_indexer_client/models/_account_state_delta.py +29 -0
- algokit_indexer_client/models/_accounts_response.py +29 -0
- algokit_indexer_client/models/_application.py +35 -0
- algokit_indexer_client/models/_application_local_state.py +45 -0
- algokit_indexer_client/models/_application_local_states_response.py +29 -0
- algokit_indexer_client/models/_application_log_data.py +28 -0
- algokit_indexer_client/models/_application_logs_response.py +33 -0
- algokit_indexer_client/models/_application_params.py +62 -0
- algokit_indexer_client/models/_application_response.py +20 -0
- algokit_indexer_client/models/_application_state_schema.py +22 -0
- algokit_indexer_client/models/_applications_response.py +29 -0
- algokit_indexer_client/models/_asset.py +35 -0
- algokit_indexer_client/models/_asset_balances_response.py +29 -0
- algokit_indexer_client/models/_asset_holding.py +41 -0
- algokit_indexer_client/models/_asset_holdings_response.py +29 -0
- algokit_indexer_client/models/_asset_params.py +102 -0
- algokit_indexer_client/models/_asset_response.py +19 -0
- algokit_indexer_client/models/_assets_response.py +29 -0
- algokit_indexer_client/models/_block.py +150 -0
- algokit_indexer_client/models/_block_headers_response.py +29 -0
- algokit_indexer_client/models/_block_rewards.py +38 -0
- algokit_indexer_client/models/_block_upgrade_state.py +34 -0
- algokit_indexer_client/models/_block_upgrade_vote.py +26 -0
- algokit_indexer_client/models/_box.py +36 -0
- algokit_indexer_client/models/_box_descriptor.py +24 -0
- algokit_indexer_client/models/_box_reference.py +28 -0
- algokit_indexer_client/models/_boxes_response.py +29 -0
- algokit_indexer_client/models/_error_response.py +18 -0
- algokit_indexer_client/models/_eval_delta.py +32 -0
- algokit_indexer_client/models/_eval_delta_key_value.py +28 -0
- algokit_indexer_client/models/_hash_factory.py +14 -0
- algokit_indexer_client/models/_hb_proof_fields.py +57 -0
- algokit_indexer_client/models/_health_check.py +42 -0
- algokit_indexer_client/models/_holding_ref.py +23 -0
- algokit_indexer_client/models/_indexer_state_proof_message.py +40 -0
- algokit_indexer_client/models/_locals_ref.py +23 -0
- algokit_indexer_client/models/_merkle_array_proof.py +29 -0
- algokit_indexer_client/models/_mini_asset_holding.py +38 -0
- algokit_indexer_client/models/_on_completion.py +25 -0
- algokit_indexer_client/models/_participation_updates.py +22 -0
- algokit_indexer_client/models/_resource_ref.py +42 -0
- algokit_indexer_client/models/_serde_helpers.py +241 -0
- algokit_indexer_client/models/_state_delta.py +6 -0
- algokit_indexer_client/models/_state_proof_fields.py +57 -0
- algokit_indexer_client/models/_state_proof_participant.py +20 -0
- algokit_indexer_client/models/_state_proof_reveal.py +25 -0
- algokit_indexer_client/models/_state_proof_sig_slot.py +20 -0
- algokit_indexer_client/models/_state_proof_signature.py +37 -0
- algokit_indexer_client/models/_state_proof_tracking.py +32 -0
- algokit_indexer_client/models/_state_proof_verifier.py +24 -0
- algokit_indexer_client/models/_state_schema.py +25 -0
- algokit_indexer_client/models/_teal_key_value.py +28 -0
- algokit_indexer_client/models/_teal_key_value_store.py +6 -0
- algokit_indexer_client/models/_teal_value.py +32 -0
- algokit_indexer_client/models/_transaction.py +213 -0
- algokit_indexer_client/models/_transaction_application.py +105 -0
- algokit_indexer_client/models/_transaction_asset_config.py +31 -0
- algokit_indexer_client/models/_transaction_asset_freeze.py +29 -0
- algokit_indexer_client/models/_transaction_asset_transfer.py +41 -0
- algokit_indexer_client/models/_transaction_heartbeat.py +52 -0
- algokit_indexer_client/models/_transaction_keyreg.py +59 -0
- algokit_indexer_client/models/_transaction_payment.py +33 -0
- algokit_indexer_client/models/_transaction_response.py +19 -0
- algokit_indexer_client/models/_transaction_signature.py +35 -0
- algokit_indexer_client/models/_transaction_signature_logicsig.py +59 -0
- algokit_indexer_client/models/_transaction_signature_multisig.py +36 -0
- algokit_indexer_client/models/_transaction_signature_multisig_subsignature.py +28 -0
- algokit_indexer_client/models/_transaction_state_proof.py +32 -0
- algokit_indexer_client/models/_transactions_response.py +29 -0
- algokit_indexer_client/py.typed +1 -0
- algokit_indexer_client/types.py +7 -0
- algokit_kmd_client/__init__.py +10 -0
- algokit_kmd_client/client.py +1240 -0
- algokit_kmd_client/config.py +36 -0
- algokit_kmd_client/exceptions.py +59 -0
- algokit_kmd_client/models/__init__.py +112 -0
- algokit_kmd_client/models/_classical_signatures.py +4 -0
- algokit_kmd_client/models/_create_wallet_request.py +30 -0
- algokit_kmd_client/models/_create_wallet_response.py +19 -0
- algokit_kmd_client/models/_delete_key_request.py +27 -0
- algokit_kmd_client/models/_delete_multisig_request.py +27 -0
- algokit_kmd_client/models/_digest_represents_a32_byte_value_holding_the256_bit_hash_digest.py +4 -0
- algokit_kmd_client/models/_ed25519_public_key.py +4 -0
- algokit_kmd_client/models/_export_key_request.py +27 -0
- algokit_kmd_client/models/_export_key_response.py +24 -0
- algokit_kmd_client/models/_export_master_key_request.py +22 -0
- algokit_kmd_client/models/_export_master_key_response.py +18 -0
- algokit_kmd_client/models/_export_multisig_request.py +23 -0
- algokit_kmd_client/models/_export_multisig_response.py +26 -0
- algokit_kmd_client/models/_generate_key_request.py +18 -0
- algokit_kmd_client/models/_generate_key_response.py +19 -0
- algokit_kmd_client/models/_import_key_request.py +28 -0
- algokit_kmd_client/models/_import_key_response.py +19 -0
- algokit_kmd_client/models/_import_multisig_request.py +30 -0
- algokit_kmd_client/models/_import_multisig_response.py +19 -0
- algokit_kmd_client/models/_init_wallet_handle_token_request.py +22 -0
- algokit_kmd_client/models/_init_wallet_handle_token_response.py +18 -0
- algokit_kmd_client/models/_list_keys_request.py +18 -0
- algokit_kmd_client/models/_list_keys_response.py +18 -0
- algokit_kmd_client/models/_list_multisig_request.py +18 -0
- algokit_kmd_client/models/_list_multisig_response.py +18 -0
- algokit_kmd_client/models/_list_wallets_request.py +11 -0
- algokit_kmd_client/models/_list_wallets_response.py +25 -0
- algokit_kmd_client/models/_master_derivation_key.py +4 -0
- algokit_kmd_client/models/_multisig_sig.py +33 -0
- algokit_kmd_client/models/_multisig_subsig.py +23 -0
- algokit_kmd_client/models/_public_key.py +4 -0
- algokit_kmd_client/models/_release_wallet_handle_token_request.py +18 -0
- algokit_kmd_client/models/_rename_wallet_request.py +26 -0
- algokit_kmd_client/models/_rename_wallet_response.py +19 -0
- algokit_kmd_client/models/_renew_wallet_handle_token_request.py +18 -0
- algokit_kmd_client/models/_renew_wallet_handle_token_response.py +19 -0
- algokit_kmd_client/models/_serde_helpers.py +241 -0
- algokit_kmd_client/models/_sign_multisig_response.py +24 -0
- algokit_kmd_client/models/_sign_multisig_txn_request.py +45 -0
- algokit_kmd_client/models/_sign_program_multisig_request.py +50 -0
- algokit_kmd_client/models/_sign_program_multisig_response.py +24 -0
- algokit_kmd_client/models/_sign_program_request.py +37 -0
- algokit_kmd_client/models/_sign_program_response.py +24 -0
- algokit_kmd_client/models/_sign_transaction_response.py +24 -0
- algokit_kmd_client/models/_sign_txn_request.py +36 -0
- algokit_kmd_client/models/_signature.py +4 -0
- algokit_kmd_client/models/_tx_type.py +4 -0
- algokit_kmd_client/models/_versions_request.py +11 -0
- algokit_kmd_client/models/_versions_response.py +19 -0
- algokit_kmd_client/models/_wallet.py +38 -0
- algokit_kmd_client/models/_wallet_handle.py +24 -0
- algokit_kmd_client/models/_wallet_info_request.py +18 -0
- algokit_kmd_client/models/_wallet_info_response.py +19 -0
- algokit_kmd_client/py.typed +1 -0
- algokit_kmd_client/types.py +7 -0
- algokit_transact/__init__.py +190 -0
- algokit_transact/codec/__init__.py +0 -0
- algokit_transact/codec/msgpack.py +11 -0
- algokit_transact/codec/serde.py +7 -0
- algokit_transact/codec/signed.py +57 -0
- algokit_transact/codec/transaction.py +65 -0
- algokit_transact/exceptions.py +17 -0
- algokit_transact/logicsig.py +220 -0
- algokit_transact/models/__init__.py +0 -0
- algokit_transact/models/app_call.py +447 -0
- algokit_transact/models/asset_config.py +19 -0
- algokit_transact/models/asset_freeze.py +11 -0
- algokit_transact/models/asset_transfer.py +13 -0
- algokit_transact/models/common.py +17 -0
- algokit_transact/models/heartbeat.py +21 -0
- algokit_transact/models/key_registration.py +14 -0
- algokit_transact/models/payment.py +14 -0
- algokit_transact/models/signed_transaction.py +21 -0
- algokit_transact/models/state_proof.py +150 -0
- algokit_transact/models/transaction.py +88 -0
- algokit_transact/multisig.py +93 -0
- algokit_transact/ops/__init__.py +0 -0
- algokit_transact/ops/fees.py +47 -0
- algokit_transact/ops/group.py +28 -0
- algokit_transact/ops/ids.py +14 -0
- algokit_transact/ops/validate.py +503 -0
- algokit_transact/py.typed +0 -0
- algokit_transact/signer.py +195 -0
- algokit_transact/signing/__init__.py +0 -0
- algokit_transact/signing/logic_signature.py +19 -0
- algokit_transact/signing/multisig.py +84 -0
- algokit_transact/signing/types.py +39 -0
- algokit_transact/signing/validation.py +63 -0
- algokit_utils/__init__.py +23 -0
- algokit_utils/_debugging.py +304 -0
- algokit_utils/accounts/__init__.py +2 -0
- algokit_utils/accounts/account_manager.py +1051 -0
- algokit_utils/accounts/kmd_account_manager.py +206 -0
- algokit_utils/algo25.py +46 -0
- algokit_utils/algorand.py +383 -0
- algokit_utils/applications/__init__.py +7 -0
- algokit_utils/applications/abi.py +280 -0
- algokit_utils/applications/app_client.py +2193 -0
- algokit_utils/applications/app_deployer.py +788 -0
- algokit_utils/applications/app_factory.py +1140 -0
- algokit_utils/applications/app_manager.py +575 -0
- algokit_utils/applications/app_spec/__init__.py +6 -0
- algokit_utils/applications/enums.py +40 -0
- algokit_utils/assets/__init__.py +1 -0
- algokit_utils/assets/asset_manager.py +344 -0
- algokit_utils/clients/__init__.py +41 -0
- algokit_utils/clients/client_manager.py +756 -0
- algokit_utils/clients/dispenser_api_client.py +212 -0
- algokit_utils/common.py +40 -0
- algokit_utils/config.py +159 -0
- algokit_utils/errors/__init__.py +1 -0
- algokit_utils/errors/logic_error.py +160 -0
- algokit_utils/models/__init__.py +7 -0
- algokit_utils/models/account.py +12 -0
- algokit_utils/models/amount.py +198 -0
- algokit_utils/models/application.py +90 -0
- algokit_utils/models/network.py +29 -0
- algokit_utils/models/simulate.py +7 -0
- algokit_utils/models/state.py +53 -0
- algokit_utils/models/transaction.py +49 -0
- algokit_utils/protocols/__init__.py +3 -0
- algokit_utils/protocols/account.py +11 -0
- algokit_utils/protocols/signer.py +17 -0
- algokit_utils/protocols/typed_clients.py +110 -0
- algokit_utils/py.typed +0 -0
- algokit_utils/transact.py +195 -0
- algokit_utils/transactions/__init__.py +3 -0
- algokit_utils/transactions/builders/__init__.py +67 -0
- algokit_utils/transactions/builders/app.py +248 -0
- algokit_utils/transactions/builders/asset.py +256 -0
- algokit_utils/transactions/builders/common.py +263 -0
- algokit_utils/transactions/builders/keyreg.py +103 -0
- algokit_utils/transactions/builders/method_call.py +380 -0
- algokit_utils/transactions/builders/payment.py +43 -0
- algokit_utils/transactions/composer_resources.py +409 -0
- algokit_utils/transactions/fee_coverage.py +79 -0
- algokit_utils/transactions/helpers.py +9 -0
- algokit_utils/transactions/transaction_composer.py +1574 -0
- algokit_utils/transactions/transaction_creator.py +699 -0
- algokit_utils/transactions/transaction_sender.py +1240 -0
- algokit_utils/transactions/types.py +262 -0
- algokit_utils-5.0.0a3.dist-info/METADATA +105 -0
- algokit_utils-5.0.0a3.dist-info/RECORD +337 -0
- algokit_utils-5.0.0a3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
|
|
3
|
+
from algokit_transact.codec.serde import bytes_seq, nested, wire
|
|
4
|
+
from algokit_transact.signing.types import MultisigSignature
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass(slots=True, frozen=True)
|
|
8
|
+
class LogicSignature:
|
|
9
|
+
logic: bytes = field(metadata=wire("l"))
|
|
10
|
+
args: list[bytes] | None = field(default=None, metadata=bytes_seq("arg"))
|
|
11
|
+
sig: bytes | None = field(default=None, metadata=wire("sig"))
|
|
12
|
+
msig: MultisigSignature | None = field(
|
|
13
|
+
default=None,
|
|
14
|
+
metadata=nested("msig", MultisigSignature),
|
|
15
|
+
)
|
|
16
|
+
lmsig: MultisigSignature | None = field(
|
|
17
|
+
default=None,
|
|
18
|
+
metadata=nested("lmsig", MultisigSignature),
|
|
19
|
+
)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from dataclasses import replace
|
|
3
|
+
|
|
4
|
+
from algokit_common import (
|
|
5
|
+
MULTISIG_DOMAIN_SEPARATOR,
|
|
6
|
+
PUBLIC_KEY_BYTE_LENGTH,
|
|
7
|
+
address_from_public_key,
|
|
8
|
+
public_key_from_address,
|
|
9
|
+
sha512_256,
|
|
10
|
+
)
|
|
11
|
+
from algokit_transact.signing.types import MultisigSignature, MultisigSubsignature
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def new_multisig_signature(version: int, threshold: int, participants: Iterable[str]) -> MultisigSignature:
|
|
15
|
+
participants = list(participants)
|
|
16
|
+
if version == 0:
|
|
17
|
+
raise ValueError("Version cannot be zero")
|
|
18
|
+
if not participants:
|
|
19
|
+
raise ValueError("Participants cannot be empty")
|
|
20
|
+
if threshold == 0 or threshold > len(participants):
|
|
21
|
+
raise ValueError("Threshold must be greater than zero and less than or equal to the number of participants")
|
|
22
|
+
|
|
23
|
+
subsigs = [MultisigSubsignature(public_key=public_key_from_address(address)) for address in participants]
|
|
24
|
+
return MultisigSignature(version=version, threshold=threshold, subsigs=subsigs)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def participants_from_multisig_signature(multisig_signature: MultisigSignature) -> list[str]:
|
|
28
|
+
return [address_from_public_key(subsig.public_key) for subsig in multisig_signature.subsigs]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def address_from_multisig_signature(multisig_signature: MultisigSignature) -> str:
|
|
32
|
+
prefix = MULTISIG_DOMAIN_SEPARATOR.encode()
|
|
33
|
+
participant_keys = [subsig.public_key for subsig in multisig_signature.subsigs]
|
|
34
|
+
|
|
35
|
+
buffer = bytearray()
|
|
36
|
+
buffer.extend(prefix)
|
|
37
|
+
buffer.append(multisig_signature.version)
|
|
38
|
+
buffer.append(multisig_signature.threshold)
|
|
39
|
+
for pk in participant_keys:
|
|
40
|
+
if len(pk) != PUBLIC_KEY_BYTE_LENGTH:
|
|
41
|
+
raise ValueError("Invalid participant public key length")
|
|
42
|
+
buffer.extend(pk)
|
|
43
|
+
|
|
44
|
+
public_key = sha512_256(bytes(buffer))
|
|
45
|
+
return address_from_public_key(public_key)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def apply_multisig_subsignature(
|
|
49
|
+
multisig_signature: MultisigSignature, participant: str, signature: bytes
|
|
50
|
+
) -> MultisigSignature:
|
|
51
|
+
found = False
|
|
52
|
+
updated = []
|
|
53
|
+
participant_pk = public_key_from_address(participant)
|
|
54
|
+
for subsig in multisig_signature.subsigs:
|
|
55
|
+
if subsig.public_key == participant_pk:
|
|
56
|
+
found = True
|
|
57
|
+
updated.append(MultisigSubsignature(public_key=subsig.public_key, sig=signature))
|
|
58
|
+
else:
|
|
59
|
+
updated.append(subsig)
|
|
60
|
+
if not found:
|
|
61
|
+
raise ValueError("Address not found in multisig signature")
|
|
62
|
+
return replace(multisig_signature, subsigs=updated)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def merge_multisignatures(multisig_a: MultisigSignature, multisig_b: MultisigSignature) -> MultisigSignature:
|
|
66
|
+
if multisig_a.version != multisig_b.version:
|
|
67
|
+
raise ValueError("Cannot merge multisig signatures with different versions")
|
|
68
|
+
if multisig_a.threshold != multisig_b.threshold:
|
|
69
|
+
raise ValueError("Cannot merge multisig signatures with different thresholds")
|
|
70
|
+
|
|
71
|
+
participants_a = participants_from_multisig_signature(multisig_a)
|
|
72
|
+
participants_b = participants_from_multisig_signature(multisig_b)
|
|
73
|
+
if participants_a != participants_b:
|
|
74
|
+
raise ValueError("Cannot merge multisig signatures with different participants")
|
|
75
|
+
|
|
76
|
+
merged_subsigs = []
|
|
77
|
+
for subsig_a, subsig_b in zip(multisig_a.subsigs, multisig_b.subsigs, strict=False):
|
|
78
|
+
sig = subsig_b.sig if subsig_b.sig is not None else subsig_a.sig
|
|
79
|
+
merged_subsigs.append(MultisigSubsignature(public_key=subsig_a.public_key, sig=sig))
|
|
80
|
+
return MultisigSignature(
|
|
81
|
+
version=multisig_a.version,
|
|
82
|
+
threshold=multisig_a.threshold,
|
|
83
|
+
subsigs=merged_subsigs,
|
|
84
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from typing import cast
|
|
4
|
+
|
|
5
|
+
from algokit_transact.codec.serde import from_wire, to_wire, wire
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _encode_subsig_seq(value: object) -> object:
|
|
9
|
+
if value is None:
|
|
10
|
+
return None
|
|
11
|
+
if isinstance(value, tuple | list):
|
|
12
|
+
payload = [to_wire(subsig) for subsig in value]
|
|
13
|
+
return payload if payload else None
|
|
14
|
+
return value
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _decode_subsig_seq(value: object) -> object:
|
|
18
|
+
if isinstance(value, list):
|
|
19
|
+
decoded: list[MultisigSubsignature] = []
|
|
20
|
+
for entry in value:
|
|
21
|
+
if isinstance(entry, Mapping):
|
|
22
|
+
decoded.append(from_wire(MultisigSubsignature, cast(Mapping[str, object], entry)))
|
|
23
|
+
return tuple(decoded)
|
|
24
|
+
return value
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(slots=True, frozen=True)
|
|
28
|
+
class MultisigSubsignature:
|
|
29
|
+
public_key: bytes = field(metadata=wire("pk"))
|
|
30
|
+
sig: bytes | None = field(default=None, metadata=wire("s"))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(slots=True, frozen=True)
|
|
34
|
+
class MultisigSignature:
|
|
35
|
+
version: int = field(metadata=wire("v", keep_zero=True))
|
|
36
|
+
threshold: int = field(metadata=wire("thr", keep_zero=True))
|
|
37
|
+
subsigs: list[MultisigSubsignature] = field(
|
|
38
|
+
metadata=wire("subsig", encode=_encode_subsig_seq, decode=_decode_subsig_seq)
|
|
39
|
+
)
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Program validation utilities for TEAL bytecode.
|
|
2
|
+
|
|
3
|
+
This module provides sanity checks for compiled TEAL programs to help
|
|
4
|
+
detect common errors such as passing source code instead of bytecode,
|
|
5
|
+
or passing base64-encoded programs.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import base64
|
|
9
|
+
|
|
10
|
+
from algokit_common.address import public_key_from_address
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def sanity_check_program(program: bytes) -> None:
|
|
14
|
+
"""Perform sanity checks on a compiled TEAL program.
|
|
15
|
+
|
|
16
|
+
This function validates that the provided bytes appear to be compiled
|
|
17
|
+
TEAL bytecode rather than common mistakes like:
|
|
18
|
+
- Empty program
|
|
19
|
+
- An Algorand address string
|
|
20
|
+
- A base64-encoded string
|
|
21
|
+
- TEAL source code (ASCII text)
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
program: The compiled TEAL program bytes to validate.
|
|
25
|
+
|
|
26
|
+
Raises:
|
|
27
|
+
ValueError: If the program fails any sanity check:
|
|
28
|
+
- "empty program" if the program is None or empty
|
|
29
|
+
- "requesting program bytes, get Algorand address" if the bytes
|
|
30
|
+
decode to a valid Algorand address
|
|
31
|
+
- "program should not be b64 encoded" if the bytes appear to be
|
|
32
|
+
a base64-encoded string
|
|
33
|
+
- "program bytes are all ASCII printable characters, not looking
|
|
34
|
+
like Teal byte code" if all bytes are printable ASCII
|
|
35
|
+
"""
|
|
36
|
+
if not program:
|
|
37
|
+
raise ValueError("empty program")
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
ascii_str = program.decode("ascii")
|
|
41
|
+
except UnicodeDecodeError:
|
|
42
|
+
# not ascii, probably bytecode
|
|
43
|
+
return
|
|
44
|
+
|
|
45
|
+
if any(not line.isprintable() for line in ascii_str.splitlines()):
|
|
46
|
+
# not printable, probably bytecode
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
public_key_from_address(ascii_str)
|
|
51
|
+
except (TypeError, ValueError):
|
|
52
|
+
pass
|
|
53
|
+
else:
|
|
54
|
+
raise ValueError("requesting program bytes, get Algorand address")
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
base64.b64decode(ascii_str)
|
|
58
|
+
except (TypeError, ValueError):
|
|
59
|
+
pass
|
|
60
|
+
else:
|
|
61
|
+
raise ValueError("program should not be b64 encoded")
|
|
62
|
+
|
|
63
|
+
raise ValueError("program bytes are all ASCII printable characters, not looking like Teal byte code")
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""AlgoKit Python Utilities - a set of utilities for building solutions on Algorand
|
|
2
|
+
|
|
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
|
+
from algokit_utils.transact import Transaction, TransactionSigner
|
|
10
|
+
etc.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
# Core types and utilities that are commonly used
|
|
14
|
+
from algokit_utils.applications import * # noqa: F403
|
|
15
|
+
from algokit_utils.assets import * # noqa: F403
|
|
16
|
+
from algokit_utils.protocols import * # noqa: F403
|
|
17
|
+
from algokit_utils.models import * # noqa: F403
|
|
18
|
+
from algokit_utils.accounts import * # noqa: F403
|
|
19
|
+
from algokit_utils.clients import * # noqa: F403
|
|
20
|
+
from algokit_utils.transactions import * # noqa: F403
|
|
21
|
+
from algokit_utils.errors import * # noqa: F403
|
|
22
|
+
from algokit_utils.algorand import * # noqa: F403
|
|
23
|
+
from algokit_utils.transact import * # noqa: F403
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
import typing
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from datetime import datetime, timezone
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from algokit_common import ProgramSourceMap, sha512_256
|
|
11
|
+
from algokit_common.serde import to_wire
|
|
12
|
+
from algokit_utils.applications.app_manager import AppManager
|
|
13
|
+
from algokit_utils.config import config
|
|
14
|
+
from algokit_utils.models.application import CompiledTeal
|
|
15
|
+
from algokit_utils.transactions.transaction_composer import SendTransactionComposerResults, TransactionComposer
|
|
16
|
+
|
|
17
|
+
if typing.TYPE_CHECKING:
|
|
18
|
+
from algosdk.atomic_transaction_composer import SimulateAtomicTransactionResponse # type: ignore[import-not-found]
|
|
19
|
+
|
|
20
|
+
from algokit_algod_client import AlgodClient
|
|
21
|
+
else:
|
|
22
|
+
SimulateAtomicTransactionResponse = typing.Any # type: ignore[assignment]
|
|
23
|
+
AlgodClient = typing.Any # type: ignore[assignment]
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
ALGOKIT_DIR = ".algokit"
|
|
28
|
+
SOURCES_DIR = "sources"
|
|
29
|
+
SOURCES_FILE = "sources.avm.json"
|
|
30
|
+
TRACES_FILE_EXT = ".trace.avm.json"
|
|
31
|
+
DEBUG_TRACES_DIR = "debug_traces"
|
|
32
|
+
TEAL_FILE_EXT = ".teal"
|
|
33
|
+
TEAL_SOURCEMAP_EXT = ".teal.map"
|
|
34
|
+
TRACE_FILENAME_DATE_FORMAT = "%Y%m%d_%H%M%S"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass
|
|
38
|
+
class AVMDebuggerSourceMapEntry:
|
|
39
|
+
location: str = field(metadata={"json": "sourcemap-location"})
|
|
40
|
+
program_hash: str = field(metadata={"json": "hash"})
|
|
41
|
+
|
|
42
|
+
def __eq__(self, other: object) -> bool:
|
|
43
|
+
if isinstance(other, AVMDebuggerSourceMapEntry):
|
|
44
|
+
return self.location == other.location and self.program_hash == other.program_hash
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
def __str__(self) -> str:
|
|
48
|
+
return json.dumps({"sourcemap-location": self.location, "hash": self.program_hash})
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class AVMDebuggerSourceMap:
|
|
53
|
+
txn_group_sources: list[AVMDebuggerSourceMapEntry] = field(metadata={"json": "txn-group-sources"})
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def from_dict(cls, data: dict) -> "AVMDebuggerSourceMap":
|
|
57
|
+
return cls(
|
|
58
|
+
txn_group_sources=[
|
|
59
|
+
AVMDebuggerSourceMapEntry(location=item["sourcemap-location"], program_hash=item["hash"])
|
|
60
|
+
for item in data.get("txn-group-sources", [])
|
|
61
|
+
]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def to_dict(self) -> dict:
|
|
65
|
+
return {"txn-group-sources": [json.loads(str(item)) for item in self.txn_group_sources]}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass
|
|
69
|
+
class PersistSourceMapInput:
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
app_name: str,
|
|
73
|
+
file_name: str,
|
|
74
|
+
raw_teal: str | None = None,
|
|
75
|
+
compiled_teal: CompiledTeal | None = None,
|
|
76
|
+
):
|
|
77
|
+
self.compiled_teal = compiled_teal
|
|
78
|
+
self.app_name = app_name
|
|
79
|
+
self._raw_teal = raw_teal
|
|
80
|
+
self._file_name = self.strip_teal_extension(file_name)
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def from_raw_teal(cls, raw_teal: str, app_name: str, file_name: str) -> "PersistSourceMapInput":
|
|
84
|
+
return cls(app_name, file_name, raw_teal=raw_teal)
|
|
85
|
+
|
|
86
|
+
@classmethod
|
|
87
|
+
def from_compiled_teal(cls, compiled_teal: CompiledTeal, app_name: str, file_name: str) -> "PersistSourceMapInput":
|
|
88
|
+
return cls(app_name, file_name, compiled_teal=compiled_teal)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def raw_teal(self) -> str:
|
|
92
|
+
if self._raw_teal:
|
|
93
|
+
return self._raw_teal
|
|
94
|
+
elif self.compiled_teal:
|
|
95
|
+
return self.compiled_teal.teal
|
|
96
|
+
else:
|
|
97
|
+
raise ValueError("No teal content found")
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def file_name(self) -> str:
|
|
101
|
+
return self._file_name
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def strip_teal_extension(file_name: str) -> str:
|
|
105
|
+
if file_name.endswith(".teal"):
|
|
106
|
+
return file_name[:-5]
|
|
107
|
+
return file_name
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _write_to_file(path: Path, content: str) -> None:
|
|
111
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
112
|
+
path.write_text(content)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _compile_raw_teal(raw_teal: str, client: AlgodClient) -> tuple[bytes, ProgramSourceMap, str]:
|
|
116
|
+
teal_to_compile = AppManager.strip_teal_comments(raw_teal)
|
|
117
|
+
compiled = client.teal_compile(teal_to_compile.encode("utf-8"), sourcemap=True)
|
|
118
|
+
compiled_bytes = base64.b64decode(compiled.result)
|
|
119
|
+
sourcemap_dict = to_wire(compiled.sourcemap) if compiled.sourcemap else {}
|
|
120
|
+
return compiled_bytes, ProgramSourceMap(sourcemap_dict), raw_teal
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _build_avm_sourcemap(
|
|
124
|
+
*,
|
|
125
|
+
app_name: str,
|
|
126
|
+
file_name: str,
|
|
127
|
+
output_path: Path,
|
|
128
|
+
client: AlgodClient,
|
|
129
|
+
raw_teal: str | None = None,
|
|
130
|
+
compiled_teal: CompiledTeal | None = None,
|
|
131
|
+
with_sources: bool = True,
|
|
132
|
+
) -> AVMDebuggerSourceMapEntry:
|
|
133
|
+
if not raw_teal and not compiled_teal:
|
|
134
|
+
raise ValueError("Either raw teal or compiled teal must be provided")
|
|
135
|
+
|
|
136
|
+
if isinstance(compiled_teal, CompiledTeal):
|
|
137
|
+
program_hash = base64.b64encode(sha512_256(compiled_teal.compiled_base64_to_bytes)).decode()
|
|
138
|
+
source_map = compiled_teal.source_map.__dict__ if compiled_teal.source_map else {}
|
|
139
|
+
teal_content = compiled_teal.teal
|
|
140
|
+
else:
|
|
141
|
+
compiled_bytes, source_map_obj, teal_content = _compile_raw_teal(str(raw_teal), client)
|
|
142
|
+
program_hash = base64.b64encode(sha512_256(compiled_bytes)).decode()
|
|
143
|
+
source_map = source_map_obj.__dict__
|
|
144
|
+
|
|
145
|
+
source_map["sources"] = [f"{file_name}{TEAL_FILE_EXT}"] if with_sources else []
|
|
146
|
+
|
|
147
|
+
output_dir_path = output_path / ALGOKIT_DIR / SOURCES_DIR / app_name
|
|
148
|
+
source_map_output_path = output_dir_path / f"{file_name}{TEAL_SOURCEMAP_EXT}"
|
|
149
|
+
teal_output_path = output_dir_path / f"{file_name}{TEAL_FILE_EXT}"
|
|
150
|
+
_write_to_file(source_map_output_path, json.dumps(source_map))
|
|
151
|
+
|
|
152
|
+
if with_sources:
|
|
153
|
+
_write_to_file(teal_output_path, teal_content)
|
|
154
|
+
|
|
155
|
+
return AVMDebuggerSourceMapEntry(str(source_map_output_path), program_hash)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def cleanup_old_trace_files(output_dir: Path, buffer_size_mb: float) -> None:
|
|
159
|
+
"""
|
|
160
|
+
Cleanup old trace files if total size exceeds buffer size limit.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
output_dir (Path): Directory containing trace files
|
|
164
|
+
buffer_size_mb (float): Maximum allowed size in megabytes
|
|
165
|
+
"""
|
|
166
|
+
total_size = sum(f.stat().st_size for f in output_dir.glob("*") if f.is_file())
|
|
167
|
+
if total_size > buffer_size_mb * 1024 * 1024:
|
|
168
|
+
sorted_files = sorted(output_dir.glob("*"), key=lambda p: p.stat().st_mtime)
|
|
169
|
+
while total_size > buffer_size_mb * 1024 * 1024 and sorted_files:
|
|
170
|
+
oldest_file = sorted_files.pop(0)
|
|
171
|
+
total_size -= oldest_file.stat().st_size
|
|
172
|
+
oldest_file.unlink()
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _summarize_txn_types(trace: dict[str, Any]) -> str:
|
|
176
|
+
counts: dict[str, int] = {}
|
|
177
|
+
for group in trace.get("txn-groups", []):
|
|
178
|
+
for txn_result in group.get("txn-results", []):
|
|
179
|
+
txn = txn_result.get("txn-result", {}).get("txn", {}).get("txn", {})
|
|
180
|
+
txn_type = txn.get("type")
|
|
181
|
+
if txn_type and not isinstance(txn_type, str):
|
|
182
|
+
txn_type = getattr(txn_type, "value", str(txn_type))
|
|
183
|
+
if not txn_type:
|
|
184
|
+
continue
|
|
185
|
+
counts[txn_type] = counts.get(txn_type, 0) + 1
|
|
186
|
+
return "_".join(f"{count}{txn_type}" for txn_type, count in counts.items())
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def _persist_simulation_trace(
|
|
190
|
+
trace: dict[str, Any],
|
|
191
|
+
project_root: Path,
|
|
192
|
+
*,
|
|
193
|
+
timestamp: datetime | None = None,
|
|
194
|
+
buffer_size_mb: float | None = None,
|
|
195
|
+
) -> Path:
|
|
196
|
+
project_root.mkdir(parents=True, exist_ok=True)
|
|
197
|
+
trace_dir = project_root / DEBUG_TRACES_DIR
|
|
198
|
+
trace_dir.mkdir(parents=True, exist_ok=True)
|
|
199
|
+
|
|
200
|
+
now = timestamp or datetime.now(timezone.utc)
|
|
201
|
+
last_round = trace.get("last-round", 0)
|
|
202
|
+
txn_part = _summarize_txn_types(trace)
|
|
203
|
+
filename = (
|
|
204
|
+
f"{now.astimezone(timezone.utc).strftime(TRACE_FILENAME_DATE_FORMAT)}_lr{last_round}_{txn_part}"
|
|
205
|
+
f"{TRACES_FILE_EXT}"
|
|
206
|
+
)
|
|
207
|
+
output_path = trace_dir / filename
|
|
208
|
+
|
|
209
|
+
def _default_encoder(value: object) -> str:
|
|
210
|
+
if isinstance(value, (bytes | bytearray | memoryview)):
|
|
211
|
+
return base64.b64encode(bytes(value)).decode("utf-8")
|
|
212
|
+
return getattr(value, "value", str(value))
|
|
213
|
+
|
|
214
|
+
_write_to_file(output_path, json.dumps(trace, default=_default_encoder))
|
|
215
|
+
|
|
216
|
+
if buffer_size_mb is not None:
|
|
217
|
+
cleanup_old_trace_files(trace_dir, buffer_size_mb)
|
|
218
|
+
|
|
219
|
+
return output_path
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _extract_simulation_trace_from_algokit(result: SendTransactionComposerResults) -> dict[str, Any]:
|
|
223
|
+
if result.simulate_response is None:
|
|
224
|
+
raise ValueError("No simulate_response available to persist")
|
|
225
|
+
return to_wire(result.simulate_response)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _extract_simulation_trace_from_atc(response: SimulateAtomicTransactionResponse) -> dict[str, Any]:
|
|
229
|
+
# algosdk simulate responses are already dict-like
|
|
230
|
+
return dict(response.simulate_response) if hasattr(response, "simulate_response") else dict(response)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def simulate_and_persist_response(
|
|
234
|
+
composer: TransactionComposer | object,
|
|
235
|
+
project_root: Path,
|
|
236
|
+
algod: AlgodClient,
|
|
237
|
+
*,
|
|
238
|
+
buffer_size_mb: float | None = None,
|
|
239
|
+
result: SendTransactionComposerResults | SimulateAtomicTransactionResponse | None = None,
|
|
240
|
+
) -> Path:
|
|
241
|
+
"""
|
|
242
|
+
Run a simulation on the provided composer and persist the trace to disk.
|
|
243
|
+
|
|
244
|
+
:param composer: Transaction composer (AlgoKit or algosdk AtomicTransactionComposer)
|
|
245
|
+
:param project_root: Root directory where traces should be stored
|
|
246
|
+
:param algod: Algod client to use for simulation
|
|
247
|
+
:param buffer_size_mb: Optional buffer size to enforce via cleanup_old_trace_files
|
|
248
|
+
:param result: Optional existing simulation result to persist instead of re-running simulation
|
|
249
|
+
:return: Path to the persisted trace file
|
|
250
|
+
:raises TypeError: If the composer does not implement a compatible ``simulate`` method
|
|
251
|
+
"""
|
|
252
|
+
if result is None and isinstance(composer, TransactionComposer):
|
|
253
|
+
result = composer.simulate(_persist_trace=False)
|
|
254
|
+
trace = _extract_simulation_trace_from_algokit(result)
|
|
255
|
+
elif result is None and hasattr(composer, "simulate"):
|
|
256
|
+
result = composer.simulate(algod)
|
|
257
|
+
trace = _extract_simulation_trace_from_atc(result)
|
|
258
|
+
elif result is not None:
|
|
259
|
+
trace = (
|
|
260
|
+
_extract_simulation_trace_from_algokit(result)
|
|
261
|
+
if isinstance(result, SendTransactionComposerResults)
|
|
262
|
+
else _extract_simulation_trace_from_atc(result)
|
|
263
|
+
)
|
|
264
|
+
else:
|
|
265
|
+
raise TypeError("Composer must support simulate()")
|
|
266
|
+
|
|
267
|
+
effective_root = config.project_root or project_root
|
|
268
|
+
effective_buffer = buffer_size_mb
|
|
269
|
+
if config.trace_all and buffer_size_mb is None:
|
|
270
|
+
effective_buffer = config.trace_buffer_size_mb
|
|
271
|
+
|
|
272
|
+
return _persist_simulation_trace(
|
|
273
|
+
trace,
|
|
274
|
+
effective_root,
|
|
275
|
+
buffer_size_mb=effective_buffer,
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def persist_sourcemaps(
|
|
280
|
+
*,
|
|
281
|
+
sources: list[PersistSourceMapInput],
|
|
282
|
+
project_root: Path,
|
|
283
|
+
client: AlgodClient,
|
|
284
|
+
with_sources: bool = True,
|
|
285
|
+
) -> None:
|
|
286
|
+
"""
|
|
287
|
+
Persist the sourcemaps for the given sources as an AlgoKit AVM Debugger compliant artifacts.
|
|
288
|
+
|
|
289
|
+
:param sources: A list of PersistSourceMapInput objects.
|
|
290
|
+
:param project_root: The root directory of the project.
|
|
291
|
+
:param client: An AlgodClient instance for interacting with the Algorand blockchain.
|
|
292
|
+
:param with_sources: If True, it will dump teal source files along with sourcemaps.
|
|
293
|
+
"""
|
|
294
|
+
|
|
295
|
+
for source in sources:
|
|
296
|
+
_build_avm_sourcemap(
|
|
297
|
+
raw_teal=source.raw_teal,
|
|
298
|
+
compiled_teal=source.compiled_teal,
|
|
299
|
+
app_name=source.app_name,
|
|
300
|
+
file_name=source.file_name,
|
|
301
|
+
output_path=project_root,
|
|
302
|
+
client=client,
|
|
303
|
+
with_sources=with_sources,
|
|
304
|
+
)
|