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
algokit_algosdk/error.py
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Vendored from py-algorand-sdk/algosdk/error.py (MIT License).
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class BadTxnSenderError(Exception):
|
|
5
|
+
def __init__(self) -> None:
|
|
6
|
+
super().__init__("transaction sender does not match multisig parameters")
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InvalidThresholdError(Exception):
|
|
10
|
+
def __init__(self) -> None:
|
|
11
|
+
super().__init__("invalid multisig threshold")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class InvalidSecretKeyError(Exception):
|
|
15
|
+
def __init__(self) -> None:
|
|
16
|
+
super().__init__("secret key has no corresponding public key in multisig")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class MergeKeysMismatchError(Exception):
|
|
20
|
+
def __init__(self) -> None:
|
|
21
|
+
super().__init__("multisig parameters do not match")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MergeAuthAddrMismatchError(Exception):
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
super().__init__("multisig transaction auth addresses do not match")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class DuplicateSigMismatchError(Exception):
|
|
30
|
+
def __init__(self) -> None:
|
|
31
|
+
super().__init__("mismatched duplicate signatures in multisig")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class LogicSigOverspecifiedSignature(Exception):
|
|
35
|
+
def __init__(self) -> None:
|
|
36
|
+
super().__init__("LogicSig has too many signatures. At most one of sig or msig may be present")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class LogicSigSigningKeyMissing(Exception):
|
|
40
|
+
def __init__(self) -> None:
|
|
41
|
+
super().__init__("LogicSigAccount is missing signing key")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class WrongAmountType(Exception):
|
|
45
|
+
def __init__(self) -> None:
|
|
46
|
+
super().__init__("amount (amt) must be a non-negative integer")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class WrongChecksumError(Exception):
|
|
50
|
+
def __init__(self) -> None:
|
|
51
|
+
super().__init__("checksum failed to validate")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class WrongKeyLengthError(Exception):
|
|
55
|
+
def __init__(self) -> None:
|
|
56
|
+
super().__init__("key length must be 58")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class WrongMnemonicLengthError(Exception):
|
|
60
|
+
def __init__(self) -> None:
|
|
61
|
+
super().__init__("mnemonic length must be 25")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class WrongHashLengthError(Exception):
|
|
65
|
+
"""General error that is normally changed to be more specific"""
|
|
66
|
+
|
|
67
|
+
def __init__(self) -> None:
|
|
68
|
+
super().__init__("length must be 32 bytes")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class WrongKeyBytesLengthError(Exception):
|
|
72
|
+
def __init__(self) -> None:
|
|
73
|
+
super().__init__("key length in bytes must be 32")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class UnknownMsigVersionError(Exception):
|
|
77
|
+
def __init__(self) -> None:
|
|
78
|
+
super().__init__("unknown multisig version != 1")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class WrongMetadataLengthError(Exception):
|
|
82
|
+
def __init__(self) -> None:
|
|
83
|
+
super().__init__("metadata length must be 32 bytes")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class WrongLeaseLengthError(Exception):
|
|
87
|
+
def __init__(self) -> None:
|
|
88
|
+
super().__init__("lease length must be 32 bytes")
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class WrongNoteType(Exception):
|
|
92
|
+
def __init__(self) -> None:
|
|
93
|
+
super().__init__('note must be of type "bytes"')
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class WrongNoteLength(Exception):
|
|
97
|
+
def __init__(self) -> None:
|
|
98
|
+
super().__init__("note length must be at most 1024")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class InvalidProgram(Exception):
|
|
102
|
+
def __init__(self, message: str = "invalid program for logic sig") -> None:
|
|
103
|
+
super().__init__(message)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class TransactionGroupSizeError(Exception):
|
|
107
|
+
def __init__(self) -> None:
|
|
108
|
+
super().__init__("transaction groups are limited to 16 transactions")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class MultisigAccountSizeError(Exception):
|
|
112
|
+
def __init__(self) -> None:
|
|
113
|
+
super().__init__("multisig accounts are limited to 256 addresses")
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class OutOfRangeDecimalsError(Exception):
|
|
117
|
+
def __init__(self) -> None:
|
|
118
|
+
super().__init__("decimals must be between 0 and 19, inclusive")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class EmptyAddressError(Exception):
|
|
122
|
+
def __init__(self) -> None:
|
|
123
|
+
super().__init__(
|
|
124
|
+
"manager, freeze, reserve, and clawback should not be empty unless strict_empty_address_check is set to False",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class OverspecifiedRoundError(Exception):
|
|
129
|
+
def __init__(self) -> None:
|
|
130
|
+
super().__init__("Two arguments were given for the round or block number; please only give one")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class UnderspecifiedRoundError(Exception):
|
|
134
|
+
def __init__(self) -> None:
|
|
135
|
+
super().__init__("Please specify a round number")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class ZeroAddressError(Exception):
|
|
139
|
+
def __init__(self) -> None:
|
|
140
|
+
super().__init__(
|
|
141
|
+
"For the zero address, please specify AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class KeyregOnlineTxnInitError(Exception):
|
|
146
|
+
def __init__(self, attr: str) -> None:
|
|
147
|
+
super().__init__(attr + " should not be None")
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class KMDHTTPError(Exception):
|
|
151
|
+
pass
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class AlgodRequestError(Exception):
|
|
155
|
+
def __init__(self, msg: str) -> None:
|
|
156
|
+
super().__init__(msg)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class AlgodHTTPError(Exception):
|
|
160
|
+
def __init__(self, msg: str, code: int | None = None, data: str | None = None) -> None:
|
|
161
|
+
super().__init__(msg)
|
|
162
|
+
self.code = code
|
|
163
|
+
self.data = data
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
class AlgodResponseError(Exception):
|
|
167
|
+
def __init__(self, msg: str) -> None:
|
|
168
|
+
super().__init__(msg)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class IndexerHTTPError(Exception):
|
|
172
|
+
pass
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class ConfirmationTimeoutError(Exception):
|
|
176
|
+
pass
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
class TransactionRejectedError(Exception):
|
|
180
|
+
pass
|
algokit_algosdk/logic.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
|
|
3
|
+
from nacl.signing import SigningKey
|
|
4
|
+
|
|
5
|
+
# Vendored from py-algorand-sdk/algosdk/logic.py (MIT License).
|
|
6
|
+
|
|
7
|
+
from . import constants, encoding
|
|
8
|
+
from .error import InvalidProgram
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"address",
|
|
12
|
+
"get_application_address",
|
|
13
|
+
"teal_sign",
|
|
14
|
+
"teal_sign_from_program",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def address(program: bytes) -> str:
|
|
19
|
+
"""Return the address of the program."""
|
|
20
|
+
to_sign = constants.logic_prefix + program
|
|
21
|
+
checksum = encoding.checksum(to_sign)
|
|
22
|
+
encoded = encoding.encode_address(checksum)
|
|
23
|
+
assert isinstance(encoded, str)
|
|
24
|
+
return encoded
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def teal_sign(private_key: str, data: bytes, contract_addr: str) -> bytes:
|
|
28
|
+
"""
|
|
29
|
+
Return the signature suitable for ed25519verify TEAL opcode.
|
|
30
|
+
"""
|
|
31
|
+
decoded_key = base64.b64decode(private_key)
|
|
32
|
+
signing_key = SigningKey(decoded_key[: constants.key_len_bytes])
|
|
33
|
+
|
|
34
|
+
contract_bytes = encoding.decode_address(contract_addr)
|
|
35
|
+
if not isinstance(contract_bytes, bytes):
|
|
36
|
+
raise InvalidProgram("contract address failed to decode")
|
|
37
|
+
|
|
38
|
+
to_sign = constants.logic_data_prefix + contract_bytes + data
|
|
39
|
+
signed = signing_key.sign(to_sign)
|
|
40
|
+
return signed.signature
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def teal_sign_from_program(private_key: str, data: bytes, program: bytes) -> bytes:
|
|
44
|
+
"""
|
|
45
|
+
Return the signature suitable for ed25519verify TEAL opcode using the program hash.
|
|
46
|
+
"""
|
|
47
|
+
return teal_sign(private_key, data, address(program))
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_application_address(app_id: int) -> str:
|
|
51
|
+
"""
|
|
52
|
+
Return the escrow address of an application.
|
|
53
|
+
"""
|
|
54
|
+
if not isinstance(app_id, int):
|
|
55
|
+
raise TypeError(f"Expected an int for app_id but received {type(app_id)}")
|
|
56
|
+
|
|
57
|
+
to_sign = constants.APPID_PREFIX + app_id.to_bytes(8, "big")
|
|
58
|
+
checksum = encoding.checksum(to_sign)
|
|
59
|
+
encoded = encoding.encode_address(checksum)
|
|
60
|
+
assert isinstance(encoded, str)
|
|
61
|
+
return encoded
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import binascii
|
|
3
|
+
from collections import OrderedDict
|
|
4
|
+
from typing import Sequence
|
|
5
|
+
|
|
6
|
+
from nacl.exceptions import BadSignatureError
|
|
7
|
+
from nacl.signing import SigningKey, VerifyKey
|
|
8
|
+
|
|
9
|
+
from . import constants, encoding, error
|
|
10
|
+
from .multisig import Multisig
|
|
11
|
+
|
|
12
|
+
# Vendored from py-algorand-sdk/algosdk/transaction.py (logic sig sections) under MIT License.
|
|
13
|
+
|
|
14
|
+
__all__ = ["LogicSig", "LogicSigAccount"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LogicSig:
|
|
18
|
+
"""
|
|
19
|
+
Represents a logic signature consisting of compiled TEAL bytes and optional arguments.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, program: bytes, args: Sequence[bytes] | None = None) -> None:
|
|
23
|
+
self._sanity_check_program(program)
|
|
24
|
+
self.logic = program
|
|
25
|
+
self.args = list(args) if args else None
|
|
26
|
+
self.sig: str | None = None
|
|
27
|
+
self.msig: Multisig | None = None
|
|
28
|
+
self.lmsig: Multisig | None = None
|
|
29
|
+
|
|
30
|
+
@staticmethod
|
|
31
|
+
def _sanity_check_program(program: bytes) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Reject common user mistakes (passing addresses or base64 strings instead of bytecode).
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def is_ascii_printable(program_bytes: bytes) -> bool:
|
|
37
|
+
return all(x == ord("\n") or (ord(" ") <= x <= ord("~")) for x in program_bytes)
|
|
38
|
+
|
|
39
|
+
if not program:
|
|
40
|
+
raise error.InvalidProgram("empty program")
|
|
41
|
+
|
|
42
|
+
if is_ascii_printable(program):
|
|
43
|
+
try:
|
|
44
|
+
encoding.decode_address(program.decode("utf-8"))
|
|
45
|
+
raise error.InvalidProgram("requesting program bytes, got Algorand address")
|
|
46
|
+
except (error.WrongChecksumError, error.WrongKeyLengthError):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
try:
|
|
50
|
+
base64.b64decode(program.decode("utf-8"))
|
|
51
|
+
raise error.InvalidProgram("program should not be b64 encoded")
|
|
52
|
+
except binascii.Error:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
raise error.InvalidProgram("program bytes look ASCII, not compiled TEAL")
|
|
56
|
+
|
|
57
|
+
def dictify(self) -> OrderedDict[str, object]:
|
|
58
|
+
payload: OrderedDict[str, object] = OrderedDict()
|
|
59
|
+
if self.args:
|
|
60
|
+
payload["arg"] = self.args
|
|
61
|
+
payload["l"] = self.logic
|
|
62
|
+
if self.sig:
|
|
63
|
+
payload["sig"] = base64.b64decode(self.sig)
|
|
64
|
+
elif self.msig:
|
|
65
|
+
payload["msig"] = self.msig.dictify()
|
|
66
|
+
elif self.lmsig:
|
|
67
|
+
payload["lmsig"] = self.lmsig.dictify()
|
|
68
|
+
return payload
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def undictify(data: dict[str, object]) -> "LogicSig":
|
|
72
|
+
lsig = LogicSig(data["l"], data.get("arg")) # type: ignore[arg-type]
|
|
73
|
+
if "sig" in data:
|
|
74
|
+
lsig.sig = base64.b64encode(data["sig"]).decode() # type: ignore[arg-type]
|
|
75
|
+
elif "msig" in data:
|
|
76
|
+
lsig.msig = Multisig.undictify(data["msig"]) # type: ignore[arg-type]
|
|
77
|
+
elif "lmsig" in data:
|
|
78
|
+
lsig.lmsig = Multisig.undictify(data["lmsig"]) # type: ignore[arg-type]
|
|
79
|
+
return lsig
|
|
80
|
+
|
|
81
|
+
def sig_count(self) -> int:
|
|
82
|
+
return int(self.sig is not None) + int(self.msig is not None) + int(self.lmsig is not None)
|
|
83
|
+
|
|
84
|
+
def verify(self, public_key: bytes) -> bool:
|
|
85
|
+
"""Verifies LogicSig against the provided sender address bytes."""
|
|
86
|
+
try:
|
|
87
|
+
self._sanity_check_program(self.logic)
|
|
88
|
+
except error.InvalidProgram:
|
|
89
|
+
return False
|
|
90
|
+
|
|
91
|
+
if self.sig_count() > 1:
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
if self.sig:
|
|
95
|
+
verify_key = VerifyKey(public_key)
|
|
96
|
+
to_sign = constants.logic_prefix + self.logic
|
|
97
|
+
try:
|
|
98
|
+
verify_key.verify(to_sign, base64.b64decode(self.sig))
|
|
99
|
+
return True
|
|
100
|
+
except (BadSignatureError, ValueError, TypeError):
|
|
101
|
+
return False
|
|
102
|
+
|
|
103
|
+
if self.msig:
|
|
104
|
+
to_sign = constants.logic_prefix + self.logic
|
|
105
|
+
return self.msig.verify(to_sign)
|
|
106
|
+
|
|
107
|
+
if self.lmsig:
|
|
108
|
+
to_sign = constants.multisig_logic_prefix + self.logic
|
|
109
|
+
return self.lmsig.verify(to_sign)
|
|
110
|
+
|
|
111
|
+
addr = self.address()
|
|
112
|
+
encoded = encoding.encode_address(public_key)
|
|
113
|
+
return addr == encoded
|
|
114
|
+
|
|
115
|
+
def sign(self, private_key: str, multisig: Multisig | None = None) -> None:
|
|
116
|
+
"""
|
|
117
|
+
Sign the program bytes. If `multisig` is provided, append the signature to that multisig.
|
|
118
|
+
"""
|
|
119
|
+
if self.sig_count() > 0 and not multisig:
|
|
120
|
+
raise error.LogicSigOverspecifiedSignature
|
|
121
|
+
|
|
122
|
+
private_key_bytes = base64.b64decode(private_key)
|
|
123
|
+
signing_key = SigningKey(private_key_bytes[: constants.key_len_bytes])
|
|
124
|
+
to_sign = constants.logic_prefix + self.logic
|
|
125
|
+
|
|
126
|
+
if not multisig:
|
|
127
|
+
signature = signing_key.sign(to_sign).signature
|
|
128
|
+
self.sig = base64.b64encode(signature).decode()
|
|
129
|
+
self.msig = None
|
|
130
|
+
self.lmsig = None
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
# Multisig signing
|
|
134
|
+
sig = signing_key.sign(constants.logic_prefix + self.logic).signature
|
|
135
|
+
for idx, subsig in enumerate(multisig.subsigs):
|
|
136
|
+
if subsig.public_key == signing_key.verify_key.encode():
|
|
137
|
+
if not subsig.signature:
|
|
138
|
+
subsig.signature = sig
|
|
139
|
+
self.msig = multisig
|
|
140
|
+
self.sig = None
|
|
141
|
+
self.lmsig = None
|
|
142
|
+
return
|
|
143
|
+
subsig.signature = sig
|
|
144
|
+
self.msig = multisig
|
|
145
|
+
self.sig = None
|
|
146
|
+
self.lmsig = None
|
|
147
|
+
return
|
|
148
|
+
|
|
149
|
+
raise error.InvalidSecretKeyError
|
|
150
|
+
|
|
151
|
+
def append_to_multisig(self, private_key: str) -> None:
|
|
152
|
+
if not self.msig:
|
|
153
|
+
raise error.InvalidSecretKeyError
|
|
154
|
+
self.sign(private_key, self.msig)
|
|
155
|
+
|
|
156
|
+
def address(self) -> str:
|
|
157
|
+
"""Return the hash of the program bytes as an address."""
|
|
158
|
+
checksum = encoding.checksum(constants.logic_prefix + self.logic)
|
|
159
|
+
encoded = encoding.encode_address(checksum)
|
|
160
|
+
assert isinstance(encoded, str)
|
|
161
|
+
return encoded
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class LogicSigAccount:
|
|
165
|
+
"""
|
|
166
|
+
Safe wrapper around LogicSig that tracks the signing key for delegated logic.
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
def __init__(self, program: bytes, args: Sequence[bytes] | None = None) -> None:
|
|
170
|
+
self.lsig = LogicSig(program, args)
|
|
171
|
+
self.sigkey: bytes | None = None
|
|
172
|
+
|
|
173
|
+
def dictify(self) -> OrderedDict[str, object]:
|
|
174
|
+
payload = OrderedDict()
|
|
175
|
+
payload["lsig"] = self.lsig.dictify()
|
|
176
|
+
if self.sigkey:
|
|
177
|
+
payload["sigkey"] = self.sigkey
|
|
178
|
+
return payload
|
|
179
|
+
|
|
180
|
+
@staticmethod
|
|
181
|
+
def undictify(data: dict[str, object]) -> "LogicSigAccount":
|
|
182
|
+
account = LogicSigAccount(b"", [])
|
|
183
|
+
account.lsig = LogicSig.undictify(data["lsig"]) # type: ignore[arg-type]
|
|
184
|
+
account.sigkey = data.get("sigkey") # type: ignore[assignment]
|
|
185
|
+
return account
|
|
186
|
+
|
|
187
|
+
def verify(self, public_key: bytes) -> bool:
|
|
188
|
+
return self.lsig.verify(public_key)
|
|
189
|
+
|
|
190
|
+
def address(self) -> str:
|
|
191
|
+
if self.sigkey:
|
|
192
|
+
encoded = encoding.encode_address(self.sigkey)
|
|
193
|
+
assert isinstance(encoded, str)
|
|
194
|
+
return encoded
|
|
195
|
+
if self.lsig.msig:
|
|
196
|
+
return self.lsig.msig.address()
|
|
197
|
+
if self.lsig.lmsig:
|
|
198
|
+
return self.lsig.lmsig.address()
|
|
199
|
+
return self.lsig.address()
|
|
200
|
+
|
|
201
|
+
def sign_multisig(self, multisig: Multisig, private_key: str) -> None:
|
|
202
|
+
if self.lsig.sig:
|
|
203
|
+
raise error.LogicSigOverspecifiedSignature
|
|
204
|
+
self.lsig.sign(private_key, multisig)
|
|
205
|
+
self.sigkey = None
|
|
206
|
+
|
|
207
|
+
def append_to_multisig(self, private_key: str) -> None:
|
|
208
|
+
if not self.lsig.msig:
|
|
209
|
+
raise error.InvalidSecretKeyError
|
|
210
|
+
self.lsig.append_to_multisig(private_key)
|
|
211
|
+
self.sigkey = None
|
|
212
|
+
|
|
213
|
+
def sign(self, private_key: str) -> None:
|
|
214
|
+
if self.lsig.msig:
|
|
215
|
+
raise error.LogicSigOverspecifiedSignature
|
|
216
|
+
self.lsig.sign(private_key)
|
|
217
|
+
decoded = base64.b64decode(bytes(private_key, "utf-8"))
|
|
218
|
+
self.sigkey = decoded[constants.key_len_bytes :]
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from nacl import signing
|
|
2
|
+
import base64
|
|
3
|
+
from . import wordlist
|
|
4
|
+
from . import error
|
|
5
|
+
from . import constants
|
|
6
|
+
from . import encoding
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
word_to_index = {}
|
|
11
|
+
index_to_word = {}
|
|
12
|
+
for i, word in enumerate(wordlist.word_list_raw().split("\n")):
|
|
13
|
+
index_to_word[i] = word
|
|
14
|
+
# Put all prefixes of words at least four letters long into map,
|
|
15
|
+
# since they are guarenteed unique, so some people may only save
|
|
16
|
+
# that part, and expect to be able to recover.
|
|
17
|
+
for length in range(4, len(word)):
|
|
18
|
+
assert word[:length] not in word_to_index
|
|
19
|
+
word_to_index[word[:length]] = i
|
|
20
|
+
word_to_index[word] = i # in case word is less than four letters long
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def from_master_derivation_key(key):
|
|
24
|
+
"""
|
|
25
|
+
Return the mnemonic for the master derivation key.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
key (str): master derivation key in base64
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
str: mnemonic
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
key = base64.b64decode(key)
|
|
35
|
+
return _from_key(key)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def to_master_derivation_key(mnemonic):
|
|
39
|
+
"""
|
|
40
|
+
Return the master derivation key for the mnemonic.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
mnemonic (str): mnemonic of the master derivation key
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
str: master derivation key in base64
|
|
47
|
+
"""
|
|
48
|
+
key_bytes = _to_key(mnemonic)
|
|
49
|
+
return base64.b64encode(key_bytes).decode()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def from_private_key(key):
|
|
53
|
+
"""
|
|
54
|
+
Return the mnemonic for the private key.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
key (str): private key in base64
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
str: mnemonic
|
|
61
|
+
"""
|
|
62
|
+
key = base64.b64decode(key)
|
|
63
|
+
return _from_key(key[: constants.key_len_bytes])
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def to_private_key(mnemonic) -> str:
|
|
67
|
+
"""
|
|
68
|
+
Return the private key for the mnemonic.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
mnemonic (str): mnemonic of the private key
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
str: private key in base64
|
|
75
|
+
"""
|
|
76
|
+
key_bytes = _to_key(mnemonic)
|
|
77
|
+
key = signing.SigningKey(key_bytes)
|
|
78
|
+
return base64.b64encode(key.encode() + key.verify_key.encode()).decode()
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _from_key(key):
|
|
82
|
+
"""
|
|
83
|
+
Return the mnemonic for the key.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
key (bytes): key to compute mnemonic of
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
str: mnemonic
|
|
90
|
+
"""
|
|
91
|
+
if not len(key) == constants.key_len_bytes:
|
|
92
|
+
raise error.WrongKeyBytesLengthError
|
|
93
|
+
chkword = index_to_word[_checksum(key)]
|
|
94
|
+
nums = _to_11_bit(key)
|
|
95
|
+
words = _apply_words(nums)
|
|
96
|
+
return " ".join(words) + " " + chkword
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _to_key(mnemonic):
|
|
100
|
+
"""
|
|
101
|
+
Give the corresponding key for the mnemonic.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
mnemonic (str): mnemonic for the key
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
bytes: key
|
|
108
|
+
"""
|
|
109
|
+
mnemonic = mnemonic.lower().split()
|
|
110
|
+
if not len(mnemonic) == constants.mnemonic_len:
|
|
111
|
+
raise error.WrongMnemonicLengthError
|
|
112
|
+
try:
|
|
113
|
+
m_checksum = word_to_index[mnemonic[-1]]
|
|
114
|
+
mnemonic = _from_words(mnemonic[:-1])
|
|
115
|
+
except KeyError: # We used to return ValueError, so keep it
|
|
116
|
+
raise ValueError(mnemonic)
|
|
117
|
+
m_bytes = _to_bytes(mnemonic)
|
|
118
|
+
if not m_bytes[-1 : len(m_bytes)] == b"\x00":
|
|
119
|
+
raise error.WrongChecksumError
|
|
120
|
+
chksum = _checksum(m_bytes[: constants.key_len_bytes])
|
|
121
|
+
if chksum == m_checksum:
|
|
122
|
+
return m_bytes[: constants.key_len_bytes]
|
|
123
|
+
else:
|
|
124
|
+
raise error.WrongChecksumError
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _checksum(data):
|
|
128
|
+
"""
|
|
129
|
+
Compute the mnemonic checksum.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
data (bytes): data to compute checksum of
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
int: checksum
|
|
136
|
+
"""
|
|
137
|
+
chksum = encoding.checksum(data)
|
|
138
|
+
temp = chksum[0:2]
|
|
139
|
+
nums = _to_11_bit(temp)
|
|
140
|
+
return nums[0]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _apply_words(nums):
|
|
144
|
+
"""
|
|
145
|
+
Get the corresponding words for a list of 11-bit numbers.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
nums (int[]): list of 11-bit numbers
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
str[]: list of words
|
|
152
|
+
"""
|
|
153
|
+
return [index_to_word[n] for n in nums]
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _from_words(words):
|
|
157
|
+
"""
|
|
158
|
+
Get the corresponding 11-bit numbers for a list of words.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
words (str[]): list of words
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
int[]: list of 11-bit numbers
|
|
165
|
+
"""
|
|
166
|
+
return [word_to_index[w] for w in words]
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _to_11_bit(data):
|
|
170
|
+
"""
|
|
171
|
+
Convert a bytearray to an list of 11-bit numbers.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
data (bytes): bytearray to convert to 11-bit numbers
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
int[]: list of 11-bit numbers
|
|
178
|
+
"""
|
|
179
|
+
buffer = 0
|
|
180
|
+
num_of_bits = 0
|
|
181
|
+
output = []
|
|
182
|
+
for i in range(len(data)):
|
|
183
|
+
buffer |= data[i] << num_of_bits
|
|
184
|
+
num_of_bits += 8
|
|
185
|
+
if num_of_bits >= 11:
|
|
186
|
+
output.append(buffer & 2047)
|
|
187
|
+
buffer = buffer >> 11
|
|
188
|
+
num_of_bits -= 11
|
|
189
|
+
if num_of_bits != 0:
|
|
190
|
+
output.append(buffer & 2047)
|
|
191
|
+
return output
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _to_bytes(nums):
|
|
195
|
+
"""
|
|
196
|
+
Convert a list of 11-bit numbers to a bytearray.
|
|
197
|
+
|
|
198
|
+
Args:
|
|
199
|
+
nums (int[]): list of 11-bit numbers
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
bytes: bytearray
|
|
203
|
+
"""
|
|
204
|
+
buffer = 0
|
|
205
|
+
num_of_bits = 0
|
|
206
|
+
output = []
|
|
207
|
+
for i in range(len(nums)):
|
|
208
|
+
buffer |= nums[i] << num_of_bits
|
|
209
|
+
num_of_bits += 11
|
|
210
|
+
while num_of_bits >= 8:
|
|
211
|
+
output.append(buffer & 255)
|
|
212
|
+
buffer = buffer >> 8
|
|
213
|
+
num_of_bits -= 8
|
|
214
|
+
if num_of_bits != 0:
|
|
215
|
+
output.append(buffer & 255)
|
|
216
|
+
return bytes(output)
|