From fde5605029fcb46fa97111933cf0bf8b4eb68da0 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 26 May 2025 16:36:36 +0300 Subject: [PATCH 01/11] config cleanup --- multiversx_sdk_cli/cli.py | 5 +- multiversx_sdk_cli/cli_config.py | 22 +++++--- multiversx_sdk_cli/config.py | 93 ++++++++------------------------ multiversx_sdk_cli/errors.py | 7 +++ 4 files changed, 45 insertions(+), 82 deletions(-) diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index 00519941..d7d024d6 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -43,10 +43,9 @@ def main(cli_args: list[str] = sys.argv[1:]): def _do_main(cli_args: list[str]): utils.ensure_folder(config.SDK_PATH) - argv_with_config_args = config.add_config_args(cli_args) - parser = setup_parser(argv_with_config_args) + parser = setup_parser(cli_args) argcomplete.autocomplete(parser) - args = parser.parse_args(argv_with_config_args) + args = parser.parse_args(cli_args) if args.verbose: logging.basicConfig( diff --git a/multiversx_sdk_cli/cli_config.py b/multiversx_sdk_cli/cli_config.py index 3d536af0..98981feb 100644 --- a/multiversx_sdk_cli/cli_config.py +++ b/multiversx_sdk_cli/cli_config.py @@ -10,10 +10,10 @@ def setup_parser(subparsers: Any) -> Any: - parser = cli_shared.add_group_subparser(subparsers, "config", "Configure multiversx-sdk (default values etc.)") + parser = cli_shared.add_group_subparser(subparsers, "config", "Configure MultiversX CLI (default values etc.)") subparsers = parser.add_subparsers() - sub = cli_shared.add_command_subparser(subparsers, "config", "dump", "Dumps configuration.") + sub = cli_shared.add_command_subparser(subparsers, "config", "dump", "Dumps the active configuration.") sub.add_argument( "--defaults", required=False, @@ -22,20 +22,28 @@ def setup_parser(subparsers: Any) -> Any: ) sub.set_defaults(func=dump) - sub = cli_shared.add_command_subparser(subparsers, "config", "get", "Gets a configuration value.") + sub = cli_shared.add_command_subparser( + subparsers, "config", "get", "Gets a configuration value from the active configuration." + ) _add_name_arg(sub) sub.set_defaults(func=get_value) - sub = cli_shared.add_command_subparser(subparsers, "config", "set", "Sets a configuration value.") + sub = cli_shared.add_command_subparser( + subparsers, "config", "set", "Sets a configuration value for the active configuration." + ) _add_name_arg(sub) sub.add_argument("value", help="the new value") sub.set_defaults(func=set_value) - sub = cli_shared.add_command_subparser(subparsers, "config", "delete", "Deletes a configuration value.") + sub = cli_shared.add_command_subparser( + subparsers, "config", "delete", "Deletes a configuration value from the active configuration." + ) _add_name_arg(sub) sub.set_defaults(func=delete_value) - sub = cli_shared.add_command_subparser(subparsers, "config", "new", "Creates a new configuration.") + sub = cli_shared.add_command_subparser( + subparsers, "config", "new", "Creates a new configuration and sets it as the active configuration." + ) _add_name_arg(sub) sub.add_argument( "--template", @@ -44,7 +52,7 @@ def setup_parser(subparsers: Any) -> Any: ) sub.set_defaults(func=new_config) - sub = cli_shared.add_command_subparser(subparsers, "config", "switch", "Switch to a different config") + sub = cli_shared.add_command_subparser(subparsers, "config", "switch", "Switch to a different config.") _add_name_arg(sub) sub.set_defaults(func=switch_config) diff --git a/multiversx_sdk_cli/config.py b/multiversx_sdk_cli/config.py index ee83f3c5..e996f98d 100644 --- a/multiversx_sdk_cli/config.py +++ b/multiversx_sdk_cli/config.py @@ -11,23 +11,6 @@ GLOBAL_CONFIG_PATH = SDK_PATH / "mxpy.json" -class MetaChainSystemSCsCost: - STAKE = 5000000 - UNSTAKE = 5000000 - UNBOND = 5000000 - CLAIM = 5000000 - GET = 5000000 - CHANGE_REWARD_ADDRESS = 5000000 - CHANGE_VALIDATOR_KEYS = 5000000 - UNJAIL = 5000000 - DELEGATION_MANAGER_OPS = 50000000 - DELEGATION_OPS = 1000000 - UNSTAKE_TOKENS = 5000000 - UNBOND_TOKENS = 5000000 - CLEAN_REGISTERED_DATA = 5000000 - RESTAKE_UNSTAKED_NODES = 5000000 - - def get_dependency_resolution(key: str) -> str: try: return get_value(f"dependencies.{key}.resolution") @@ -145,28 +128,41 @@ def _guard_valid_config_deletion(name: str): def get_defaults() -> dict[str, Any]: return { - "dependencies.vmtools.tag": "v1.5.24", - "dependencies.vmtools.urlTemplate.linux": "https://github.com/multiversx/mx-chain-vm-go/archive/{TAG}.tar.gz", - "dependencies.vmtools.urlTemplate.osx": "https://github.com/multiversx/mx-chain-vm-go/archive/{TAG}.tar.gz", - "dependencies.vmtools.urlTemplate.windows": "https://github.com/multiversx/mx-chain-vm-go/archive/{TAG}.tar.gz", - "dependencies.rust.tag": "stable", "dependencies.golang.resolution": "SDK", "dependencies.golang.tag": "go1.20.7", "dependencies.golang.urlTemplate.linux": "https://golang.org/dl/{TAG}.linux-amd64.tar.gz", "dependencies.golang.urlTemplate.osx": "https://golang.org/dl/{TAG}.darwin-amd64.tar.gz", "dependencies.golang.urlTemplate.windows": "https://golang.org/dl/{TAG}.windows-amd64.zip", - "dependencies.twiggy.tag": "", - "dependencies.sc-meta.tag": "", "dependencies.testwallets.tag": "v1.0.0", "dependencies.testwallets.urlTemplate.linux": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", "dependencies.testwallets.urlTemplate.osx": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", "dependencies.testwallets.urlTemplate.windows": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", - "dependencies.wasm-opt.tag": "0.112.0", "github_api_token": "", "default_address_hrp": "erd", + "proxy_url": "", + "explorer_url": "", + "ask_confirmation": "true", } +def get_proxy_url() -> str: + return get_value("proxy_url") + + +def get_explorer_url() -> str: + return get_value("explorer_url") + + +def get_confirmation_setting() -> bool: + confirmation_value = get_value("ask_confirmation") + if confirmation_value.lower() in ["true", "yes", "1"]: + return True + elif confirmation_value.lower() in ["false", "no", "0"]: + return False + else: + raise errors.InvalidConfirmationSettingError(confirmation_value) + + def get_deprecated_entries_in_config_file(): default_config_keys = set(get_defaults().keys()) current_config_keys = set(get_active().keys()) @@ -192,53 +188,6 @@ def write_file(data: dict[str, Any]): utils.write_json_file(str(config_path), data) -def add_config_args(argv: list[str]) -> list[str]: - try: - command, subcommand, *_ = argv - except ValueError: - return argv - - config = read_file() - - try: - config_args = config[command][subcommand] - except KeyError: - return argv - - final_args = determine_final_args(argv, config_args) - print(f"Found extra arguments in mxpy.json. Final arguments: {final_args}") - return final_args - - -def determine_final_args(argv: list[str], config_args: dict[str, Any]) -> list[str]: - extra_args: list[str] = [] - for key, value in config_args.items(): - key_arg = f"--{key}" - # arguments from the command line override the config - if key_arg in argv: - continue - if any(arg.startswith(f"{key_arg}=") for arg in argv): - continue - extra_args.append(key_arg) - if value is True: - continue - if isinstance(value, list): - for item in value: # type: ignore - extra_args.append(str(item)) # type: ignore - else: - extra_args.append(str(value)) - - # the verbose flag is an exception since it has to go before the command and subcommand - # eg. mxpy --verbose contract deploy - verbose_flag = "--verbose" - pre_args = [] - if verbose_flag in extra_args: - extra_args.remove(verbose_flag) - pre_args = [verbose_flag] - - return pre_args + argv + extra_args - - def get_dependency_directory(key: str, tag: str) -> Path: parent_directory = get_dependency_parent_directory(key) return parent_directory / tag diff --git a/multiversx_sdk_cli/errors.py b/multiversx_sdk_cli/errors.py index 577d6207..eb8025d7 100644 --- a/multiversx_sdk_cli/errors.py +++ b/multiversx_sdk_cli/errors.py @@ -149,3 +149,10 @@ def __init__(self, message: str): class InvalidArgumentsError(KnownError): def __init__(self, message: str): super().__init__(message) + + +class InvalidConfirmationSettingError(KnownError): + def __init__(self, value: str): + super().__init__( + f"Invalid confirmation setting: {value}. Valid values are: ['true', 'false', 'yes', 'no', '1', '0']." + ) From afba2a8926d962720e4fe51c2ab01d3dc0aa95be Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 27 May 2025 13:48:20 +0300 Subject: [PATCH 02/11] allow users to set proxy url in config --- multiversx_sdk_cli/cli.py | 9 ++++ multiversx_sdk_cli/cli_contracts.py | 16 ++++++- multiversx_sdk_cli/cli_delegation.py | 59 +++++++++++++++++++++++++- multiversx_sdk_cli/cli_dns.py | 14 +++++- multiversx_sdk_cli/cli_shared.py | 35 ++++++++++++++- multiversx_sdk_cli/cli_transactions.py | 16 ++++++- multiversx_sdk_cli/cli_validators.py | 34 +++++++++++++++ multiversx_sdk_cli/config.py | 20 ++++++++- multiversx_sdk_cli/utils.py | 44 ++++++++++++------- 9 files changed, 224 insertions(+), 23 deletions(-) diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index d7d024d6..6876d719 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -45,6 +45,8 @@ def _do_main(cli_args: list[str]): utils.ensure_folder(config.SDK_PATH) parser = setup_parser(cli_args) argcomplete.autocomplete(parser) + + _handle_verbose_argument(cli_args) args = parser.parse_args(cli_args) if args.verbose: @@ -146,6 +148,13 @@ def verify_deprecated_entries_in_config_file(): ux.show_warning(message.rstrip("\n")) +def _handle_verbose_argument(args: list[str]): + verbose_arg = "--verbose" + if verbose_arg in args: + args.remove(verbose_arg) + args.insert(0, verbose_arg) + + if __name__ == "__main__": ret = main(sys.argv[1:]) sys.exit(ret) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index a5a54506..825622cc 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -25,7 +25,7 @@ validate_transaction_args, ) from multiversx_sdk_cli.cli_output import CLIOutputBuilder -from multiversx_sdk_cli.config import get_config_for_network_providers +from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS from multiversx_sdk_cli.contract_verification import trigger_contract_verification from multiversx_sdk_cli.contracts import SmartContract @@ -369,13 +369,16 @@ def build(args: Any): The primary tool for building smart contracts is `sc-meta`. To install `sc-meta` check out the documentation: https://docs.multiversx.com/sdk-and-tools/troubleshooting/rust-setup. -After installing, use the `sc-meta all build` command. To lear more about `sc-meta`, check out this page: https://docs.multiversx.com/developers/meta/sc-meta-cli/#calling-build.""" +After installing, use the `sc-meta all build` command. To learn more about `sc-meta`, check out this page: https://docs.multiversx.com/developers/meta/sc-meta-cli/#calling-build.""" show_warning(message) def deploy(args: Any): logger.debug("deploy") + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) @@ -425,6 +428,9 @@ def deploy(args: Any): def call(args: Any): logger.debug("call") + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) @@ -467,6 +473,9 @@ def call(args: Any): def upgrade(args: Any): logger.debug("upgrade") + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) @@ -512,6 +521,9 @@ def upgrade(args: Any): def query(args: Any): logger.debug("query") + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_proxy_argument(args) # we don't need chainID to query a contract; we use the provided proxy diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index ab7e27bb..973ca898 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -19,7 +19,7 @@ validate_proxy_argument, validate_receiver_args, ) -from multiversx_sdk_cli.config import get_config_for_network_providers +from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers from multiversx_sdk_cli.delegation import DelegationOperations @@ -402,6 +402,9 @@ def _get_delegation_controller(args: Any): def do_create_delegation_contract(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -430,6 +433,9 @@ def do_create_delegation_contract(args: Any): def get_contract_address_by_deploy_tx_hash(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_proxy_argument(args) config = get_config_for_network_providers() @@ -447,6 +453,9 @@ def get_contract_address_by_deploy_tx_hash(args: Any): def add_new_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -495,6 +504,9 @@ def _get_public_keys_and_signed_messages(args: Any) -> tuple[list[ValidatorPubli def remove_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -544,6 +556,9 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def stake_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -582,6 +597,9 @@ def _check_if_either_bls_keys_or_validators_file_are_provided(args: Any): def unbond_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -612,6 +630,9 @@ def unbond_nodes(args: Any): def unstake_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -642,6 +663,9 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -672,6 +696,9 @@ def unjail_nodes(args: Any): def delegate(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -700,6 +727,9 @@ def delegate(args: Any): def claim_rewards(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -726,6 +756,9 @@ def claim_rewards(args: Any): def redelegate_rewards(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -752,6 +785,9 @@ def redelegate_rewards(args: Any): def undelegate(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -780,6 +816,9 @@ def undelegate(args: Any): def withdraw(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -807,6 +846,9 @@ def withdraw(args: Any): def change_service_fee(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -835,6 +877,9 @@ def change_service_fee(args: Any): def modify_delegation_cap(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -863,6 +908,9 @@ def modify_delegation_cap(args: Any): def automatic_activation(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -892,6 +940,9 @@ def automatic_activation(args: Any): def redelegate_cap(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -921,6 +972,9 @@ def redelegate_cap(args: Any): def set_metadata(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -951,6 +1005,9 @@ def set_metadata(args: Any): def make_new_contract_from_validator_data(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_arguments(args) sender = cli_shared.prepare_sender(args) diff --git a/multiversx_sdk_cli/cli_dns.py b/multiversx_sdk_cli/cli_dns.py index 2568a06d..f028148f 100644 --- a/multiversx_sdk_cli/cli_dns.py +++ b/multiversx_sdk_cli/cli_dns.py @@ -5,7 +5,7 @@ from rich.table import Table from multiversx_sdk_cli import cli_shared -from multiversx_sdk_cli.config import get_config_for_network_providers +from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers from multiversx_sdk_cli.constants import ADDRESS_ZERO_HEX from multiversx_sdk_cli.dns import ( compute_dns_address_for_shard_id, @@ -136,6 +136,9 @@ def _ensure_proxy_is_provided(args: Any): def dns_resolve(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _ensure_proxy_is_provided(args) config = get_config_for_network_providers() @@ -145,6 +148,9 @@ def dns_resolve(args: Any): def dns_validate_name(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _ensure_proxy_is_provided(args) config = get_config_for_network_providers() @@ -168,6 +174,9 @@ def get_dns_address_for_name_hex(args: Any): def get_registration_cost(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _ensure_proxy_is_provided(args) config = get_config_for_network_providers() @@ -175,6 +184,9 @@ def get_registration_cost(args: Any): def get_version(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + _ensure_proxy_is_provided(args) config = get_config_for_network_providers() diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 316b8629..eb7ac39f 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -1,5 +1,7 @@ import argparse import ast +import base64 +import logging import sys from argparse import FileType from pathlib import Path @@ -36,7 +38,10 @@ from multiversx_sdk_cli.simulation import Simulator from multiversx_sdk_cli.transactions import send_and_wait_for_result from multiversx_sdk_cli.utils import log_explorer_transaction -from multiversx_sdk_cli.ux import show_warning +from multiversx_sdk_cli.ux import confirm_continuation, show_warning + +logger = logging.getLogger("cli_shared") + trusted_cosigner_service_url_by_chain_id = { "1": "https://tools.multiversx.com/guardian", @@ -557,11 +562,17 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL output_builder.set_emitted_transaction(tx) outfile = args.outfile if hasattr(args, "outfile") else None + cli_config = config.MxpyConfig.from_active_config() + hash = "" try: if send_wait_result: + _confirm_continuation_if_required(cli_config, tx) + transaction_on_network = send_and_wait_for_result(tx, proxy, args.timeout) output_builder.set_awaited_transaction(transaction_on_network) elif send_only: + _confirm_continuation_if_required(cli_config, tx) + hash = proxy.send_transaction(tx) output_builder.set_emitted_transaction_hash(hash.hex()) elif simulate: @@ -573,7 +584,7 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL if dump_output: utils.dump_out_json(output_transaction, outfile=outfile) - if send_only: + if send_only and hash: log_explorer_transaction( chain=output_transaction["emittedTransaction"]["chainID"], transaction_hash=output_transaction["emittedTransactionHash"], @@ -582,6 +593,18 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL return output_builder +def _confirm_continuation_if_required(config: config.MxpyConfig, tx: Transaction) -> None: + if config.ask_confirmation: + transaction = tx.to_dictionary() + + # decode the data field from base64 if it exists + data = base64.b64decode(transaction.get("data", "")).decode() + transaction["data"] = data if data else "" + + utils.dump_out_json(transaction) + confirm_continuation("You are about to send the above transaction. Do you want to continue?") + + def prepare_sender(args: Any): """Returns the sender's account. If no account was provided, will raise an exception.""" @@ -617,3 +640,11 @@ def prepare_guardian_relayer_data(args: Any) -> GuardianRelayerData: relayer=relayer, relayer_address=relayer_address, ) + + +def set_proxy_from_config_if_not_provided(args: Any, config: config.MxpyConfig) -> None: + """This function modifies the `args` object by setting the proxy from the config if not already set.""" + if not args.proxy: + if config.proxy_url: + logger.info(f"Using proxy URL from config: {config.proxy_url}") + args.proxy = config.proxy_url diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 27785f43..e3b96de0 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -23,7 +23,7 @@ ) from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.cli_output import CLIOutputBuilder -from multiversx_sdk_cli.config import get_config_for_network_providers +from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers from multiversx_sdk_cli.errors import BadUsage, IncorrectWalletError, NoWalletProvided from multiversx_sdk_cli.transactions import ( TransactionsController, @@ -114,6 +114,9 @@ def _add_common_arguments(args: list[str], sub: Any): def create_transaction(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_nonce_args(args) validate_receiver_args(args) ensure_wallet_args_are_provided(args) @@ -172,6 +175,9 @@ def prepare_token_transfers(transfers: list[Any]) -> list[TokenTransfer]: def send_transaction(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_proxy_argument(args) tx = load_transaction_from_file(args.infile) @@ -181,6 +187,8 @@ def send_transaction(args: Any): proxy = ProxyNetworkProvider(url=args.proxy, config=config) try: + cli_shared._confirm_continuation_if_required(cli_config, tx) + tx_hash = proxy.send_transaction(tx) output.set_emitted_transaction_hash(tx_hash.hex()) finally: @@ -189,6 +197,9 @@ def send_transaction(args: Any): def sign_transaction(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_broadcast_args(args) tx = load_transaction_from_file(args.infile) @@ -228,6 +239,9 @@ def sign_transaction(args: Any): def relay_transaction(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + ensure_relayer_wallet_args_are_provided(args) validate_broadcast_args(args) diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index 7d06feb9..5087e0a9 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -11,6 +11,7 @@ validate_nonce_args, validate_receiver_args, ) +from multiversx_sdk_cli.config import MxpyConfig from multiversx_sdk_cli.validators import ValidatorsController @@ -218,6 +219,9 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def do_unstake(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -246,6 +250,9 @@ def do_unstake(args: Any): def do_unjail(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -274,6 +281,9 @@ def do_unjail(args: Any): def do_unbond(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -302,6 +312,9 @@ def do_unbond(args: Any): def change_reward_address(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -330,6 +343,9 @@ def change_reward_address(args: Any): def do_claim(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -356,6 +372,9 @@ def do_claim(args: Any): def do_unstake_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -385,6 +404,9 @@ def do_unstake_nodes(args: Any): def do_unstake_tokens(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -413,6 +435,9 @@ def do_unstake_tokens(args: Any): def do_unbond_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -442,6 +467,9 @@ def do_unbond_nodes(args: Any): def do_unbond_tokens(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -470,6 +498,9 @@ def do_unbond_tokens(args: Any): def do_clean_registered_data(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -496,6 +527,9 @@ def do_clean_registered_data(args: Any): def do_restake_unstaked_nodes(args: Any): + cli_config = MxpyConfig.from_active_config() + cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + validate_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( diff --git a/multiversx_sdk_cli/config.py b/multiversx_sdk_cli/config.py index e996f98d..ceff70bc 100644 --- a/multiversx_sdk_cli/config.py +++ b/multiversx_sdk_cli/config.py @@ -1,4 +1,5 @@ import os +from dataclasses import dataclass from pathlib import Path from typing import Any @@ -141,7 +142,7 @@ def get_defaults() -> dict[str, Any]: "default_address_hrp": "erd", "proxy_url": "", "explorer_url": "", - "ask_confirmation": "true", + "ask_confirmation": "false", } @@ -199,3 +200,20 @@ def get_dependency_parent_directory(key: str) -> Path: def get_config_for_network_providers() -> NetworkProviderConfig: return NetworkProviderConfig(client_name="mxpy") + + +@dataclass +class MxpyConfig: + address_hrp: str + proxy_url: str + explorer_url: str + ask_confirmation: bool + + @classmethod + def from_active_config(cls) -> "MxpyConfig": + return cls( + address_hrp=get_address_hrp(), + proxy_url=get_proxy_url(), + explorer_url=get_explorer_url(), + ask_confirmation=get_confirmation_setting(), + ) diff --git a/multiversx_sdk_cli/utils.py b/multiversx_sdk_cli/utils.py index f15518a4..9aaedd2d 100644 --- a/multiversx_sdk_cli/utils.py +++ b/multiversx_sdk_cli/utils.py @@ -150,22 +150,36 @@ def is_arg_present(args: list[str], key: str) -> bool: return False -def log_explorer(chain: str, name: str, path: str, details: str): - networks = { - "1": ("MultiversX Mainnet Explorer", "https://explorer.multiversx.com"), - "T": ("MultiversX Testnet Explorer", "https://testnet-explorer.multiversx.com"), - "D": ("MultiversX Devnet Explorer", "https://devnet-explorer.multiversx.com"), - } - try: - explorer_name, explorer_url = networks[chain] - logger.info(f"View this {name} in the {explorer_name}: {explorer_url}/{path}/{details}") - except KeyError: - return +def log_explorer(name: str, explorer: str, path: str, details: str): + logger.info(f"View this {name} in the MultiversX Explorer: {explorer}/{path}/{details}") + + +def log_explorer_contract_address(chain: str, address: str, explorer_url: Optional[str] = ""): + if explorer_url: + log_explorer("contract address", explorer_url, "accounts", address) + else: + explorer = get_explorer_by_chain_id(chain_id=chain) + if explorer: + log_explorer("contract address", explorer, "accounts", address) -def log_explorer_contract_address(chain: str, address: str): - log_explorer(chain, "contract address", "accounts", address) +def log_explorer_transaction(chain: str, transaction_hash: str, explorer_url: Optional[str] = ""): + if explorer_url: + log_explorer("transaction", explorer_url, "transactions", transaction_hash) + else: + explorer = get_explorer_by_chain_id(chain_id=chain) + if explorer: + log_explorer("transaction", explorer, "transactions", transaction_hash) -def log_explorer_transaction(chain: str, transaction_hash: str): - log_explorer(chain, "transaction", "transactions", transaction_hash) +def get_explorer_by_chain_id(chain_id: str) -> str: + explorers_by_chain_id = { + "1": "https://explorer.multiversx.com", + "T": "https://testnet-explorer.multiversx.com", + "D": "https://devnet-explorer.multiversx.com", + } + + try: + return explorers_by_chain_id[chain_id] + except KeyError: + return "" From 827cd350a12856622e3559f468f9e496927b4d25 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 27 May 2025 14:02:14 +0300 Subject: [PATCH 03/11] update gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 50374163..ca36e556 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ venv.bak/ typings multiversx_sdk_cli/tests/testdata-out + +.DS_store From e118b945981aad5657e02558915ca09b0ea0311b Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 27 May 2025 14:35:49 +0300 Subject: [PATCH 04/11] require python 3.10 or greater --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index a7b38afc..a6f06f85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ authors = [ license = "MIT" description = "MultiversX Smart Contracts Tools" readme = "README.md" -requires-python = ">=3.8" +requires-python = ">=3.10" classifiers = [ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", From b7d1ff31de8617dd5e9f3a94877db0f826e29798 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 27 May 2025 16:16:21 +0300 Subject: [PATCH 05/11] add caching --- multiversx_sdk_cli/cli_shared.py | 3 +++ multiversx_sdk_cli/config.py | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index eb7ac39f..53566d46 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -4,6 +4,7 @@ import logging import sys from argparse import FileType +from functools import cache from pathlib import Path from typing import Any, Text, Union, cast @@ -507,6 +508,7 @@ def get_current_nonce_for_address(address: Address, proxy_url: Union[str, None]) return proxy.get_account(address).nonce +@cache def get_chain_id(chain_id: str, proxy_url: str) -> str: if chain_id and proxy_url: fetched_chain_id = _fetch_chain_id(proxy_url) @@ -523,6 +525,7 @@ def get_chain_id(chain_id: str, proxy_url: str) -> str: return _fetch_chain_id(proxy_url) +@cache def _fetch_chain_id(proxy_url: str) -> str: network_provider_config = config.get_config_for_network_providers() proxy = ProxyNetworkProvider(url=proxy_url, config=network_provider_config) diff --git a/multiversx_sdk_cli/config.py b/multiversx_sdk_cli/config.py index ceff70bc..9afd8db4 100644 --- a/multiversx_sdk_cli/config.py +++ b/multiversx_sdk_cli/config.py @@ -1,5 +1,6 @@ import os from dataclasses import dataclass +from functools import cache from pathlib import Path from typing import Any @@ -32,6 +33,7 @@ def get_dependency_url(key: str, tag: str, platform: str) -> str: return url_template.replace("{TAG}", tag) +@cache def get_value(name: str) -> str: _guard_valid_name(name) data = get_active() @@ -41,6 +43,7 @@ def get_value(name: str) -> str: return value +@cache def get_address_hrp() -> str: return get_value("default_address_hrp") @@ -146,14 +149,17 @@ def get_defaults() -> dict[str, Any]: } +@cache def get_proxy_url() -> str: return get_value("proxy_url") +@cache def get_explorer_url() -> str: return get_value("explorer_url") +@cache def get_confirmation_setting() -> bool: confirmation_value = get_value("ask_confirmation") if confirmation_value.lower() in ["true", "yes", "1"]: @@ -176,6 +182,7 @@ def resolve_config_path() -> Path: return GLOBAL_CONFIG_PATH +@cache def read_file() -> dict[str, Any]: config_path = resolve_config_path() if config_path.exists(): @@ -210,6 +217,7 @@ class MxpyConfig: ask_confirmation: bool @classmethod + @cache def from_active_config(cls) -> "MxpyConfig": return cls( address_hrp=get_address_hrp(), From e066bc9ba767f514b15e0e03f344a6d90a27bf67 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 27 May 2025 16:35:50 +0300 Subject: [PATCH 06/11] pass explorer url when logging transactions --- multiversx_sdk_cli/cli_contracts.py | 2 +- multiversx_sdk_cli/cli_shared.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index 825622cc..f442fe18 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -420,7 +420,7 @@ def deploy(args: Any): contract_address = address_computer.compute_contract_address(deployer=sender.address, deployment_nonce=tx.nonce) logger.info("Contract address: %s", contract_address.to_bech32()) - utils.log_explorer_contract_address(args.chain, contract_address.to_bech32()) + utils.log_explorer_contract_address(args.chain, contract_address.to_bech32(), cli_config.explorer_url) _send_or_simulate(tx, contract_address, args) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 53566d46..5bf89541 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -591,6 +591,7 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL log_explorer_transaction( chain=output_transaction["emittedTransaction"]["chainID"], transaction_hash=output_transaction["emittedTransactionHash"], + explorer_url=cli_config.explorer_url, ) return output_builder From 2906430f09b76b300ba81a448677021dc70d5fcb Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 28 May 2025 14:06:39 +0300 Subject: [PATCH 07/11] fixes --- multiversx_sdk_cli/cli_contracts.py | 6 +++--- multiversx_sdk_cli/cli_delegation.py | 2 +- multiversx_sdk_cli/cli_shared.py | 21 +++++++------------ multiversx_sdk_cli/cli_transactions.py | 2 +- multiversx_sdk_cli/cli_validators.py | 2 +- multiversx_sdk_cli/dns.py | 2 +- .../tests/test_cli_contracts.py | 1 + 7 files changed, 16 insertions(+), 20 deletions(-) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index f442fe18..e1649dee 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -390,7 +390,7 @@ def deploy(args: Any): args=args, ) - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) config = TransactionsFactoryConfig(chain_id) abi = Abi.load(Path(args.abi)) if args.abi else None @@ -442,7 +442,7 @@ def call(args: Any): args=args, ) - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) config = TransactionsFactoryConfig(chain_id) abi = Abi.load(Path(args.abi)) if args.abi else None @@ -487,7 +487,7 @@ def upgrade(args: Any): args=args, ) - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) config = TransactionsFactoryConfig(chain_id) abi = Abi.load(Path(args.abi)) if args.abi else None diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 973ca898..d541121f 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -395,7 +395,7 @@ def validate_arguments(args: Any): def _get_delegation_controller(args: Any): - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) config = TransactionsFactoryConfig(chain_id) delegation = DelegationOperations(config) return delegation diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 5bf89541..e50561f8 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -6,7 +6,7 @@ from argparse import FileType from functools import cache from pathlib import Path -from typing import Any, Text, Union, cast +from typing import Any, Optional, Text, Union, cast from multiversx_sdk import ( Account, @@ -39,7 +39,7 @@ from multiversx_sdk_cli.simulation import Simulator from multiversx_sdk_cli.transactions import send_and_wait_for_result from multiversx_sdk_cli.utils import log_explorer_transaction -from multiversx_sdk_cli.ux import confirm_continuation, show_warning +from multiversx_sdk_cli.ux import confirm_continuation logger = logging.getLogger("cli_shared") @@ -509,16 +509,8 @@ def get_current_nonce_for_address(address: Address, proxy_url: Union[str, None]) @cache -def get_chain_id(chain_id: str, proxy_url: str) -> str: - if chain_id and proxy_url: - fetched_chain_id = _fetch_chain_id(proxy_url) - - if chain_id != fetched_chain_id: - show_warning( - f"The chain ID you have provided does not match the chain ID you got from the proxy. Will use the proxy's value: '{fetched_chain_id}'" - ) - return fetched_chain_id - +def get_chain_id(proxy_url: str, chain_id: Optional[str] = None) -> str: + """We know and have already validated that if chainID is not provided, proxy is provided.""" if chain_id: return chain_id @@ -647,8 +639,11 @@ def prepare_guardian_relayer_data(args: Any) -> GuardianRelayerData: def set_proxy_from_config_if_not_provided(args: Any, config: config.MxpyConfig) -> None: - """This function modifies the `args` object by setting the proxy from the config if not already set.""" + """This function modifies the `args` object by setting the proxy from the config if not already set. If proxy is not needed (chainID and nonce are provided), the proxy will not be set.""" if not args.proxy: + if hasattr(args, "chain") and args.chain and hasattr(args, "nonce") and args.nonce: + return + if config.proxy_url: logger.info(f"Using proxy URL from config: {config.proxy_url}") args.proxy = config.proxy_url diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index e3b96de0..439bb1c3 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -138,7 +138,7 @@ def create_transaction(args: Any): transfers = getattr(args, "token_transfers", None) transfers = prepare_token_transfers(transfers) if transfers else None - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) tx_controller = TransactionsController(chain_id) tx = tx_controller.create_transaction( diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index 5087e0a9..8ab154e0 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -198,7 +198,7 @@ def do_stake(args: Any): def _get_validators_controller(args: Any): - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) validators = ValidatorsController(chain_id) return validators diff --git a/multiversx_sdk_cli/dns.py b/multiversx_sdk_cli/dns.py index 95ab0a85..2104a3a9 100644 --- a/multiversx_sdk_cli/dns.py +++ b/multiversx_sdk_cli/dns.py @@ -77,7 +77,7 @@ def register(args: Any): receiver = dns_address_for_name(args.name) data = dns_register_data(args.name) - chain_id = cli_shared.get_chain_id(args.chain, args.proxy) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) controller = TransactionsController(chain_id) tx = controller.create_transaction( diff --git a/multiversx_sdk_cli/tests/test_cli_contracts.py b/multiversx_sdk_cli/tests/test_cli_contracts.py index 4d579cfe..fa9d5bf6 100644 --- a/multiversx_sdk_cli/tests/test_cli_contracts.py +++ b/multiversx_sdk_cli/tests/test_cli_contracts.py @@ -270,6 +270,7 @@ def test_contract_flow(capsys: Any): def test_contract_deploy_without_required_arguments(): + """This test passes with an unaltered config. If proxy is set in the config, the test will fail due to mxpy fetching the nonce and the chain ID.""" alice = f"{parent}/testdata/alice.pem" adder = f"{parent}/testdata/adder.wasm" From bf2f946014eb43c4a9e831f19c486085fb795527 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 28 May 2025 17:10:28 +0300 Subject: [PATCH 08/11] fix mypy error --- multiversx_sdk_cli/cli_shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index e50561f8..7c31ac74 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -558,7 +558,7 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL outfile = args.outfile if hasattr(args, "outfile") else None cli_config = config.MxpyConfig.from_active_config() - hash = "" + hash = b"" try: if send_wait_result: _confirm_continuation_if_required(cli_config, tx) From 4e029f28f8c17829819a3b539b44cc4e97132be9 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 29 May 2025 17:51:23 +0300 Subject: [PATCH 09/11] move env to separate env file --- CLI.md | 181 ++++++++++++++++++++++-- CLI.md.sh | 10 ++ multiversx_sdk_cli/cli.py | 5 +- multiversx_sdk_cli/cli_contracts.py | 11 +- multiversx_sdk_cli/cli_delegation.py | 41 +++--- multiversx_sdk_cli/cli_dns.py | 11 +- multiversx_sdk_cli/cli_env.py | 149 ++++++++++++++++++++ multiversx_sdk_cli/cli_shared.py | 17 +-- multiversx_sdk_cli/cli_transactions.py | 11 +- multiversx_sdk_cli/cli_validators.py | 24 ++-- multiversx_sdk_cli/cli_wallet.py | 2 +- multiversx_sdk_cli/config.py | 49 ------- multiversx_sdk_cli/contracts.py | 2 +- multiversx_sdk_cli/delegation.py | 2 +- multiversx_sdk_cli/dns.py | 2 +- multiversx_sdk_cli/env.py | 182 +++++++++++++++++++++++++ multiversx_sdk_cli/errors.py | 20 +++ 17 files changed, 596 insertions(+), 123 deletions(-) create mode 100644 multiversx_sdk_cli/cli_env.py create mode 100644 multiversx_sdk_cli/env.py diff --git a/CLI.md b/CLI.md index 79de3032..2cf2143a 100644 --- a/CLI.md +++ b/CLI.md @@ -23,7 +23,7 @@ See: COMMAND GROUPS: - {contract,tx,validator,ledger,wallet,validator-wallet,deps,config,localnet,data,staking-provider,dns,faucet} + {contract,tx,validator,ledger,wallet,validator-wallet,deps,config,localnet,data,staking-provider,dns,faucet,env} TOP-LEVEL OPTIONS: -h, --help show this help message and exit @@ -40,12 +40,13 @@ ledger Get Ledger App addresses and version wallet Create wallet, derive secret key from mnemonic, bech32 address helpers etc. validator-wallet Create a validator wallet, sign and verify messages and convert a validator wallet to a hex secret key. deps Manage dependencies or multiversx-sdk modules -config Configure multiversx-sdk (default values etc.) +config Configure MultiversX CLI (default values etc.) localnet Set up, start and control localnets data Data manipulation omnitool staking-provider Staking provider omnitool dns Operations related to the Domain Name Service faucet Get xEGLD on Devnet or Testnet +env Configure MultiversX CLI to use specific environment values. ``` ## Group **Contract** @@ -421,6 +422,7 @@ options: or Ledger devices (default: 0) --sender-username SENDER_USERNAME 🖄 the username of the sender --hrp HRP The hrp used to convert the address to its bech32 representation + --skip-confirmation, -y can be used to skip the confirmation prompt ``` ### Contract.ReproducibleBuild @@ -2830,7 +2832,7 @@ options: $ mxpy config --help usage: mxpy config COMMAND [-h] ... -Configure multiversx-sdk (default values etc.) +Configure MultiversX CLI (default values etc.) COMMANDS: {dump,get,set,delete,new,switch,list,reset} @@ -2841,12 +2843,12 @@ OPTIONS: ---------------- COMMANDS summary ---------------- -dump Dumps configuration. -get Gets a configuration value. -set Sets a configuration value. -delete Deletes a configuration value. -new Creates a new configuration. -switch Switch to a different config +dump Dumps the active configuration. +get Gets a configuration value from the active configuration. +set Sets a configuration value for the active configuration. +delete Deletes a configuration value from the active configuration. +new Creates a new configuration and sets it as the active configuration. +switch Switch to a different config. list List available configs reset Deletes the config file. Default config will be used. @@ -2858,7 +2860,7 @@ reset Deletes the config file. Default config will be u $ mxpy config dump --help usage: mxpy config dump [-h] ... -Dumps configuration. +Dumps the active configuration. options: -h, --help show this help message and exit @@ -2872,7 +2874,7 @@ options: $ mxpy config get --help usage: mxpy config get [-h] ... -Gets a configuration value. +Gets a configuration value from the active configuration. positional arguments: name the name of the configuration entry @@ -2888,7 +2890,7 @@ options: $ mxpy config set --help usage: mxpy config set [-h] ... -Sets a configuration value. +Sets a configuration value for the active configuration. positional arguments: name the name of the configuration entry @@ -2905,7 +2907,7 @@ options: $ mxpy config new --help usage: mxpy config new [-h] ... -Creates a new configuration. +Creates a new configuration and sets it as the active configuration. positional arguments: name the name of the configuration entry @@ -2922,7 +2924,7 @@ options: $ mxpy config switch --help usage: mxpy config switch [-h] ... -Switch to a different config +Switch to a different config. positional arguments: name the name of the configuration entry @@ -3074,3 +3076,154 @@ options: --wallet-url WALLET_URL custom wallet url to call the faucet from ``` +## Group **Environment** + + +``` +$ mxpy env --help +usage: mxpy env COMMAND [-h] ... + +Configure MultiversX CLI to use specific environment values. + +COMMANDS: + {new,get,set,dump,delete,switch,list,remove,reset} + +OPTIONS: + -h, --help show this help message and exit + +---------------- +COMMANDS summary +---------------- +new Creates a new environment and sets it as the active environment. +get Gets an env value from the active environment. +set Sets an env value for the active environment. +dump Dumps the active environment. +delete Deletes an env value from the active environment. +switch Switch to a different environment. +list List available environments +remove Deletes an environment from the env file. Will switch to default env. +reset Deletes the environment file. Default env will be used. + +``` +### Environment.New + + +``` +$ mxpy env new --help +usage: mxpy env new [-h] ... + +Creates a new environment and sets it as the active environment. + +positional arguments: + name the name of the configuration entry + +options: + -h, --help show this help message and exit + --template TEMPLATE an environment from which to create the new environment + +``` +### Environment.Set + + +``` +$ mxpy env set --help +usage: mxpy env set [-h] ... + +Sets an env value for the active environment. + +positional arguments: + name the name of the configuration entry + value the new value + +options: + -h, --help show this help message and exit + +``` +### Environment.Get + + +``` +$ mxpy env get --help +usage: mxpy env get [-h] ... + +Gets an env value from the active environment. + +positional arguments: + name the name of the configuration entry + +options: + -h, --help show this help message and exit + +``` +### Environment.Dump + + +``` +$ mxpy env dump --help +usage: mxpy env dump [-h] ... + +Dumps the active environment. + +options: + -h, --help show this help message and exit + --default dumps the default environment instead of the active one. + +``` +### Environment.Switch + + +``` +$ mxpy env switch --help +usage: mxpy env switch [-h] ... + +Switch to a different environment. + +positional arguments: + name the name of the configuration entry + +options: + -h, --help show this help message and exit + +``` +### Environment.List + + +``` +$ mxpy env list --help +usage: mxpy env list [-h] ... + +List available environments + +options: + -h, --help show this help message and exit + +``` +### Environment.Remove + + +``` +$ mxpy env remove --help +usage: mxpy env remove [-h] ... + +Deletes an environment from the env file. Will switch to default env. + +positional arguments: + environment The environment to remove from env file. + +options: + -h, --help show this help message and exit + +``` +### Environment.Reset + + +``` +$ mxpy env reset --help +usage: mxpy env reset [-h] ... + +Deletes the environment file. Default env will be used. + +options: + -h, --help show this help message and exit + +``` diff --git a/CLI.md.sh b/CLI.md.sh index 46ebfb16..e40cf91e 100755 --- a/CLI.md.sh +++ b/CLI.md.sh @@ -130,6 +130,16 @@ generate() { group "Faucet" "faucet" command "Faucet.Request" "faucet request" + + group "Environment" "env" + command "Environment.New" "env new" + command "Environment.Set" "env set" + command "Environment.Get" "env get" + command "Environment.Dump" "env dump" + command "Environment.Switch" "env switch" + command "Environment.List" "env list" + command "Environment.Remove" "env remove" + command "Environment.Reset" "env reset" } generate diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index 6876d719..3e21b209 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -15,6 +15,7 @@ import multiversx_sdk_cli.cli_delegation import multiversx_sdk_cli.cli_deps import multiversx_sdk_cli.cli_dns +import multiversx_sdk_cli.cli_env import multiversx_sdk_cli.cli_faucet import multiversx_sdk_cli.cli_ledger import multiversx_sdk_cli.cli_localnet @@ -24,6 +25,7 @@ import multiversx_sdk_cli.cli_wallet import multiversx_sdk_cli.version from multiversx_sdk_cli import config, errors, utils, ux +from multiversx_sdk_cli.env import get_address_hrp logger = logging.getLogger("cli") @@ -64,7 +66,7 @@ def _do_main(cli_args: list[str]): ) verify_deprecated_entries_in_config_file() - default_hrp = config.get_address_hrp() + default_hrp = get_address_hrp() LibraryConfig.default_address_hrp = default_hrp if hasattr(args, "recall_nonce") and args.recall_nonce: @@ -123,6 +125,7 @@ def setup_parser(args: list[str]): commands.append(multiversx_sdk_cli.cli_delegation.setup_parser(args, subparsers)) commands.append(multiversx_sdk_cli.cli_dns.setup_parser(args, subparsers)) commands.append(multiversx_sdk_cli.cli_faucet.setup_parser(args, subparsers)) + commands.append(multiversx_sdk_cli.cli_env.setup_parser(subparsers)) parser.epilog = """ ---------------------- diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index e1649dee..38c5cb70 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -25,11 +25,12 @@ validate_transaction_args, ) from multiversx_sdk_cli.cli_output import CLIOutputBuilder -from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers +from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS from multiversx_sdk_cli.contract_verification import trigger_contract_verification from multiversx_sdk_cli.contracts import SmartContract from multiversx_sdk_cli.docker import is_docker_installed, run_docker +from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.errors import DockerMissingError from multiversx_sdk_cli.ux import show_warning @@ -376,7 +377,7 @@ def build(args: Any): def deploy(args: Any): logger.debug("deploy") - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_transaction_args(args) @@ -428,7 +429,7 @@ def deploy(args: Any): def call(args: Any): logger.debug("call") - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_transaction_args(args) @@ -473,7 +474,7 @@ def call(args: Any): def upgrade(args: Any): logger.debug("upgrade") - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_transaction_args(args) @@ -521,7 +522,7 @@ def upgrade(args: Any): def query(args: Any): logger.debug("query") - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_proxy_argument(args) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index d541121f..bba9ae6b 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -19,8 +19,9 @@ validate_proxy_argument, validate_receiver_args, ) -from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers +from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.delegation import DelegationOperations +from multiversx_sdk_cli.env import MxpyEnv def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -402,7 +403,7 @@ def _get_delegation_controller(args: Any): def do_create_delegation_contract(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -433,7 +434,7 @@ def do_create_delegation_contract(args: Any): def get_contract_address_by_deploy_tx_hash(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_proxy_argument(args) @@ -453,7 +454,7 @@ def get_contract_address_by_deploy_tx_hash(args: Any): def add_new_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -504,7 +505,7 @@ def _get_public_keys_and_signed_messages(args: Any) -> tuple[list[ValidatorPubli def remove_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -556,7 +557,7 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def stake_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -597,7 +598,7 @@ def _check_if_either_bls_keys_or_validators_file_are_provided(args: Any): def unbond_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -630,7 +631,7 @@ def unbond_nodes(args: Any): def unstake_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -663,7 +664,7 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -696,7 +697,7 @@ def unjail_nodes(args: Any): def delegate(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -727,7 +728,7 @@ def delegate(args: Any): def claim_rewards(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -756,7 +757,7 @@ def claim_rewards(args: Any): def redelegate_rewards(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -785,7 +786,7 @@ def redelegate_rewards(args: Any): def undelegate(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -816,7 +817,7 @@ def undelegate(args: Any): def withdraw(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -846,7 +847,7 @@ def withdraw(args: Any): def change_service_fee(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -877,7 +878,7 @@ def change_service_fee(args: Any): def modify_delegation_cap(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -908,7 +909,7 @@ def modify_delegation_cap(args: Any): def automatic_activation(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -940,7 +941,7 @@ def automatic_activation(args: Any): def redelegate_cap(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -972,7 +973,7 @@ def redelegate_cap(args: Any): def set_metadata(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) @@ -1005,7 +1006,7 @@ def set_metadata(args: Any): def make_new_contract_from_validator_data(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_arguments(args) diff --git a/multiversx_sdk_cli/cli_dns.py b/multiversx_sdk_cli/cli_dns.py index f028148f..010450bc 100644 --- a/multiversx_sdk_cli/cli_dns.py +++ b/multiversx_sdk_cli/cli_dns.py @@ -5,7 +5,7 @@ from rich.table import Table from multiversx_sdk_cli import cli_shared -from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers +from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.constants import ADDRESS_ZERO_HEX from multiversx_sdk_cli.dns import ( compute_dns_address_for_shard_id, @@ -17,6 +17,7 @@ validate_name, version, ) +from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.errors import ArgumentsNotProvidedError @@ -136,7 +137,7 @@ def _ensure_proxy_is_provided(args: Any): def dns_resolve(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _ensure_proxy_is_provided(args) @@ -148,7 +149,7 @@ def dns_resolve(args: Any): def dns_validate_name(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _ensure_proxy_is_provided(args) @@ -174,7 +175,7 @@ def get_dns_address_for_name_hex(args: Any): def get_registration_cost(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _ensure_proxy_is_provided(args) @@ -184,7 +185,7 @@ def get_registration_cost(args: Any): def get_version(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) _ensure_proxy_is_provided(args) diff --git a/multiversx_sdk_cli/cli_env.py b/multiversx_sdk_cli/cli_env.py new file mode 100644 index 00000000..4e3614a9 --- /dev/null +++ b/multiversx_sdk_cli/cli_env.py @@ -0,0 +1,149 @@ +import logging +import os +from typing import Any + +from multiversx_sdk_cli import cli_shared +from multiversx_sdk_cli.env import ( + create_new_env, + delete_env, + delete_value, + get_active_env, + get_defaults, + get_value, + read_env_file, + resolve_env_path, + set_active, + set_value, +) +from multiversx_sdk_cli.utils import dump_out_json +from multiversx_sdk_cli.ux import confirm_continuation + +logger = logging.getLogger("cli.env") + + +def setup_parser(subparsers: Any) -> Any: + parser = cli_shared.add_group_subparser( + subparsers, "env", "Configure MultiversX CLI to use specific environment values." + ) + subparsers = parser.add_subparsers() + + sub = cli_shared.add_command_subparser( + subparsers, "env", "new", "Creates a new environment and sets it as the active environment." + ) + _add_name_arg(sub) + sub.add_argument( + "--template", + required=False, + help="an environment from which to create the new environment", + ) + sub.set_defaults(func=new_env) + + sub = cli_shared.add_command_subparser(subparsers, "env", "get", "Gets an env value from the active environment.") + _add_name_arg(sub) + sub.set_defaults(func=get_env_value) + + sub = cli_shared.add_command_subparser(subparsers, "env", "set", "Sets an env value for the active environment.") + _add_name_arg(sub) + sub.add_argument("value", type=str, help="the new value") + sub.set_defaults(func=set_env_value) + + sub = cli_shared.add_command_subparser(subparsers, "env", "dump", "Dumps the active environment.") + sub.add_argument( + "--default", + required=False, + help="dumps the default environment instead of the active one.", + action="store_true", + ) + sub.set_defaults(func=dump) + + sub = cli_shared.add_command_subparser( + subparsers, "env", "delete", "Deletes an env value from the active environment." + ) + _add_name_arg(sub) + sub.set_defaults(func=delete_env_value) + + sub = cli_shared.add_command_subparser(subparsers, "env", "switch", "Switch to a different environment.") + _add_name_arg(sub) + sub.set_defaults(func=switch_env) + + sub = cli_shared.add_command_subparser(subparsers, "env", "list", "List available environments") + sub.set_defaults(func=list_envs) + + sub = cli_shared.add_command_subparser( + subparsers, + "env", + "remove", + "Deletes an environment from the env file. Will switch to default env.", + ) + sub.add_argument("environment", type=str, help="The environment to remove from env file.") + sub.set_defaults(func=remove_env_entry) + + sub = cli_shared.add_command_subparser( + subparsers, + "env", + "reset", + "Deletes the environment file. Default env will be used.", + ) + sub.set_defaults(func=delete_env_file) + + parser.epilog = cli_shared.build_group_epilog(subparsers) + return subparsers + + +def _add_name_arg(sub: Any): + sub.add_argument("name", type=str, help="the name of the configuration entry") + + +def dump(args: Any): + if args.default: + dump_out_json(get_defaults()) + else: + dump_out_json(get_active_env()) + + +def get_env_value(args: Any): + value = get_value(args.name) + print(value) + + +def set_env_value(args: Any): + set_value(args.name, args.value) + + +def delete_env_value(args: Any): + delete_value(args.name) + + +def new_env(args: Any): + create_new_env(name=args.name, template=args.template) + dump_out_json(get_active_env()) + + +def switch_env(args: Any): + set_active(args.name) + dump_out_json(get_active_env()) + + +def list_envs(args: Any): + data = read_env_file() + dump_out_json(data) + + +def remove_env_entry(args: Any): + envs_file = resolve_env_path() + if not envs_file.is_file(): + logger.info("Environment file not found. Aborting...") + return + + delete_env(args.environment) + + +def delete_env_file(args: Any): + envs_file = resolve_env_path() + if not envs_file.is_file(): + logger.info("Environment file not found. Aborting...") + return + + confirm_continuation(f"The file `{str(envs_file)}` will be deleted. Do you want to continue? (y/n)") + os.remove(envs_file) + logger.info("Successfully deleted the environment file.") diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 7c31ac74..d09bf308 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -29,6 +29,7 @@ DEFAULT_TX_VERSION, TCS_SERVICE_ID, ) +from multiversx_sdk_cli.env import MxpyEnv, get_address_hrp from multiversx_sdk_cli.errors import ( ArgumentsNotProvidedError, BadUsage, @@ -328,7 +329,7 @@ def _get_address_hrp(args: Any) -> str: if hrp: return hrp - return config.get_address_hrp() + return get_address_hrp() def _get_hrp_from_proxy(args: Any) -> str: @@ -557,7 +558,7 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL output_builder.set_emitted_transaction(tx) outfile = args.outfile if hasattr(args, "outfile") else None - cli_config = config.MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() hash = b"" try: if send_wait_result: @@ -589,8 +590,8 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL return output_builder -def _confirm_continuation_if_required(config: config.MxpyConfig, tx: Transaction) -> None: - if config.ask_confirmation: +def _confirm_continuation_if_required(env: MxpyEnv, tx: Transaction) -> None: + if env.ask_confirmation: transaction = tx.to_dictionary() # decode the data field from base64 if it exists @@ -638,12 +639,12 @@ def prepare_guardian_relayer_data(args: Any) -> GuardianRelayerData: ) -def set_proxy_from_config_if_not_provided(args: Any, config: config.MxpyConfig) -> None: +def set_proxy_from_config_if_not_provided(args: Any, env: MxpyEnv) -> None: """This function modifies the `args` object by setting the proxy from the config if not already set. If proxy is not needed (chainID and nonce are provided), the proxy will not be set.""" if not args.proxy: if hasattr(args, "chain") and args.chain and hasattr(args, "nonce") and args.nonce: return - if config.proxy_url: - logger.info(f"Using proxy URL from config: {config.proxy_url}") - args.proxy = config.proxy_url + if env.proxy_url: + logger.info(f"Using proxy URL from config: {env.proxy_url}") + args.proxy = env.proxy_url diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 439bb1c3..14dc8222 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -23,7 +23,8 @@ ) from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.cli_output import CLIOutputBuilder -from multiversx_sdk_cli.config import MxpyConfig, get_config_for_network_providers +from multiversx_sdk_cli.config import get_config_for_network_providers +from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.errors import BadUsage, IncorrectWalletError, NoWalletProvided from multiversx_sdk_cli.transactions import ( TransactionsController, @@ -114,7 +115,7 @@ def _add_common_arguments(args: list[str], sub: Any): def create_transaction(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_nonce_args(args) @@ -175,7 +176,7 @@ def prepare_token_transfers(transfers: list[Any]) -> list[TokenTransfer]: def send_transaction(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_proxy_argument(args) @@ -197,7 +198,7 @@ def send_transaction(args: Any): def sign_transaction(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_broadcast_args(args) @@ -239,7 +240,7 @@ def sign_transaction(args: Any): def relay_transaction(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) ensure_relayer_wallet_args_are_provided(args) diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index 8ab154e0..9d6ebeba 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -11,7 +11,7 @@ validate_nonce_args, validate_receiver_args, ) -from multiversx_sdk_cli.config import MxpyConfig +from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.validators import ValidatorsController @@ -219,7 +219,7 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def do_unstake(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -250,7 +250,7 @@ def do_unstake(args: Any): def do_unjail(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -281,7 +281,7 @@ def do_unjail(args: Any): def do_unbond(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -312,7 +312,7 @@ def do_unbond(args: Any): def change_reward_address(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -343,7 +343,7 @@ def change_reward_address(args: Any): def do_claim(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -372,7 +372,7 @@ def do_claim(args: Any): def do_unstake_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -404,7 +404,7 @@ def do_unstake_nodes(args: Any): def do_unstake_tokens(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -435,7 +435,7 @@ def do_unstake_tokens(args: Any): def do_unbond_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -467,7 +467,7 @@ def do_unbond_nodes(args: Any): def do_unbond_tokens(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -498,7 +498,7 @@ def do_unbond_tokens(args: Any): def do_clean_registered_data(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) @@ -527,7 +527,7 @@ def do_clean_registered_data(args: Any): def do_restake_unstaked_nodes(args: Any): - cli_config = MxpyConfig.from_active_config() + cli_config = MxpyEnv.from_active_env() cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) validate_args(args) diff --git a/multiversx_sdk_cli/cli_wallet.py b/multiversx_sdk_cli/cli_wallet.py index 558e720a..48d99048 100644 --- a/multiversx_sdk_cli/cli_wallet.py +++ b/multiversx_sdk_cli/cli_wallet.py @@ -9,8 +9,8 @@ from multiversx_sdk.core.address import get_shard_of_pubkey from multiversx_sdk_cli import cli_shared, utils -from multiversx_sdk_cli.config import get_address_hrp from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS +from multiversx_sdk_cli.env import get_address_hrp from multiversx_sdk_cli.errors import ( BadUsage, BadUserInput, diff --git a/multiversx_sdk_cli/config.py b/multiversx_sdk_cli/config.py index 9afd8db4..219c7770 100644 --- a/multiversx_sdk_cli/config.py +++ b/multiversx_sdk_cli/config.py @@ -1,5 +1,4 @@ import os -from dataclasses import dataclass from functools import cache from pathlib import Path from typing import Any @@ -43,11 +42,6 @@ def get_value(name: str) -> str: return value -@cache -def get_address_hrp() -> str: - return get_value("default_address_hrp") - - def set_value(name: str, value: Any): _guard_valid_name(name) data = read_file() @@ -142,34 +136,9 @@ def get_defaults() -> dict[str, Any]: "dependencies.testwallets.urlTemplate.osx": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", "dependencies.testwallets.urlTemplate.windows": "https://github.com/multiversx/mx-sdk-testwallets/archive/{TAG}.tar.gz", "github_api_token": "", - "default_address_hrp": "erd", - "proxy_url": "", - "explorer_url": "", - "ask_confirmation": "false", } -@cache -def get_proxy_url() -> str: - return get_value("proxy_url") - - -@cache -def get_explorer_url() -> str: - return get_value("explorer_url") - - -@cache -def get_confirmation_setting() -> bool: - confirmation_value = get_value("ask_confirmation") - if confirmation_value.lower() in ["true", "yes", "1"]: - return True - elif confirmation_value.lower() in ["false", "no", "0"]: - return False - else: - raise errors.InvalidConfirmationSettingError(confirmation_value) - - def get_deprecated_entries_in_config_file(): default_config_keys = set(get_defaults().keys()) current_config_keys = set(get_active().keys()) @@ -207,21 +176,3 @@ def get_dependency_parent_directory(key: str) -> Path: def get_config_for_network_providers() -> NetworkProviderConfig: return NetworkProviderConfig(client_name="mxpy") - - -@dataclass -class MxpyConfig: - address_hrp: str - proxy_url: str - explorer_url: str - ask_confirmation: bool - - @classmethod - @cache - def from_active_config(cls) -> "MxpyConfig": - return cls( - address_hrp=get_address_hrp(), - proxy_url=get_proxy_url(), - explorer_url=get_explorer_url(), - ask_confirmation=get_confirmation_setting(), - ) diff --git a/multiversx_sdk_cli/contracts.py b/multiversx_sdk_cli/contracts.py index f4b19f2c..f34798c7 100644 --- a/multiversx_sdk_cli/contracts.py +++ b/multiversx_sdk_cli/contracts.py @@ -27,7 +27,7 @@ from multiversx_sdk_cli import errors from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.config import get_address_hrp +from multiversx_sdk_cli.env import get_address_hrp from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount diff --git a/multiversx_sdk_cli/delegation.py b/multiversx_sdk_cli/delegation.py index 17a8c377..e87e2862 100644 --- a/multiversx_sdk_cli/delegation.py +++ b/multiversx_sdk_cli/delegation.py @@ -8,7 +8,7 @@ from multiversx_sdk.abi import BigUIntValue, Serializer from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.config import get_address_hrp +from multiversx_sdk_cli.env import get_address_hrp from multiversx_sdk_cli.errors import BadUsage from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount diff --git a/multiversx_sdk_cli/dns.py b/multiversx_sdk_cli/dns.py index 2104a3a9..2714ca5a 100644 --- a/multiversx_sdk_cli/dns.py +++ b/multiversx_sdk_cli/dns.py @@ -15,8 +15,8 @@ validate_chain_id_args, validate_transaction_args, ) -from multiversx_sdk_cli.config import get_address_hrp from multiversx_sdk_cli.constants import ADDRESS_ZERO_HEX +from multiversx_sdk_cli.env import get_address_hrp from multiversx_sdk_cli.transactions import TransactionsController MaxNumShards = 256 diff --git a/multiversx_sdk_cli/env.py b/multiversx_sdk_cli/env.py new file mode 100644 index 00000000..8a878268 --- /dev/null +++ b/multiversx_sdk_cli/env.py @@ -0,0 +1,182 @@ +from dataclasses import dataclass +from functools import cache +from pathlib import Path +from typing import Any + +from multiversx_sdk_cli.errors import ( + EnvironmentAlreadyExistsError, + EnvironmentProtectedError, + InvalidConfirmationSettingError, + InvalidEnvironmentValue, + UnknownEnvironmentError, +) +from multiversx_sdk_cli.utils import read_json_file, write_json_file + +SDK_PATH = Path("~/multiversx-sdk").expanduser().resolve() +LOCAL_ENV_PATH = Path("env.mxpy.json").resolve() +GLOBAL_ENV_PATH = SDK_PATH / "env.mxpy.json" + + +@dataclass +class MxpyEnv: + address_hrp: str + proxy_url: str + explorer_url: str + ask_confirmation: bool + + @classmethod + @cache + def from_active_env(cls) -> "MxpyEnv": + return cls( + address_hrp=get_address_hrp(), + proxy_url=get_proxy_url(), + explorer_url=get_explorer_url(), + ask_confirmation=get_confirmation_setting(), + ) + + +def get_defaults() -> dict[str, str]: + return { + "default_address_hrp": "erd", + "proxy_url": "", + "explorer_url": "", + "ask_confirmation": "false", + } + + +@cache +def get_address_hrp() -> str: + return get_value("default_address_hrp") + + +@cache +def get_proxy_url() -> str: + return get_value("proxy_url") + + +@cache +def get_explorer_url() -> str: + return get_value("explorer_url") + + +@cache +def get_confirmation_setting() -> bool: + confirmation_value = get_value("ask_confirmation") + if confirmation_value.lower() in ["true", "yes", "1"]: + return True + elif confirmation_value.lower() in ["false", "no", "0"]: + return False + else: + raise InvalidConfirmationSettingError(confirmation_value) + + +@cache +def get_value(name: str) -> str: + _guard_valid_name(name) + data = get_active_env() + default_value = get_defaults()[name] + value = data.get(name, default_value) + assert isinstance(value, str) + return value + + +def _guard_valid_name(name: str): + if name not in get_defaults().keys(): + raise InvalidEnvironmentValue(f"Key is not present in environment config: [{name}]") + + +def get_active_env() -> dict[str, str]: + data = read_env_file() + envs: dict[str, Any] = data.get("environments", {}) + active_env_name: str = data.get("active", "default") + result: dict[str, str] = envs.get(active_env_name, {}) + + return result + + +@cache +def read_env_file() -> dict[str, Any]: + env_path = resolve_env_path() + if env_path.exists(): + data: dict[str, Any] = read_json_file(env_path) + return data + return dict() + + +def resolve_env_path() -> Path: + if LOCAL_ENV_PATH.is_file(): + return LOCAL_ENV_PATH + return GLOBAL_ENV_PATH + + +def set_value(name: str, value: Any): + _guard_valid_name(name) + data = read_env_file() + active_env = data.get("active", "default") + data.setdefault("environments", {}) + data["environments"].setdefault(active_env, {}) + data["environments"][active_env][name] = value + write_file(data) + + +def write_file(data: dict[str, Any]): + env_path = resolve_env_path() + write_json_file(str(env_path), data) + + +def delete_value(name: str): + """Deletes a key-value pair of the active env.""" + _guard_valid_env_deletion(name) + data = read_env_file() + active_env = data.get("active", "default") + data.setdefault("environments", {}) + data["environments"].setdefault(active_env, {}) + del data["environments"][active_env][name] + write_file(data) + + +def _guard_valid_env_deletion(name: str): + if name == "default": + raise EnvironmentProtectedError(name) + + +def set_active(name: str): + data = read_env_file() + _guard_valid_env_name(data, name) + data["active"] = name + write_file(data) + + +def _guard_valid_env_name(env: Any, name: str): + envs = env.get("environments", {}) + if name not in envs: + raise UnknownEnvironmentError(name) + + +def create_new_env(name: str, template: str): + data = read_env_file() + _guard_env_unique(data, name) + new_env = {} + if template: + _guard_valid_env_name(data, template) + new_env = data["environments"][template] + + data["active"] = name + data.setdefault("environments", {}) + data["environments"][name] = new_env + write_file(data) + + +def _guard_env_unique(env: Any, name: str): + envs = env.get("environments", {}) + if name in envs: + raise EnvironmentAlreadyExistsError(name) + + +def delete_env(name: str): + _guard_valid_env_deletion(name) + data = read_env_file() + data["environments"].pop(name, None) + if data["active"] == name: + data["active"] = "default" + write_file(data) diff --git a/multiversx_sdk_cli/errors.py b/multiversx_sdk_cli/errors.py index eb8025d7..4e418501 100644 --- a/multiversx_sdk_cli/errors.py +++ b/multiversx_sdk_cli/errors.py @@ -156,3 +156,23 @@ def __init__(self, value: str): super().__init__( f"Invalid confirmation setting: {value}. Valid values are: ['true', 'false', 'yes', 'no', '1', '0']." ) + + +class InvalidEnvironmentValue(KnownError): + def __init__(self, message: str): + super().__init__(message) + + +class EnvironmentProtectedError(KnownError): + def __init__(self, name: str): + super().__init__(f"This environment name is protected: {name}.") + + +class UnknownEnvironmentError(KnownError): + def __init__(self, name: str): + super().__init__(f"Environment entry is not known: {name}.") + + +class EnvironmentAlreadyExistsError(KnownError): + def __init__(self, name: str): + super().__init__(f"Environment entry already exists: {name}.") From 32787af5bb8c34cf5d32950bca175d5bed922331 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 5 Jun 2025 16:07:26 +0300 Subject: [PATCH 10/11] refactoring --- multiversx_sdk_cli/cli_contracts.py | 14 ++--- multiversx_sdk_cli/cli_delegation.py | 58 ++++++------------- multiversx_sdk_cli/cli_dns.py | 13 ++--- multiversx_sdk_cli/cli_governance.py | 4 +- multiversx_sdk_cli/cli_multisig.py | 7 +-- multiversx_sdk_cli/cli_shared.py | 13 +++-- multiversx_sdk_cli/cli_transactions.py | 15 ++--- multiversx_sdk_cli/cli_validators.py | 34 ++++------- .../tests/test_cli_governance.py | 3 +- multiversx_sdk_cli/tests/test_cli_multisig.py | 3 +- 10 files changed, 60 insertions(+), 104 deletions(-) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index f1155985..3cb6c705 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -319,8 +319,7 @@ def build(args: Any): def deploy(args: Any): logger.debug("deploy") - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_transaction_args(args) ensure_wallet_args_are_provided(args) @@ -363,6 +362,8 @@ def deploy(args: Any): contract_address = address_computer.compute_contract_address(deployer=sender.address, deployment_nonce=tx.nonce) logger.info("Contract address: %s", contract_address.to_bech32()) + + cli_config = MxpyEnv.from_active_env() utils.log_explorer_contract_address(args.chain, contract_address.to_bech32(), cli_config.explorer_url) _send_or_simulate(tx, contract_address, args) @@ -371,8 +372,7 @@ def deploy(args: Any): def call(args: Any): logger.debug("call") - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_transaction_args(args) ensure_wallet_args_are_provided(args) @@ -420,8 +420,7 @@ def call(args: Any): def upgrade(args: Any): logger.debug("upgrade") - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_transaction_args(args) ensure_wallet_args_are_provided(args) @@ -468,8 +467,7 @@ def upgrade(args: Any): def query(args: Any): logger.debug("query") - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_proxy_argument(args) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index bba9ae6b..73d61a0e 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -21,7 +21,6 @@ ) from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.delegation import DelegationOperations -from multiversx_sdk_cli.env import MxpyEnv def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -403,8 +402,7 @@ def _get_delegation_controller(args: Any): def do_create_delegation_contract(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -434,8 +432,7 @@ def do_create_delegation_contract(args: Any): def get_contract_address_by_deploy_tx_hash(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_proxy_argument(args) @@ -454,8 +451,7 @@ def get_contract_address_by_deploy_tx_hash(args: Any): def add_new_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -505,8 +501,7 @@ def _get_public_keys_and_signed_messages(args: Any) -> tuple[list[ValidatorPubli def remove_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -557,8 +552,7 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def stake_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -598,8 +592,7 @@ def _check_if_either_bls_keys_or_validators_file_are_provided(args: Any): def unbond_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -631,8 +624,7 @@ def unbond_nodes(args: Any): def unstake_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -664,8 +656,7 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -697,8 +688,7 @@ def unjail_nodes(args: Any): def delegate(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -728,8 +718,7 @@ def delegate(args: Any): def claim_rewards(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -757,8 +746,7 @@ def claim_rewards(args: Any): def redelegate_rewards(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -786,8 +774,7 @@ def redelegate_rewards(args: Any): def undelegate(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -817,8 +804,7 @@ def undelegate(args: Any): def withdraw(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -847,8 +833,7 @@ def withdraw(args: Any): def change_service_fee(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -878,8 +863,7 @@ def change_service_fee(args: Any): def modify_delegation_cap(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -909,8 +893,7 @@ def modify_delegation_cap(args: Any): def automatic_activation(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -941,8 +924,7 @@ def automatic_activation(args: Any): def redelegate_cap(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -973,8 +955,7 @@ def redelegate_cap(args: Any): def set_metadata(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) @@ -1006,8 +987,7 @@ def set_metadata(args: Any): def make_new_contract_from_validator_data(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_arguments(args) diff --git a/multiversx_sdk_cli/cli_dns.py b/multiversx_sdk_cli/cli_dns.py index 010450bc..734dde82 100644 --- a/multiversx_sdk_cli/cli_dns.py +++ b/multiversx_sdk_cli/cli_dns.py @@ -17,7 +17,6 @@ validate_name, version, ) -from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.errors import ArgumentsNotProvidedError @@ -137,8 +136,7 @@ def _ensure_proxy_is_provided(args: Any): def dns_resolve(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _ensure_proxy_is_provided(args) @@ -149,8 +147,7 @@ def dns_resolve(args: Any): def dns_validate_name(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _ensure_proxy_is_provided(args) @@ -175,8 +172,7 @@ def get_dns_address_for_name_hex(args: Any): def get_registration_cost(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _ensure_proxy_is_provided(args) @@ -185,8 +181,7 @@ def get_registration_cost(args: Any): def get_version(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) _ensure_proxy_is_provided(args) diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index 3458a946..337f614c 100644 --- a/multiversx_sdk_cli/cli_governance.py +++ b/multiversx_sdk_cli/cli_governance.py @@ -19,7 +19,6 @@ ) from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.governance import GovernanceWrapper @@ -200,8 +199,7 @@ def _ensure_args(args: Any): def _ensure_proxy_arg(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_proxy_argument(args) diff --git a/multiversx_sdk_cli/cli_multisig.py b/multiversx_sdk_cli/cli_multisig.py index 3a9c92d8..e9ba68ae 100644 --- a/multiversx_sdk_cli/cli_multisig.py +++ b/multiversx_sdk_cli/cli_multisig.py @@ -38,7 +38,6 @@ from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS -from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.multisig import MultisigWrapper logger = logging.getLogger("cli.multisig") @@ -656,8 +655,7 @@ def _add_common_args(args: Any, sub: Any, with_contract_arg: bool = True, with_r def _ensure_args(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_transaction_args(args) ensure_wallet_args_are_provided(args) @@ -666,8 +664,7 @@ def _ensure_args(args: Any): def _ensure_proxy_arg(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_proxy_argument(args) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index ec6bfbb1..9cc06559 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -603,16 +603,15 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL output_builder.set_emitted_transaction(tx) outfile = args.outfile if hasattr(args, "outfile") else None - cli_config = MxpyEnv.from_active_env() hash = b"" try: if send_wait_result: - _confirm_continuation_if_required(cli_config, tx) + _confirm_continuation_if_required(tx) transaction_on_network = send_and_wait_for_result(tx, proxy, args.timeout) output_builder.set_awaited_transaction(transaction_on_network) elif send_only: - _confirm_continuation_if_required(cli_config, tx) + _confirm_continuation_if_required(tx) hash = proxy.send_transaction(tx) output_builder.set_emitted_transaction_hash(hash.hex()) @@ -626,6 +625,7 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL utils.dump_out_json(output_transaction, outfile=outfile) if send_only and hash: + cli_config = MxpyEnv.from_active_env() log_explorer_transaction( chain=output_transaction["emittedTransaction"]["chainID"], transaction_hash=output_transaction["emittedTransactionHash"], @@ -635,7 +635,9 @@ def send_or_simulate(tx: Transaction, args: Any, dump_output: bool = True) -> CL return output_builder -def _confirm_continuation_if_required(env: MxpyEnv, tx: Transaction) -> None: +def _confirm_continuation_if_required(tx: Transaction) -> None: + env = MxpyEnv.from_active_env() + if env.ask_confirmation: transaction = tx.to_dictionary() @@ -702,12 +704,13 @@ def prepare_token_transfers(transfers: list[str]) -> list[TokenTransfer]: return token_transfers -def set_proxy_from_config_if_not_provided(args: Any, env: MxpyEnv) -> None: +def set_proxy_from_config_if_not_provided(args: Any) -> None: """This function modifies the `args` object by setting the proxy from the config if not already set. If proxy is not needed (chainID and nonce are provided), the proxy will not be set.""" if not args.proxy: if hasattr(args, "chain") and args.chain and hasattr(args, "nonce") and args.nonce is not None: return + env = MxpyEnv.from_active_env() if env.proxy_url: logger.info(f"Using proxy URL from config: {env.proxy_url}") args.proxy = env.proxy_url diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 07b7e9f6..8f5f9734 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -17,7 +17,6 @@ from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.errors import BadUsage, IncorrectWalletError, NoWalletProvided from multiversx_sdk_cli.transactions import ( TransactionsController, @@ -98,8 +97,7 @@ def _add_common_arguments(args: list[str], sub: Any): def create_transaction(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_nonce_args(args) validate_receiver_args(args) @@ -143,8 +141,7 @@ def create_transaction(args: Any): def send_transaction(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_proxy_argument(args) @@ -155,7 +152,7 @@ def send_transaction(args: Any): proxy = ProxyNetworkProvider(url=args.proxy, config=config) try: - cli_shared._confirm_continuation_if_required(cli_config, tx) + cli_shared._confirm_continuation_if_required(tx) tx_hash = proxy.send_transaction(tx) output.set_emitted_transaction_hash(tx_hash.hex()) @@ -165,8 +162,7 @@ def send_transaction(args: Any): def sign_transaction(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_broadcast_args(args) @@ -207,8 +203,7 @@ def sign_transaction(args: Any): def relay_transaction(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) ensure_relayer_wallet_args_are_provided(args) validate_broadcast_args(args) diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index 9d6ebeba..2a01d60b 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -11,7 +11,6 @@ validate_nonce_args, validate_receiver_args, ) -from multiversx_sdk_cli.env import MxpyEnv from multiversx_sdk_cli.validators import ValidatorsController @@ -219,8 +218,7 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def do_unstake(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -250,8 +248,7 @@ def do_unstake(args: Any): def do_unjail(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -281,8 +278,7 @@ def do_unjail(args: Any): def do_unbond(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -312,8 +308,7 @@ def do_unbond(args: Any): def change_reward_address(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -343,8 +338,7 @@ def change_reward_address(args: Any): def do_claim(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -372,8 +366,7 @@ def do_claim(args: Any): def do_unstake_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -404,8 +397,7 @@ def do_unstake_nodes(args: Any): def do_unstake_tokens(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -435,8 +427,7 @@ def do_unstake_tokens(args: Any): def do_unbond_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -467,8 +458,7 @@ def do_unbond_nodes(args: Any): def do_unbond_tokens(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -498,8 +488,7 @@ def do_unbond_tokens(args: Any): def do_clean_registered_data(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) @@ -527,8 +516,7 @@ def do_clean_registered_data(args: Any): def do_restake_unstaked_nodes(args: Any): - cli_config = MxpyEnv.from_active_env() - cli_shared.set_proxy_from_config_if_not_provided(args, cli_config) + cli_shared.set_proxy_from_config_if_not_provided(args) validate_args(args) sender = cli_shared.prepare_sender(args) diff --git a/multiversx_sdk_cli/tests/test_cli_governance.py b/multiversx_sdk_cli/tests/test_cli_governance.py index c67922d2..65887c12 100644 --- a/multiversx_sdk_cli/tests/test_cli_governance.py +++ b/multiversx_sdk_cli/tests/test_cli_governance.py @@ -209,4 +209,5 @@ def _read_stdout(capsys: Any) -> str: def get_transaction(capsys: Any) -> dict[str, Any]: out = _read_stdout(capsys) output: dict[str, Any] = json.loads(out) - return output["emittedTransaction"] + tx: dict[str, Any] = output["emittedTransaction"] + return tx diff --git a/multiversx_sdk_cli/tests/test_cli_multisig.py b/multiversx_sdk_cli/tests/test_cli_multisig.py index e280e867..f2788f43 100644 --- a/multiversx_sdk_cli/tests/test_cli_multisig.py +++ b/multiversx_sdk_cli/tests/test_cli_multisig.py @@ -955,4 +955,5 @@ def _read_stdout(capsys: Any) -> str: def get_transaction(capsys: Any) -> dict[str, Any]: out = _read_stdout(capsys) output: dict[str, Any] = json.loads(out) - return output["emittedTransaction"] + tx: dict[str, Any] = output["emittedTransaction"] + return tx From 2a5d73b582dba6cf9623b4983254475f682dafa3 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 11 Jun 2025 15:41:53 +0300 Subject: [PATCH 11/11] fix after review --- multiversx_sdk_cli/cli.py | 2 ++ multiversx_sdk_cli/cli_contracts.py | 8 ----- multiversx_sdk_cli/cli_delegation.py | 38 ----------------------- multiversx_sdk_cli/cli_dns.py | 8 ----- multiversx_sdk_cli/cli_governance.py | 13 +++----- multiversx_sdk_cli/cli_multisig.py | 43 +++++++++++--------------- multiversx_sdk_cli/cli_shared.py | 3 ++ multiversx_sdk_cli/cli_transactions.py | 8 ----- multiversx_sdk_cli/cli_validators.py | 33 +++++++------------- 9 files changed, 38 insertions(+), 118 deletions(-) diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index c52dae5f..b41797bc 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -27,6 +27,7 @@ import multiversx_sdk_cli.cli_wallet import multiversx_sdk_cli.version from multiversx_sdk_cli import config, errors, utils, ux +from multiversx_sdk_cli.cli_shared import set_proxy_from_config_if_not_provided from multiversx_sdk_cli.env import get_address_hrp logger = logging.getLogger("cli") @@ -77,6 +78,7 @@ def _do_main(cli_args: list[str]): if not hasattr(args, "func"): parser.print_help() else: + set_proxy_from_config_if_not_provided(args) args.func(args) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index 3cb6c705..2f40d60c 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -319,8 +319,6 @@ def build(args: Any): def deploy(args: Any): logger.debug("deploy") - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) @@ -372,8 +370,6 @@ def deploy(args: Any): def call(args: Any): logger.debug("call") - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) @@ -420,8 +416,6 @@ def call(args: Any): def upgrade(args: Any): logger.debug("upgrade") - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) @@ -467,8 +461,6 @@ def upgrade(args: Any): def query(args: Any): logger.debug("query") - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_proxy_argument(args) # we don't need chainID to query a contract; we use the provided proxy diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 73d61a0e..994a40d3 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -402,8 +402,6 @@ def _get_delegation_controller(args: Any): def do_create_delegation_contract(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -432,8 +430,6 @@ def do_create_delegation_contract(args: Any): def get_contract_address_by_deploy_tx_hash(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_proxy_argument(args) config = get_config_for_network_providers() @@ -451,8 +447,6 @@ def get_contract_address_by_deploy_tx_hash(args: Any): def add_new_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -501,8 +495,6 @@ def _get_public_keys_and_signed_messages(args: Any) -> tuple[list[ValidatorPubli def remove_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) _check_if_either_bls_keys_or_validators_file_are_provided(args) @@ -552,8 +544,6 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def stake_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -592,8 +582,6 @@ def _check_if_either_bls_keys_or_validators_file_are_provided(args: Any): def unbond_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -624,8 +612,6 @@ def unbond_nodes(args: Any): def unstake_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -656,8 +642,6 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) @@ -688,8 +672,6 @@ def unjail_nodes(args: Any): def delegate(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -718,8 +700,6 @@ def delegate(args: Any): def claim_rewards(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -746,8 +726,6 @@ def claim_rewards(args: Any): def redelegate_rewards(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -774,8 +752,6 @@ def redelegate_rewards(args: Any): def undelegate(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -804,8 +780,6 @@ def undelegate(args: Any): def withdraw(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -833,8 +807,6 @@ def withdraw(args: Any): def change_service_fee(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -863,8 +835,6 @@ def change_service_fee(args: Any): def modify_delegation_cap(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -893,8 +863,6 @@ def modify_delegation_cap(args: Any): def automatic_activation(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -924,8 +892,6 @@ def automatic_activation(args: Any): def redelegate_cap(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -955,8 +921,6 @@ def redelegate_cap(args: Any): def set_metadata(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) @@ -987,8 +951,6 @@ def set_metadata(args: Any): def make_new_contract_from_validator_data(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_arguments(args) sender = cli_shared.prepare_sender(args) diff --git a/multiversx_sdk_cli/cli_dns.py b/multiversx_sdk_cli/cli_dns.py index 734dde82..2568a06d 100644 --- a/multiversx_sdk_cli/cli_dns.py +++ b/multiversx_sdk_cli/cli_dns.py @@ -136,8 +136,6 @@ def _ensure_proxy_is_provided(args: Any): def dns_resolve(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _ensure_proxy_is_provided(args) config = get_config_for_network_providers() @@ -147,8 +145,6 @@ def dns_resolve(args: Any): def dns_validate_name(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _ensure_proxy_is_provided(args) config = get_config_for_network_providers() @@ -172,8 +168,6 @@ def get_dns_address_for_name_hex(args: Any): def get_registration_cost(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _ensure_proxy_is_provided(args) config = get_config_for_network_providers() @@ -181,8 +175,6 @@ def get_registration_cost(args: Any): def get_version(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - _ensure_proxy_is_provided(args) config = get_config_for_network_providers() diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index 337f614c..88798f3a 100644 --- a/multiversx_sdk_cli/cli_governance.py +++ b/multiversx_sdk_cli/cli_governance.py @@ -198,11 +198,6 @@ def _ensure_args(args: Any): validate_chain_id_args(args) -def _ensure_proxy_arg(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_proxy_argument(args) - - def create_proposal(args: Any): _ensure_args(args) @@ -368,7 +363,7 @@ def change_config(args: Any): def get_voting_power(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) config = get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=config) @@ -382,7 +377,7 @@ def get_voting_power(args: Any): def get_config(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) config = get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=config) @@ -394,7 +389,7 @@ def get_config(args: Any): def get_proposal(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) config = get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=config) @@ -406,7 +401,7 @@ def get_proposal(args: Any): def get_delegated_vote_info(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) config = get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=config) diff --git a/multiversx_sdk_cli/cli_multisig.py b/multiversx_sdk_cli/cli_multisig.py index e9ba68ae..4bf03fc3 100644 --- a/multiversx_sdk_cli/cli_multisig.py +++ b/multiversx_sdk_cli/cli_multisig.py @@ -655,19 +655,12 @@ def _add_common_args(args: Any, sub: Any, with_contract_arg: bool = True, with_r def _ensure_args(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_transaction_args(args) ensure_wallet_args_are_provided(args) validate_broadcast_args(args) validate_chain_id_args(args) -def _ensure_proxy_arg(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_proxy_argument(args) - - def deploy(args: Any): logger.debug("multisig.deploy") _ensure_args(args) @@ -1438,7 +1431,7 @@ def perform_batch(args: Any): def get_quorum(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1451,7 +1444,7 @@ def get_quorum(args: Any): def get_num_board_members(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1464,7 +1457,7 @@ def get_num_board_members(args: Any): def get_num_groups(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1477,7 +1470,7 @@ def get_num_groups(args: Any): def get_num_proposers(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1490,7 +1483,7 @@ def get_num_proposers(args: Any): def get_action_group(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1503,7 +1496,7 @@ def get_action_group(args: Any): def get_last_group_action_id(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1516,7 +1509,7 @@ def get_last_group_action_id(args: Any): def get_action_last_index(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1529,7 +1522,7 @@ def get_action_last_index(args: Any): def is_signed_by(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1546,7 +1539,7 @@ def is_signed_by(args: Any): def is_quorum_reached(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1562,7 +1555,7 @@ def is_quorum_reached(args: Any): def get_pending_actions_full_info(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1578,7 +1571,7 @@ def get_pending_actions_full_info(args: Any): def get_user_role(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1594,7 +1587,7 @@ def get_user_role(args: Any): def get_all_board_members(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1614,7 +1607,7 @@ def get_all_board_members(args: Any): def get_all_proposers(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1634,7 +1627,7 @@ def get_all_proposers(args: Any): def get_action_data(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1650,7 +1643,7 @@ def get_action_data(args: Any): def get_action_signers(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1668,7 +1661,7 @@ def get_action_signers(args: Any): def get_action_signer_count(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1684,7 +1677,7 @@ def get_action_signer_count(args: Any): def get_action_valid_signer_count(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() @@ -1700,7 +1693,7 @@ def get_action_valid_signer_count(args: Any): def parse_proposal(args: Any): - _ensure_proxy_arg(args) + validate_proxy_argument(args) abi = Abi.load(Path(args.abi)) config = get_config_for_network_providers() diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index bdb87e77..e21ec67c 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -716,6 +716,9 @@ def prepare_token_transfers(transfers: list[str]) -> list[TokenTransfer]: def set_proxy_from_config_if_not_provided(args: Any) -> None: """This function modifies the `args` object by setting the proxy from the config if not already set. If proxy is not needed (chainID and nonce are provided), the proxy will not be set.""" + if not hasattr(args, "proxy"): + return + if not args.proxy: if hasattr(args, "chain") and args.chain and hasattr(args, "nonce") and args.nonce is not None: return diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 8f5f9734..ccd65068 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -97,8 +97,6 @@ def _add_common_arguments(args: list[str], sub: Any): def create_transaction(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_nonce_args(args) validate_receiver_args(args) ensure_wallet_args_are_provided(args) @@ -141,8 +139,6 @@ def create_transaction(args: Any): def send_transaction(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_proxy_argument(args) tx = load_transaction_from_file(args.infile) @@ -162,8 +158,6 @@ def send_transaction(args: Any): def sign_transaction(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_broadcast_args(args) tx = load_transaction_from_file(args.infile) @@ -203,8 +197,6 @@ def sign_transaction(args: Any): def relay_transaction(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - ensure_relayer_wallet_args_are_provided(args) validate_broadcast_args(args) diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index 2a01d60b..32a8532e 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -218,9 +218,8 @@ def _parse_public_bls_keys(public_bls_keys: str) -> list[ValidatorPublicKey]: def do_unstake(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -248,9 +247,8 @@ def do_unstake(args: Any): def do_unjail(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -278,9 +276,8 @@ def do_unjail(args: Any): def do_unbond(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -308,9 +305,8 @@ def do_unbond(args: Any): def change_reward_address(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -338,9 +334,8 @@ def change_reward_address(args: Any): def do_claim(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -366,9 +361,8 @@ def do_claim(args: Any): def do_unstake_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -397,9 +391,8 @@ def do_unstake_nodes(args: Any): def do_unstake_tokens(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -427,9 +420,8 @@ def do_unstake_tokens(args: Any): def do_unbond_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -458,9 +450,8 @@ def do_unbond_nodes(args: Any): def do_unbond_tokens(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -488,9 +479,8 @@ def do_unbond_tokens(args: Any): def do_clean_registered_data(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -516,9 +506,8 @@ def do_clean_registered_data(args: Any): def do_restake_unstaked_nodes(args: Any): - cli_shared.set_proxy_from_config_if_not_provided(args) - validate_args(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(),