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,228 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
from typing import List, Optional, Tuple, Union
|
|
3
|
+
|
|
4
|
+
from . import encoding
|
|
5
|
+
from .box_reference import BoxReference
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def translate_to_resource_references(
|
|
9
|
+
app_id: int,
|
|
10
|
+
accounts: Optional[List[str]] = None,
|
|
11
|
+
foreign_assets: Optional[List[int]] = None,
|
|
12
|
+
foreign_apps: Optional[List[int]] = None,
|
|
13
|
+
boxes: Optional[List[Tuple[int, bytes]]] = None,
|
|
14
|
+
holdings: Optional[List[Tuple[int, str]]] = None,
|
|
15
|
+
locals: Optional[List[Tuple[int, str]]] = None,
|
|
16
|
+
) -> List["ResourceReference"]:
|
|
17
|
+
"""
|
|
18
|
+
Convert accounts, apps, assets, boxes, holdings, locals into list of ResourceReference
|
|
19
|
+
that is suitable for txn.Access field creation.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
app_id (int): current application id
|
|
23
|
+
accounts (list[string], optional): list of additional accounts involved in call
|
|
24
|
+
foreign_apps (list[int], optional): list of other applications (identified by index) involved in call
|
|
25
|
+
foreign_assets (list[int], optional): list of assets involved in call
|
|
26
|
+
boxes(list[(int, bytes)], optional): list of tuples specifying app id and key for boxes the app may access
|
|
27
|
+
holdings (list[int, str], optional): lists of tuples specifying the asset holdings to be accessed during evaluation of the application;
|
|
28
|
+
zero (empty) address means sender
|
|
29
|
+
locals (list[int, str], optional): lists of tuples specifying the local states to be accessed during evaluation of the application;
|
|
30
|
+
zero (empty) address means sender
|
|
31
|
+
"""
|
|
32
|
+
access: List["ResourceReference"] = []
|
|
33
|
+
|
|
34
|
+
def ensure(target: "ResourceReference") -> int:
|
|
35
|
+
for idx, a in enumerate(access):
|
|
36
|
+
if (
|
|
37
|
+
a.address == target.address
|
|
38
|
+
and a.asset_id == target.asset_id
|
|
39
|
+
and a.app_id == target.app_id
|
|
40
|
+
):
|
|
41
|
+
return idx + 1
|
|
42
|
+
access.append(target)
|
|
43
|
+
return len(access)
|
|
44
|
+
|
|
45
|
+
for account in accounts or []:
|
|
46
|
+
ensure(ResourceReference(address=account))
|
|
47
|
+
|
|
48
|
+
for asset in foreign_assets or []:
|
|
49
|
+
ensure(ResourceReference(asset_id=asset))
|
|
50
|
+
|
|
51
|
+
for app in foreign_apps or []:
|
|
52
|
+
ensure(ResourceReference(app_id=app))
|
|
53
|
+
|
|
54
|
+
for asset, addr in holdings or []:
|
|
55
|
+
addr_idx = 0
|
|
56
|
+
if addr:
|
|
57
|
+
addr_idx = ensure(ResourceReference(address=addr))
|
|
58
|
+
asset_idx = ensure(ResourceReference(asset_id=asset))
|
|
59
|
+
access.append(
|
|
60
|
+
ResourceReference(
|
|
61
|
+
holding_reference=HoldingRef(
|
|
62
|
+
asset_index=asset_idx, addr_index=addr_idx
|
|
63
|
+
)
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
for app, addr in locals or []:
|
|
68
|
+
app_idx = 0
|
|
69
|
+
if app and app != app_id:
|
|
70
|
+
app_idx = ensure(ResourceReference(app_id=app))
|
|
71
|
+
addr_idx = 0
|
|
72
|
+
if addr:
|
|
73
|
+
addr_idx = ensure(ResourceReference(address=addr))
|
|
74
|
+
access.append(
|
|
75
|
+
ResourceReference(
|
|
76
|
+
locals_reference=LocalsRef(
|
|
77
|
+
app_index=app_idx, addr_index=addr_idx
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
for app, name in boxes or []:
|
|
83
|
+
app_idx = 0
|
|
84
|
+
if app and app != app_id:
|
|
85
|
+
app_idx = ensure(ResourceReference(app_id=app))
|
|
86
|
+
access.append(
|
|
87
|
+
ResourceReference(
|
|
88
|
+
box_reference=BoxReference(app_index=app_idx, name=name)
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
return access
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class ResourceReference:
|
|
96
|
+
def __init__(
|
|
97
|
+
self,
|
|
98
|
+
address: Optional[str] = None,
|
|
99
|
+
asset_id: Optional[int] = None,
|
|
100
|
+
app_id: Optional[int] = None,
|
|
101
|
+
box_reference: Optional[BoxReference] = None,
|
|
102
|
+
holding_reference: Optional["HoldingRef"] = None,
|
|
103
|
+
locals_reference: Optional["LocalsRef"] = None,
|
|
104
|
+
):
|
|
105
|
+
self.app_id = app_id
|
|
106
|
+
self.address = address
|
|
107
|
+
self.asset_id = asset_id
|
|
108
|
+
self.box_reference = box_reference
|
|
109
|
+
self.holding_reference = holding_reference
|
|
110
|
+
self.locals_reference = locals_reference
|
|
111
|
+
|
|
112
|
+
def dictify(self):
|
|
113
|
+
d = dict()
|
|
114
|
+
if self.address:
|
|
115
|
+
d["d"] = encoding.decode_address(self.address)
|
|
116
|
+
if self.asset_id:
|
|
117
|
+
d["s"] = self.asset_id
|
|
118
|
+
if self.app_id:
|
|
119
|
+
d["p"] = self.app_id
|
|
120
|
+
if self.box_reference:
|
|
121
|
+
d["b"] = self.box_reference.dictify()
|
|
122
|
+
if self.holding_reference:
|
|
123
|
+
d["h"] = self.holding_reference.dictify()
|
|
124
|
+
if self.locals_reference:
|
|
125
|
+
d["l"] = self.locals_reference.dictify()
|
|
126
|
+
od = OrderedDict(sorted(d.items()))
|
|
127
|
+
return od
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def undictify(d):
|
|
131
|
+
return ResourceReference(
|
|
132
|
+
address=encoding.encode_address(d["d"]) if "d" in d else "",
|
|
133
|
+
asset_id=d["s"] if "s" in d else None,
|
|
134
|
+
app_id=d["p"] if "p" in d else None,
|
|
135
|
+
box_reference=BoxReference.undictify(d["b"]) if "b" in d else None,
|
|
136
|
+
holding_reference=(
|
|
137
|
+
HoldingRef.undictify(d["h"]) if "h" in d else None
|
|
138
|
+
),
|
|
139
|
+
locals_reference=LocalsRef.undictify(d["l"]) if "l" in d else None,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def __eq__(self, value):
|
|
143
|
+
if not isinstance(value, ResourceReference):
|
|
144
|
+
return False
|
|
145
|
+
return (
|
|
146
|
+
self.address == value.address
|
|
147
|
+
and self.asset_id == value.asset_id
|
|
148
|
+
and self.app_id == value.app_id
|
|
149
|
+
and self.box_reference == value.box_reference
|
|
150
|
+
and self.holding_reference == value.holding_reference
|
|
151
|
+
and self.locals_reference == value.locals_reference
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class LocalsRef:
|
|
156
|
+
"""
|
|
157
|
+
Represents a local reference in txn.Access with an app index and address index.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
app_index (int): index of the application in the access array
|
|
161
|
+
addr_index (int): index of the address in the access array
|
|
162
|
+
"""
|
|
163
|
+
|
|
164
|
+
def __init__(self, app_index: int, addr_index: int):
|
|
165
|
+
self.app_index = app_index
|
|
166
|
+
self.addr_index = addr_index
|
|
167
|
+
|
|
168
|
+
def dictify(self):
|
|
169
|
+
d = dict()
|
|
170
|
+
if self.app_index:
|
|
171
|
+
d["p"] = self.app_index
|
|
172
|
+
if self.addr_index:
|
|
173
|
+
d["d"] = self.addr_index
|
|
174
|
+
od = OrderedDict(sorted(d.items()))
|
|
175
|
+
return od
|
|
176
|
+
|
|
177
|
+
@staticmethod
|
|
178
|
+
def undictify(d):
|
|
179
|
+
return LocalsRef(
|
|
180
|
+
d["p"] if "p" in d else 0,
|
|
181
|
+
d["d"] if "d" in d else 0,
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def __eq__(self, other):
|
|
185
|
+
if not isinstance(other, LocalsRef):
|
|
186
|
+
return False
|
|
187
|
+
return (
|
|
188
|
+
self.app_index == other.app_index
|
|
189
|
+
and self.addr_index == other.addr_index
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class HoldingRef:
|
|
194
|
+
"""
|
|
195
|
+
Represents a holding reference in txn.Access with an asset index and address index.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
asset_index (int): index of the asset in the access array
|
|
199
|
+
addr_index (int): index of the address in the access array
|
|
200
|
+
"""
|
|
201
|
+
|
|
202
|
+
def __init__(self, asset_index: int, addr_index: int):
|
|
203
|
+
self.asset_index = asset_index
|
|
204
|
+
self.addr_index = addr_index
|
|
205
|
+
|
|
206
|
+
def dictify(self):
|
|
207
|
+
d = dict()
|
|
208
|
+
if self.asset_index:
|
|
209
|
+
d["s"] = self.asset_index
|
|
210
|
+
if self.addr_index:
|
|
211
|
+
d["d"] = self.addr_index
|
|
212
|
+
od = OrderedDict(sorted(d.items()))
|
|
213
|
+
return od
|
|
214
|
+
|
|
215
|
+
@staticmethod
|
|
216
|
+
def undictify(d):
|
|
217
|
+
return HoldingRef(
|
|
218
|
+
d["s"] if "s" in d else 0,
|
|
219
|
+
d["d"] if "d" in d else 0,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
def __eq__(self, other):
|
|
223
|
+
if not isinstance(other, HoldingRef):
|
|
224
|
+
return False
|
|
225
|
+
return (
|
|
226
|
+
self.asset_index == other.asset_index
|
|
227
|
+
and self.addr_index == other.addr_index
|
|
228
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from collections import OrderedDict
|
|
2
|
+
from typing import List, Tuple, Union
|
|
3
|
+
|
|
4
|
+
from . import encoding, error
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BoxReference:
|
|
8
|
+
"""
|
|
9
|
+
Represents a box reference with a foreign app index and the box name.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
app_index (int): index of the application in the foreign app array
|
|
13
|
+
name (bytes): key for the box in bytes
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, app_index: int, name: bytes):
|
|
17
|
+
if app_index < 0:
|
|
18
|
+
raise ValueError(
|
|
19
|
+
f"Box app index must be a non-negative integer: {app_index}"
|
|
20
|
+
)
|
|
21
|
+
self.app_index = app_index
|
|
22
|
+
self.name = name
|
|
23
|
+
|
|
24
|
+
@staticmethod
|
|
25
|
+
def translate_box_reference(
|
|
26
|
+
ref: Union[
|
|
27
|
+
Tuple[int, Union[bytes, bytearray, str, int]], "BoxReference"
|
|
28
|
+
],
|
|
29
|
+
foreign_apps: List[int],
|
|
30
|
+
this_app_id: int,
|
|
31
|
+
) -> "BoxReference":
|
|
32
|
+
# Do not need to translate the references if they are already BoxReference type.
|
|
33
|
+
if isinstance(ref, BoxReference):
|
|
34
|
+
return ref
|
|
35
|
+
|
|
36
|
+
# Try checking reference id and name type.
|
|
37
|
+
ref_id, ref_name = ref[0], encoding.encode_as_bytes(ref[1])
|
|
38
|
+
if not isinstance(ref_id, int):
|
|
39
|
+
raise TypeError("Box reference ID must be an int")
|
|
40
|
+
|
|
41
|
+
index = 0
|
|
42
|
+
try:
|
|
43
|
+
# Foreign apps start from index 1; index 0 is its own app ID.
|
|
44
|
+
index = foreign_apps.index(ref_id) + 1
|
|
45
|
+
except (ValueError, AttributeError):
|
|
46
|
+
# Check if the app referenced is itself after checking the
|
|
47
|
+
# foreign apps array (in case its own app id is in its own
|
|
48
|
+
# foreign apps array).
|
|
49
|
+
if ref_id != 0 and ref_id != this_app_id:
|
|
50
|
+
raise error.InvalidForeignIndexError(
|
|
51
|
+
f"Box ref with appId {ref_id} not in foreign-apps"
|
|
52
|
+
)
|
|
53
|
+
return BoxReference(index, ref_name)
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def translate_box_references(
|
|
57
|
+
references: List[Tuple[int, Union[bytes, bytearray, str, int]]],
|
|
58
|
+
foreign_apps: List[int],
|
|
59
|
+
this_app_id: int,
|
|
60
|
+
) -> List["BoxReference"]:
|
|
61
|
+
"""
|
|
62
|
+
Translates a list of tuples with app IDs and names into an array of
|
|
63
|
+
BoxReferences with foreign indices.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
references (list[(int, bytes)]): list of tuples specifying app id
|
|
67
|
+
and key for boxes the app may access
|
|
68
|
+
foreign_apps (list[int]): list of other applications in appl call
|
|
69
|
+
this_app_id (int): app ID of the box being references
|
|
70
|
+
"""
|
|
71
|
+
if not references:
|
|
72
|
+
return []
|
|
73
|
+
|
|
74
|
+
return [
|
|
75
|
+
BoxReference.translate_box_reference(
|
|
76
|
+
ref, foreign_apps, this_app_id
|
|
77
|
+
)
|
|
78
|
+
for ref in references
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
def dictify(self):
|
|
82
|
+
d = dict()
|
|
83
|
+
if self.app_index:
|
|
84
|
+
d["i"] = self.app_index
|
|
85
|
+
if self.name:
|
|
86
|
+
d["n"] = self.name
|
|
87
|
+
od = OrderedDict(sorted(d.items()))
|
|
88
|
+
return od
|
|
89
|
+
|
|
90
|
+
@staticmethod
|
|
91
|
+
def undictify(d):
|
|
92
|
+
return BoxReference(
|
|
93
|
+
d["i"] if "i" in d else 0,
|
|
94
|
+
d["n"] if "n" in d else b"",
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
def __eq__(self, other):
|
|
98
|
+
if not isinstance(other, BoxReference):
|
|
99
|
+
return False
|
|
100
|
+
return self.app_index == other.app_index and self.name == other.name
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Vendored from py-algorand-sdk/algosdk/constants.py (MIT License).
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Contains useful constants.
|
|
5
|
+
"""
|
|
6
|
+
KMD_AUTH_HEADER = "X-KMD-API-Token"
|
|
7
|
+
"""str: header key for kmd requests"""
|
|
8
|
+
ALGOD_AUTH_HEADER = "X-Algo-API-Token"
|
|
9
|
+
"""str: header key for algod requests"""
|
|
10
|
+
INDEXER_AUTH_HEADER = "X-Indexer-API-Token"
|
|
11
|
+
"""str: header key for indexer requests"""
|
|
12
|
+
UNVERSIONED_PATHS = ["/health", "/versions", "/metrics", "/genesis", "/ready"]
|
|
13
|
+
"""str[]: paths that don't use the version path prefix"""
|
|
14
|
+
NO_AUTH: list[str] = []
|
|
15
|
+
"""str[]: requests that don't require authentication"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# transaction types
|
|
19
|
+
PAYMENT_TXN = "pay"
|
|
20
|
+
"""str: indicates a payment transaction"""
|
|
21
|
+
KEYREG_TXN = "keyreg"
|
|
22
|
+
"""str: indicates a key registration transaction"""
|
|
23
|
+
ASSETCONFIG_TXN = "acfg"
|
|
24
|
+
"""str: indicates an asset configuration transaction"""
|
|
25
|
+
ASSETFREEZE_TXN = "afrz"
|
|
26
|
+
"""str: indicates an asset freeze transaction"""
|
|
27
|
+
ASSETTRANSFER_TXN = "axfer"
|
|
28
|
+
"""str: indicates an asset transfer transaction"""
|
|
29
|
+
APPCALL_TXN = "appl"
|
|
30
|
+
"""str: indicates an app call transaction, allows creating, deleting, and interacting with an application"""
|
|
31
|
+
STATEPROOF_TXN = "stpf"
|
|
32
|
+
"""str: indicates an state proof transaction"""
|
|
33
|
+
HEARTBEAT_TXN = "hb"
|
|
34
|
+
"""str: indicates a heartbeat transaction"""
|
|
35
|
+
|
|
36
|
+
# note field types
|
|
37
|
+
NOTE_FIELD_TYPE_DEPOSIT = "d"
|
|
38
|
+
"""str: indicates a signed deposit in NoteField"""
|
|
39
|
+
NOTE_FIELD_TYPE_BID = "b"
|
|
40
|
+
"""str: indicates a signed bid in NoteField"""
|
|
41
|
+
NOTE_FIELD_TYPE_SETTLEMENT = "s"
|
|
42
|
+
"""str: indicates a signed settlement in NoteField"""
|
|
43
|
+
NOTE_FIELD_TYPE_PARAMS = "p"
|
|
44
|
+
"""str: indicates signed params in NoteField"""
|
|
45
|
+
|
|
46
|
+
# prefixes
|
|
47
|
+
TXID_PREFIX = b"TX"
|
|
48
|
+
"""bytes: transaction prefix when signing"""
|
|
49
|
+
TGID_PREFIX = b"TG"
|
|
50
|
+
"""bytes: transaction group prefix when computing the group ID"""
|
|
51
|
+
BID_PREFIX = b"aB"
|
|
52
|
+
"""bytes: bid prefix when signing"""
|
|
53
|
+
BYTES_PREFIX = b"MX"
|
|
54
|
+
"""bytes: bytes prefix when signing"""
|
|
55
|
+
MSIG_ADDR_PREFIX = "MultisigAddr"
|
|
56
|
+
"""str: prefix for multisig addresses"""
|
|
57
|
+
LOGIC_PREFIX = b"Program"
|
|
58
|
+
"""bytes: program (logic) prefix when signing"""
|
|
59
|
+
MULTISIG_LOGIC_PREFIX = b"MsigProgram"
|
|
60
|
+
"""bytes: program (logic) prefix when signing"""
|
|
61
|
+
LOGIC_DATA_PREFIX = b"ProgData"
|
|
62
|
+
"""bytes: program (logic) data prefix when signing"""
|
|
63
|
+
APPID_PREFIX = b"appID"
|
|
64
|
+
"""bytes: application ID prefix when signing"""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
HASH_LEN = 32
|
|
68
|
+
"""int: how long various hash-like fields should be"""
|
|
69
|
+
CHECK_SUM_LEN_BYTES = 4
|
|
70
|
+
"""int: how long checksums should be"""
|
|
71
|
+
KEN_LEN_BYTES = 32
|
|
72
|
+
"""int: how long addresses are in bytes"""
|
|
73
|
+
ADDRESS_LEN = 58
|
|
74
|
+
"""int: how long addresses are in base32, including the checksum"""
|
|
75
|
+
MNEMONIC_LEN = 25
|
|
76
|
+
"""int: how long mnemonic phrases are"""
|
|
77
|
+
MIN_TXN_FEE = 1000
|
|
78
|
+
"""int: minimum transaction fee"""
|
|
79
|
+
MICROALGOS_TO_ALGOS_RATIO = 1000000
|
|
80
|
+
"""int: how many microalgos per algo"""
|
|
81
|
+
METADATA_LENGTH = 32
|
|
82
|
+
"""int: length of asset metadata"""
|
|
83
|
+
NOTE_MAX_LENGTH = 1024
|
|
84
|
+
"""int: maximum length of note field"""
|
|
85
|
+
LEASE_LENGTH = 32
|
|
86
|
+
"""int: byte length of leases"""
|
|
87
|
+
MULTISIG_ACCOUNT_LIMIT = 255
|
|
88
|
+
"""int: maximum number of addresses in a multisig account"""
|
|
89
|
+
TX_GROUP_LIMIT = 16
|
|
90
|
+
"""int: maximum number of transaction in a transaction group"""
|
|
91
|
+
MAX_ASSET_DECIMALS = 19
|
|
92
|
+
"""int: maximum value for decimals in assets"""
|
|
93
|
+
|
|
94
|
+
# logic sig related
|
|
95
|
+
LOGIC_SIG_MAX_COST = 20000
|
|
96
|
+
"""int: max execution cost of a teal program"""
|
|
97
|
+
LOGIC_SIG_MAX_SIZE = 1000
|
|
98
|
+
"""int: max size of a teal program and its arguments in bytes"""
|
|
99
|
+
|
|
100
|
+
APP_PAGE_MAX_SIZE = 2048
|
|
101
|
+
"""int: max size of a page for an application in bytes"""
|
|
102
|
+
|
|
103
|
+
ZERO_ADDRESS = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"
|
|
104
|
+
"""str: algorand encoded address of 32 zero bytes"""
|
|
105
|
+
|
|
106
|
+
# for backward compatibility:
|
|
107
|
+
kmd_auth_header = KMD_AUTH_HEADER
|
|
108
|
+
algod_auth_header = ALGOD_AUTH_HEADER
|
|
109
|
+
indexer_auth_header = INDEXER_AUTH_HEADER
|
|
110
|
+
unversioned_paths = UNVERSIONED_PATHS
|
|
111
|
+
no_auth = NO_AUTH
|
|
112
|
+
payment_txn = PAYMENT_TXN
|
|
113
|
+
keyreg_txn = KEYREG_TXN
|
|
114
|
+
assetconfig_txn = ASSETCONFIG_TXN
|
|
115
|
+
assetfreeze_txn = ASSETFREEZE_TXN
|
|
116
|
+
assettransfer_txn = ASSETTRANSFER_TXN
|
|
117
|
+
appcall_txn = APPCALL_TXN
|
|
118
|
+
note_field_type_deposit = NOTE_FIELD_TYPE_DEPOSIT
|
|
119
|
+
note_field_type_bid = NOTE_FIELD_TYPE_BID
|
|
120
|
+
note_field_type_settlement = NOTE_FIELD_TYPE_SETTLEMENT
|
|
121
|
+
note_field_type_params = NOTE_FIELD_TYPE_PARAMS
|
|
122
|
+
txid_prefix = TXID_PREFIX
|
|
123
|
+
tgid_prefix = TGID_PREFIX
|
|
124
|
+
bid_prefix = BID_PREFIX
|
|
125
|
+
bytes_prefix = BYTES_PREFIX
|
|
126
|
+
msig_addr_prefix = MSIG_ADDR_PREFIX
|
|
127
|
+
logic_prefix = LOGIC_PREFIX
|
|
128
|
+
multisig_logic_prefix = MULTISIG_LOGIC_PREFIX
|
|
129
|
+
logic_data_prefix = LOGIC_DATA_PREFIX
|
|
130
|
+
hash_len = HASH_LEN
|
|
131
|
+
check_sum_len_bytes = CHECK_SUM_LEN_BYTES
|
|
132
|
+
key_len_bytes = KEN_LEN_BYTES
|
|
133
|
+
address_len = ADDRESS_LEN
|
|
134
|
+
mnemonic_len = MNEMONIC_LEN
|
|
135
|
+
min_txn_fee = MIN_TXN_FEE
|
|
136
|
+
microalgos_to_algos_ratio = MICROALGOS_TO_ALGOS_RATIO
|
|
137
|
+
metadata_length = METADATA_LENGTH
|
|
138
|
+
note_max_length = NOTE_MAX_LENGTH
|
|
139
|
+
lease_length = LEASE_LENGTH
|
|
140
|
+
multisig_account_limit = MULTISIG_ACCOUNT_LIMIT
|
|
141
|
+
tx_group_limit = TX_GROUP_LIMIT
|
|
142
|
+
max_asset_decimals = MAX_ASSET_DECIMALS
|
|
143
|
+
logic_sig_max_cost = LOGIC_SIG_MAX_COST
|
|
144
|
+
logic_sig_max_size = LOGIC_SIG_MAX_SIZE
|
|
145
|
+
app_page_max_size = APP_PAGE_MAX_SIZE
|
|
146
|
+
stateproof_txn = STATEPROOF_TXN
|
|
147
|
+
heartbeat_txn = HEARTBEAT_TXN
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
# Derived from py-algorand-sdk/algosdk/encoding.py (MIT License).
|
|
4
|
+
|
|
5
|
+
from Cryptodome.Hash import SHA512
|
|
6
|
+
|
|
7
|
+
from . import constants, error
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"checksum",
|
|
11
|
+
"decode_address",
|
|
12
|
+
"encode_address",
|
|
13
|
+
"is_valid_address",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def is_valid_address(addr: str | bytes | None) -> bool:
|
|
18
|
+
"""
|
|
19
|
+
Check if the string address is a valid Algorand address.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
addr: base32 address
|
|
23
|
+
"""
|
|
24
|
+
if not isinstance(addr, str):
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
if len(_undo_padding(addr)) != constants.address_len:
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
decoded = decode_address(addr)
|
|
32
|
+
return isinstance(decoded, bytes)
|
|
33
|
+
except Exception:
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def decode_address(addr: str | None) -> bytes | str | None:
|
|
38
|
+
"""
|
|
39
|
+
Decode a string address into its address bytes and checksum.
|
|
40
|
+
"""
|
|
41
|
+
if not addr:
|
|
42
|
+
return addr
|
|
43
|
+
if len(addr) != constants.address_len:
|
|
44
|
+
raise error.WrongKeyLengthError
|
|
45
|
+
|
|
46
|
+
decoded = base64.b32decode(_correct_padding(addr))
|
|
47
|
+
addr_bytes = decoded[: -constants.check_sum_len_bytes]
|
|
48
|
+
expected_checksum = decoded[-constants.check_sum_len_bytes :]
|
|
49
|
+
chksum = _checksum(addr_bytes)
|
|
50
|
+
|
|
51
|
+
if chksum == expected_checksum:
|
|
52
|
+
return addr_bytes
|
|
53
|
+
raise error.WrongChecksumError
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def encode_address(addr_bytes: bytes | None) -> bytes | str | None:
|
|
57
|
+
"""
|
|
58
|
+
Encode a byte address into a string composed of the encoded bytes and the checksum.
|
|
59
|
+
"""
|
|
60
|
+
if not addr_bytes:
|
|
61
|
+
return addr_bytes
|
|
62
|
+
if len(addr_bytes) != constants.key_len_bytes:
|
|
63
|
+
raise error.WrongKeyBytesLengthError
|
|
64
|
+
chksum = _checksum(addr_bytes)
|
|
65
|
+
addr = base64.b32encode(addr_bytes + chksum)
|
|
66
|
+
return _undo_padding(addr.decode())
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def checksum(data: bytes) -> bytes:
|
|
70
|
+
"""
|
|
71
|
+
Compute the checksum of arbitrary binary input.
|
|
72
|
+
"""
|
|
73
|
+
digest = SHA512.new(truncate="256")
|
|
74
|
+
digest.update(data)
|
|
75
|
+
return digest.digest()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _checksum(addr_bytes: bytes) -> bytes:
|
|
79
|
+
return checksum(addr_bytes)[-constants.check_sum_len_bytes :]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _correct_padding(value: str) -> str:
|
|
83
|
+
if len(value) % 8 == 0:
|
|
84
|
+
return value
|
|
85
|
+
return value + "=" * (8 - len(value) % 8)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _undo_padding(value: str) -> str:
|
|
89
|
+
return value.strip("=")
|