From 1c91d5c3ddcca0f041933bbea57a664ab33bd82a Mon Sep 17 00:00:00 2001 From: Lara Tifui Date: Mon, 8 Sep 2025 05:19:33 +0200 Subject: [PATCH 01/33] setup parser for cli_token --- multiversx_sdk_cli/cli.py | 2 ++ multiversx_sdk_cli/cli_token.py | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 multiversx_sdk_cli/cli_token.py diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index 8ad91fd5..f9eff03e 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -23,6 +23,7 @@ import multiversx_sdk_cli.cli_ledger import multiversx_sdk_cli.cli_localnet import multiversx_sdk_cli.cli_multisig +import multiversx_sdk_cli.cli_token import multiversx_sdk_cli.cli_transactions import multiversx_sdk_cli.cli_validator_wallet import multiversx_sdk_cli.cli_validators @@ -142,6 +143,7 @@ def setup_parser(args: list[str]): commands.append(multiversx_sdk_cli.cli_governance.setup_parser(args, subparsers)) commands.append(multiversx_sdk_cli.cli_config_env.setup_parser(subparsers)) commands.append(multiversx_sdk_cli.cli_get.setup_parser(subparsers)) + commands.append(multiversx_sdk_cli.cli_token.setup_parser(args, subparsers)) parser.epilog = """ ---------------------- diff --git a/multiversx_sdk_cli/cli_token.py b/multiversx_sdk_cli/cli_token.py new file mode 100644 index 00000000..7ace42a7 --- /dev/null +++ b/multiversx_sdk_cli/cli_token.py @@ -0,0 +1,53 @@ +from typing import Any + +from multiversx_sdk_cli import cli_shared +from multiversx_sdk_cli.cli_output import CLIOutputBuilder +from multiversx_sdk_cli.cli_transactions import _add_common_arguments + + +def setup_parser(args: list[str], subparsers: Any) -> Any: + parser = cli_shared.add_group_subparser(subparsers, "token", "Perform operations with tokens") + subparsers = parser.add_subparsers() + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "issue-fungible", + f"Issue a new fungible ESDT token.{CLIOutputBuilder.describe()}", + ) + sub.add_argument( + "--token-name", + required=True, + type=str, + help="the name of the token to be issued: 3-20 alphanumerical characters", + ) + sub.add_argument( + "--token-ticker", + required=True, + type=str, + help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", + ) + sub.add_argument("--initial-supply", required=True, type=int, help="the initial supply of the token to be issued") + sub.add_argument( + "--num-decimals", + required=True, + type=int, + help="a numerical value between 0 and 18 representing number of decimals", + ) + sub.add_argument("--can-freeze", type=bool, help="whether a token can be freezed") + sub.add_argument("--can-wipe", type=bool, help="whether a token can be wiped") + sub.add_argument("--can-pause", type=bool, help="whether a token can be paused") + sub.add_argument("--can-change-owner", type=bool, help="whether a token can change owner") + sub.add_argument("--can-upgrade", type=bool, help="whether a token can be upgraded") + sub.add_argument("--can-add_special-roles", type=bool, help="whether special roles can be added for the token") + + _add_common_arguments(args, sub) + cli_shared.add_broadcast_args(sub) + cli_shared.add_proxy_arg(sub) + cli_shared.add_wait_result_and_timeout_args(sub) + + sub.set_defaults(func=issue_fungible) + + +def issue_fungible(arg: Any): + pass From cb5d4723d2d56d0bce21cf91987720df3f195320 Mon Sep 17 00:00:00 2001 From: Lara Tifui Date: Mon, 8 Sep 2025 06:37:47 +0200 Subject: [PATCH 02/33] added token wraper and issue fungible --- multiversx_sdk_cli/cli_token.py | 56 ++++++++++++++++++++++- multiversx_sdk_cli/token.py | 79 +++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 multiversx_sdk_cli/token.py diff --git a/multiversx_sdk_cli/cli_token.py b/multiversx_sdk_cli/cli_token.py index 7ace42a7..7746c9d4 100644 --- a/multiversx_sdk_cli/cli_token.py +++ b/multiversx_sdk_cli/cli_token.py @@ -1,8 +1,15 @@ from typing import Any +from multiversx_sdk import TransactionsFactoryConfig + from multiversx_sdk_cli import cli_shared +from multiversx_sdk_cli.args_validation import ( + validate_broadcast_args, + validate_chain_id_args, +) from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.cli_transactions import _add_common_arguments +from multiversx_sdk_cli.token import TokenWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -45,9 +52,56 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: cli_shared.add_broadcast_args(sub) cli_shared.add_proxy_arg(sub) cli_shared.add_wait_result_and_timeout_args(sub) + cli_shared.add_guardian_wallet_args(args, sub) + cli_shared.add_relayed_v3_wallet_args(args, sub) + cli_shared.add_outfile_arg(sub) sub.set_defaults(func=issue_fungible) + parser.epilog = cli_shared.build_group_epilog(subparsers) + return subparsers + -def issue_fungible(arg: Any): +def validate_token_args(args: Any): pass + + +def _ensure_args(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + validate_token_args(args) + + +def issue_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokenWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + + transaction = controller.create_transaction_for_issuing_fungible_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + initial_supply=args.initial_supply, + num_decimals=args.num_decimals, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + can_freeze=args.can_freeze if args.can_freeze is not None else True, + can_wipe=args.can_wipe if args.can_wipe is not None else True, + can_pause=args.can_pause if args.can_pause is not None else True, + can_change_owner=args.can_change_owner if args.can_change_owner is not None else True, + can_upgrade=args.can_upgrade if args.can_upgrade is not None else True, + can_add_special_roles=args.can_add_special_roles if args.can_add_special_roles is not None else True, + ) + + cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/token.py b/multiversx_sdk_cli/token.py new file mode 100644 index 00000000..230f373a --- /dev/null +++ b/multiversx_sdk_cli/token.py @@ -0,0 +1,79 @@ +from typing import Optional + +from multiversx_sdk import ( + GasLimitEstimator, + TokenManagementTransactionsFactory, + Transaction, + TransactionsFactoryConfig, +) + +from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount + + +class TokenWrapper(BaseTransactionsController): + def __init__( + self, + config: TransactionsFactoryConfig, + gas_limit_estimator: Optional[GasLimitEstimator] = None, + ) -> None: + self.factory = TokenManagementTransactionsFactory(config=config, gas_limit_estimator=gas_limit_estimator) + + def create_transaction_for_issuing_fungible_token( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + initial_supply: int, + num_decimals: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + can_freeze: bool = True, + can_wipe: bool = True, + can_pause: bool = True, + can_change_owner: bool = True, + can_upgrade: bool = True, + can_add_special_roles: bool = True, + ) -> Transaction: + tx = self.factory.create_transaction_for_issuing_fungible( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + initial_supply=initial_supply, + num_decimals=num_decimals, + can_freeze=can_freeze, + can_wipe=can_wipe, + can_pause=can_pause, + can_change_owner=can_change_owner, + can_upgrade=can_upgrade, + can_add_special_roles=can_add_special_roles, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx From 53b9ad5a49d7bfdc341b49baf4025c636e6639ba Mon Sep 17 00:00:00 2001 From: Lara Tifui Date: Mon, 8 Sep 2025 06:47:39 +0200 Subject: [PATCH 03/33] addition of args validation --- multiversx_sdk_cli/cli_token.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/multiversx_sdk_cli/cli_token.py b/multiversx_sdk_cli/cli_token.py index 7746c9d4..4e397cb0 100644 --- a/multiversx_sdk_cli/cli_token.py +++ b/multiversx_sdk_cli/cli_token.py @@ -63,7 +63,17 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: def validate_token_args(args: Any): - pass + if args.initial_supply < 0: + raise ValueError("Initial supply must be a non-negative integer") + + if not (0 <= args.num_decimals <= 18): + raise ValueError("Number of decimals must be between 0 and 18") + + if not (3 <= len(args.token_name) <= 20) or not args.token_name.isalnum(): + raise ValueError("Token name must be 3-20 alphanumerical characters") + + if not (3 <= len(args.token_ticker) <= 10) or not args.token_ticker.isalnum() or not args.token_ticker.isupper(): + raise ValueError("Token ticker must be 3-10 UPPERCASE alphanumerical characters") def _ensure_args(args: Any): From 94ca7681d8f3c629c94df6118b51c622a48cdf0a Mon Sep 17 00:00:00 2001 From: Lara Tifui Date: Mon, 8 Sep 2025 12:28:38 +0200 Subject: [PATCH 04/33] update after comments --- multiversx_sdk_cli/cli.py | 4 +- .../{cli_token.py => cli_tokens.py} | 52 +++++++++++++------ multiversx_sdk_cli/{token.py => tokens.py} | 12 ++--- 3 files changed, 43 insertions(+), 25 deletions(-) rename multiversx_sdk_cli/{cli_token.py => cli_tokens.py} (68%) rename multiversx_sdk_cli/{token.py => tokens.py} (91%) diff --git a/multiversx_sdk_cli/cli.py b/multiversx_sdk_cli/cli.py index f9eff03e..f6be73cc 100644 --- a/multiversx_sdk_cli/cli.py +++ b/multiversx_sdk_cli/cli.py @@ -23,7 +23,7 @@ import multiversx_sdk_cli.cli_ledger import multiversx_sdk_cli.cli_localnet import multiversx_sdk_cli.cli_multisig -import multiversx_sdk_cli.cli_token +import multiversx_sdk_cli.cli_tokens import multiversx_sdk_cli.cli_transactions import multiversx_sdk_cli.cli_validator_wallet import multiversx_sdk_cli.cli_validators @@ -143,7 +143,7 @@ def setup_parser(args: list[str]): commands.append(multiversx_sdk_cli.cli_governance.setup_parser(args, subparsers)) commands.append(multiversx_sdk_cli.cli_config_env.setup_parser(subparsers)) commands.append(multiversx_sdk_cli.cli_get.setup_parser(subparsers)) - commands.append(multiversx_sdk_cli.cli_token.setup_parser(args, subparsers)) + commands.append(multiversx_sdk_cli.cli_tokens.setup_parser(args, subparsers)) parser.epilog = """ ---------------------- diff --git a/multiversx_sdk_cli/cli_token.py b/multiversx_sdk_cli/cli_tokens.py similarity index 68% rename from multiversx_sdk_cli/cli_token.py rename to multiversx_sdk_cli/cli_tokens.py index 4e397cb0..c1b3ea76 100644 --- a/multiversx_sdk_cli/cli_token.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -8,12 +8,13 @@ validate_chain_id_args, ) from multiversx_sdk_cli.cli_output import CLIOutputBuilder -from multiversx_sdk_cli.cli_transactions import _add_common_arguments -from multiversx_sdk_cli.token import TokenWrapper +from multiversx_sdk_cli.tokens import TokenWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: - parser = cli_shared.add_group_subparser(subparsers, "token", "Perform operations with tokens") + parser = cli_shared.add_group_subparser( + subparsers, "token", "Perform token management operations (issue tokens, create NFTs, set roles, etc.)" + ) subparsers = parser.add_subparsers() sub = cli_shared.add_command_subparser( @@ -41,14 +42,31 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: type=int, help="a numerical value between 0 and 18 representing number of decimals", ) - sub.add_argument("--can-freeze", type=bool, help="whether a token can be freezed") - sub.add_argument("--can-wipe", type=bool, help="whether a token can be wiped") - sub.add_argument("--can-pause", type=bool, help="whether a token can be paused") - sub.add_argument("--can-change-owner", type=bool, help="whether a token can change owner") - sub.add_argument("--can-upgrade", type=bool, help="whether a token can be upgraded") - sub.add_argument("--can-add_special-roles", type=bool, help="whether special roles can be added for the token") - - _add_common_arguments(args, sub) + sub.add_argument( + "--can-freeze", required=True, type=lambda x: x.lower() == "true", help="whether a token can be freezed" + ) + sub.add_argument( + "--can-wipe", required=True, type=lambda x: x.lower() == "true", help="whether a token can be wiped" + ) + sub.add_argument( + "--can-pause", required=True, type=lambda x: x.lower() == "true", help="whether a token can be paused" + ) + sub.add_argument( + "--can-change-owner", required=True, type=lambda x: x.lower() == "true", help="whether a token can change owner" + ) + sub.add_argument( + "--can-upgrade", required=True, type=lambda x: x.lower() == "true", help="whether a token can be upgraded" + ) + sub.add_argument( + "--can-add_special-roles", + required=lambda x: x.lower() == "true", + type=bool, + help="whether special roles can be added for the token", + ) + + cli_shared.add_wallet_args(args, sub) + cli_shared.add_tx_args(args, sub, with_receiver=False, with_data=False) + sub.add_argument("--data-file", type=str, default=None, help="a file containing transaction data") cli_shared.add_broadcast_args(sub) cli_shared.add_proxy_arg(sub) cli_shared.add_wait_result_and_timeout_args(sub) @@ -106,12 +124,12 @@ def issue_fungible(args: Any): version=args.version, options=args.options, guardian_and_relayer_data=guardian_and_relayer_data, - can_freeze=args.can_freeze if args.can_freeze is not None else True, - can_wipe=args.can_wipe if args.can_wipe is not None else True, - can_pause=args.can_pause if args.can_pause is not None else True, - can_change_owner=args.can_change_owner if args.can_change_owner is not None else True, - can_upgrade=args.can_upgrade if args.can_upgrade is not None else True, - can_add_special_roles=args.can_add_special_roles if args.can_add_special_roles is not None else True, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, ) cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/token.py b/multiversx_sdk_cli/tokens.py similarity index 91% rename from multiversx_sdk_cli/token.py rename to multiversx_sdk_cli/tokens.py index 230f373a..a17ed13f 100644 --- a/multiversx_sdk_cli/token.py +++ b/multiversx_sdk_cli/tokens.py @@ -28,17 +28,17 @@ def create_transaction_for_issuing_fungible_token( token_ticker: str, initial_supply: int, num_decimals: int, + can_freeze: bool, + can_wipe: bool, + can_pause: bool, + can_change_owner: bool, + can_upgrade: bool, + can_add_special_roles: bool, gas_limit: Optional[int], gas_price: int, version: int, options: int, guardian_and_relayer_data: GuardianRelayerData, - can_freeze: bool = True, - can_wipe: bool = True, - can_pause: bool = True, - can_change_owner: bool = True, - can_upgrade: bool = True, - can_add_special_roles: bool = True, ) -> Transaction: tx = self.factory.create_transaction_for_issuing_fungible( sender=sender.address, From 920c2a216814ec721fb558268c3ca985f325c78f Mon Sep 17 00:00:00 2001 From: Lara Tifui Date: Mon, 8 Sep 2025 16:41:17 +0200 Subject: [PATCH 05/33] Added semi- & non- fungible issuing implementation + fixes and reformating --- multiversx_sdk_cli/cli_tokens.py | 165 ++++++++++++++++++++++++------- multiversx_sdk_cli/tokens.py | 112 +++++++++++++++++++++ 2 files changed, 244 insertions(+), 33 deletions(-) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index c1b3ea76..e7154201 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -17,12 +17,50 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) subparsers = parser.add_subparsers() + sub = cli_shared.add_command_subparser( + subparsers, "token", "issue-fungible", f"Issue a new fungible ESDT token.{CLIOutputBuilder.describe()}" + ) + sub.add_argument("--initial-supply", required=True, type=int, help="the initial supply of the token to be issued") + add_issuing_tokens_args(args, sub, with_num_decimals=True, with_transfer_nft_create_role=False) + add_common_args(args, sub) + sub.set_defaults(func=issue_fungible) + sub = cli_shared.add_command_subparser( subparsers, "token", - "issue-fungible", - f"Issue a new fungible ESDT token.{CLIOutputBuilder.describe()}", + "issue-semi-fungible", + f"Issue a new semi-fungible ESDT token.{CLIOutputBuilder.describe()}", + ) + add_issuing_tokens_args(args, sub) + add_common_args(args, sub) + sub.set_defaults(func=issue_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "issue-non-fungible", f"Issue a new non-fungible ESDT token.{CLIOutputBuilder.describe()}" ) + add_issuing_tokens_args(args, sub) + add_common_args(args, sub) + sub.set_defaults(func=issue_non_fungible) + + parser.epilog = cli_shared.build_group_epilog(subparsers) + return subparsers + + +def add_common_args(args: list[str], sub: Any): + cli_shared.add_wallet_args(args, sub) + cli_shared.add_tx_args(args, sub, with_receiver=False, with_data=False) + sub.add_argument("--data-file", type=str, default=None, help="a file containing transaction data") + cli_shared.add_broadcast_args(sub) + cli_shared.add_proxy_arg(sub) + cli_shared.add_wait_result_and_timeout_args(sub) + cli_shared.add_guardian_wallet_args(args, sub) + cli_shared.add_relayed_v3_wallet_args(args, sub) + cli_shared.add_outfile_arg(sub) + + +def add_issuing_tokens_args( + args: list[str], sub: Any, with_num_decimals: bool = False, with_transfer_nft_create_role: bool = True +): sub.add_argument( "--token-name", required=True, @@ -35,13 +73,6 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: type=str, help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", ) - sub.add_argument("--initial-supply", required=True, type=int, help="the initial supply of the token to be issued") - sub.add_argument( - "--num-decimals", - required=True, - type=int, - help="a numerical value between 0 and 18 representing number of decimals", - ) sub.add_argument( "--can-freeze", required=True, type=lambda x: x.lower() == "true", help="whether a token can be freezed" ) @@ -59,32 +90,32 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) sub.add_argument( "--can-add_special-roles", - required=lambda x: x.lower() == "true", - type=bool, + required=True, + type=lambda x: x.lower() == "true", help="whether special roles can be added for the token", ) - cli_shared.add_wallet_args(args, sub) - cli_shared.add_tx_args(args, sub, with_receiver=False, with_data=False) - sub.add_argument("--data-file", type=str, default=None, help="a file containing transaction data") - cli_shared.add_broadcast_args(sub) - cli_shared.add_proxy_arg(sub) - cli_shared.add_wait_result_and_timeout_args(sub) - cli_shared.add_guardian_wallet_args(args, sub) - cli_shared.add_relayed_v3_wallet_args(args, sub) - cli_shared.add_outfile_arg(sub) - - sub.set_defaults(func=issue_fungible) - - parser.epilog = cli_shared.build_group_epilog(subparsers) - return subparsers - - -def validate_token_args(args: Any): - if args.initial_supply < 0: + if with_num_decimals: + sub.add_argument( + "--num-decimals", + required=True, + type=int, + help="a numerical value between 0 and 18 representing number of decimals", + ) + if with_transfer_nft_create_role: + sub.add_argument( + "--can-transfer-nft-create-role", + required=True, + type=lambda x: x.lower() == "true", + help="whether nft create roles can be transfered for the token", + ) + + +def validate_token_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): + if with_initial_supply and args.initial_supply < 0: raise ValueError("Initial supply must be a non-negative integer") - if not (0 <= args.num_decimals <= 18): + if with_num_decimals and not (0 <= args.num_decimals <= 18): raise ValueError("Number of decimals must be between 0 and 18") if not (3 <= len(args.token_name) <= 20) or not args.token_name.isalnum(): @@ -94,14 +125,14 @@ def validate_token_args(args: Any): raise ValueError("Token ticker must be 3-10 UPPERCASE alphanumerical characters") -def _ensure_args(args: Any): +def _ensure_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): validate_broadcast_args(args) validate_chain_id_args(args) - validate_token_args(args) + validate_token_args(args, with_initial_supply, with_num_decimals) def issue_fungible(args: Any): - _ensure_args(args) + _ensure_args(args, with_initial_supply=True, with_num_decimals=True) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -133,3 +164,71 @@ def issue_fungible(args: Any): ) cli_shared.send_or_simulate(transaction, args) + + +def issue_semi_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokenWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + + transaction = controller.create_transaction_for_issuing_semi_fungible_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def issue_non_fungible(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokenWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + + transaction = controller.create_transaction_for_issuing_non_fungible_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + ) + + cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/tokens.py b/multiversx_sdk_cli/tokens.py index a17ed13f..2adf7e12 100644 --- a/multiversx_sdk_cli/tokens.py +++ b/multiversx_sdk_cli/tokens.py @@ -77,3 +77,115 @@ def create_transaction_for_issuing_fungible_token( ) return tx + + def create_transaction_for_issuing_semi_fungible_token( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + can_freeze: bool, + can_wipe: bool, + can_pause: bool, + can_transfer_nft_create_role: bool, + can_change_owner: bool, + can_upgrade: bool, + can_add_special_roles: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_issuing_semi_fungible( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + can_freeze=can_freeze, + can_wipe=can_wipe, + can_pause=can_pause, + can_transfer_nft_create_role=can_transfer_nft_create_role, + can_change_owner=can_change_owner, + can_upgrade=can_upgrade, + can_add_special_roles=can_add_special_roles, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_issuing_non_fungible_token( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + can_freeze: bool, + can_wipe: bool, + can_pause: bool, + can_transfer_nft_create_role: bool, + can_change_owner: bool, + can_upgrade: bool, + can_add_special_roles: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_issuing_non_fungible( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + can_freeze=can_freeze, + can_wipe=can_wipe, + can_pause=can_pause, + can_transfer_nft_create_role=can_transfer_nft_create_role, + can_change_owner=can_change_owner, + can_upgrade=can_upgrade, + can_add_special_roles=can_add_special_roles, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx From 0907961c7e59337e91079feb6cf074025a3da64d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 11 Sep 2025 17:00:03 +0300 Subject: [PATCH 06/33] token manangement operations --- multiversx_sdk_cli/cli_tokens.py | 2261 ++++++++++++++++++++++++++++-- multiversx_sdk_cli/tokens.py | 1844 +++++++++++++++++++++++- 2 files changed, 3978 insertions(+), 127 deletions(-) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index e7154201..9dbd899a 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -1,14 +1,13 @@ from typing import Any -from multiversx_sdk import TransactionsFactoryConfig +from multiversx_sdk import Address, TokenType, TransactionsFactoryConfig from multiversx_sdk_cli import cli_shared from multiversx_sdk_cli.args_validation import ( validate_broadcast_args, validate_chain_id_args, ) -from multiversx_sdk_cli.cli_output import CLIOutputBuilder -from multiversx_sdk_cli.tokens import TokenWrapper +from multiversx_sdk_cli.tokens import TokensManagementWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -17,122 +16,2142 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) subparsers = parser.add_subparsers() + sub = cli_shared.add_command_subparser(subparsers, "token", "issue-fungible", "Issue a new fungible ESDT token.") + add_issuing_tokens_args( + sub, + with_initial_supply=True, + with_num_decimals=True, + with_transfer_nft_create_role=False, + ) + add_common_args(args, sub) + sub.set_defaults(func=issue_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "issue-semi-fungible", + "Issue a new semi-fungible ESDT token.", + ) + add_issuing_tokens_args(sub) + add_common_args(args, sub) + sub.set_defaults(func=issue_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "issue-non-fungible", "Issue a new non-fungible ESDT token (NFT)." + ) + add_issuing_tokens_args(sub) + add_common_args(args, sub) + sub.set_defaults(func=issue_non_fungible) + + sub = cli_shared.add_command_subparser(subparsers, "token", "register-meta-esdt", "Register a MetaESDT token.") + add_issuing_tokens_args(sub, with_num_decimals=True) + add_common_args(args, sub) + sub.set_defaults(func=register_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "register-and-set-all-roles", "Register a token and set all roles." + ) + sub.add_argument( + "--token-name", + required=True, + type=str, + help="the name of the token to be issued: 3-20 alphanumerical characters", + ) + sub.add_argument( + "--token-ticker", + required=True, + type=str, + help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", + ) + sub.add_argument( + "--num-decimals", + required=True, + type=int, + help="a numerical value between 0 and 18 representing number of decimals", + ) + sub.add_argument( + "--token-type", + required=True, + type=str, + choices=["NFT", "SFT", "META", "FNG"], + help="the token type", + ) + add_common_args(args, sub) + sub.set_defaults(func=register_and_set_all_roles) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "set-burn-role-globally", "Set the burn role globally for a token." + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_burn_role_globally) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "unset-burn-role-globally", "Unset the burn role globally for a token." + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unset_burn_role_globally) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "set-special-role-fungible", "Set special roles on a fungible token for a user." + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_fungible(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "unset-special-role-fungible", "Unset special roles on a fungible token for a user." + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_fungible(sub) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, "token", "set-special-role-semi-fungible", "Set special roles on a semi-fungible token for a user." + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_semi_fungible(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unset-special-role-semi-fungible", + "Unset special roles on a semi-fungible token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_semi_fungible(sub, with_nft_create=False) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_semi_fungible) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-special-role-meta-esdt", + "Set special roles on a meta-esdt token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_meta_esdt(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unset-special-role-meta-esdt", + "Unset special roles on a meta-esdt token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_meta_esdt(sub, with_nft_create=False) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-special-role-nft", + "Set special roles on a non-fungible token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_nft(sub) + add_common_args(args, sub) + sub.set_defaults(func=set_special_role_on_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unset-special-role-nft", + "Unset special roles on a non-fungible token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + _add_special_roles_args_for_nft(sub) + add_common_args(args, sub) + sub.set_defaults(func=unset_special_role_on_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "create-nft", + "Create a non-fungible token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--initial-quantity", type=int, required=True, help="The initial quantity of the token.") + sub.add_argument("--name", type=str, required=True, help="The name of the token.") + sub.add_argument("--royalties", type=int, required=True, help="The royalties of the token.") + sub.add_argument("--hash", type=str, required=True, help="The hash of the token.") + sub.add_argument("--attributes", type=str, required=True, help="The hex-string attributes of the token.") + sub.add_argument("--uris", nargs="+", required=True, help="The uris of the token.") + add_common_args(args, sub) + sub.set_defaults(func=create_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "pause", + "Pause a token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=pause_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unpause", + "Unpause a token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unpause_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "freeze", + "Freeze a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=freeze_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unfreeze", + "Unfreeze a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unfreeze_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "wipe", + "Wipe a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=wipe_token) + sub = cli_shared.add_command_subparser( - subparsers, "token", "issue-fungible", f"Issue a new fungible ESDT token.{CLIOutputBuilder.describe()}" + subparsers, + "token", + "local-mint", + "Mint new tokens.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--supply-to-mint", required=True, type=int, help="The amount of new tokens to mint") + add_common_args(args, sub) + sub.set_defaults(func=local_mint) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "local-burn", + "Burn tokens.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--supply-to-burn", required=True, type=int, help="The amount of tokens to burn") + add_common_args(args, sub) + sub.set_defaults(func=local_burn) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-attributes", + "Update token attributes.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--attributes", required=True, type=str, help="The hex-string attributes of the token") + add_common_args(args, sub) + sub.set_defaults(func=update_attributes) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "add-quantity", + "Increase token quantity.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--quantity", required=True, type=str, help="The quantity to add") + add_common_args(args, sub) + sub.set_defaults(func=add_quantity) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "burn-quantity", + "Burn token quantity.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--quantity", required=True, type=str, help="The quantity to burn") + add_common_args(args, sub) + sub.set_defaults(func=burn_quantity) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "modify-royalties", + "Modify token royalties.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--royalties", required=True, type=str, help="The new token royalties (e.g. 1234 for 12.34%)") + add_common_args(args, sub) + sub.set_defaults(func=modify_royalties) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-new-uris", + "Set new uris.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=set_new_uris) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "modify-creator", + "Modify the creator of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + add_common_args(args, sub) + sub.set_defaults(func=modify_creator) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-metadata", + "Update the metadata of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") + sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") + sub.add_argument( + "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" + ) + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=update_metadata) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "nft-metadata-recreate", + "Recreate the metadata of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") + sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") + sub.add_argument( + "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" + ) + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=nft_metadata_recreate) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "change-to-dynamic", + "Change a token to a dynamic token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=change_to_dynamic) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-token-id", + "Update token id.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=update_token_id) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "register-dynamic-token", + "Register a dynamic token.", + ) + sub.add_argument("--token-name", type=str, required=True, help="The token name") + sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") + sub.add_argument( + "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" + ) + sub.add_argument( + "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" + ) + add_common_args(args, sub) + sub.set_defaults(func=register_dynamic_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "register-dynamic-and-set-all-roles", + "Register a dynamic token and set all roles.", + ) + sub.add_argument("--token-name", type=str, required=True, help="The token name") + sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") + sub.add_argument( + "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" + ) + sub.add_argument( + "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" + ) + add_common_args(args, sub) + sub.set_defaults(func=register_dynamic_and_set_all_roles) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "transfer-ownership", + "Transfer the ownership of a token to another user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--new-owner", type=str, required=True, help="The new token owner") + add_common_args(args, sub) + sub.set_defaults(func=transfer_ownership) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "freeze-single-nft", + "Freeze the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=freeze_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unfreeze-single-nft", + "Unfreeze the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unfreeze_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "change-sft-to-meta-esdt", + "Change a semi fungible token to a Meta ESDT.", + ) + sub.add_argument("--collection", required=True, type=str, help="The collection identifier") + sub.add_argument("--decimals", type=int, required=True, help="The number of decimals the meta esdt will have") + add_common_args(args, sub) + sub.set_defaults(func=change_sft_to_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "transfer-nft-create-role", + "Transfer the nft create role to a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=transfer_nft_create_role) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "stop-nft-creation", + "Stop the creation of new NFTs.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=stop_nft_creation) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "wipe-single-nft", + "Wipe the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=wipe_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "add-uris", + "Add uris for a token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") + sub.add_argument("--uris", nargs="+", required=True, help="The new uris to be added to the token.") + add_common_args(args, sub) + sub.set_defaults(func=add_uris) + + parser.epilog = cli_shared.build_group_epilog(subparsers) + return subparsers + + +def add_common_args(args: list[str], sub: Any): + cli_shared.add_wallet_args(args, sub) + cli_shared.add_tx_args(args, sub, with_receiver=False, with_data=False) + cli_shared.add_proxy_arg(sub) + cli_shared.add_broadcast_args(sub) + cli_shared.add_wait_result_and_timeout_args(sub) + cli_shared.add_guardian_wallet_args(args, sub) + cli_shared.add_relayed_v3_wallet_args(args, sub) + cli_shared.add_outfile_arg(sub) + + +def add_issuing_tokens_args( + sub: Any, + with_initial_supply: bool = False, + with_num_decimals: bool = False, + with_transfer_nft_create_role: bool = True, +): + sub.add_argument( + "--token-name", + required=True, + type=str, + help="the name of the token to be issued: 3-20 alphanumerical characters", + ) + sub.add_argument( + "--token-ticker", + required=True, + type=str, + help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", + ) + + if with_initial_supply: + sub.add_argument( + "--initial-supply", required=True, type=int, help="the initial supply of the token to be issued" + ) + + if with_num_decimals: + sub.add_argument( + "--num-decimals", + required=True, + type=int, + help="a numerical value between 0 and 18 representing number of decimals", + ) + + sub.add_argument( + "--can-freeze", required=True, type=lambda x: x.lower() == "true", help="whether a token can be freezed" + ) + sub.add_argument( + "--can-wipe", required=True, type=lambda x: x.lower() == "true", help="whether a token can be wiped" + ) + sub.add_argument( + "--can-pause", required=True, type=lambda x: x.lower() == "true", help="whether a token can be paused" + ) + sub.add_argument( + "--can-change-owner", required=True, type=lambda x: x.lower() == "true", help="whether a token can change owner" + ) + sub.add_argument( + "--can-upgrade", required=True, type=lambda x: x.lower() == "true", help="whether a token can be upgraded" + ) + sub.add_argument( + "--can-add_special-roles", + required=True, + type=lambda x: x.lower() == "true", + help="whether special roles can be added for the token", + ) + + if with_transfer_nft_create_role: + sub.add_argument( + "--can-transfer-nft-create-role", + required=True, + type=lambda x: x.lower() == "true", + help="whether nft create roles can be transfered for the token", + ) + + +def _add_token_identifier_arg(sub: Any): + sub.add_argument("--identifier", required=True, type=str, help="the token identifier") + + +def _add_user_arg(sub: Any): + sub.add_argument("--user", required=True, type=str, help="the bech32 address of the user") + + +def _add_special_roles_args_for_fungible(sub: Any): + sub.add_argument( + "--local-mint", + action="store_true", + default=False, + help="role for local minting", + ) + sub.add_argument( + "--local-burn", + action="store_true", + default=False, + help="role for local burning", + ) + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + + +def _add_special_roles_args_for_meta_esdt(sub: Any, with_nft_create: bool = True): + if with_nft_create: + sub.add_argument( + "--nft-create", + action="store_true", + default=False, + help="role for nft create", + ) + + sub.add_argument( + "--nft-burn", + action="store_true", + default=False, + help="role for nft burn", + ) + sub.add_argument( + "--nft-add-quantity", + action="store_true", + default=False, + help="role for adding quantity", + ) + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + + +def _add_special_roles_args_for_nft(sub: Any, with_nft_create: bool = True): + if with_nft_create: + sub.add_argument( + "--nft-create", + action="store_true", + default=False, + help="role for nft create", + ) + + sub.add_argument( + "--nft-burn", + action="store_true", + default=False, + help="role for nft burn", + ) + sub.add_argument( + "--nft-update-attributes", + action="store_true", + default=False, + help="role for updating attributes", + ) + + sub.add_argument( + "--nft-add-uri", + action="store_true", + default=False, + help="role for adding uri", + ) + + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + + sub.add_argument( + "--nft-update", + action="store_true", + default=False, + help="role for updating nft", + ) + + sub.add_argument( + "--esdt-modify-royalties", + action="store_true", + default=False, + help="role for modifying royalties", + ) + + sub.add_argument( + "--esdt-set-new-uri", + action="store_true", + default=False, + help="role for setting new uri", + ) + + sub.add_argument( + "--esdt-modify-creator", + action="store_true", + default=False, + help="role for modifying creator", + ) + + sub.add_argument( + "--nft-recreate", + action="store_true", + default=False, + help="role for recreating nft", + ) + + +def _add_special_roles_args_for_semi_fungible(sub: Any, with_nft_create: bool = True): + if with_nft_create: + sub.add_argument( + "--nft-create", + action="store_true", + default=False, + help="role for nft create", + ) + + sub.add_argument( + "--nft-burn", + action="store_true", + default=False, + help="role for nft burn", + ) + sub.add_argument( + "--nft-add-quantity", + action="store_true", + default=False, + help="role for adding quantity", + ) + sub.add_argument( + "--esdt-transfer-role", + action="store_true", + default=False, + help="role for esdt transfer", + ) + sub.add_argument( + "--nft-update", + action="store_true", + default=False, + help="role for updating nft", + ) + sub.add_argument( + "--esdt-modify-royalties", + action="store_true", + default=False, + help="role for modifying royalties", + ) + sub.add_argument( + "--esdt-set-new-uri", + action="store_true", + default=False, + help="role for setting new uri", + ) + sub.add_argument( + "--esdt-modify-creator", + action="store_true", + default=False, + help="role for modifying creator", + ) + sub.add_argument( + "--nft-recreate", + action="store_true", + default=False, + help="role for recreating nft", + ) + + +def validate_token_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): + if with_initial_supply and args.initial_supply < 0: + raise ValueError("Initial supply must be a non-negative integer") + + if with_num_decimals and not (0 <= args.num_decimals <= 18): + raise ValueError("Number of decimals must be between 0 and 18") + + if not (3 <= len(args.token_name) <= 20) or not args.token_name.isalnum(): + raise ValueError("Token name must be 3-20 alphanumerical characters") + + if not (3 <= len(args.token_ticker) <= 10) or not args.token_ticker.isalnum() or not args.token_ticker.isupper(): + raise ValueError("Token ticker must be 3-10 UPPERCASE alphanumerical characters") + + +def _ensure_issue_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): + validate_broadcast_args(args) + validate_chain_id_args(args) + validate_token_args(args, with_initial_supply, with_num_decimals) + + +def issue_fungible(args: Any): + _ensure_issue_args(args, with_initial_supply=True, with_num_decimals=True) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_issuing_fungible_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + initial_supply=args.initial_supply, + num_decimals=args.num_decimals, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def issue_semi_fungible(args: Any): + _ensure_issue_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_issuing_semi_fungible_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def issue_non_fungible(args: Any): + _ensure_issue_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_issuing_non_fungible_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def register_meta_esdt(args: Any): + _ensure_issue_args(args, with_num_decimals=True) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_registering_meta_esdt( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + decimals=args.num_decimals, + can_freeze=args.can_freeze, + can_wipe=args.can_wipe, + can_pause=args.can_pause, + can_transfer_nft_create_role=args.can_transfer_nft_create_role, + can_change_owner=args.can_change_owner, + can_upgrade=args.can_upgrade, + can_add_special_roles=args.can_add_special_roles, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def register_and_set_all_roles(args: Any): + _ensure_issue_args(args, with_num_decimals=True) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + [token_type] = [type for type in TokenType if args.token_type == type.value] + + transaction = controller.create_transaction_for_registering_and_set_all_roles( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + decimals=args.num_decimals, + token_type=token_type, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def set_burn_role_globally(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_setting_burn_role_globally( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unset_burn_role_globally(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unsetting_burn_role_globally( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_fungible(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_setting_special_role_on_fungible( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_local_mint=args.local_mint, + add_role_local_burn=args.local_burn, + add_role_esdt_transfer_role=args.esdt_transfer_role, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_fungible(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unsetting_special_role_on_fungible( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_local_mint=args.local_mint, + remove_role_local_burn=args.local_burn, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_semi_fungible(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_setting_special_role_on_semi_fungible( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_nft_create=args.nft_create, + add_role_nft_burn=args.nft_burn, + add_role_nft_add_quantity=args.nft_add_quantity, + add_role_esdt_transfer_role=args.esdt_transfer_role, + add_role_nft_update=args.nft_update, + add_role_esdt_modify_royalties=args.esdt_modify_royalties, + add_role_esdt_set_new_uri=args.esdt_set_new_uri, + add_role_esdt_modify_creator=args.esdt_modify_creator, + add_role_nft_recreate=args.nft_recreate, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_semi_fungible(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unsetting_special_role_on_semi_fungible( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_nft_burn=args.nft_burn, + remove_role_nft_add_quantity=args.nft_add_quantity, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + remove_role_nft_update=args.nft_update, + remove_role_esdt_modify_royalties=args.esdt_modify_royalties, + remove_role_esdt_set_new_uri=args.esdt_set_new_uri, + remove_role_esdt_modify_creator=args.esdt_modify_creator, + remove_role_nft_recreate=args.nft_recreate, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_meta_esdt(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_setting_special_role_on_meta_esdt( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_nft_create=args.nft_create, + add_role_nft_burn=args.nft_burn, + add_role_nft_add_quantity=args.nft_add_quantity, + add_role_esdt_transfer_role=args.esdt_transfer_role, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_meta_esdt(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unsetting_special_role_on_meta_esdt( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_nft_burn=args.nft_burn, + remove_role_nft_add_quantity=args.nft_add_quantity, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def set_special_role_on_nft(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_setting_special_role_on_non_fungible( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + add_role_nft_create=args.nft_create, + add_role_nft_burn=args.nft_burn, + add_role_nft_update_attributes=args.nft_update_attributes, + add_role_nft_add_uri=args.nft_add_uri, + add_role_esdt_transfer_role=args.esdt_transfer_role, + add_role_nft_update=args.nft_update, + add_role_esdt_modify_royalties=args.esdt_modify_royalties, + add_role_esdt_set_new_uri=args.esdt_set_new_uri, + add_role_esdt_modify_creator=args.esdt_modify_creator, + add_role_nft_recreate=args.nft_recreate, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unset_special_role_on_nft(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unsetting_special_role_on_non_fungible( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + remove_role_nft_burn=args.nft_burn, + remove_role_nft_update_attributes=args.nft_update_attributes, + remove_role_nft_add_uri=args.nft_add_uri, + remove_role_esdt_transfer_role=args.esdt_transfer_role, + remove_role_nft_update=args.nft_update, + remove_role_esdt_modify_royalties=args.esdt_modify_royalties, + remove_role_esdt_set_new_uri=args.esdt_set_new_uri, + remove_role_esdt_modify_creator=args.esdt_modify_creator, + remove_role_nft_recreate=args.nft_recreate, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def create_nft(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_creating_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + initial_quantity=args.initial_quantity, + name=args.name, + royalties=args.royalties, + hash=args.hash, + attributes=bytes.fromhex(args.attributes), + uris=args.uris, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def pause_token(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_pausing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unpause_token(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unpausing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def freeze_token(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_freezing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def unfreeze_token(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_unfreezing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def wipe_token(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_wiping( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def local_mint(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_local_minting( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + supply_to_mint=args.supply_to_mint, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def local_burn(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_local_burning( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + supply_to_burn=args.supply_to_burn, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def update_attributes(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_updating_attributes( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + attributes=bytes.fromhex(args.attributes), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def add_quantity(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_adding_quantity( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + quantity=args.quantity, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def burn_quantity(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_burning_quantity( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + quantity=args.quantity, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def modify_royalties(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_modifying_royalties( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + royalties=args.royalties, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def set_new_uris(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_setting_new_uris( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + uris=args.uris, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def modify_creator(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_modifying_creator( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def update_metadata(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_updating_metadata( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_token_name=args.token_name, + new_royalties=args.royalties, + new_hash=args.hash, + new_attributes=bytes.fromhex(args.attributes), + new_uris=args.uris, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def nft_metadata_recreate(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_recreating_metadata( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_token_name=args.token_name, + new_royalties=args.royalties, + new_hash=args.hash, + new_attributes=bytes.fromhex(args.attributes), + new_uris=args.uris, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def change_to_dynamic(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_changing_token_to_dynamic( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def update_token_id(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) + + transaction = controller.create_transaction_for_updating_token_id( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def register_dynamic_token(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, ) - sub.add_argument("--initial-supply", required=True, type=int, help="the initial supply of the token to be issued") - add_issuing_tokens_args(args, sub, with_num_decimals=True, with_transfer_nft_create_role=False) - add_common_args(args, sub) - sub.set_defaults(func=issue_fungible) - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "issue-semi-fungible", - f"Issue a new semi-fungible ESDT token.{CLIOutputBuilder.describe()}", + [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + transaction = controller.create_transaction_for_registering_dynamic_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + token_type=token_type, + denominator=args.denominator, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, ) - add_issuing_tokens_args(args, sub) - add_common_args(args, sub) - sub.set_defaults(func=issue_semi_fungible) - sub = cli_shared.add_command_subparser( - subparsers, "token", "issue-non-fungible", f"Issue a new non-fungible ESDT token.{CLIOutputBuilder.describe()}" + cli_shared.send_or_simulate(transaction, args) + + +def register_dynamic_and_set_all_roles(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, ) - add_issuing_tokens_args(args, sub) - add_common_args(args, sub) - sub.set_defaults(func=issue_non_fungible) - parser.epilog = cli_shared.build_group_epilog(subparsers) - return subparsers + [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + transaction = controller.create_transaction_for_registering_dynamic_and_setting_roles( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + token_type=token_type, + denominator=args.denominator, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) -def add_common_args(args: list[str], sub: Any): - cli_shared.add_wallet_args(args, sub) - cli_shared.add_tx_args(args, sub, with_receiver=False, with_data=False) - sub.add_argument("--data-file", type=str, default=None, help="a file containing transaction data") - cli_shared.add_broadcast_args(sub) - cli_shared.add_proxy_arg(sub) - cli_shared.add_wait_result_and_timeout_args(sub) - cli_shared.add_guardian_wallet_args(args, sub) - cli_shared.add_relayed_v3_wallet_args(args, sub) - cli_shared.add_outfile_arg(sub) +def transfer_ownership(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) -def add_issuing_tokens_args( - args: list[str], sub: Any, with_num_decimals: bool = False, with_transfer_nft_create_role: bool = True -): - sub.add_argument( - "--token-name", - required=True, - type=str, - help="the name of the token to be issued: 3-20 alphanumerical characters", + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, ) - sub.add_argument( - "--token-ticker", - required=True, - type=str, - help="the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical characters", + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, ) - sub.add_argument( - "--can-freeze", required=True, type=lambda x: x.lower() == "true", help="whether a token can be freezed" + + transaction = controller.create_transaction_for_transferring_ownership( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + new_owner=Address.new_from_bech32(args.new_owner), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, ) - sub.add_argument( - "--can-wipe", required=True, type=lambda x: x.lower() == "true", help="whether a token can be wiped" + + cli_shared.send_or_simulate(transaction, args) + + +def freeze_single_nft(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, ) - sub.add_argument( - "--can-pause", required=True, type=lambda x: x.lower() == "true", help="whether a token can be paused" + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, ) - sub.add_argument( - "--can-change-owner", required=True, type=lambda x: x.lower() == "true", help="whether a token can change owner" + + transaction = controller.create_transaction_for_freezing_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, ) - sub.add_argument( - "--can-upgrade", required=True, type=lambda x: x.lower() == "true", help="whether a token can be upgraded" + + cli_shared.send_or_simulate(transaction, args) + + +def unfreeze_single_nft(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, ) - sub.add_argument( - "--can-add_special-roles", - required=True, - type=lambda x: x.lower() == "true", - help="whether special roles can be added for the token", + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, ) - if with_num_decimals: - sub.add_argument( - "--num-decimals", - required=True, - type=int, - help="a numerical value between 0 and 18 representing number of decimals", - ) - if with_transfer_nft_create_role: - sub.add_argument( - "--can-transfer-nft-create-role", - required=True, - type=lambda x: x.lower() == "true", - help="whether nft create roles can be transfered for the token", - ) + transaction = controller.create_transaction_for_unfreezing_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + cli_shared.send_or_simulate(transaction, args) -def validate_token_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): - if with_initial_supply and args.initial_supply < 0: - raise ValueError("Initial supply must be a non-negative integer") - if with_num_decimals and not (0 <= args.num_decimals <= 18): - raise ValueError("Number of decimals must be between 0 and 18") +def change_sft_to_meta_esdt(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) - if not (3 <= len(args.token_name) <= 20) or not args.token_name.isalnum(): - raise ValueError("Token name must be 3-20 alphanumerical characters") + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) - if not (3 <= len(args.token_ticker) <= 10) or not args.token_ticker.isalnum() or not args.token_ticker.isupper(): - raise ValueError("Token ticker must be 3-10 UPPERCASE alphanumerical characters") + transaction = controller.create_transaction_for_changing_sft_to_meta_esdt( + sender=sender, + nonce=sender.nonce, + collection_identifier=args.collection, + decimals=args.decimals, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) -def _ensure_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): +def transfer_nft_create_role(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) - validate_token_args(args, with_initial_supply, with_num_decimals) + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) -def issue_fungible(args: Any): - _ensure_args(args, with_initial_supply=True, with_num_decimals=True) + transaction = controller.create_transaction_for_transferring_nft_create_role( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + gas_limit=args.gas_limit, + gas_price=args.gas_price, + version=args.version, + options=args.options, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + cli_shared.send_or_simulate(transaction, args) + + +def stop_nft_creation(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -141,33 +2160,28 @@ def issue_fungible(args: Any): ) chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokenWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) - transaction = controller.create_transaction_for_issuing_fungible_token( + transaction = controller.create_transaction_for_stopping_nft_creation( sender=sender, nonce=sender.nonce, - token_name=args.token_name, - token_ticker=args.token_ticker, - initial_supply=args.initial_supply, - num_decimals=args.num_decimals, + token_identifier=args.token_identifier, gas_limit=args.gas_limit, gas_price=args.gas_price, version=args.version, options=args.options, guardian_and_relayer_data=guardian_and_relayer_data, - can_freeze=args.can_freeze, - can_wipe=args.can_wipe, - can_pause=args.can_pause, - can_change_owner=args.can_change_owner, - can_upgrade=args.can_upgrade, - can_add_special_roles=args.can_add_special_roles, ) cli_shared.send_or_simulate(transaction, args) -def issue_semi_fungible(args: Any): - _ensure_args(args) +def wipe_single_nft(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -176,32 +2190,30 @@ def issue_semi_fungible(args: Any): ) chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokenWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) - transaction = controller.create_transaction_for_issuing_semi_fungible_token( + transaction = controller.create_transaction_for_wiping_single_nft( sender=sender, nonce=sender.nonce, - token_name=args.token_name, - token_ticker=args.token_ticker, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), gas_limit=args.gas_limit, gas_price=args.gas_price, version=args.version, options=args.options, guardian_and_relayer_data=guardian_and_relayer_data, - can_freeze=args.can_freeze, - can_wipe=args.can_wipe, - can_pause=args.can_pause, - can_transfer_nft_create_role=args.can_transfer_nft_create_role, - can_change_owner=args.can_change_owner, - can_upgrade=args.can_upgrade, - can_add_special_roles=args.can_add_special_roles, ) cli_shared.send_or_simulate(transaction, args) -def issue_non_fungible(args: Any): - _ensure_args(args) +def add_uris(args: Any): + validate_broadcast_args(args) + validate_chain_id_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -210,25 +2222,22 @@ def issue_non_fungible(args: Any): ) chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokenWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = TokensManagementWrapper( + config=TransactionsFactoryConfig(chain_id), + gas_limit_estimator=gas_estimator, + ) - transaction = controller.create_transaction_for_issuing_non_fungible_token( + transaction = controller.create_transaction_for_adding_uris( sender=sender, nonce=sender.nonce, - token_name=args.token_name, - token_ticker=args.token_ticker, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + uris=args.uris, gas_limit=args.gas_limit, gas_price=args.gas_price, version=args.version, options=args.options, guardian_and_relayer_data=guardian_and_relayer_data, - can_freeze=args.can_freeze, - can_wipe=args.can_wipe, - can_pause=args.can_pause, - can_transfer_nft_create_role=args.can_transfer_nft_create_role, - can_change_owner=args.can_change_owner, - can_upgrade=args.can_upgrade, - can_add_special_roles=args.can_add_special_roles, ) cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/tokens.py b/multiversx_sdk_cli/tokens.py index 2adf7e12..1b2beeec 100644 --- a/multiversx_sdk_cli/tokens.py +++ b/multiversx_sdk_cli/tokens.py @@ -1,8 +1,10 @@ from typing import Optional from multiversx_sdk import ( + Address, GasLimitEstimator, TokenManagementTransactionsFactory, + TokenType, Transaction, TransactionsFactoryConfig, ) @@ -12,7 +14,7 @@ from multiversx_sdk_cli.interfaces import IAccount -class TokenWrapper(BaseTransactionsController): +class TokensManagementWrapper(BaseTransactionsController): def __init__( self, config: TransactionsFactoryConfig, @@ -189,3 +191,1843 @@ def create_transaction_for_issuing_non_fungible_token( ) return tx + + def create_transaction_for_registering_meta_esdt( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + decimals: int, + can_freeze: bool, + can_wipe: bool, + can_pause: bool, + can_transfer_nft_create_role: bool, + can_change_owner: bool, + can_upgrade: bool, + can_add_special_roles: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_registering_meta_esdt( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + num_decimals=decimals, + can_freeze=can_freeze, + can_wipe=can_wipe, + can_pause=can_pause, + can_transfer_nft_create_role=can_transfer_nft_create_role, + can_change_owner=can_change_owner, + can_upgrade=can_upgrade, + can_add_special_roles=can_add_special_roles, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_registering_and_set_all_roles( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + decimals: int, + token_type: TokenType, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_registering_and_setting_roles( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + num_decimals=decimals, + token_type=token_type, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_setting_burn_role_globally( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_setting_burn_role_globally( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unsetting_burn_role_globally( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unsetting_burn_role_globally( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_setting_special_role_on_fungible( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + add_role_local_mint: bool, + add_role_local_burn: bool, + add_role_esdt_transfer_role: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_setting_special_role_on_fungible_token( + sender=sender.address, + token_identifier=token_identifier, + user=user, + add_role_local_mint=add_role_local_mint, + add_role_local_burn=add_role_local_burn, + add_role_esdt_transfer_role=add_role_esdt_transfer_role, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unsetting_special_role_on_fungible( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + remove_role_local_mint: bool, + remove_role_local_burn: bool, + remove_role_esdt_transfer_role: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unsetting_special_role_on_fungible_token( + sender=sender.address, + token_identifier=token_identifier, + user=user, + remove_role_local_mint=remove_role_local_mint, + remove_role_local_burn=remove_role_local_burn, + remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_setting_special_role_on_semi_fungible( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + add_role_nft_create: bool, + add_role_nft_burn: bool, + add_role_nft_add_quantity: bool, + add_role_esdt_transfer_role: bool, + add_role_nft_update: bool, + add_role_esdt_modify_royalties: bool, + add_role_esdt_set_new_uri: bool, + add_role_esdt_modify_creator: bool, + add_role_nft_recreate: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_setting_special_role_on_semi_fungible_token( + sender=sender.address, + token_identifier=token_identifier, + user=user, + add_role_nft_create=add_role_nft_create, + add_role_nft_burn=add_role_nft_burn, + add_role_nft_add_quantity=add_role_nft_add_quantity, + add_role_esdt_transfer_role=add_role_esdt_transfer_role, + add_role_nft_update=add_role_nft_update, + add_role_esdt_modify_royalties=add_role_esdt_modify_royalties, + add_role_esdt_set_new_uri=add_role_esdt_set_new_uri, + add_role_esdt_modify_creator=add_role_esdt_modify_creator, + add_role_nft_recreate=add_role_nft_recreate, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unsetting_special_role_on_semi_fungible( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + remove_role_nft_burn: bool, + remove_role_nft_add_quantity: bool, + remove_role_esdt_transfer_role: bool, + remove_role_nft_update: bool, + remove_role_esdt_modify_royalties: bool, + remove_role_esdt_set_new_uri: bool, + remove_role_esdt_modify_creator: bool, + remove_role_nft_recreate: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unsetting_special_role_on_semi_fungible_token( + sender=sender.address, + token_identifier=token_identifier, + user=user, + remove_role_nft_burn=remove_role_nft_burn, + remove_role_nft_add_quantity=remove_role_nft_add_quantity, + remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, + remove_role_nft_update=remove_role_nft_update, + remove_role_esdt_modify_royalties=remove_role_esdt_modify_royalties, + remove_role_esdt_set_new_uri=remove_role_esdt_set_new_uri, + remove_role_esdt_modify_creator=remove_role_esdt_modify_creator, + remove_role_nft_recreate=remove_role_nft_recreate, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_setting_special_role_on_meta_esdt( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + add_role_nft_create: bool, + add_role_nft_burn: bool, + add_role_nft_add_quantity: bool, + add_role_esdt_transfer_role: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_setting_special_role_on_meta_esdt( + sender=sender.address, + token_identifier=token_identifier, + user=user, + add_role_nft_create=add_role_nft_create, + add_role_nft_burn=add_role_nft_burn, + add_role_nft_add_quantity=add_role_nft_add_quantity, + add_role_esdt_transfer_role=add_role_esdt_transfer_role, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unsetting_special_role_on_meta_esdt( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + remove_role_nft_burn: bool, + remove_role_nft_add_quantity: bool, + remove_role_esdt_transfer_role: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unsetting_special_role_on_meta_esdt( + sender=sender.address, + token_identifier=token_identifier, + user=user, + remove_role_nft_burn=remove_role_nft_burn, + remove_role_nft_add_quantity=remove_role_nft_add_quantity, + remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_setting_special_role_on_non_fungible( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + add_role_nft_create: bool, + add_role_nft_burn: bool, + add_role_nft_update_attributes: bool, + add_role_nft_add_uri: bool, + add_role_esdt_transfer_role: bool, + add_role_nft_update: bool, + add_role_esdt_modify_royalties: bool, + add_role_esdt_set_new_uri: bool, + add_role_esdt_modify_creator: bool, + add_role_nft_recreate: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_setting_special_role_on_non_fungible_token( + sender=sender.address, + token_identifier=token_identifier, + user=user, + add_role_nft_create=add_role_nft_create, + add_role_nft_burn=add_role_nft_burn, + add_role_nft_update_attributes=add_role_nft_update_attributes, + add_role_nft_add_uri=add_role_nft_add_uri, + add_role_esdt_transfer_role=add_role_esdt_transfer_role, + add_role_nft_update=add_role_nft_update, + add_role_esdt_modify_royalties=add_role_esdt_modify_royalties, + add_role_esdt_set_new_uri=add_role_esdt_set_new_uri, + add_role_esdt_modify_creator=add_role_esdt_modify_creator, + add_role_nft_recreate=add_role_nft_recreate, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unsetting_special_role_on_non_fungible( + self, + sender: IAccount, + nonce: int, + user: Address, + token_identifier: str, + remove_role_nft_burn: bool, + remove_role_nft_update_attributes: bool, + remove_role_nft_add_uri: bool, + remove_role_esdt_transfer_role: bool, + remove_role_nft_update: bool, + remove_role_esdt_modify_royalties: bool, + remove_role_esdt_set_new_uri: bool, + remove_role_esdt_modify_creator: bool, + remove_role_nft_recreate: bool, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unsetting_special_role_on_non_fungible_token( + sender=sender.address, + token_identifier=token_identifier, + user=user, + remove_role_nft_burn=remove_role_nft_burn, + remove_role_nft_update_attributes=remove_role_nft_update_attributes, + remove_role_nft_remove_uri=remove_role_nft_add_uri, + remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, + remove_role_nft_update=remove_role_nft_update, + remove_role_esdt_modify_royalties=remove_role_esdt_modify_royalties, + remove_role_esdt_set_new_uri=remove_role_esdt_set_new_uri, + remove_role_esdt_modify_creator=remove_role_esdt_modify_creator, + remove_role_nft_recreate=remove_role_nft_recreate, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_creating_nft( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + initial_quantity: int, + name: str, + royalties: int, + hash: str, + attributes: bytes, + uris: list[str], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_creating_nft( + sender=sender.address, + token_identifier=token_identifier, + initial_quantity=initial_quantity, + name=name, + royalties=royalties, + hash=hash, + attributes=attributes, + uris=uris, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_pausing( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_pausing( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unpausing( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unpausing( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_freezing( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_freezing( + sender=sender.address, + token_identifier=token_identifier, + user=user, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unfreezing( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unfreezing( + sender=sender.address, + token_identifier=token_identifier, + user=user, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_wiping( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_wiping( + sender=sender.address, + user=user, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_local_minting( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + supply_to_mint: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_local_minting( + sender=sender.address, + token_identifier=token_identifier, + supply_to_mint=supply_to_mint, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_local_burning( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + supply_to_burn: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_local_burning( + sender=sender.address, + token_identifier=token_identifier, + supply_to_burn=supply_to_burn, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_updating_attributes( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + attributes: bytes, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_updating_attributes( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + attributes=attributes, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_adding_quantity( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + quantity: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_adding_quantity( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + quantity_to_add=quantity, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_burning_quantity( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + quantity: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_burning_quantity( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + quantity_to_burn=quantity, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_modifying_royalties( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + royalties: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_modifying_royalties( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + new_royalties=royalties, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_setting_new_uris( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + uris: list[str], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_setting_new_uris( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + new_uris=uris, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_modifying_creator( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_modifying_creator( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_updating_metadata( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + new_token_name: str, + new_royalties: int, + new_hash: str, + new_attributes: bytes, + new_uris: list[str], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_updating_metadata( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + new_token_name=new_token_name, + new_royalties=new_royalties, + new_hash=new_hash, + new_attributes=new_attributes, + new_uris=new_uris, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_recreating_metadata( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + new_token_name: str, + new_royalties: int, + new_hash: str, + new_attributes: bytes, + new_uris: list[str], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_nft_metadata_recreate( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + new_token_name=new_token_name, + new_royalties=new_royalties, + new_hash=new_hash, + new_attributes=new_attributes, + new_uris=new_uris, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_changing_token_to_dynamic( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_changing_token_to_dynamic( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_updating_token_id( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_updating_token_id( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_registering_dynamic_token( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + token_type: TokenType, + denominator: Optional[int], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_registering_dynamic_token( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + token_type=token_type, + denominator=denominator, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_registering_dynamic_and_setting_roles( + self, + sender: IAccount, + nonce: int, + token_name: str, + token_ticker: str, + token_type: TokenType, + denominator: Optional[int], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_registering_dynamic_and_setting_roles( + sender=sender.address, + token_name=token_name, + token_ticker=token_ticker, + token_type=token_type, + denominator=denominator, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_transferring_ownership( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + new_owner: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_transferring_ownership( + sender=sender.address, + token_identifier=token_identifier, + new_owner=new_owner, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_freezing_single_nft( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_freezing_single_nft( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + user=user, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_unfreezing_single_nft( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_unfreezing_single_nft( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + user=user, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_changing_sft_to_meta_esdt( + self, + sender: IAccount, + nonce: int, + collection_identifier: str, + decimals: int, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_changing_sft_to_meta_esdt( + sender=sender.address, + collection=collection_identifier, + num_decimals=decimals, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_transferring_nft_create_role( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_transferring_nft_create_role( + sender=sender.address, + token_identifier=token_identifier, + user=user, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_stopping_nft_creation( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_stopping_nft_creation( + sender=sender.address, + token_identifier=token_identifier, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_wiping_single_nft( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + user: Address, + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transaction_for_wiping_single_nft( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + user=user, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx + + def create_transaction_for_adding_uris( + self, + sender: IAccount, + nonce: int, + token_identifier: str, + token_nonce: int, + uris: list[str], + gas_limit: Optional[int], + gas_price: int, + version: int, + options: int, + guardian_and_relayer_data: GuardianRelayerData, + ) -> Transaction: + tx = self.factory.create_transction_for_adding_uris( + sender=sender.address, + token_identifier=token_identifier, + token_nonce=token_nonce, + uris=uris, + ) + + self._set_transaction_fields( + transaction=tx, + nonce=nonce, + version=version, + options=options, + gas_price=gas_price, + guardian_and_relayer_data=guardian_and_relayer_data, + ) + + self.add_extra_gas_limit_if_required(tx) + if gas_limit: + tx.gas_limit = gas_limit + + self.sign_transaction( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + return tx From 5739b1ed35b9f92a2edc7a19dc4ce6bd0c474a96 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 12 Sep 2025 16:56:03 +0300 Subject: [PATCH 07/33] wip: tests --- multiversx_sdk_cli/cli_tokens.py | 50 +- multiversx_sdk_cli/tests/test_cli_token.py | 591 +++++++++++++++++++++ 2 files changed, 627 insertions(+), 14 deletions(-) create mode 100644 multiversx_sdk_cli/tests/test_cli_token.py diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index 9dbd899a..96b499c9 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -571,38 +571,60 @@ def add_issuing_tokens_args( ) sub.add_argument( - "--can-freeze", required=True, type=lambda x: x.lower() == "true", help="whether a token can be freezed" + "--can-not-freeze", + action="store_false", + dest="can_freeze", + default=True, + help="make token not freezable", ) sub.add_argument( - "--can-wipe", required=True, type=lambda x: x.lower() == "true", help="whether a token can be wiped" + "--can-not-wipe", + action="store_false", + dest="can_wipe", + default=True, + help="make token not wipable", ) sub.add_argument( - "--can-pause", required=True, type=lambda x: x.lower() == "true", help="whether a token can be paused" + "--can-not-pause", + action="store_false", + dest="can_pause", + default=True, + help="make token not pausable", ) sub.add_argument( - "--can-change-owner", required=True, type=lambda x: x.lower() == "true", help="whether a token can change owner" + "--can-not-change-owner", + action="store_false", + dest="can_change_owner", + default=True, + help="don't allow changing the token's owner", ) sub.add_argument( - "--can-upgrade", required=True, type=lambda x: x.lower() == "true", help="whether a token can be upgraded" + "--can-not-upgrade", + action="store_false", + dest="can_upgrade", + default=True, + help="don't allow upgrading the token", ) sub.add_argument( - "--can-add_special-roles", - required=True, - type=lambda x: x.lower() == "true", - help="whether special roles can be added for the token", + "--can-not-add-special-roles", + action="store_false", + dest="can_add_special_roles", + default=True, + help="don't allow special roles to be added for the token", ) if with_transfer_nft_create_role: sub.add_argument( - "--can-transfer-nft-create-role", - required=True, - type=lambda x: x.lower() == "true", - help="whether nft create roles can be transfered for the token", + "--can-not-transfer-nft-create-role", + action="store_false", + dest="can_transfer_nft_create_role", + default=True, + help="don't allow for nft create roles to be transfered for the token", ) def _add_token_identifier_arg(sub: Any): - sub.add_argument("--identifier", required=True, type=str, help="the token identifier") + sub.add_argument("--token-identifier", required=True, type=str, help="the token identifier") def _add_user_arg(sub: Any): diff --git a/multiversx_sdk_cli/tests/test_cli_token.py b/multiversx_sdk_cli/tests/test_cli_token.py new file mode 100644 index 00000000..f3534b47 --- /dev/null +++ b/multiversx_sdk_cli/tests/test_cli_token.py @@ -0,0 +1,591 @@ +import base64 +import json +from pathlib import Path +from typing import Any + +from multiversx_sdk_cli.cli import main + +testdata = Path(__file__).parent / "testdata" +user = testdata / "testUser.pem" +user_address = "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" +grace = "erd1r69gk66fmedhhcg24g2c5kn2f2a5k4kvpr6jfw67dn2lyydd8cfswy6ede" + + +def test_issue_fungible(capsys: Any): + return_code = main( + [ + "token", + "issue-fungible", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--initial-supply", + "100", + "--num-decimals", + "0", + "--can-not-upgrade", + "--can-not-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "issue@4652414e4b@4652414e4b@64@@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_issue_semi_fungible(capsys: Any): + return_code = main( + [ + "token", + "issue-semi-fungible", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--can-not-upgrade", + "--can-not-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "issueSemiFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_issue_non_fungible(capsys: Any): + return_code = main( + [ + "token", + "issue-non-fungible", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--can-not-upgrade", + "--can-not-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "issueNonFungible@4652414e4b@4652414e4b@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_register_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-meta-esdt", + "--token-name", + "FRANK", + "--token-ticker", + "FRANK", + "--num-decimals", + "10", + "--can-not-upgrade", + "--can-not-add-special-roles", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "registerMetaESDT@4652414e4b@4652414e4b@0a@63616e467265657a65@74727565@63616e57697065@74727565@63616e5061757365@74727565@63616e5472616e736665724e4654437265617465526f6c65@74727565@63616e4368616e67654f776e6572@74727565@63616e55706772616465@66616c7365@63616e4164645370656369616c526f6c6573@66616c7365" + ) + + +def test_register_and_set_all_roles(capsys: Any): + return_code = main( + [ + "token", + "register-and-set-all-roles", + "--token-name", + "TEST", + "--token-ticker", + "TEST", + "--num-decimals", + "2", + "--token-type", + "FNG", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRoles@54455354@54455354@464e47@02" + + +def test_set_special_role_nft(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-nft", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-create", + "--nft-update-attributes", + "--nft-add-uri", + "--esdt-modify-creator", + "--nft-recreate", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249@45534454526f6c654d6f6469667943726561746f72@45534454526f6c654e46545265637265617465" + ) + + +def test_unset_special_role_nft(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-nft", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-update-attributes", + "--nft-add-uri", + "--esdt-modify-creator", + "--nft-recreate", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e465455706461746541747472696275746573@45534454526f6c654e4654416464555249@45534454526f6c654d6f6469667943726561746f72@45534454526f6c654e46545265637265617465" + ) + + +def test_create_nft(capsys: Any): + return_code = main( + [ + "token", + "create-nft", + "--token-identifier", + "FRANK-aa9e8d", + "--initial-quantity", + "1", + "--name", + "test", + "--royalties", + "1000", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "a", + "b", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTCreate@4652414e4b2d616139653864@01@74657374@03e8@61626261@74657374@61@62" + + +def test_set_special_role_on_fungible_token(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--local-mint", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654c6f63616c4d696e74" + ) + + +def test_unset_special_role_on_fungible_token(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--local-mint", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654c6f63616c4d696e74" + ) + + +def test_set_all_roles_on_fungible_token(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--local-mint", + "--local-burn", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654c6f63616c4d696e74@45534454526f6c654c6f63616c4275726e@455344545472616e73666572526f6c65" + ) + + +def test_set_special_roles_on_semi_fungible(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-semi-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-create", + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_unset_special_roles_on_semi_fungible(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-semi-fungible", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_set_special_roles_on_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "set-special-role-meta-esdt", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-create", + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "setSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e4654437265617465@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_unset_special_roles_on_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "unset-special-role-meta-esdt", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--nft-burn", + "--nft-add-quantity", + "--esdt-transfer-role", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unSetSpecialRole@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13@45534454526f6c654e46544275726e@45534454526f6c654e46544164645175616e74697479@455344545472616e73666572526f6c65" + ) + + +def test_pause_token(capsys: Any): + return_code = main( + [ + "token", + "pause", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "pause@4652414e4b2d313163653365" + + +def test_unpause_token(capsys: Any): + return_code = main( + [ + "token", + "unpause", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unPause@4652414e4b2d313163653365" + + +def _read_stdout(capsys: Any) -> str: + stdout: str = capsys.readouterr().out.strip() + return stdout + + +def get_transaction(capsys: Any) -> dict[str, Any]: + out = _read_stdout(capsys) + output: dict[str, Any] = json.loads(out) + tx: dict[str, Any] = output["emittedTransaction"] + return tx From 228fe1eb6742585a347535445a62eb0f1e4fa27e Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 15 Sep 2025 14:03:34 +0300 Subject: [PATCH 08/33] finish tests --- multiversx_sdk_cli/cli_tokens.py | 12 +- multiversx_sdk_cli/tests/test_cli_token.py | 877 +++++++++++++++++++++ 2 files changed, 883 insertions(+), 6 deletions(-) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index 96b499c9..3bb30611 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -291,7 +291,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) _add_token_identifier_arg(sub) sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--quantity", required=True, type=str, help="The quantity to add") + sub.add_argument("--quantity", required=True, type=int, help="The quantity to add") add_common_args(args, sub) sub.set_defaults(func=add_quantity) @@ -303,7 +303,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) _add_token_identifier_arg(sub) sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--quantity", required=True, type=str, help="The quantity to burn") + sub.add_argument("--quantity", required=True, type=int, help="The quantity to burn") add_common_args(args, sub) sub.set_defaults(func=burn_quantity) @@ -315,7 +315,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) _add_token_identifier_arg(sub) sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--royalties", required=True, type=str, help="The new token royalties (e.g. 1234 for 12.34%)") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") add_common_args(args, sub) sub.set_defaults(func=modify_royalties) @@ -351,7 +351,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: _add_token_identifier_arg(sub) sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") - sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") sub.add_argument( "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" @@ -369,7 +369,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: _add_token_identifier_arg(sub) sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") - sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") sub.add_argument( "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" @@ -401,7 +401,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: sub = cli_shared.add_command_subparser( subparsers, "token", - "register-dynamic-token", + "register-dynamic", "Register a dynamic token.", ) sub.add_argument("--token-name", type=str, required=True, help="The token name") diff --git a/multiversx_sdk_cli/tests/test_cli_token.py b/multiversx_sdk_cli/tests/test_cli_token.py index f3534b47..ae46a955 100644 --- a/multiversx_sdk_cli/tests/test_cli_token.py +++ b/multiversx_sdk_cli/tests/test_cli_token.py @@ -9,6 +9,7 @@ user = testdata / "testUser.pem" user_address = "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" grace = "erd1r69gk66fmedhhcg24g2c5kn2f2a5k4kvpr6jfw67dn2lyydd8cfswy6ede" +frank = "erd1kdl46yctawygtwg2k462307dmz2v55c605737dp3zkxh04sct7asqylhyv" def test_issue_fungible(capsys: Any): @@ -579,6 +580,882 @@ def test_unpause_token(capsys: Any): assert data == "unPause@4652414e4b2d313163653365" +def test_freeze_token(capsys: Any): + return_code = main( + [ + "token", + "freeze", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "freeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_unfreeze_token(capsys: Any): + return_code = main( + [ + "token", + "unfreeze", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unFreeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_local_mint(capsys: Any): + return_code = main( + [ + "token", + "local-mint", + "--token-identifier", + "FRANK-11ce3e", + "--supply-to-mint", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTLocalMint@4652414e4b2d313163653365@0a" + + +def test_local_burn(capsys: Any): + return_code = main( + [ + "token", + "local-burn", + "--token-identifier", + "FRANK-11ce3e", + "--supply-to-burn", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTLocalBurn@4652414e4b2d313163653365@0a" + + +def test_update_attributes(capsys: Any): + return_code = main( + [ + "token", + "update-attributes", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--attributes", + "74657374", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTUpdateAttributes@4652414e4b2d313163653365@0a@74657374" + + +def test_add_quantity(capsys: Any): + return_code = main( + [ + "token", + "add-quantity", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--quantity", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTAddQuantity@4652414e4b2d313163653365@0a@0a" + + +def test_burn_quantity(capsys: Any): + return_code = main( + [ + "token", + "burn-quantity", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--quantity", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTBurn@4652414e4b2d313163653365@0a@0a" + + +def test_set_burn_role_globally(capsys: Any): + return_code = main( + [ + "token", + "set-burn-role-globally", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "setBurnRoleGlobally@4652414e4b2d313163653365" + + +def test_unset_burn_role_globally(capsys: Any): + return_code = main( + [ + "token", + "unset-burn-role-globally", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unsetBurnRoleGlobally@4652414e4b2d313163653365" + + +def test_wipe(capsys: Any): + return_code = main( + [ + "token", + "wipe", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "wipe@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_modify_royalties(capsys: Any): + return_code = main( + [ + "token", + "modify-royalties", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--royalties", + "1234", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTModifyRoyalties@544553542d313233343536@01@04d2" + + +def test_set_new_uris(capsys: Any): + return_code = main( + [ + "token", + "set-new-uris", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTSetNewURIs@544553542d313233343536@01@6669727374555249@7365636f6e64555249" + + +def test_modify_creator(capsys: Any): + return_code = main( + [ + "token", + "modify-creator", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTModifyCreator@544553542d313233343536@01" + + +def test_update_metadata(capsys: Any): + return_code = main( + [ + "token", + "update-metadata", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--token-name", + "Test", + "--royalties", + "1234", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "ESDTMetaDataUpdate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" + ) + + +def test_recreate_metadata(capsys: Any): + return_code = main( + [ + "token", + "nft-metadata-recreate", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--token-name", + "Test", + "--royalties", + "1234", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "ESDTMetaDataRecreate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" + ) + + +def test_change_token_to_dynamic(capsys: Any): + return_code = main( + [ + "token", + "change-to-dynamic", + "--token-identifier", + "TEST-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "changeToDynamic@544553542d313233343536" + + +def test_update_token_id(capsys: Any): + return_code = main( + [ + "token", + "update-token-id", + "--token-identifier", + "TEST-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "updateTokenID@544553542d313233343536" + + +def test_register_dynamic(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic", + "--token-name", + "Test", + "--token-ticker", + "TEST-123456", + "--token-type", + "SFT", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerDynamic@54657374@544553542d313233343536@534654" + + +def test_register_dynamic_and_set_all_roles(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic-and-set-all-roles", + "--token-name", + "Test", + "--token-ticker", + "TEST-123456", + "--token-type", + "SFT", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRolesDynamic@54657374@544553542d313233343536@534654" + + +def test_register_dynamic_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic", + "--token-name", + "Test", + "--token-ticker", + "TEST-987654", + "--token-type", + "META", + "--denominator", + "18", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerDynamic@54657374@544553542d393837363534@4d455441@12" + + +def test_register_dynamic_and_set_all_roles_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic-and-set-all-roles", + "--token-name", + "Test", + "--token-ticker", + "TEST-987654", + "--token-type", + "META", + "--denominator", + "18", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRolesDynamic@54657374@544553542d393837363534@4d455441@12" + + +def test_transfer_ownership(capsys: Any): + return_code = main( + [ + "token", + "transfer-ownership", + "--token-identifier", + "AND-1d56f2", + "--new-owner", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "transferOwnership@414e442d316435366632@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_freeze_single_nft(capsys: Any): + return_code = main( + [ + "token", + "freeze-single-nft", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "freezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_unfreeze_single_nft(capsys: Any): + return_code = main( + [ + "token", + "unfreeze-single-nft", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unFreezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_change_sft_to_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "change-sft-to-meta-esdt", + "--collection", + "SFT-123456", + "--decimals", + "6", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "changeSFTToMetaESDT@5346542d313233343536@06" + + +def test_transfer_nft_create_role(capsys: Any): + return_code = main( + [ + "token", + "transfer-nft-create-role", + "--token-identifier", + "SFT-123456", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "transferNFTCreateRole@5346542d313233343536@c0006edaaee4fd479f2f248b341eb11eaecaec4d7dee190619958332bba5200f@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_stop_nft_create(capsys: Any): + return_code = main( + [ + "token", + "stop-nft-creation", + "--token-identifier", + "SFT-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "stopNFTCreate@5346542d313233343536" + + +def test_wipe_single_nft(capsys: Any): + return_code = main( + [ + "token", + "wipe-single-nft", + "--token-identifier", + "SFT-123456", + "--token-nonce", + "10", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data == "wipeSingleNFT@5346542d313233343536@0a@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_add_uris(capsys: Any): + return_code = main( + [ + "token", + "add-uris", + "--token-identifier", + "SFT-123456", + "--token-nonce", + "10", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTAddURI@5346542d313233343536@0a@6669727374555249@7365636f6e64555249" + + def _read_stdout(capsys: Any) -> str: stdout: str = capsys.readouterr().out.strip() return stdout From 9aa9a63db0dce21a32f369332ea0b8396b929dc7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 16 Sep 2025 10:49:29 +0300 Subject: [PATCH 09/33] refactoring to remove token management wrapper --- multiversx_sdk_cli/cli_tokens.py | 650 ++++------ multiversx_sdk_cli/tokens.py | 2033 ------------------------------ pyproject.toml | 2 +- requirements.txt | 2 +- 4 files changed, 237 insertions(+), 2450 deletions(-) delete mode 100644 multiversx_sdk_cli/tokens.py diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index 3bb30611..d372a3f6 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -1,13 +1,21 @@ from typing import Any -from multiversx_sdk import Address, TokenType, TransactionsFactoryConfig +from multiversx_sdk import ( + Address, + ProxyNetworkProvider, + TokenManagementController, + TokenType, + Transaction, +) from multiversx_sdk_cli import cli_shared from multiversx_sdk_cli.args_validation import ( validate_broadcast_args, validate_chain_id_args, ) -from multiversx_sdk_cli.tokens import TokensManagementWrapper +from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -832,6 +840,30 @@ def _ensure_issue_args(args: Any, with_initial_supply: bool = False, with_num_de validate_token_args(args, with_initial_supply, with_num_decimals) +def _initialize_controller(args: Any) -> TokenManagementController: + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + + proxy_url = args.proxy if args.proxy else "" + return TokenManagementController( + chain_id=chain_id, + network_provider=ProxyNetworkProvider(proxy_url), + gas_limit_estimator=gas_estimator, + ) + + +def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): + base = BaseTransactionsController() + base.sign_transaction( + transaction=transaction, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) + + def issue_fungible(args: Any): _ensure_issue_args(args, with_initial_supply=True, with_num_decimals=True) @@ -840,33 +872,28 @@ def issue_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_issuing_fungible_token( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_issuing_fungible( sender=sender, nonce=sender.nonce, token_name=args.token_name, token_ticker=args.token_ticker, initial_supply=args.initial_supply, num_decimals=args.num_decimals, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, can_freeze=args.can_freeze, can_wipe=args.can_wipe, can_pause=args.can_pause, can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -878,23 +905,13 @@ def issue_semi_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_issuing_semi_fungible_token( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_issuing_semi_fungible( sender=sender, nonce=sender.nonce, token_name=args.token_name, token_ticker=args.token_ticker, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, can_freeze=args.can_freeze, can_wipe=args.can_wipe, can_pause=args.can_pause, @@ -902,8 +919,13 @@ def issue_semi_fungible(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -915,23 +937,13 @@ def issue_non_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_issuing_non_fungible_token( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_issuing_non_fungible( sender=sender, nonce=sender.nonce, token_name=args.token_name, token_ticker=args.token_ticker, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, can_freeze=args.can_freeze, can_wipe=args.can_wipe, can_pause=args.can_pause, @@ -939,8 +951,13 @@ def issue_non_fungible(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -952,19 +969,14 @@ def register_meta_esdt(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_registering_meta_esdt( sender=sender, nonce=sender.nonce, token_name=args.token_name, token_ticker=args.token_ticker, - decimals=args.num_decimals, + num_decimals=args.num_decimals, can_freeze=args.can_freeze, can_wipe=args.can_wipe, can_pause=args.can_pause, @@ -972,13 +984,13 @@ def register_meta_esdt(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -990,28 +1002,24 @@ def register_and_set_all_roles(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + + controller = _initialize_controller(args) [token_type] = [type for type in TokenType if args.token_type == type.value] - transaction = controller.create_transaction_for_registering_and_set_all_roles( + transaction = controller.create_transaction_for_registering_and_setting_roles( sender=sender, nonce=sender.nonce, token_name=args.token_name, token_ticker=args.token_ticker, - decimals=args.num_decimals, + num_decimals=args.num_decimals, token_type=token_type, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1024,24 +1032,19 @@ def set_burn_role_globally(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_setting_burn_role_globally( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1054,24 +1057,19 @@ def unset_burn_role_globally(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_unsetting_burn_role_globally( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1084,14 +1082,9 @@ def set_special_role_on_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_setting_special_role_on_fungible( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_fungible_token( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, @@ -1099,13 +1092,13 @@ def set_special_role_on_fungible(args: Any): add_role_local_mint=args.local_mint, add_role_local_burn=args.local_burn, add_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1118,14 +1111,9 @@ def unset_special_role_on_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_unsetting_special_role_on_fungible( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_fungible_token( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, @@ -1133,13 +1121,13 @@ def unset_special_role_on_fungible(args: Any): remove_role_local_mint=args.local_mint, remove_role_local_burn=args.local_burn, remove_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1152,14 +1140,9 @@ def set_special_role_on_semi_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_setting_special_role_on_semi_fungible( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_semi_fungible_token( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, @@ -1173,13 +1156,13 @@ def set_special_role_on_semi_fungible(args: Any): add_role_esdt_set_new_uri=args.esdt_set_new_uri, add_role_esdt_modify_creator=args.esdt_modify_creator, add_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1192,14 +1175,9 @@ def unset_special_role_on_semi_fungible(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_unsetting_special_role_on_semi_fungible( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_semi_fungible_token( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, @@ -1212,13 +1190,13 @@ def unset_special_role_on_semi_fungible(args: Any): remove_role_esdt_set_new_uri=args.esdt_set_new_uri, remove_role_esdt_modify_creator=args.esdt_modify_creator, remove_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1231,13 +1209,8 @@ def set_special_role_on_meta_esdt(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_setting_special_role_on_meta_esdt( sender=sender, nonce=sender.nonce, @@ -1247,13 +1220,13 @@ def set_special_role_on_meta_esdt(args: Any): add_role_nft_burn=args.nft_burn, add_role_nft_add_quantity=args.nft_add_quantity, add_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1266,13 +1239,8 @@ def unset_special_role_on_meta_esdt(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_unsetting_special_role_on_meta_esdt( sender=sender, nonce=sender.nonce, @@ -1281,13 +1249,13 @@ def unset_special_role_on_meta_esdt(args: Any): remove_role_nft_burn=args.nft_burn, remove_role_nft_add_quantity=args.nft_add_quantity, remove_role_esdt_transfer_role=args.esdt_transfer_role, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1300,14 +1268,9 @@ def set_special_role_on_nft(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_setting_special_role_on_non_fungible( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_special_role_on_non_fungible_token( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, @@ -1322,13 +1285,13 @@ def set_special_role_on_nft(args: Any): add_role_esdt_set_new_uri=args.esdt_set_new_uri, add_role_esdt_modify_creator=args.esdt_modify_creator, add_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1341,34 +1304,29 @@ def unset_special_role_on_nft(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_unsetting_special_role_on_non_fungible( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unsetting_special_role_on_non_fungible_token( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), remove_role_nft_burn=args.nft_burn, remove_role_nft_update_attributes=args.nft_update_attributes, - remove_role_nft_add_uri=args.nft_add_uri, + remove_role_nft_remove_uri=args.nft_add_uri, remove_role_esdt_transfer_role=args.esdt_transfer_role, remove_role_nft_update=args.nft_update, remove_role_esdt_modify_royalties=args.esdt_modify_royalties, remove_role_esdt_set_new_uri=args.esdt_set_new_uri, remove_role_esdt_modify_creator=args.esdt_modify_creator, remove_role_nft_recreate=args.nft_recreate, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1381,13 +1339,8 @@ def create_nft(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_creating_nft( sender=sender, nonce=sender.nonce, @@ -1398,13 +1351,13 @@ def create_nft(args: Any): hash=args.hash, attributes=bytes.fromhex(args.attributes), uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1417,24 +1370,19 @@ def pause_token(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_pausing( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1447,24 +1395,19 @@ def unpause_token(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_unpausing( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1477,25 +1420,20 @@ def freeze_token(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_freezing( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1508,25 +1446,20 @@ def unfreeze_token(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_unfreezing( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1539,25 +1472,20 @@ def wipe_token(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_wiping( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1570,25 +1498,20 @@ def local_mint(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_local_minting( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, supply_to_mint=args.supply_to_mint, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1601,25 +1524,20 @@ def local_burn(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_local_burning( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, supply_to_burn=args.supply_to_burn, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1632,26 +1550,21 @@ def update_attributes(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_updating_attributes( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, attributes=bytes.fromhex(args.attributes), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1664,26 +1577,21 @@ def add_quantity(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_adding_quantity( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, - quantity=args.quantity, + quantity_to_add=args.quantity, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1696,26 +1604,21 @@ def burn_quantity(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_burning_quantity( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, - quantity=args.quantity, + quantity_to_burn=args.quantity, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1728,26 +1631,21 @@ def modify_royalties(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_modifying_royalties( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, - royalties=args.royalties, + new_royalties=args.royalties, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1760,26 +1658,21 @@ def set_new_uris(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_setting_new_uris( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, - uris=args.uris, + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1792,25 +1685,20 @@ def modify_creator(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_modifying_creator( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1823,13 +1711,8 @@ def update_metadata(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_updating_metadata( sender=sender, nonce=sender.nonce, @@ -1840,13 +1723,13 @@ def update_metadata(args: Any): new_hash=args.hash, new_attributes=bytes.fromhex(args.attributes), new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1859,14 +1742,9 @@ def nft_metadata_recreate(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) - transaction = controller.create_transaction_for_recreating_metadata( + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_nft_metadata_recreate( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, @@ -1876,13 +1754,13 @@ def nft_metadata_recreate(args: Any): new_hash=args.hash, new_attributes=bytes.fromhex(args.attributes), new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1895,24 +1773,19 @@ def change_to_dynamic(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_changing_token_to_dynamic( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1925,24 +1798,19 @@ def update_token_id(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_updating_token_id( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1955,14 +1823,10 @@ def register_dynamic_token(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + transaction = controller.create_transaction_for_registering_dynamic_token( sender=sender, nonce=sender.nonce, @@ -1970,13 +1834,13 @@ def register_dynamic_token(args: Any): token_ticker=args.token_ticker, token_type=token_type, denominator=args.denominator, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -1989,14 +1853,10 @@ def register_dynamic_and_set_all_roles(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + transaction = controller.create_transaction_for_registering_dynamic_and_setting_roles( sender=sender, nonce=sender.nonce, @@ -2004,13 +1864,13 @@ def register_dynamic_and_set_all_roles(args: Any): token_ticker=args.token_ticker, token_type=token_type, denominator=args.denominator, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2023,25 +1883,20 @@ def transfer_ownership(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_transferring_ownership( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, new_owner=Address.new_from_bech32(args.new_owner), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2054,26 +1909,21 @@ def freeze_single_nft(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_freezing_single_nft( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2086,26 +1936,21 @@ def unfreeze_single_nft(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_unfreezing_single_nft( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2118,25 +1963,20 @@ def change_sft_to_meta_esdt(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_changing_sft_to_meta_esdt( sender=sender, nonce=sender.nonce, - collection_identifier=args.collection, - decimals=args.decimals, + collection=args.collection, + num_decimals=args.decimals, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2149,25 +1989,20 @@ def transfer_nft_create_role(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_transferring_nft_create_role( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2180,24 +2015,19 @@ def stop_nft_creation(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_stopping_nft_creation( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2210,26 +2040,21 @@ def wipe_single_nft(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_wiping_single_nft( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -2242,24 +2067,19 @@ def add_uris(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TokensManagementWrapper( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_estimator, - ) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_adding_uris( sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/tokens.py b/multiversx_sdk_cli/tokens.py deleted file mode 100644 index 1b2beeec..00000000 --- a/multiversx_sdk_cli/tokens.py +++ /dev/null @@ -1,2033 +0,0 @@ -from typing import Optional - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - TokenManagementTransactionsFactory, - TokenType, - Transaction, - TransactionsFactoryConfig, -) - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - - -class TokensManagementWrapper(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ) -> None: - self.factory = TokenManagementTransactionsFactory(config=config, gas_limit_estimator=gas_limit_estimator) - - def create_transaction_for_issuing_fungible_token( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - initial_supply: int, - num_decimals: int, - can_freeze: bool, - can_wipe: bool, - can_pause: bool, - can_change_owner: bool, - can_upgrade: bool, - can_add_special_roles: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_issuing_fungible( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - initial_supply=initial_supply, - num_decimals=num_decimals, - can_freeze=can_freeze, - can_wipe=can_wipe, - can_pause=can_pause, - can_change_owner=can_change_owner, - can_upgrade=can_upgrade, - can_add_special_roles=can_add_special_roles, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_issuing_semi_fungible_token( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - can_freeze: bool, - can_wipe: bool, - can_pause: bool, - can_transfer_nft_create_role: bool, - can_change_owner: bool, - can_upgrade: bool, - can_add_special_roles: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_issuing_semi_fungible( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - can_freeze=can_freeze, - can_wipe=can_wipe, - can_pause=can_pause, - can_transfer_nft_create_role=can_transfer_nft_create_role, - can_change_owner=can_change_owner, - can_upgrade=can_upgrade, - can_add_special_roles=can_add_special_roles, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_issuing_non_fungible_token( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - can_freeze: bool, - can_wipe: bool, - can_pause: bool, - can_transfer_nft_create_role: bool, - can_change_owner: bool, - can_upgrade: bool, - can_add_special_roles: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_issuing_non_fungible( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - can_freeze=can_freeze, - can_wipe=can_wipe, - can_pause=can_pause, - can_transfer_nft_create_role=can_transfer_nft_create_role, - can_change_owner=can_change_owner, - can_upgrade=can_upgrade, - can_add_special_roles=can_add_special_roles, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_registering_meta_esdt( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - decimals: int, - can_freeze: bool, - can_wipe: bool, - can_pause: bool, - can_transfer_nft_create_role: bool, - can_change_owner: bool, - can_upgrade: bool, - can_add_special_roles: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_registering_meta_esdt( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - num_decimals=decimals, - can_freeze=can_freeze, - can_wipe=can_wipe, - can_pause=can_pause, - can_transfer_nft_create_role=can_transfer_nft_create_role, - can_change_owner=can_change_owner, - can_upgrade=can_upgrade, - can_add_special_roles=can_add_special_roles, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_registering_and_set_all_roles( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - decimals: int, - token_type: TokenType, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_registering_and_setting_roles( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - num_decimals=decimals, - token_type=token_type, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_setting_burn_role_globally( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_setting_burn_role_globally( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unsetting_burn_role_globally( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unsetting_burn_role_globally( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_setting_special_role_on_fungible( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - add_role_local_mint: bool, - add_role_local_burn: bool, - add_role_esdt_transfer_role: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_setting_special_role_on_fungible_token( - sender=sender.address, - token_identifier=token_identifier, - user=user, - add_role_local_mint=add_role_local_mint, - add_role_local_burn=add_role_local_burn, - add_role_esdt_transfer_role=add_role_esdt_transfer_role, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unsetting_special_role_on_fungible( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - remove_role_local_mint: bool, - remove_role_local_burn: bool, - remove_role_esdt_transfer_role: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unsetting_special_role_on_fungible_token( - sender=sender.address, - token_identifier=token_identifier, - user=user, - remove_role_local_mint=remove_role_local_mint, - remove_role_local_burn=remove_role_local_burn, - remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_setting_special_role_on_semi_fungible( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - add_role_nft_create: bool, - add_role_nft_burn: bool, - add_role_nft_add_quantity: bool, - add_role_esdt_transfer_role: bool, - add_role_nft_update: bool, - add_role_esdt_modify_royalties: bool, - add_role_esdt_set_new_uri: bool, - add_role_esdt_modify_creator: bool, - add_role_nft_recreate: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_setting_special_role_on_semi_fungible_token( - sender=sender.address, - token_identifier=token_identifier, - user=user, - add_role_nft_create=add_role_nft_create, - add_role_nft_burn=add_role_nft_burn, - add_role_nft_add_quantity=add_role_nft_add_quantity, - add_role_esdt_transfer_role=add_role_esdt_transfer_role, - add_role_nft_update=add_role_nft_update, - add_role_esdt_modify_royalties=add_role_esdt_modify_royalties, - add_role_esdt_set_new_uri=add_role_esdt_set_new_uri, - add_role_esdt_modify_creator=add_role_esdt_modify_creator, - add_role_nft_recreate=add_role_nft_recreate, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unsetting_special_role_on_semi_fungible( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - remove_role_nft_burn: bool, - remove_role_nft_add_quantity: bool, - remove_role_esdt_transfer_role: bool, - remove_role_nft_update: bool, - remove_role_esdt_modify_royalties: bool, - remove_role_esdt_set_new_uri: bool, - remove_role_esdt_modify_creator: bool, - remove_role_nft_recreate: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unsetting_special_role_on_semi_fungible_token( - sender=sender.address, - token_identifier=token_identifier, - user=user, - remove_role_nft_burn=remove_role_nft_burn, - remove_role_nft_add_quantity=remove_role_nft_add_quantity, - remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, - remove_role_nft_update=remove_role_nft_update, - remove_role_esdt_modify_royalties=remove_role_esdt_modify_royalties, - remove_role_esdt_set_new_uri=remove_role_esdt_set_new_uri, - remove_role_esdt_modify_creator=remove_role_esdt_modify_creator, - remove_role_nft_recreate=remove_role_nft_recreate, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_setting_special_role_on_meta_esdt( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - add_role_nft_create: bool, - add_role_nft_burn: bool, - add_role_nft_add_quantity: bool, - add_role_esdt_transfer_role: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_setting_special_role_on_meta_esdt( - sender=sender.address, - token_identifier=token_identifier, - user=user, - add_role_nft_create=add_role_nft_create, - add_role_nft_burn=add_role_nft_burn, - add_role_nft_add_quantity=add_role_nft_add_quantity, - add_role_esdt_transfer_role=add_role_esdt_transfer_role, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unsetting_special_role_on_meta_esdt( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - remove_role_nft_burn: bool, - remove_role_nft_add_quantity: bool, - remove_role_esdt_transfer_role: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unsetting_special_role_on_meta_esdt( - sender=sender.address, - token_identifier=token_identifier, - user=user, - remove_role_nft_burn=remove_role_nft_burn, - remove_role_nft_add_quantity=remove_role_nft_add_quantity, - remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_setting_special_role_on_non_fungible( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - add_role_nft_create: bool, - add_role_nft_burn: bool, - add_role_nft_update_attributes: bool, - add_role_nft_add_uri: bool, - add_role_esdt_transfer_role: bool, - add_role_nft_update: bool, - add_role_esdt_modify_royalties: bool, - add_role_esdt_set_new_uri: bool, - add_role_esdt_modify_creator: bool, - add_role_nft_recreate: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_setting_special_role_on_non_fungible_token( - sender=sender.address, - token_identifier=token_identifier, - user=user, - add_role_nft_create=add_role_nft_create, - add_role_nft_burn=add_role_nft_burn, - add_role_nft_update_attributes=add_role_nft_update_attributes, - add_role_nft_add_uri=add_role_nft_add_uri, - add_role_esdt_transfer_role=add_role_esdt_transfer_role, - add_role_nft_update=add_role_nft_update, - add_role_esdt_modify_royalties=add_role_esdt_modify_royalties, - add_role_esdt_set_new_uri=add_role_esdt_set_new_uri, - add_role_esdt_modify_creator=add_role_esdt_modify_creator, - add_role_nft_recreate=add_role_nft_recreate, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unsetting_special_role_on_non_fungible( - self, - sender: IAccount, - nonce: int, - user: Address, - token_identifier: str, - remove_role_nft_burn: bool, - remove_role_nft_update_attributes: bool, - remove_role_nft_add_uri: bool, - remove_role_esdt_transfer_role: bool, - remove_role_nft_update: bool, - remove_role_esdt_modify_royalties: bool, - remove_role_esdt_set_new_uri: bool, - remove_role_esdt_modify_creator: bool, - remove_role_nft_recreate: bool, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unsetting_special_role_on_non_fungible_token( - sender=sender.address, - token_identifier=token_identifier, - user=user, - remove_role_nft_burn=remove_role_nft_burn, - remove_role_nft_update_attributes=remove_role_nft_update_attributes, - remove_role_nft_remove_uri=remove_role_nft_add_uri, - remove_role_esdt_transfer_role=remove_role_esdt_transfer_role, - remove_role_nft_update=remove_role_nft_update, - remove_role_esdt_modify_royalties=remove_role_esdt_modify_royalties, - remove_role_esdt_set_new_uri=remove_role_esdt_set_new_uri, - remove_role_esdt_modify_creator=remove_role_esdt_modify_creator, - remove_role_nft_recreate=remove_role_nft_recreate, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_creating_nft( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - initial_quantity: int, - name: str, - royalties: int, - hash: str, - attributes: bytes, - uris: list[str], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_creating_nft( - sender=sender.address, - token_identifier=token_identifier, - initial_quantity=initial_quantity, - name=name, - royalties=royalties, - hash=hash, - attributes=attributes, - uris=uris, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_pausing( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_pausing( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unpausing( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unpausing( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_freezing( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_freezing( - sender=sender.address, - token_identifier=token_identifier, - user=user, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unfreezing( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unfreezing( - sender=sender.address, - token_identifier=token_identifier, - user=user, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_wiping( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_wiping( - sender=sender.address, - user=user, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_local_minting( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - supply_to_mint: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_local_minting( - sender=sender.address, - token_identifier=token_identifier, - supply_to_mint=supply_to_mint, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_local_burning( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - supply_to_burn: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_local_burning( - sender=sender.address, - token_identifier=token_identifier, - supply_to_burn=supply_to_burn, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_updating_attributes( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - attributes: bytes, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_updating_attributes( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - attributes=attributes, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_adding_quantity( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - quantity: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_adding_quantity( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - quantity_to_add=quantity, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_burning_quantity( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - quantity: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_burning_quantity( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - quantity_to_burn=quantity, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_modifying_royalties( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - royalties: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_modifying_royalties( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - new_royalties=royalties, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_setting_new_uris( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - uris: list[str], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_setting_new_uris( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - new_uris=uris, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_modifying_creator( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_modifying_creator( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_updating_metadata( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - new_token_name: str, - new_royalties: int, - new_hash: str, - new_attributes: bytes, - new_uris: list[str], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_updating_metadata( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - new_token_name=new_token_name, - new_royalties=new_royalties, - new_hash=new_hash, - new_attributes=new_attributes, - new_uris=new_uris, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_recreating_metadata( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - new_token_name: str, - new_royalties: int, - new_hash: str, - new_attributes: bytes, - new_uris: list[str], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_nft_metadata_recreate( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - new_token_name=new_token_name, - new_royalties=new_royalties, - new_hash=new_hash, - new_attributes=new_attributes, - new_uris=new_uris, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_changing_token_to_dynamic( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_changing_token_to_dynamic( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_updating_token_id( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_updating_token_id( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_registering_dynamic_token( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - token_type: TokenType, - denominator: Optional[int], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_registering_dynamic_token( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - token_type=token_type, - denominator=denominator, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_registering_dynamic_and_setting_roles( - self, - sender: IAccount, - nonce: int, - token_name: str, - token_ticker: str, - token_type: TokenType, - denominator: Optional[int], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_registering_dynamic_and_setting_roles( - sender=sender.address, - token_name=token_name, - token_ticker=token_ticker, - token_type=token_type, - denominator=denominator, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_transferring_ownership( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - new_owner: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_transferring_ownership( - sender=sender.address, - token_identifier=token_identifier, - new_owner=new_owner, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_freezing_single_nft( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_freezing_single_nft( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - user=user, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_unfreezing_single_nft( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_unfreezing_single_nft( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - user=user, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_changing_sft_to_meta_esdt( - self, - sender: IAccount, - nonce: int, - collection_identifier: str, - decimals: int, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_changing_sft_to_meta_esdt( - sender=sender.address, - collection=collection_identifier, - num_decimals=decimals, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_transferring_nft_create_role( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_transferring_nft_create_role( - sender=sender.address, - token_identifier=token_identifier, - user=user, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_stopping_nft_creation( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_stopping_nft_creation( - sender=sender.address, - token_identifier=token_identifier, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_wiping_single_nft( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - user: Address, - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_wiping_single_nft( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - user=user, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_adding_uris( - self, - sender: IAccount, - nonce: int, - token_identifier: str, - token_nonce: int, - uris: list[str], - gas_limit: Optional[int], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transction_for_adding_uris( - sender=sender.address, - token_identifier=token_identifier, - token_nonce=token_nonce, - uris=uris, - ) - - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx diff --git a/pyproject.toml b/pyproject.toml index f6e3ab7e..8b78dfe8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ dependencies = [ "ledgercomm[hid]", "rich==13.3.4", "argcomplete==3.2.2", - "multiversx-sdk[ledger]==2.0.1" + "multiversx-sdk[ledger]==2.2.0" ] [project.scripts] diff --git a/requirements.txt b/requirements.txt index 33c1b918..01f3c357 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,4 @@ ledgercomm[hid] rich==13.3.4 argcomplete==3.2.2 -multiversx-sdk[ledger]==2.0.1 +multiversx-sdk[ledger]==2.2.0 From bc82b2243c93e19df870fa03096d0a3daa8a5770 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 16 Sep 2025 11:13:24 +0300 Subject: [PATCH 10/33] split PR --- multiversx_sdk_cli/cli_tokens.py | 1051 -------------------- multiversx_sdk_cli/tests/test_cli_token.py | 928 ----------------- 2 files changed, 1979 deletions(-) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index d372a3f6..08939093 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -204,333 +204,6 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: add_common_args(args, sub) sub.set_defaults(func=create_nft) - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "pause", - "Pause a token.", - ) - _add_token_identifier_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=pause_token) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "unpause", - "Unpause a token.", - ) - _add_token_identifier_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=unpause_token) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "freeze", - "Freeze a token for a user.", - ) - _add_token_identifier_arg(sub) - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=freeze_token) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "unfreeze", - "Unfreeze a token for a user.", - ) - _add_token_identifier_arg(sub) - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=unfreeze_token) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "wipe", - "Wipe a token for a user.", - ) - _add_token_identifier_arg(sub) - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=wipe_token) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "local-mint", - "Mint new tokens.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--supply-to-mint", required=True, type=int, help="The amount of new tokens to mint") - add_common_args(args, sub) - sub.set_defaults(func=local_mint) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "local-burn", - "Burn tokens.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--supply-to-burn", required=True, type=int, help="The amount of tokens to burn") - add_common_args(args, sub) - sub.set_defaults(func=local_burn) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "update-attributes", - "Update token attributes.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--attributes", required=True, type=str, help="The hex-string attributes of the token") - add_common_args(args, sub) - sub.set_defaults(func=update_attributes) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "add-quantity", - "Increase token quantity.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--quantity", required=True, type=int, help="The quantity to add") - add_common_args(args, sub) - sub.set_defaults(func=add_quantity) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "burn-quantity", - "Burn token quantity.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--quantity", required=True, type=int, help="The quantity to burn") - add_common_args(args, sub) - sub.set_defaults(func=burn_quantity) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "modify-royalties", - "Modify token royalties.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") - add_common_args(args, sub) - sub.set_defaults(func=modify_royalties) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "set-new-uris", - "Set new uris.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--uris", required=True, nargs="+", help="The new uris") - add_common_args(args, sub) - sub.set_defaults(func=set_new_uris) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "modify-creator", - "Modify the creator of the token.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - add_common_args(args, sub) - sub.set_defaults(func=modify_creator) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "update-metadata", - "Update the metadata of the token.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") - sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") - sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") - sub.add_argument( - "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" - ) - sub.add_argument("--uris", required=True, nargs="+", help="The new uris") - add_common_args(args, sub) - sub.set_defaults(func=update_metadata) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "nft-metadata-recreate", - "Recreate the metadata of the token.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") - sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") - sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") - sub.add_argument( - "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" - ) - sub.add_argument("--uris", required=True, nargs="+", help="The new uris") - add_common_args(args, sub) - sub.set_defaults(func=nft_metadata_recreate) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "change-to-dynamic", - "Change a token to a dynamic token.", - ) - _add_token_identifier_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=change_to_dynamic) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "update-token-id", - "Update token id.", - ) - _add_token_identifier_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=update_token_id) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "register-dynamic", - "Register a dynamic token.", - ) - sub.add_argument("--token-name", type=str, required=True, help="The token name") - sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") - sub.add_argument( - "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" - ) - sub.add_argument( - "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" - ) - add_common_args(args, sub) - sub.set_defaults(func=register_dynamic_token) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "register-dynamic-and-set-all-roles", - "Register a dynamic token and set all roles.", - ) - sub.add_argument("--token-name", type=str, required=True, help="The token name") - sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") - sub.add_argument( - "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" - ) - sub.add_argument( - "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" - ) - add_common_args(args, sub) - sub.set_defaults(func=register_dynamic_and_set_all_roles) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "transfer-ownership", - "Transfer the ownership of a token to another user.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--new-owner", type=str, required=True, help="The new token owner") - add_common_args(args, sub) - sub.set_defaults(func=transfer_ownership) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "freeze-single-nft", - "Freeze the NFT of a user.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=freeze_single_nft) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "unfreeze-single-nft", - "Unfreeze the NFT of a user.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=unfreeze_single_nft) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "change-sft-to-meta-esdt", - "Change a semi fungible token to a Meta ESDT.", - ) - sub.add_argument("--collection", required=True, type=str, help="The collection identifier") - sub.add_argument("--decimals", type=int, required=True, help="The number of decimals the meta esdt will have") - add_common_args(args, sub) - sub.set_defaults(func=change_sft_to_meta_esdt) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "transfer-nft-create-role", - "Transfer the nft create role to a user.", - ) - _add_token_identifier_arg(sub) - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=transfer_nft_create_role) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "stop-nft-creation", - "Stop the creation of new NFTs.", - ) - _add_token_identifier_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=stop_nft_creation) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "wipe-single-nft", - "Wipe the NFT of a user.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") - _add_user_arg(sub) - add_common_args(args, sub) - sub.set_defaults(func=wipe_single_nft) - - sub = cli_shared.add_command_subparser( - subparsers, - "token", - "add-uris", - "Add uris for a token.", - ) - _add_token_identifier_arg(sub) - sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") - sub.add_argument("--uris", nargs="+", required=True, help="The new uris to be added to the token.") - add_common_args(args, sub) - sub.set_defaults(func=add_uris) - parser.epilog = cli_shared.build_group_epilog(subparsers) return subparsers @@ -1359,727 +1032,3 @@ def create_nft(args: Any): _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) - - -def pause_token(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_pausing( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def unpause_token(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_unpausing( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def freeze_token(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_freezing( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def unfreeze_token(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_unfreezing( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def wipe_token(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_wiping( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def local_mint(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_local_minting( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - supply_to_mint=args.supply_to_mint, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def local_burn(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_local_burning( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - supply_to_burn=args.supply_to_burn, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def update_attributes(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_updating_attributes( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - attributes=bytes.fromhex(args.attributes), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def add_quantity(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_adding_quantity( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - quantity_to_add=args.quantity, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def burn_quantity(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_burning_quantity( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - quantity_to_burn=args.quantity, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def modify_royalties(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_modifying_royalties( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - new_royalties=args.royalties, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def set_new_uris(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_setting_new_uris( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - new_uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def modify_creator(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_modifying_creator( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def update_metadata(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_updating_metadata( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - new_token_name=args.token_name, - new_royalties=args.royalties, - new_hash=args.hash, - new_attributes=bytes.fromhex(args.attributes), - new_uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def nft_metadata_recreate(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_nft_metadata_recreate( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - new_token_name=args.token_name, - new_royalties=args.royalties, - new_hash=args.hash, - new_attributes=bytes.fromhex(args.attributes), - new_uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def change_to_dynamic(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_changing_token_to_dynamic( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def update_token_id(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_updating_token_id( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def register_dynamic_token(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] - - transaction = controller.create_transaction_for_registering_dynamic_token( - sender=sender, - nonce=sender.nonce, - token_name=args.token_name, - token_ticker=args.token_ticker, - token_type=token_type, - denominator=args.denominator, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def register_dynamic_and_set_all_roles(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] - - transaction = controller.create_transaction_for_registering_dynamic_and_setting_roles( - sender=sender, - nonce=sender.nonce, - token_name=args.token_name, - token_ticker=args.token_ticker, - token_type=token_type, - denominator=args.denominator, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def transfer_ownership(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_transferring_ownership( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - new_owner=Address.new_from_bech32(args.new_owner), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def freeze_single_nft(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_freezing_single_nft( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def unfreeze_single_nft(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_unfreezing_single_nft( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def change_sft_to_meta_esdt(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_changing_sft_to_meta_esdt( - sender=sender, - nonce=sender.nonce, - collection=args.collection, - num_decimals=args.decimals, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def transfer_nft_create_role(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_transferring_nft_create_role( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def stop_nft_creation(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_stopping_nft_creation( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def wipe_single_nft(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_wiping_single_nft( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) - - -def add_uris(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) - - sender = cli_shared.prepare_sender(args) - guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( - sender=sender.address.to_bech32(), - args=args, - ) - - controller = _initialize_controller(args) - transaction = controller.create_transaction_for_adding_uris( - sender=sender, - nonce=sender.nonce, - token_identifier=args.token_identifier, - token_nonce=args.token_nonce, - uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - ) - - _sign_transaction(transaction, sender, guardian_and_relayer_data) - cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/tests/test_cli_token.py b/multiversx_sdk_cli/tests/test_cli_token.py index ae46a955..fb16cbcf 100644 --- a/multiversx_sdk_cli/tests/test_cli_token.py +++ b/multiversx_sdk_cli/tests/test_cli_token.py @@ -528,934 +528,6 @@ def test_unset_special_roles_on_meta_esdt(capsys: Any): ) -def test_pause_token(capsys: Any): - return_code = main( - [ - "token", - "pause", - "--token-identifier", - "FRANK-11ce3e", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "pause@4652414e4b2d313163653365" - - -def test_unpause_token(capsys: Any): - return_code = main( - [ - "token", - "unpause", - "--token-identifier", - "FRANK-11ce3e", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "unPause@4652414e4b2d313163653365" - - -def test_freeze_token(capsys: Any): - return_code = main( - [ - "token", - "freeze", - "--token-identifier", - "FRANK-11ce3e", - "--user", - grace, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "freeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" - - -def test_unfreeze_token(capsys: Any): - return_code = main( - [ - "token", - "unfreeze", - "--token-identifier", - "FRANK-11ce3e", - "--user", - grace, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "unFreeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" - - -def test_local_mint(capsys: Any): - return_code = main( - [ - "token", - "local-mint", - "--token-identifier", - "FRANK-11ce3e", - "--supply-to-mint", - "10", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTLocalMint@4652414e4b2d313163653365@0a" - - -def test_local_burn(capsys: Any): - return_code = main( - [ - "token", - "local-burn", - "--token-identifier", - "FRANK-11ce3e", - "--supply-to-burn", - "10", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTLocalBurn@4652414e4b2d313163653365@0a" - - -def test_update_attributes(capsys: Any): - return_code = main( - [ - "token", - "update-attributes", - "--token-identifier", - "FRANK-11ce3e", - "--token-nonce", - "10", - "--attributes", - "74657374", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTNFTUpdateAttributes@4652414e4b2d313163653365@0a@74657374" - - -def test_add_quantity(capsys: Any): - return_code = main( - [ - "token", - "add-quantity", - "--token-identifier", - "FRANK-11ce3e", - "--token-nonce", - "10", - "--quantity", - "10", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTNFTAddQuantity@4652414e4b2d313163653365@0a@0a" - - -def test_burn_quantity(capsys: Any): - return_code = main( - [ - "token", - "burn-quantity", - "--token-identifier", - "FRANK-11ce3e", - "--token-nonce", - "10", - "--quantity", - "10", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTNFTBurn@4652414e4b2d313163653365@0a@0a" - - -def test_set_burn_role_globally(capsys: Any): - return_code = main( - [ - "token", - "set-burn-role-globally", - "--token-identifier", - "FRANK-11ce3e", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "setBurnRoleGlobally@4652414e4b2d313163653365" - - -def test_unset_burn_role_globally(capsys: Any): - return_code = main( - [ - "token", - "unset-burn-role-globally", - "--token-identifier", - "FRANK-11ce3e", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "unsetBurnRoleGlobally@4652414e4b2d313163653365" - - -def test_wipe(capsys: Any): - return_code = main( - [ - "token", - "wipe", - "--token-identifier", - "FRANK-11ce3e", - "--user", - grace, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "wipe@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" - - -def test_modify_royalties(capsys: Any): - return_code = main( - [ - "token", - "modify-royalties", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--royalties", - "1234", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTModifyRoyalties@544553542d313233343536@01@04d2" - - -def test_set_new_uris(capsys: Any): - return_code = main( - [ - "token", - "set-new-uris", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--uris", - "firstURI", - "secondURI", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTSetNewURIs@544553542d313233343536@01@6669727374555249@7365636f6e64555249" - - -def test_modify_creator(capsys: Any): - return_code = main( - [ - "token", - "modify-creator", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTModifyCreator@544553542d313233343536@01" - - -def test_update_metadata(capsys: Any): - return_code = main( - [ - "token", - "update-metadata", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--token-name", - "Test", - "--royalties", - "1234", - "--hash", - "abba", - "--attributes", - "74657374", - "--uris", - "firstURI", - "secondURI", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data - == "ESDTMetaDataUpdate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" - ) - - -def test_recreate_metadata(capsys: Any): - return_code = main( - [ - "token", - "nft-metadata-recreate", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--token-name", - "Test", - "--royalties", - "1234", - "--hash", - "abba", - "--attributes", - "74657374", - "--uris", - "firstURI", - "secondURI", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == user_address - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data - == "ESDTMetaDataRecreate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" - ) - - -def test_change_token_to_dynamic(capsys: Any): - return_code = main( - [ - "token", - "change-to-dynamic", - "--token-identifier", - "TEST-123456", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "changeToDynamic@544553542d313233343536" - - -def test_update_token_id(capsys: Any): - return_code = main( - [ - "token", - "update-token-id", - "--token-identifier", - "TEST-123456", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "updateTokenID@544553542d313233343536" - - -def test_register_dynamic(capsys: Any): - return_code = main( - [ - "token", - "register-dynamic", - "--token-name", - "Test", - "--token-ticker", - "TEST-123456", - "--token-type", - "SFT", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "50000000000000000" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "registerDynamic@54657374@544553542d313233343536@534654" - - -def test_register_dynamic_and_set_all_roles(capsys: Any): - return_code = main( - [ - "token", - "register-dynamic-and-set-all-roles", - "--token-name", - "Test", - "--token-ticker", - "TEST-123456", - "--token-type", - "SFT", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "50000000000000000" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "registerAndSetAllRolesDynamic@54657374@544553542d313233343536@534654" - - -def test_register_dynamic_meta_esdt(capsys: Any): - return_code = main( - [ - "token", - "register-dynamic", - "--token-name", - "Test", - "--token-ticker", - "TEST-987654", - "--token-type", - "META", - "--denominator", - "18", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "50000000000000000" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "registerDynamic@54657374@544553542d393837363534@4d455441@12" - - -def test_register_dynamic_and_set_all_roles_meta_esdt(capsys: Any): - return_code = main( - [ - "token", - "register-dynamic-and-set-all-roles", - "--token-name", - "Test", - "--token-ticker", - "TEST-987654", - "--token-type", - "META", - "--denominator", - "18", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "50000000000000000" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "registerAndSetAllRolesDynamic@54657374@544553542d393837363534@4d455441@12" - - -def test_transfer_ownership(capsys: Any): - return_code = main( - [ - "token", - "transfer-ownership", - "--token-identifier", - "AND-1d56f2", - "--new-owner", - frank, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data - == "transferOwnership@414e442d316435366632@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" - ) - - -def test_freeze_single_nft(capsys: Any): - return_code = main( - [ - "token", - "freeze-single-nft", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--user", - frank, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data - == "freezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" - ) - - -def test_unfreeze_single_nft(capsys: Any): - return_code = main( - [ - "token", - "unfreeze-single-nft", - "--token-identifier", - "TEST-123456", - "--token-nonce", - "1", - "--user", - frank, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data - == "unFreezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" - ) - - -def test_change_sft_to_meta_esdt(capsys: Any): - return_code = main( - [ - "token", - "change-sft-to-meta-esdt", - "--collection", - "SFT-123456", - "--decimals", - "6", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "changeSFTToMetaESDT@5346542d313233343536@06" - - -def test_transfer_nft_create_role(capsys: Any): - return_code = main( - [ - "token", - "transfer-nft-create-role", - "--token-identifier", - "SFT-123456", - "--user", - frank, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data - == "transferNFTCreateRole@5346542d313233343536@c0006edaaee4fd479f2f248b341eb11eaecaec4d7dee190619958332bba5200f@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" - ) - - -def test_stop_nft_create(capsys: Any): - return_code = main( - [ - "token", - "stop-nft-creation", - "--token-identifier", - "SFT-123456", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "stopNFTCreate@5346542d313233343536" - - -def test_wipe_single_nft(capsys: Any): - return_code = main( - [ - "token", - "wipe-single-nft", - "--token-identifier", - "SFT-123456", - "--token-nonce", - "10", - "--user", - frank, - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert ( - data == "wipeSingleNFT@5346542d313233343536@0a@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" - ) - - -def test_add_uris(capsys: Any): - return_code = main( - [ - "token", - "add-uris", - "--token-identifier", - "SFT-123456", - "--token-nonce", - "10", - "--uris", - "firstURI", - "secondURI", - "--pem", - str(user), - "--nonce", - "7", - "--chain", - "D", - ] - ) - assert not return_code - - transaction = get_transaction(capsys) - assert transaction["sender"] == user_address - assert transaction["receiver"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction["value"] == "0" - assert transaction["chainID"] == "D" - data = base64.b64decode(transaction["data"]).decode() - assert data == "ESDTNFTAddURI@5346542d313233343536@0a@6669727374555249@7365636f6e64555249" - - def _read_stdout(capsys: Any) -> str: stdout: str = capsys.readouterr().out.strip() return stdout From 64763e54adf9f470c0a69a188fc51c68efb5004a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 16 Sep 2025 15:18:37 +0300 Subject: [PATCH 11/33] refactoring to remove delegation wrapper --- multiversx_sdk_cli/cli_delegation.py | 367 ++++---- multiversx_sdk_cli/delegation.py | 806 ------------------ .../tests/test_cli_staking_provider.py | 2 +- pyproject.toml | 2 +- requirements.txt | 2 +- 5 files changed, 207 insertions(+), 972 deletions(-) delete mode 100644 multiversx_sdk_cli/delegation.py diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index d76a52b9..941f3407 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -3,10 +3,12 @@ from multiversx_sdk import ( Address, + DelegationController, DelegationTransactionsOutcomeParser, ProxyNetworkProvider, - TransactionsFactoryConfig, + Transaction, ValidatorPublicKey, + ValidatorsController, ValidatorsSigners, ) @@ -18,8 +20,10 @@ validate_proxy_argument, validate_receiver_args, ) +from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.delegation import DelegationOperations +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -394,10 +398,28 @@ def validate_arguments(args: Any): def _get_delegation_controller(args: Any): chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - config = TransactionsFactoryConfig(chain_id) + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" + proxy = ProxyNetworkProvider(url=proxy_url, config=config) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - delegation = DelegationOperations(config=config, gas_limit_estimator=gas_estimator) - return delegation + + return DelegationController( + chain_id=chain_id, + network_provider=proxy, + gas_limit_estimator=gas_estimator, + ) + + +def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): + base = BaseTransactionsController() + base.sign_transaction( + transaction=transaction, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + guardian_service_url=guardian_and_relayer_data.guardian_service_url, + guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + ) def do_create_delegation_contract(args: Any): @@ -410,20 +432,19 @@ def do_create_delegation_contract(args: Any): ) delegation = _get_delegation_controller(args) - - tx = delegation.prepare_transaction_for_new_delegation_contract( - owner=sender, - native_amount=int(args.value), + tx = delegation.create_transaction_for_new_delegation_contract( + sender=sender, + nonce=sender.nonce, + amount=int(args.value), total_delegation_cap=int(args.total_delegation_cap), service_fee=int(args.service_fee), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -456,20 +477,19 @@ def add_new_nodes(args: Any): public_keys, signed_messages = _get_public_keys_and_signed_messages(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_adding_nodes( - owner=sender, + tx = delegation.create_transaction_for_adding_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, signed_messages=signed_messages, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -504,19 +524,18 @@ def remove_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_removing_nodes( - owner=sender, + tx = delegation.create_transaction_for_removing_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -552,19 +571,18 @@ def stake_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_staking_nodes( - owner=sender, + tx = delegation.create_transaction_for_staking_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -589,19 +607,18 @@ def unbond_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_unbonding_nodes( - owner=sender, + tx = delegation.create_transaction_for_unbonding_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -618,19 +635,18 @@ def unstake_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_unstaking_nodes( - owner=sender, + tx = delegation.create_transaction_for_unstaking_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -647,19 +663,19 @@ def unjail_nodes(args: Any): public_keys = _load_validators_public_keys(args) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_unjailing_nodes( - owner=sender, + tx = delegation.create_transaction_for_unjailing_nodes( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, + amount=int(args.value), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -673,18 +689,18 @@ def delegate(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_delegating( - owner=sender, + tx = delegation.create_transaction_for_delegating( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + amount=int(args.value), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -698,17 +714,17 @@ def claim_rewards(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_claiming_rewards( - owner=sender, + tx = delegation.create_transaction_for_claiming_rewards( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -722,17 +738,17 @@ def redelegate_rewards(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_redelegating_rewards( - owner=sender, + tx = delegation.create_transaction_for_redelegating_rewards( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -746,18 +762,18 @@ def undelegate(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_undelegating( - owner=sender, + tx = delegation.create_transaction_for_undelegating( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + amount=int(args.value), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -771,18 +787,17 @@ def withdraw(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_withdrawing( - owner=sender, + tx = delegation.create_transaction_for_withdrawing( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -796,19 +811,18 @@ def change_service_fee(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_changing_service_fee( - owner=sender, + tx = delegation.create_transaction_for_changing_service_fee( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), service_fee=int(args.service_fee), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -822,19 +836,18 @@ def modify_delegation_cap(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_modifying_delegation_cap( - owner=sender, + tx = delegation.create_transaction_for_modifying_delegation_cap( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), delegation_cap=int(args.delegation_cap), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -848,20 +861,34 @@ def automatic_activation(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_automatic_activation( - owner=sender, - delegation_contract=Address.new_from_bech32(args.delegation_contract), - set=args.set, - unset=args.unset, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, - ) + if args.set and args.unset: + raise errors.BadUsage("Cannot set and unset at the same time") + + if args.set: + tx = delegation.create_transaction_for_setting_automatic_activation( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + elif args.unset: + tx = delegation.create_transaction_for_unsetting_automatic_activation( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + else: + raise errors.BadUsage("Both set and unset automatic activation are False") + + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -875,20 +902,33 @@ def redelegate_cap(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_redelegate_cap( - owner=sender, - delegation_contract=Address.new_from_bech32(args.delegation_contract), - set=args.set, - unset=args.unset, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, - ) - + if args.set and args.unset: + raise errors.BadUsage("Cannot set and unset at the same time") + + if args.set: + tx = delegation.create_transaction_for_setting_cap_check_on_redelegate_rewards( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + elif args.unset: + tx = delegation.create_transaction_for_unsetting_cap_check_on_redelegate_rewards( + sender=sender, + nonce=sender.nonce, + delegation_contract=Address.new_from_bech32(args.delegation_contract), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + else: + raise errors.BadUsage("Either set or unset should be True") + + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -902,21 +942,20 @@ def set_metadata(args: Any): ) delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_setting_metadata( - owner=sender, + tx = delegation.create_transaction_for_setting_metadata( + sender=sender, + nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), name=args.name, website=args.website, identifier=args.identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -929,18 +968,20 @@ def make_new_contract_from_validator_data(args: Any): args=args, ) - delegation = _get_delegation_controller(args) - tx = delegation.prepare_transaction_for_creating_delegation_contract_from_validator( - owner=sender, + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + validators_controller = ValidatorsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) + + tx = validators_controller.create_transaction_for_new_delegation_contract_from_validator_data( + sender=sender, + nonce=sender.nonce, max_cap=args.max_cap, - service_fee=args.fee, + fee=args.fee, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/delegation.py b/multiversx_sdk_cli/delegation.py deleted file mode 100644 index 6526d02d..00000000 --- a/multiversx_sdk_cli/delegation.py +++ /dev/null @@ -1,806 +0,0 @@ -from typing import Optional, Union - -from multiversx_sdk import ( - Address, - DelegationTransactionsFactory, - GasLimitEstimator, - Transaction, - TransactionsFactoryConfig, - ValidatorPublicKey, -) -from multiversx_sdk.abi import BigUIntValue, Serializer - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.config_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 - -DELEGATION_MANAGER_SC_ADDRESS_HEX = "000000000000000000010000000000000000000000000000000000000004ffff" - - -class DelegationOperations(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ) -> None: - self._factory = DelegationTransactionsFactory(config=config, gas_limit_estimator=gas_limit_estimator) - self.chain_id = config.chain_id - - def prepare_transaction_for_new_delegation_contract( - self, - owner: IAccount, - native_amount: int, - total_delegation_cap: int, - service_fee: int, - gas_limit: Union[int, None], - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_new_delegation_contract( - sender=owner.address, - total_delegation_cap=total_delegation_cap, - service_fee=service_fee, - amount=native_amount, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_adding_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - signed_messages: list[bytes], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_adding_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - signed_messages=signed_messages, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_removing_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_removing_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_staking_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_staking_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_unbonding_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unbonding_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_unstaking_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unstaking_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_unjailing_nodes( - self, - owner: IAccount, - delegation_contract: Address, - public_keys: list[ValidatorPublicKey], - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unjailing_nodes( - sender=owner.address, - delegation_contract=delegation_contract, - public_keys=public_keys, - amount=value, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_delegating( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_delegating( - sender=owner.address, - delegation_contract=delegation_contract, - amount=value, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_claiming_rewards( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_claiming_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_redelegating_rewards( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_redelegating_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_undelegating( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_undelegating( - sender=owner.address, - delegation_contract=delegation_contract, - amount=value, - ) - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_withdrawing( - self, - owner: IAccount, - delegation_contract: Address, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_withdrawing( - sender=owner.address, delegation_contract=delegation_contract - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_changing_service_fee( - self, - owner: IAccount, - delegation_contract: Address, - service_fee: int, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_changing_service_fee( - sender=owner.address, - delegation_contract=delegation_contract, - service_fee=service_fee, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_modifying_delegation_cap( - self, - owner: IAccount, - delegation_contract: Address, - delegation_cap: int, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_modifying_delegation_cap( - sender=owner.address, - delegation_contract=delegation_contract, - delegation_cap=delegation_cap, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_automatic_activation( - self, - owner: IAccount, - delegation_contract: Address, - set: bool, - unset: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - if set and unset: - raise BadUsage("Cannot set and unset at the same time") - - if set: - tx = self._factory.create_transaction_for_setting_automatic_activation( - sender=owner.address, delegation_contract=delegation_contract - ) - elif unset: - tx = self._factory.create_transaction_for_unsetting_automatic_activation( - sender=owner.address, delegation_contract=delegation_contract - ) - else: - raise BadUsage("Both set and unset automatic activation are False") - - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_redelegate_cap( - self, - owner: IAccount, - delegation_contract: Address, - set: bool, - unset: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - if set and unset: - raise BadUsage("Cannot set and unset at the same time") - - if set: - tx = self._factory.create_transaction_for_setting_cap_check_on_redelegate_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - elif unset: - tx = self._factory.create_transaction_for_unsetting_cap_check_on_redelegate_rewards( - sender=owner.address, delegation_contract=delegation_contract - ) - else: - raise BadUsage("Either set or unset should be True") - - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transaction_for_setting_metadata( - self, - owner: IAccount, - delegation_contract: Address, - name: str, - website: str, - identifier: str, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_setting_metadata( - sender=owner.address, - delegation_contract=delegation_contract, - name=name, - website=website, - identifier=identifier, - ) - tx.value = value - tx.gas_price = gas_price - tx.nonce = nonce - tx.version = version - tx.options = options - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(tx) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - # will be replaced in the future once it's implemented in sdk-py - def prepare_transaction_for_creating_delegation_contract_from_validator( - self, - owner: IAccount, - max_cap: int, - service_fee: int, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - receiver = Address.new_from_hex(DELEGATION_MANAGER_SC_ADDRESS_HEX, get_address_hrp()) - - serializer = Serializer() - data = "makeNewContractFromValidatorData@" + serializer.serialize( - [BigUIntValue(max_cap), BigUIntValue(service_fee)] - ) - - tx = Transaction( - sender=owner.address, - receiver=receiver, - gas_limit=510000000, - chain_id=self.chain_id, - data=data.encode(), - nonce=nonce, - version=version, - options=options, - guardian=guardian_and_relayer_data.guardian_address, - relayer=guardian_and_relayer_data.relayer_address, - gas_price=gas_price, - value=value, - ) - - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx diff --git a/multiversx_sdk_cli/tests/test_cli_staking_provider.py b/multiversx_sdk_cli/tests/test_cli_staking_provider.py index 5c3da677..c5fd219f 100644 --- a/multiversx_sdk_cli/tests/test_cli_staking_provider.py +++ b/multiversx_sdk_cli/tests/test_cli_staking_provider.py @@ -586,7 +586,7 @@ def test_create_delegation_contract_from_validator(capsys: Any): assert data == "makeNewContractFromValidatorData@@0ea1" assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" - assert transaction["gasLimit"] == 510000000 + assert transaction["gasLimit"] == 51107000 def test_delegate(capsys: Any): diff --git a/pyproject.toml b/pyproject.toml index f6e3ab7e..8b78dfe8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ dependencies = [ "ledgercomm[hid]", "rich==13.3.4", "argcomplete==3.2.2", - "multiversx-sdk[ledger]==2.0.1" + "multiversx-sdk[ledger]==2.2.0" ] [project.scripts] diff --git a/requirements.txt b/requirements.txt index 33c1b918..01f3c357 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,4 @@ ledgercomm[hid] rich==13.3.4 argcomplete==3.2.2 -multiversx-sdk[ledger]==2.0.1 +multiversx-sdk[ledger]==2.2.0 From ccb1102b2463c8b05d0111ec5cdb1520254674d9 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 17 Sep 2025 13:37:44 +0300 Subject: [PATCH 12/33] refactoring contracts to remove wrapper --- multiversx_sdk_cli/args_converter.py | 69 +++++++ multiversx_sdk_cli/cli_contracts.py | 173 +++++++++------- multiversx_sdk_cli/cli_delegation.py | 11 +- multiversx_sdk_cli/contracts.py | 221 --------------------- multiversx_sdk_cli/signing_wrapper.py | 88 ++++++++ multiversx_sdk_cli/tests/test_contracts.py | 26 +-- multiversx_sdk_cli/tests/test_shared.py | 25 +++ 7 files changed, 286 insertions(+), 327 deletions(-) create mode 100644 multiversx_sdk_cli/args_converter.py delete mode 100644 multiversx_sdk_cli/contracts.py create mode 100644 multiversx_sdk_cli/signing_wrapper.py diff --git a/multiversx_sdk_cli/args_converter.py b/multiversx_sdk_cli/args_converter.py new file mode 100644 index 00000000..963856d9 --- /dev/null +++ b/multiversx_sdk_cli/args_converter.py @@ -0,0 +1,69 @@ +import logging +from typing import Any + +from multiversx_sdk import Address +from multiversx_sdk.abi import ( + AddressValue, + BigUIntValue, + BoolValue, + BytesValue, + StringValue, +) + +from multiversx_sdk_cli.config_env import get_address_hrp +from multiversx_sdk_cli.constants import ( + ADDRESS_PREFIX, + FALSE_STR_LOWER, + HEX_PREFIX, + MAINCHAIN_ADDRESS_HRP, + STR_PREFIX, + TRUE_STR_LOWER, +) +from multiversx_sdk_cli.errors import BadUserInput + +logger = logging.getLogger("args_converter") + + +def convert_args_to_typed_values(arguments: list[str]) -> list[Any]: + args: list[Any] = [] + + for arg in arguments: + if arg.startswith(HEX_PREFIX): + args.append(BytesValue(_hex_to_bytes(arg))) + elif arg.isnumeric(): + args.append(BigUIntValue(int(arg))) + elif arg.startswith(ADDRESS_PREFIX): + args.append(AddressValue.new_from_address(Address.new_from_bech32(arg[len(ADDRESS_PREFIX) :]))) + elif arg.startswith(MAINCHAIN_ADDRESS_HRP): + # this flow will be removed in the future + logger.warning( + "Address argument has no prefix. This flow will be removed in the future. Please provide each address using the `addr:` prefix. (e.g. --arguments addr:erd1...)" + ) + args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) + elif arg.startswith(get_address_hrp()): + args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) + elif arg.lower() == FALSE_STR_LOWER: + args.append(BoolValue(False)) + elif arg.lower() == TRUE_STR_LOWER: + args.append(BoolValue(True)) + elif arg.startswith(STR_PREFIX): + args.append(StringValue(arg[len(STR_PREFIX) :])) + else: + raise BadUserInput( + f"Unknown argument type for argument: `{arg}`. Use `mxpy contract --help` to check all supported arguments" + ) + + return args + + +def _hex_to_bytes(arg: str): + argument = arg[len(HEX_PREFIX) :] + argument = argument.upper() + argument = _ensure_even_length(argument) + return bytes.fromhex(argument) + + +def _ensure_even_length(string: str) -> str: + if len(string) % 2 == 1: + return "0" + string + return string diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index bcbc0a96..c819285c 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -11,12 +11,13 @@ AddressComputer, Message, ProxyNetworkProvider, + SmartContractController, Transaction, - TransactionsFactoryConfig, ) from multiversx_sdk.abi import Abi from multiversx_sdk_cli import cli_shared, utils +from multiversx_sdk_cli.args_converter import convert_args_to_typed_values from multiversx_sdk_cli.args_validation import ( validate_broadcast_args, validate_chain_id_args, @@ -28,9 +29,10 @@ from multiversx_sdk_cli.config_env import MxpyEnv 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.errors import DockerMissingError +from multiversx_sdk_cli.errors import DockerMissingError, QueryContractError +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.signing_wrapper import SigningWrapper from multiversx_sdk_cli.ux import show_warning logger = logging.getLogger("cli.contracts") @@ -295,6 +297,7 @@ def _add_arguments_arg(sub: Any): sub.add_argument( "--arguments", nargs="+", + default=[], help="arguments for the contract transaction, as [number, bech32-address, ascii string, " "boolean] or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba str:TOK-a1c2ef true addr:erd1[..]", ) @@ -315,6 +318,31 @@ def build(args: Any): show_warning(message) +def _initialize_controller(args: Any) -> SmartContractController: + chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" + proxy = ProxyNetworkProvider(url=proxy_url, config=config) + abi = Abi.load(Path(args.abi)) if args.abi else None + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + + return SmartContractController( + chain_id=chain_id, + network_provider=proxy, + abi=abi, + gas_limit_estimator=gas_estimator, + ) + + +def _sign_transaction(transaction: Transaction, sender: Any, guardian_and_relayer_data: GuardianRelayerData): + signer = SigningWrapper() + signer.sign_transaction( + transaction=transaction, + sender=sender, + guardian_and_relayer=guardian_and_relayer_data, + ) + + def deploy(args: Any): logger.debug("deploy") @@ -328,31 +356,25 @@ def deploy(args: Any): args=args, ) - 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 - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - contract = SmartContract(config, abi, gas_estimator) - arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - tx = contract.prepare_deploy_transaction( - owner=sender, + controller = _initialize_controller(args) + tx = controller.create_transaction_for_deploy( + sender=sender, + nonce=sender.nonce, bytecode=Path(args.bytecode), arguments=arguments, - should_prepare_args=should_prepare_args, - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, + native_transfer_amount=int(args.value), + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) address_computer = AddressComputer(NUMBER_OF_SHARDS) @@ -361,8 +383,13 @@ def deploy(args: Any): 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) + utils.log_explorer_contract_address( + chain=controller.factory.config.chain_id, + address=contract_address.to_bech32(), + explorer_url=cli_config.explorer_url, + ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract_address, args) @@ -379,36 +406,32 @@ def call(args: Any): args=args, ) - 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 - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - contract = SmartContract(config, abi, gas_estimator) - arguments, should_prepare_args = _get_contract_arguments(args) - contract_address = Address.new_from_bech32(args.contract) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - token_transfers = None + token_transfers = [] if args.token_transfers: token_transfers = cli_shared.prepare_token_transfers(args.token_transfers) - tx = contract.prepare_execute_transaction( - caller=sender, + contract_address = Address.new_from_bech32(args.contract) + controller = _initialize_controller(args) + + tx = controller.create_transaction_for_execute( + sender=sender, + nonce=sender.nonce, contract=contract_address, function=args.function, arguments=arguments, - should_prepare_args=should_prepare_args, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), + native_transfer_amount=int(args.value), token_transfers=token_transfers, - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract_address, args) @@ -425,35 +448,31 @@ def upgrade(args: Any): args=args, ) - 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 - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - contract = SmartContract(config, abi, gas_estimator) - arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) + contract_address = Address.new_from_bech32(args.contract) + controller = _initialize_controller(args) - tx = contract.prepare_upgrade_transaction( - owner=sender, + tx = controller.create_transaction_for_upgrade( + sender=sender, + nonce=sender.nonce, contract=contract_address, bytecode=Path(args.bytecode), arguments=arguments, - should_prepare_args=should_prepare_args, - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, + native_transfer_amount=int(args.value), + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - value=int(args.value), - nonce=sender.nonce, - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract_address, args) @@ -462,26 +481,32 @@ def query(args: Any): validate_proxy_argument(args) - # we don't need chainID to query a contract; we use the provided proxy - factory_config = TransactionsFactoryConfig("") abi = Abi.load(Path(args.abi)) if args.abi else None - contract = SmartContract(factory_config, abi) + contract_address = Address.new_from_bech32(args.contract) + function = args.function arguments, should_prepare_args = _get_contract_arguments(args) - contract_address = Address.new_from_bech32(args.contract) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) network_provider_config = get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=network_provider_config) - function = args.function - result = contract.query_contract( - contract_address=contract_address, - proxy=proxy, - function=function, - arguments=arguments, - should_prepare_args=should_prepare_args, + controller = SmartContractController( + chain_id="", + network_provider=proxy, + abi=abi, ) + try: + result = controller.query( + contract=contract_address, + function=function, + arguments=arguments, + ) + except Exception as e: + raise QueryContractError("Couldn't query contract: ", e) + utils.dump_out_json(result) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 941f3407..09123091 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -20,10 +20,10 @@ validate_proxy_argument, validate_receiver_args, ) -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -411,14 +411,11 @@ def _get_delegation_controller(args: Any): def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): - base = BaseTransactionsController() - base.sign_transaction( + signer = SigningWrapper() + signer.sign_transaction( transaction=transaction, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + guardian_and_relayer=guardian_and_relayer_data, ) diff --git a/multiversx_sdk_cli/contracts.py b/multiversx_sdk_cli/contracts.py deleted file mode 100644 index 91f7a7c2..00000000 --- a/multiversx_sdk_cli/contracts.py +++ /dev/null @@ -1,221 +0,0 @@ -import logging -from pathlib import Path -from typing import Any, Optional, Protocol, Union - -from multiversx_sdk import ( - Address, - AwaitingOptions, - GasLimitEstimator, - SmartContractController, - SmartContractQuery, - SmartContractQueryResponse, - SmartContractTransactionsFactory, - TokenTransfer, - Transaction, - TransactionOnNetwork, - TransactionsFactoryConfig, -) -from multiversx_sdk.abi import Abi - -from multiversx_sdk_cli import errors -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -logger = logging.getLogger("contracts") - - -# fmt: off -class INetworkProvider(Protocol): - def query_contract(self, query: SmartContractQuery) -> SmartContractQueryResponse: - ... - - def await_transaction_completed( - self, transaction_hash: Union[bytes, str], options: Optional[AwaitingOptions] = None - ) -> TransactionOnNetwork: - ... -# fmt: on - - -class SmartContract(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - abi: Optional[Abi] = None, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ): - self._abi = abi - self._config = config - self._factory = SmartContractTransactionsFactory(config, abi, gas_limit_estimator) - - def prepare_deploy_transaction( - self, - owner: IAccount, - bytecode: Path, - arguments: Union[list[Any], None], - should_prepare_args: bool, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_deploy( - sender=owner.address, - bytecode=bytecode, - gas_limit=gas_limit, - arguments=args, - native_transfer_amount=value, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_execute_transaction( - self, - caller: IAccount, - contract: Address, - function: str, - arguments: Union[list[Any], None], - should_prepare_args: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - token_transfers: Union[list[TokenTransfer], None], - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_execute( - sender=caller.address, - contract=contract, - function=function, - gas_limit=gas_limit, - arguments=args, - native_transfer_amount=value, - token_transfers=token_transfers or [], - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=caller, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_upgrade_transaction( - self, - owner: IAccount, - contract: Address, - bytecode: Path, - arguments: Union[list[str], None], - should_prepare_args: bool, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - gas_limit: Union[int, None], - gas_price: int, - value: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_upgrade( - sender=owner.address, - contract=contract, - bytecode=bytecode, - gas_limit=gas_limit, - arguments=args, - native_transfer_amount=value, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def query_contract( - self, - contract_address: Address, - proxy: INetworkProvider, - function: str, - arguments: Optional[list[Any]], - should_prepare_args: bool, - ) -> list[Any]: - args = arguments if arguments else [] - if should_prepare_args: - args = self._convert_args_to_typed_values(args) - - sc_query_controller = SmartContractController(self._config.chain_id, proxy, self._abi) - - try: - response = sc_query_controller.query(contract=contract_address, function=function, arguments=args) - except Exception as e: - raise errors.QueryContractError("Couldn't query contract: ", e) - - return response diff --git a/multiversx_sdk_cli/signing_wrapper.py b/multiversx_sdk_cli/signing_wrapper.py new file mode 100644 index 00000000..4fa4198a --- /dev/null +++ b/multiversx_sdk_cli/signing_wrapper.py @@ -0,0 +1,88 @@ +from typing import Optional, Union + +from multiversx_sdk import LedgerAccount, Transaction, TransactionComputer + +from multiversx_sdk_cli.cosign_transaction import cosign_transaction +from multiversx_sdk_cli.errors import TransactionSigningError +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount + + +class SigningWrapper: + def __init__(self): + pass + + def sign_transaction( + self, + transaction: Transaction, + sender: Optional[IAccount] = None, + guardian_and_relayer: GuardianRelayerData = GuardianRelayerData(), + ): + """Signs the transaction using the sender's account and, if required, additionally signs with the guardian's and relayer's accounts. Ensures the appropriate transaction options are set as needed.""" + self._set_options_for_guarded_transaction_if_needed(transaction) + + guardian = guardian_and_relayer.guardian + relayer = guardian_and_relayer.relayer + guardian_service_url = guardian_and_relayer.guardian_service_url + guardian_2fa_code = guardian_and_relayer.guardian_2fa_code + + self._set_options_for_hash_signing_if_needed(transaction, sender, guardian, relayer) + + if sender: + try: + transaction.signature = sender.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") + + self._sign_guarded_transaction_if_guardian( + transaction, + guardian, + guardian_service_url, + guardian_2fa_code, + ) + self._sign_relayed_transaction_if_relayer(transaction, relayer) + + def _set_options_for_guarded_transaction_if_needed(self, transaction: Transaction): + if transaction.guardian: + transaction_computer = TransactionComputer() + transaction_computer.apply_guardian(transaction, transaction.guardian) + + def _set_options_for_hash_signing_if_needed( + self, + transaction: Transaction, + sender: Union[IAccount, None], + guardian: Union[IAccount, None], + relayer: Union[IAccount, None], + ): + if ( + isinstance(sender, LedgerAccount) + or isinstance(guardian, LedgerAccount) + or isinstance(relayer, LedgerAccount) + ): + transaction_computer = TransactionComputer() + transaction_computer.apply_options_for_hash_signing(transaction) + + def _sign_guarded_transaction_if_guardian( + self, + transaction: Transaction, + guardian: Union[IAccount, None], + guardian_service_url: Union[str, None], + guardian_2fa_code: Union[str, None], + ) -> Transaction: + # If the guardian account is provided, we sign locally. Otherwise, we reach for the trusted cosign service. + if guardian: + try: + transaction.guardian_signature = guardian.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") + elif transaction.guardian and guardian_service_url and guardian_2fa_code: + cosign_transaction(transaction, guardian_service_url, guardian_2fa_code) + + return transaction + + def _sign_relayed_transaction_if_relayer(self, transaction: Transaction, relayer: Union[IAccount, None]): + if relayer and transaction.relayer: + try: + transaction.relayer_signature = relayer.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") diff --git a/multiversx_sdk_cli/tests/test_contracts.py b/multiversx_sdk_cli/tests/test_contracts.py index d3397f99..21f8b59d 100644 --- a/multiversx_sdk_cli/tests/test_contracts.py +++ b/multiversx_sdk_cli/tests/test_contracts.py @@ -2,10 +2,9 @@ from pathlib import Path from Cryptodome.Hash import keccak -from multiversx_sdk import Account, Address, TransactionsFactoryConfig +from multiversx_sdk import Account, Address from multiversx_sdk_cli.contract_verification import _create_request_signature -from multiversx_sdk_cli.contracts import SmartContract logging.basicConfig(level=logging.INFO) @@ -27,26 +26,3 @@ def test_contract_verification_create_request_signature(): signature.hex() == "30111258cc42ea08e0c6a3e053cc7086a88d614b8b119a244904e9a19896c73295b2fe5c520a1cb07cfe20f687deef9f294a0a05071e85c78a70a448ea5f0605" ) - - -def test_prepare_args_for_factories(): - sc = SmartContract(TransactionsFactoryConfig("mock")) - args = [ - "0x5", - "123", - "false", - "true", - "str:test-string", - "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - ] - - arguments = sc._convert_args_to_typed_values(args) - assert arguments[0].get_payload() == b"\x05" - assert arguments[1].get_payload() == 123 - assert arguments[2].get_payload() is False - assert arguments[3].get_payload() is True - assert arguments[4].get_payload() == "test-string" - assert ( - arguments[5].get_payload() - == Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th").get_public_key() - ) diff --git a/multiversx_sdk_cli/tests/test_shared.py b/multiversx_sdk_cli/tests/test_shared.py index 53c8b21d..8c21bac5 100644 --- a/multiversx_sdk_cli/tests/test_shared.py +++ b/multiversx_sdk_cli/tests/test_shared.py @@ -1,3 +1,6 @@ +from multiversx_sdk import Address + +from multiversx_sdk_cli.args_converter import convert_args_to_typed_values from multiversx_sdk_cli.cli_shared import prepare_token_transfers @@ -31,3 +34,25 @@ def test_prepare_token_tranfers(): assert transfers[3].token.identifier == "META-777777" assert transfers[3].token.nonce == 16 assert transfers[3].amount == 123456789 + + +def test_prepare_args_for_factories(): + args = [ + "0x5", + "123", + "false", + "true", + "str:test-string", + "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + ] + + arguments = convert_args_to_typed_values(args) + assert arguments[0].get_payload() == b"\x05" + assert arguments[1].get_payload() == 123 + assert arguments[2].get_payload() is False + assert arguments[3].get_payload() is True + assert arguments[4].get_payload() == "test-string" + assert ( + arguments[5].get_payload() + == Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th").get_public_key() + ) From 340674af1337baeebde7008ee00592f690382d81 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 17 Sep 2025 17:04:58 +0300 Subject: [PATCH 13/33] remove governance wrapper --- multiversx_sdk_cli/cli_governance.py | 119 ++++++------ multiversx_sdk_cli/governance.py | 269 --------------------------- 2 files changed, 63 insertions(+), 325 deletions(-) delete mode 100644 multiversx_sdk_cli/governance.py diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index f4b240b0..453af433 100644 --- a/multiversx_sdk_cli/cli_governance.py +++ b/multiversx_sdk_cli/cli_governance.py @@ -7,7 +7,8 @@ GovernanceController, ProposalInfo, ProxyNetworkProvider, - TransactionsFactoryConfig, + Transaction, + VoteType, ) from multiversx_sdk_cli import cli_shared, utils @@ -18,7 +19,10 @@ ) from multiversx_sdk_cli.cli_output import CLIOutputBuilder from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.governance import GovernanceWrapper +from multiversx_sdk_cli.config_env import get_address_hrp +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -196,6 +200,31 @@ def _ensure_args(args: Any): validate_chain_id_args(args) +def _initialize_controller(args: Any) -> GovernanceController: + chain = args.chain if hasattr(args, "chain") else None + chain_id = cli_shared.get_chain_id(args.proxy, chain) + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" + proxy = ProxyNetworkProvider(url=proxy_url, config=config) + gas_estimator = cli_shared.initialize_gas_limit_estimator(args) + + return GovernanceController( + chain_id=chain_id, + network_provider=proxy, + address_hrp=get_address_hrp(), + gas_limit_estimator=gas_estimator, + ) + + +def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): + signer = SigningWrapper() + signer.sign_transaction( + transaction=transaction, + sender=sender, + guardian_and_relayer=guardian_and_relayer_data, + ) + + def create_proposal(args: Any): _ensure_args(args) @@ -204,10 +233,8 @@ def create_proposal(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_new_proposal( sender=sender, nonce=sender.nonce, @@ -215,13 +242,13 @@ def create_proposal(args: Any): start_vote_epoch=args.start_vote_epoch, end_vote_epoch=args.end_vote_epoch, native_token_amount=args.value, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -233,22 +260,22 @@ def vote(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + + [vote_value] = [v for v in VoteType if v.value == args.vote] + controller = _initialize_controller(args) transaction = controller.create_transaction_for_voting( sender=sender, nonce=sender.nonce, proposal_nonce=args.proposal_nonce, - vote=args.vote, + vote=vote_value, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -260,21 +287,19 @@ def close_proposal(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_closing_proposal( sender=sender, nonce=sender.nonce, proposal_nonce=args.proposal_nonce, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -286,22 +311,21 @@ def clear_ended_proposals(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) proposers = [Address.new_from_bech32(proposer) for proposer in args.proposers] + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_clearing_ended_proposals( sender=sender, nonce=sender.nonce, proposers=proposers, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -313,20 +337,18 @@ def claim_accumulated_fees(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_claiming_accumulated_fees( sender=sender, nonce=sender.nonce, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) @@ -338,10 +360,8 @@ def change_config(args: Any): sender=sender.address.to_bech32(), args=args, ) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) - gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = GovernanceWrapper(config=TransactionsFactoryConfig(chain_id), gas_limit_estimator=gas_estimator) + controller = _initialize_controller(args) transaction = controller.create_transaction_for_changing_config( sender=sender, nonce=sender.nonce, @@ -350,24 +370,20 @@ def change_config(args: Any): min_quorum=args.min_quorum, min_veto_threshold=args.min_veto_threshold, min_pass_threshold=args.min_pass_threshold, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) def get_voting_power(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) - + controller = _initialize_controller(args) user = Address.new_from_bech32(args.user) voting_power = controller.get_voting_power(user) @@ -377,10 +393,7 @@ def get_voting_power(args: Any): def get_config(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) + controller = _initialize_controller(args) contract_config = controller.get_config() utils.dump_out_json(_config_to_dict(contract_config)) @@ -389,10 +402,7 @@ def get_config(args: Any): def get_proposal(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) + controller = _initialize_controller(args) info = controller.get_proposal(args.proposal_nonce) utils.dump_out_json(_proposal_to_dict(info)) @@ -401,10 +411,7 @@ def get_proposal(args: Any): def get_delegated_vote_info(args: Any): validate_proxy_argument(args) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - controller = GovernanceController(chain_id, proxy) + controller = _initialize_controller(args) contract = Address.new_from_bech32(args.contract) user = Address.new_from_bech32(args.user) diff --git a/multiversx_sdk_cli/governance.py b/multiversx_sdk_cli/governance.py deleted file mode 100644 index 8477c4f1..00000000 --- a/multiversx_sdk_cli/governance.py +++ /dev/null @@ -1,269 +0,0 @@ -from typing import Optional, Union - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - GovernanceTransactionsFactory, - Transaction, - TransactionsFactoryConfig, - VoteType, -) - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - - -class GovernanceWrapper(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ) -> None: - self.factory = GovernanceTransactionsFactory(config=config, gas_limit_estimator=gas_limit_estimator) - - def create_transaction_for_new_proposal( - self, - sender: IAccount, - nonce: int, - commit_hash: str, - start_vote_epoch: int, - end_vote_epoch: int, - native_token_amount: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_new_proposal( - sender=sender.address, - commit_hash=commit_hash, - start_vote_epoch=start_vote_epoch, - end_vote_epoch=end_vote_epoch, - native_token_amount=native_token_amount, - ) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_voting( - self, - sender: IAccount, - nonce: int, - proposal_nonce: int, - vote: str, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - vote_value = self._vote_type_from_string(vote) - - tx = self.factory.create_transaction_for_voting( - sender=sender.address, proposal_nonce=proposal_nonce, vote=vote_value - ) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_closing_proposal( - self, - sender: IAccount, - nonce: int, - proposal_nonce: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_closing_proposal(sender=sender.address, proposal_nonce=proposal_nonce) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_clearing_ended_proposals( - self, - sender: IAccount, - nonce: int, - proposers: list[Address], - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_clearing_ended_proposals(sender=sender.address, proposers=proposers) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_claiming_accumulated_fees( - self, - sender: IAccount, - nonce: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_claiming_accumulated_fees(sender=sender.address) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def create_transaction_for_changing_config( - self, - sender: IAccount, - nonce: int, - proposal_fee: int, - lost_proposal_fee: int, - min_quorum: int, - min_veto_threshold: int, - min_pass_threshold: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self.factory.create_transaction_for_changing_config( - sender=sender.address, - proposal_fee=proposal_fee, - lost_proposal_fee=lost_proposal_fee, - min_quorum=min_quorum, - min_veto_threshold=min_veto_threshold, - min_pass_threshold=min_pass_threshold, - ) - self._set_transaction_fields( - transaction=tx, - nonce=nonce, - version=version, - options=options, - gas_price=gas_price, - guardian_and_relayer_data=guardian_and_relayer_data, - ) - - self.add_extra_gas_limit_if_required(tx) - if gas_limit: - tx.gas_limit = gas_limit - - self.sign_transaction( - transaction=tx, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def _vote_type_from_string(self, value: str) -> VoteType: - for vote in VoteType: - if vote.value == value: - return vote - raise ValueError(f"Unknown vote type: {value}") From 42cd3ec1f128e93ff5ab13125a7af2eb9b15d895 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 18 Sep 2025 10:53:03 +0300 Subject: [PATCH 14/33] more token management operations & fixes from previous PR --- multiversx_sdk_cli/cli_tokens.py | 1102 +++++++++++++++++++- multiversx_sdk_cli/tests/test_cli_token.py | 944 ++++++++++++++++- 2 files changed, 1986 insertions(+), 60 deletions(-) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index 08939093..e8a2dfd0 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -204,6 +204,333 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: add_common_args(args, sub) sub.set_defaults(func=create_nft) + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "pause", + "Pause a token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=pause_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unpause", + "Unpause a token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unpause_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "freeze", + "Freeze a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=freeze_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unfreeze", + "Unfreeze a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unfreeze_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "wipe", + "Wipe a token for a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=wipe_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "local-mint", + "Mint new tokens.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--supply-to-mint", required=True, type=int, help="The amount of new tokens to mint") + add_common_args(args, sub) + sub.set_defaults(func=local_mint) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "local-burn", + "Burn tokens.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--supply-to-burn", required=True, type=int, help="The amount of tokens to burn") + add_common_args(args, sub) + sub.set_defaults(func=local_burn) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-attributes", + "Update token attributes.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--attributes", required=True, type=str, help="The hex-string attributes of the token") + add_common_args(args, sub) + sub.set_defaults(func=update_attributes) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "add-quantity", + "Increase token quantity.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--quantity", required=True, type=int, help="The quantity to add") + add_common_args(args, sub) + sub.set_defaults(func=add_quantity) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "burn-quantity", + "Burn token quantity.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--quantity", required=True, type=int, help="The quantity to burn") + add_common_args(args, sub) + sub.set_defaults(func=burn_quantity) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "modify-royalties", + "Modify token royalties.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") + add_common_args(args, sub) + sub.set_defaults(func=modify_royalties) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "set-new-uris", + "Set new uris.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=set_new_uris) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "modify-creator", + "Modify the creator of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + add_common_args(args, sub) + sub.set_defaults(func=modify_creator) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-metadata", + "Update the metadata of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") + sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") + sub.add_argument( + "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" + ) + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=update_metadata) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "nft-metadata-recreate", + "Recreate the metadata of the token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + sub.add_argument("--token-name", required=True, type=str, help="The new name of the token") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") + sub.add_argument("--hash", required=True, type=str, help="The new hash of the token") + sub.add_argument( + "--attributes", required=True, type=str, help="The new attributes of the token as a hex-encoded string" + ) + sub.add_argument("--uris", required=True, nargs="+", help="The new uris") + add_common_args(args, sub) + sub.set_defaults(func=nft_metadata_recreate) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "change-to-dynamic", + "Change a token to a dynamic token.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=change_to_dynamic) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "update-token-id", + "Update token id.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=update_token_id) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "register-dynamic", + "Register a dynamic token.", + ) + sub.add_argument("--token-name", type=str, required=True, help="The token name") + sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") + sub.add_argument( + "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" + ) + sub.add_argument( + "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" + ) + add_common_args(args, sub) + sub.set_defaults(func=register_dynamic_token) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "register-dynamic-and-set-all-roles", + "Register a dynamic token and set all roles.", + ) + sub.add_argument("--token-name", type=str, required=True, help="The token name") + sub.add_argument("--token-ticker", type=str, required=True, help="The token ticker") + sub.add_argument( + "--token-type", type=str, required=True, choices=["NFT", "SFT", "FNG", "META"], help="The token type" + ) + sub.add_argument( + "--denominator", type=int, default=None, help="The number of decimals, only needed when token type is META ESDT" + ) + add_common_args(args, sub) + sub.set_defaults(func=register_dynamic_and_set_all_roles) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "transfer-ownership", + "Transfer the ownership of a token to another user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--new-owner", type=str, required=True, help="The new token owner") + add_common_args(args, sub) + sub.set_defaults(func=transfer_ownership) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "freeze-single-nft", + "Freeze the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=freeze_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "unfreeze-single-nft", + "Unfreeze the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=unfreeze_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "change-sft-to-meta-esdt", + "Change a semi fungible token to a Meta ESDT.", + ) + sub.add_argument("--collection", required=True, type=str, help="The collection identifier") + sub.add_argument("--decimals", type=int, required=True, help="The number of decimals the meta esdt will have") + add_common_args(args, sub) + sub.set_defaults(func=change_sft_to_meta_esdt) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "transfer-nft-create-role", + "Transfer the nft create role to a user.", + ) + _add_token_identifier_arg(sub) + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=transfer_nft_create_role) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "stop-nft-creation", + "Stop the creation of new NFTs.", + ) + _add_token_identifier_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=stop_nft_creation) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "wipe-single-nft", + "Wipe the NFT of a user.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") + _add_user_arg(sub) + add_common_args(args, sub) + sub.set_defaults(func=wipe_single_nft) + + sub = cli_shared.add_command_subparser( + subparsers, + "token", + "add-uris", + "Add uris for a token.", + ) + _add_token_identifier_arg(sub) + sub.add_argument("--token-nonce", type=int, required=True, help="The nonce of the NFT as a decimal number") + sub.add_argument("--uris", nargs="+", required=True, help="The new uris to be added to the token.") + add_common_args(args, sub) + sub.set_defaults(func=add_uris) + parser.epilog = cli_shared.build_group_epilog(subparsers) return subparsers @@ -252,42 +579,42 @@ def add_issuing_tokens_args( ) sub.add_argument( - "--can-not-freeze", + "--cannot-freeze", action="store_false", dest="can_freeze", default=True, help="make token not freezable", ) sub.add_argument( - "--can-not-wipe", + "--cannot-wipe", action="store_false", dest="can_wipe", default=True, - help="make token not wipable", + help="make token not wipeable", ) sub.add_argument( - "--can-not-pause", + "--cannot-pause", action="store_false", dest="can_pause", default=True, help="make token not pausable", ) sub.add_argument( - "--can-not-change-owner", + "--cannot-change-owner", action="store_false", dest="can_change_owner", default=True, help="don't allow changing the token's owner", ) sub.add_argument( - "--can-not-upgrade", + "--cannot-upgrade", action="store_false", dest="can_upgrade", default=True, help="don't allow upgrading the token", ) sub.add_argument( - "--can-not-add-special-roles", + "--cannot-add-special-roles", action="store_false", dest="can_add_special_roles", default=True, @@ -296,11 +623,11 @@ def add_issuing_tokens_args( if with_transfer_nft_create_role: sub.add_argument( - "--can-not-transfer-nft-create-role", + "--cannot-transfer-nft-create-role", action="store_false", dest="can_transfer_nft_create_role", default=True, - help="don't allow for nft create roles to be transfered for the token", + help="don't allow for nft create roles to be transferred for the token", ) @@ -493,24 +820,9 @@ def _add_special_roles_args_for_semi_fungible(sub: Any, with_nft_create: bool = ) -def validate_token_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): - if with_initial_supply and args.initial_supply < 0: - raise ValueError("Initial supply must be a non-negative integer") - - if with_num_decimals and not (0 <= args.num_decimals <= 18): - raise ValueError("Number of decimals must be between 0 and 18") - - if not (3 <= len(args.token_name) <= 20) or not args.token_name.isalnum(): - raise ValueError("Token name must be 3-20 alphanumerical characters") - - if not (3 <= len(args.token_ticker) <= 10) or not args.token_ticker.isalnum() or not args.token_ticker.isupper(): - raise ValueError("Token ticker must be 3-10 UPPERCASE alphanumerical characters") - - -def _ensure_issue_args(args: Any, with_initial_supply: bool = False, with_num_decimals: bool = False): +def _ensure_args(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) - validate_token_args(args, with_initial_supply, with_num_decimals) def _initialize_controller(args: Any) -> TokenManagementController: @@ -538,7 +850,7 @@ def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_r def issue_fungible(args: Any): - _ensure_issue_args(args, with_initial_supply=True, with_num_decimals=True) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -571,7 +883,7 @@ def issue_fungible(args: Any): def issue_semi_fungible(args: Any): - _ensure_issue_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -603,7 +915,7 @@ def issue_semi_fungible(args: Any): def issue_non_fungible(args: Any): - _ensure_issue_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -635,7 +947,7 @@ def issue_non_fungible(args: Any): def register_meta_esdt(args: Any): - _ensure_issue_args(args, with_num_decimals=True) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -668,7 +980,7 @@ def register_meta_esdt(args: Any): def register_and_set_all_roles(args: Any): - _ensure_issue_args(args, with_num_decimals=True) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -697,8 +1009,7 @@ def register_and_set_all_roles(args: Any): def set_burn_role_globally(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -722,8 +1033,7 @@ def set_burn_role_globally(args: Any): def unset_burn_role_globally(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -747,8 +1057,7 @@ def unset_burn_role_globally(args: Any): def set_special_role_on_fungible(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -776,8 +1085,7 @@ def set_special_role_on_fungible(args: Any): def unset_special_role_on_fungible(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -805,8 +1113,7 @@ def unset_special_role_on_fungible(args: Any): def set_special_role_on_semi_fungible(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -840,8 +1147,7 @@ def set_special_role_on_semi_fungible(args: Any): def unset_special_role_on_semi_fungible(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -874,8 +1180,7 @@ def unset_special_role_on_semi_fungible(args: Any): def set_special_role_on_meta_esdt(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -904,8 +1209,7 @@ def set_special_role_on_meta_esdt(args: Any): def unset_special_role_on_meta_esdt(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -933,8 +1237,7 @@ def unset_special_role_on_meta_esdt(args: Any): def set_special_role_on_nft(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -969,8 +1272,7 @@ def set_special_role_on_nft(args: Any): def unset_special_role_on_nft(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -1004,8 +1306,7 @@ def unset_special_role_on_nft(args: Any): def create_nft(args: Any): - validate_broadcast_args(args) - validate_chain_id_args(args) + _ensure_args(args) sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -1032,3 +1333,700 @@ def create_nft(args: Any): _sign_transaction(transaction, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(transaction, args) + + +def pause_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_pausing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def unpause_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unpausing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def freeze_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_freezing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def unfreeze_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unfreezing( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def wipe_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_wiping( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def local_mint(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_local_minting( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + supply_to_mint=args.supply_to_mint, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def local_burn(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_local_burning( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + supply_to_burn=args.supply_to_burn, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def update_attributes(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_updating_attributes( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + attributes=bytes.fromhex(args.attributes), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def add_quantity(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_adding_quantity( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + quantity_to_add=args.quantity, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def burn_quantity(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_burning_quantity( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + quantity_to_burn=args.quantity, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def modify_royalties(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_modifying_royalties( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_royalties=args.royalties, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def set_new_uris(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_setting_new_uris( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def modify_creator(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_modifying_creator( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def update_metadata(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_updating_metadata( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_token_name=args.token_name, + new_royalties=args.royalties, + new_hash=args.hash, + new_attributes=bytes.fromhex(args.attributes), + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def nft_metadata_recreate(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_nft_metadata_recreate( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + new_token_name=args.token_name, + new_royalties=args.royalties, + new_hash=args.hash, + new_attributes=bytes.fromhex(args.attributes), + new_uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def change_to_dynamic(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_changing_token_to_dynamic( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def update_token_id(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_updating_token_id( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def register_dynamic_token(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + + transaction = controller.create_transaction_for_registering_dynamic_token( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + token_type=token_type, + denominator=args.denominator, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def register_dynamic_and_set_all_roles(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + [token_type] = [token_type for token_type in TokenType if token_type.value == args.token_type] + + transaction = controller.create_transaction_for_registering_dynamic_and_setting_roles( + sender=sender, + nonce=sender.nonce, + token_name=args.token_name, + token_ticker=args.token_ticker, + token_type=token_type, + denominator=args.denominator, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def transfer_ownership(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_transferring_ownership( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + new_owner=Address.new_from_bech32(args.new_owner), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def freeze_single_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_freezing_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def unfreeze_single_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_unfreezing_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def change_sft_to_meta_esdt(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_changing_sft_to_meta_esdt( + sender=sender, + nonce=sender.nonce, + collection=args.collection, + num_decimals=args.decimals, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def transfer_nft_create_role(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_transferring_nft_create_role( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def stop_nft_creation(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_stopping_nft_creation( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def wipe_single_nft(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_wiping_single_nft( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + user=Address.new_from_bech32(args.user), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) + + +def add_uris(args: Any): + _ensure_args(args) + + sender = cli_shared.prepare_sender(args) + guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( + sender=sender.address.to_bech32(), + args=args, + ) + + controller = _initialize_controller(args) + transaction = controller.create_transaction_for_adding_uris( + sender=sender, + nonce=sender.nonce, + token_identifier=args.token_identifier, + token_nonce=args.token_nonce, + uris=args.uris, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/tests/test_cli_token.py b/multiversx_sdk_cli/tests/test_cli_token.py index fb16cbcf..05b8a916 100644 --- a/multiversx_sdk_cli/tests/test_cli_token.py +++ b/multiversx_sdk_cli/tests/test_cli_token.py @@ -25,8 +25,8 @@ def test_issue_fungible(capsys: Any): "100", "--num-decimals", "0", - "--can-not-upgrade", - "--can-not-add-special-roles", + "--cannot-upgrade", + "--cannot-add-special-roles", "--pem", str(user), "--nonce", @@ -58,8 +58,8 @@ def test_issue_semi_fungible(capsys: Any): "FRANK", "--token-ticker", "FRANK", - "--can-not-upgrade", - "--can-not-add-special-roles", + "--cannot-upgrade", + "--cannot-add-special-roles", "--pem", str(user), "--nonce", @@ -91,8 +91,8 @@ def test_issue_non_fungible(capsys: Any): "FRANK", "--token-ticker", "FRANK", - "--can-not-upgrade", - "--can-not-add-special-roles", + "--cannot-upgrade", + "--cannot-add-special-roles", "--pem", str(user), "--nonce", @@ -126,8 +126,8 @@ def test_register_meta_esdt(capsys: Any): "FRANK", "--num-decimals", "10", - "--can-not-upgrade", - "--can-not-add-special-roles", + "--cannot-upgrade", + "--cannot-add-special-roles", "--pem", str(user), "--nonce", @@ -528,6 +528,934 @@ def test_unset_special_roles_on_meta_esdt(capsys: Any): ) +def test_pause_token(capsys: Any): + return_code = main( + [ + "token", + "pause", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "pause@4652414e4b2d313163653365" + + +def test_unpause_token(capsys: Any): + return_code = main( + [ + "token", + "unpause", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unPause@4652414e4b2d313163653365" + + +def test_freeze_token(capsys: Any): + return_code = main( + [ + "token", + "freeze", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "freeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_unfreeze_token(capsys: Any): + return_code = main( + [ + "token", + "unfreeze", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unFreeze@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_local_mint(capsys: Any): + return_code = main( + [ + "token", + "local-mint", + "--token-identifier", + "FRANK-11ce3e", + "--supply-to-mint", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTLocalMint@4652414e4b2d313163653365@0a" + + +def test_local_burn(capsys: Any): + return_code = main( + [ + "token", + "local-burn", + "--token-identifier", + "FRANK-11ce3e", + "--supply-to-burn", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTLocalBurn@4652414e4b2d313163653365@0a" + + +def test_update_attributes(capsys: Any): + return_code = main( + [ + "token", + "update-attributes", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--attributes", + "74657374", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTUpdateAttributes@4652414e4b2d313163653365@0a@74657374" + + +def test_add_quantity(capsys: Any): + return_code = main( + [ + "token", + "add-quantity", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--quantity", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTAddQuantity@4652414e4b2d313163653365@0a@0a" + + +def test_burn_quantity(capsys: Any): + return_code = main( + [ + "token", + "burn-quantity", + "--token-identifier", + "FRANK-11ce3e", + "--token-nonce", + "10", + "--quantity", + "10", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTBurn@4652414e4b2d313163653365@0a@0a" + + +def test_set_burn_role_globally(capsys: Any): + return_code = main( + [ + "token", + "set-burn-role-globally", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "setBurnRoleGlobally@4652414e4b2d313163653365" + + +def test_unset_burn_role_globally(capsys: Any): + return_code = main( + [ + "token", + "unset-burn-role-globally", + "--token-identifier", + "FRANK-11ce3e", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "unsetBurnRoleGlobally@4652414e4b2d313163653365" + + +def test_wipe(capsys: Any): + return_code = main( + [ + "token", + "wipe", + "--token-identifier", + "FRANK-11ce3e", + "--user", + grace, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "wipe@4652414e4b2d313163653365@1e8a8b6b49de5b7be10aaa158a5a6a4abb4b56cc08f524bb5e6cd5f211ad3e13" + + +def test_modify_royalties(capsys: Any): + return_code = main( + [ + "token", + "modify-royalties", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--royalties", + "1234", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTModifyRoyalties@544553542d313233343536@01@04d2" + + +def test_set_new_uris(capsys: Any): + return_code = main( + [ + "token", + "set-new-uris", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTSetNewURIs@544553542d313233343536@01@6669727374555249@7365636f6e64555249" + + +def test_modify_creator(capsys: Any): + return_code = main( + [ + "token", + "modify-creator", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTModifyCreator@544553542d313233343536@01" + + +def test_update_metadata(capsys: Any): + return_code = main( + [ + "token", + "update-metadata", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--token-name", + "Test", + "--royalties", + "1234", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "ESDTMetaDataUpdate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" + ) + + +def test_recreate_metadata(capsys: Any): + return_code = main( + [ + "token", + "nft-metadata-recreate", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--token-name", + "Test", + "--royalties", + "1234", + "--hash", + "abba", + "--attributes", + "74657374", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == user_address + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "ESDTMetaDataRecreate@544553542d313233343536@01@54657374@04d2@61626261@74657374@6669727374555249@7365636f6e64555249" + ) + + +def test_change_token_to_dynamic(capsys: Any): + return_code = main( + [ + "token", + "change-to-dynamic", + "--token-identifier", + "TEST-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "changeToDynamic@544553542d313233343536" + + +def test_update_token_id(capsys: Any): + return_code = main( + [ + "token", + "update-token-id", + "--token-identifier", + "TEST-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "updateTokenID@544553542d313233343536" + + +def test_register_dynamic(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic", + "--token-name", + "Test", + "--token-ticker", + "TEST-123456", + "--token-type", + "SFT", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerDynamic@54657374@544553542d313233343536@534654" + + +def test_register_dynamic_and_set_all_roles(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic-and-set-all-roles", + "--token-name", + "Test", + "--token-ticker", + "TEST-123456", + "--token-type", + "SFT", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRolesDynamic@54657374@544553542d313233343536@534654" + + +def test_register_dynamic_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic", + "--token-name", + "Test", + "--token-ticker", + "TEST-987654", + "--token-type", + "META", + "--denominator", + "18", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerDynamic@54657374@544553542d393837363534@4d455441@12" + + +def test_register_dynamic_and_set_all_roles_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "register-dynamic-and-set-all-roles", + "--token-name", + "Test", + "--token-ticker", + "TEST-987654", + "--token-type", + "META", + "--denominator", + "18", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "50000000000000000" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "registerAndSetAllRolesDynamic@54657374@544553542d393837363534@4d455441@12" + + +def test_transfer_ownership(capsys: Any): + return_code = main( + [ + "token", + "transfer-ownership", + "--token-identifier", + "AND-1d56f2", + "--new-owner", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "transferOwnership@414e442d316435366632@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_freeze_single_nft(capsys: Any): + return_code = main( + [ + "token", + "freeze-single-nft", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "freezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_unfreeze_single_nft(capsys: Any): + return_code = main( + [ + "token", + "unfreeze-single-nft", + "--token-identifier", + "TEST-123456", + "--token-nonce", + "1", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "unFreezeSingleNFT@544553542d313233343536@01@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_change_sft_to_meta_esdt(capsys: Any): + return_code = main( + [ + "token", + "change-sft-to-meta-esdt", + "--collection", + "SFT-123456", + "--decimals", + "6", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "changeSFTToMetaESDT@5346542d313233343536@06" + + +def test_transfer_nft_create_role(capsys: Any): + return_code = main( + [ + "token", + "transfer-nft-create-role", + "--token-identifier", + "SFT-123456", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data + == "transferNFTCreateRole@5346542d313233343536@c0006edaaee4fd479f2f248b341eb11eaecaec4d7dee190619958332bba5200f@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_stop_nft_create(capsys: Any): + return_code = main( + [ + "token", + "stop-nft-creation", + "--token-identifier", + "SFT-123456", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "stopNFTCreate@5346542d313233343536" + + +def test_wipe_single_nft(capsys: Any): + return_code = main( + [ + "token", + "wipe-single-nft", + "--token-identifier", + "SFT-123456", + "--token-nonce", + "10", + "--user", + frank, + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert ( + data == "wipeSingleNFT@5346542d313233343536@0a@b37f5d130beb8885b90ab574a8bfcdd894ca531a7d3d1f3431158d77d6185fbb" + ) + + +def test_add_uris(capsys: Any): + return_code = main( + [ + "token", + "add-uris", + "--token-identifier", + "SFT-123456", + "--token-nonce", + "10", + "--uris", + "firstURI", + "secondURI", + "--pem", + str(user), + "--nonce", + "7", + "--chain", + "D", + ] + ) + assert not return_code + + transaction = get_transaction(capsys) + assert transaction["sender"] == user_address + assert transaction["receiver"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["value"] == "0" + assert transaction["chainID"] == "D" + data = base64.b64decode(transaction["data"]).decode() + assert data == "ESDTNFTAddURI@5346542d313233343536@0a@6669727374555249@7365636f6e64555249" + + def _read_stdout(capsys: Any) -> str: stdout: str = capsys.readouterr().out.strip() return stdout From 5a5c0cfac08ba3f448f022a31574e2c64d7513e9 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 18 Sep 2025 14:08:07 +0300 Subject: [PATCH 15/33] remove multisig wrapper --- multiversx_sdk_cli/cli_governance.py | 3 +- multiversx_sdk_cli/cli_multisig.py | 416 ++++++------ multiversx_sdk_cli/cli_shared.py | 8 +- multiversx_sdk_cli/multisig.py | 922 --------------------------- 4 files changed, 223 insertions(+), 1126 deletions(-) delete mode 100644 multiversx_sdk_cli/multisig.py diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index 453af433..81ad2553 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.config_env import get_address_hrp from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount from multiversx_sdk_cli.signing_wrapper import SigningWrapper @@ -211,7 +210,7 @@ def _initialize_controller(args: Any) -> GovernanceController: return GovernanceController( chain_id=chain_id, network_provider=proxy, - address_hrp=get_address_hrp(), + address_hrp=cli_shared.get_address_hrp_with_fallback(args), gas_limit_estimator=gas_estimator, ) diff --git a/multiversx_sdk_cli/cli_multisig.py b/multiversx_sdk_cli/cli_multisig.py index fe042cb9..f44294cb 100644 --- a/multiversx_sdk_cli/cli_multisig.py +++ b/multiversx_sdk_cli/cli_multisig.py @@ -23,11 +23,11 @@ SendTransferExecuteEgld, SendTransferExecuteEsdt, Transaction, - TransactionsFactoryConfig, ) from multiversx_sdk.abi import Abi from multiversx_sdk_cli import cli_shared, utils +from multiversx_sdk_cli.args_converter import convert_args_to_typed_values from multiversx_sdk_cli.args_validation import ( validate_broadcast_args, validate_chain_id_args, @@ -37,7 +37,9 @@ 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.multisig import MultisigWrapper +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper logger = logging.getLogger("cli.multisig") @@ -629,6 +631,7 @@ def _add_arguments_arg(sub: Any): nargs="+", help="arguments for the contract transaction, as [number, bech32-address, ascii string, " "boolean] or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba str:TOK-a1c2ef true addr:erd1[..]", + default=[], ) sub.add_argument( "--arguments-file", @@ -659,17 +662,34 @@ def _ensure_args(args: Any): validate_chain_id_args(args) -def _initialize_multisig_wrapper(args: Any) -> MultisigWrapper: +def _initialize_multisig_controller(args: Any) -> MultisigController: abi = Abi.load(Path(args.abi)) - chain_id = cli_shared.get_chain_id(args.proxy, args.chain) + chain = args.chain if hasattr(args, "chain") else None + chain_id = cli_shared.get_chain_id(args.proxy, chain) + + config = get_config_for_network_providers() + proxy_url = args.proxy if args.proxy else "" gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - return MultisigWrapper( - config=TransactionsFactoryConfig(chain_id), + proxy = ProxyNetworkProvider(url=proxy_url, config=config) + + return MultisigController( + chain_id=chain_id, + network_provider=proxy, abi=abi, + address_hrp=cli_shared.get_address_hrp_with_fallback(args), gas_limit_estimator=gas_estimator, ) +def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): + signer = SigningWrapper() + signer.sign_transaction( + transaction=transaction, + sender=sender, + guardian_and_relayer=guardian_and_relayer_data, + ) + + def deploy(args: Any): logger.debug("multisig.deploy") _ensure_args(args) @@ -683,30 +703,30 @@ def deploy(args: Any): quorum = args.quorum board_members = [Address.new_from_bech32(addr) for addr in args.board_members] - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_deploy_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_deploy( + sender=sender, nonce=sender.nonce, bytecode=Path(args.bytecode), quorum=quorum, - board_members=board_members, - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, + board=board_members, + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) address_computer = AddressComputer(NUMBER_OF_SHARDS) 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(multisig._factory._sc_factory.config.chain_id, contract_address.to_bech32()) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract_address, args) @@ -726,20 +746,20 @@ def deposit(args: Any): if token_transfers: token_transfers = cli_shared.prepare_token_transfers(token_transfers) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_deposit_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_deposit( + sender=sender, nonce=sender.nonce, contract=contract, - native_amount=native_amount, + native_token_amount=native_amount, token_transfers=token_transfers, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -755,19 +775,19 @@ def discard_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_discard_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_discard_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -783,19 +803,19 @@ def discard_batch(args: Any): contract = Address.new_from_bech32(args.contract) actions = args.action_ids - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_discard_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_discard_batch( + sender=sender, nonce=sender.nonce, contract=contract, - action_ids=actions, + actions_ids=actions, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -811,19 +831,19 @@ def add_board_member(args: Any): contract = Address.new_from_bech32(args.contract) board_member = Address.new_from_bech32(args.board_member) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_add_board_member_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_add_board_member( + sender=sender, nonce=sender.nonce, contract=contract, board_member=board_member, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -839,19 +859,19 @@ def add_proposer(args: Any): contract = Address.new_from_bech32(args.contract) proposer = Address.new_from_bech32(args.proposer) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_add_proposer_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_add_proposer( + sender=sender, nonce=sender.nonce, contract=contract, proposer=proposer, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -867,19 +887,19 @@ def remove_user(args: Any): contract = Address.new_from_bech32(args.contract) user = Address.new_from_bech32(args.user) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_remove_user_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_remove_user( + sender=sender, nonce=sender.nonce, contract=contract, user=user, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -895,19 +915,19 @@ def change_quorum(args: Any): contract = Address.new_from_bech32(args.contract) quorum = int(args.quorum) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_change_quorum_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_change_quorum( + sender=sender, nonce=sender.nonce, contract=contract, - quorum=quorum, + new_quorum=quorum, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -925,27 +945,29 @@ def transfer_and_execute(args: Any): opt_gas_limit = int(args.opt_gas_limit) if args.opt_gas_limit else None function = args.function if args.function else None contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_transfer_execute_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_transfer_execute( + sender=sender, nonce=sender.nonce, contract=contract, receiver=receiver, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, opt_gas_limit=opt_gas_limit, function=function, abi=contract_abi, arguments=arguments, native_token_amount=int(args.value), + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -969,28 +991,30 @@ def transfer_and_execute_esdt(args: Any): opt_gas_limit = int(args.opt_gas_limit) if args.opt_gas_limit else None function = args.function if args.function else None contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None - arguments, should_prepare_args = _get_contract_arguments(args) token_transfers = cli_shared.prepare_token_transfers(args.token_transfers) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_transfer_execute_esdt_transaction( - owner=sender, + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) + + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_transfer_execute_esdt( + sender=sender, nonce=sender.nonce, contract=contract, receiver=receiver, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, token_transfers=token_transfers, opt_gas_limit=opt_gas_limit, function=function, abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1008,32 +1032,34 @@ def async_call(args: Any): opt_gas_limit = int(args.opt_gas_limit) if args.opt_gas_limit else None function = args.function if args.function else None contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) token_transfers = args.token_transfers or None if token_transfers: token_transfers = cli_shared.prepare_token_transfers(args.token_transfers) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_async_call_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_async_call( + sender=sender, nonce=sender.nonce, contract=contract, receiver=receiver, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, native_token_amount=int(args.value), token_transfers=token_transfers, opt_gas_limit=opt_gas_limit, function=function, abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1048,31 +1074,32 @@ def deploy_from_source(args: Any): contract = Address.new_from_bech32(args.contract) contract_to_copy = Address.new_from_bech32(args.contract_to_copy) - contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_contract_deploy_from_source_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_contract_deploy_from_source( + sender=sender, nonce=sender.nonce, contract=contract, contract_to_copy=contract_to_copy, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, native_token_amount=int(args.value), abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1088,32 +1115,33 @@ def upgrade_from_source(args: Any): contract = Address.new_from_bech32(args.contract) contract_to_upgrade = Address.new_from_bech32(args.contract_to_upgrade) contract_to_copy = Address.new_from_bech32(args.contract_to_copy) - contract_abi = Abi.load(Path(args.contract_abi)) if args.contract_abi else None + arguments, should_prepare_args = _get_contract_arguments(args) + if should_prepare_args: + arguments = convert_args_to_typed_values(arguments) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_contract_upgrade_from_source_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_propose_contract_upgrade_from_source( + sender=sender, nonce=sender.nonce, contract=contract, contract_to_upgrade=contract_to_upgrade, contract_to_copy=contract_to_copy, - gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - upgradeable=args.metadata_upgradeable, - readable=args.metadata_readable, - payable=args.metadata_payable, - payable_by_sc=args.metadata_payable_by_sc, - should_prepare_args_for_factory=should_prepare_args, - guardian_and_relayer_data=guardian_and_relayer_data, + is_upgradeable=args.metadata_upgradeable, + is_readable=args.metadata_readable, + is_payable=args.metadata_payable, + is_payable_by_sc=args.metadata_payable_by_sc, native_token_amount=int(args.value), abi=contract_abi, arguments=arguments, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1129,19 +1157,19 @@ def sign_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1157,19 +1185,19 @@ def sign_batch(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_batch( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1185,19 +1213,19 @@ def sign_and_perform(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_and_perform_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_and_perform( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1213,19 +1241,19 @@ def sign_batch_and_perform(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_sign_batch_and_perform_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_sign_batch_and_perform( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1241,19 +1269,19 @@ def unsign_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_unsign_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_unsign_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1269,19 +1297,19 @@ def unsign_batch(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_unsign_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_unsign_batch( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1297,20 +1325,20 @@ def unsign_for_outdated_board_members(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_unsign_for_outdated_board_members_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_unsign_for_outdated_board_members( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, outdated_board_members=args.outdated_members, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1326,19 +1354,19 @@ def perform_action(args: Any): contract = Address.new_from_bech32(args.contract) action_id = int(args.action) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_perform_action_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_perform_action( + sender=sender, nonce=sender.nonce, contract=contract, action_id=action_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) @@ -1354,30 +1382,22 @@ def perform_batch(args: Any): contract = Address.new_from_bech32(args.contract) batch_id = int(args.batch) - multisig = _initialize_multisig_wrapper(args) - tx = multisig.prepare_perform_batch_transaction( - owner=sender, + multisig = _initialize_multisig_controller(args) + tx = multisig.create_transaction_for_perform_batch( + sender=sender, nonce=sender.nonce, contract=contract, batch_id=batch_id, + guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, + relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, gas_limit=args.gas_limit, - gas_price=int(args.gas_price), - version=int(args.version), - options=int(args.options), - guardian_and_relayer_data=guardian_and_relayer_data, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) _send_or_simulate(tx, contract, args) -def _initialize_multisig_controller(args: Any) -> MultisigController: - abi = Abi.load(Path(args.abi)) - config = get_config_for_network_providers() - proxy = ProxyNetworkProvider(url=args.proxy, config=config) - chain_id = proxy.get_network_config().chain_id - return MultisigController(chain_id, proxy, abi) - - def get_quorum(args: Any): validate_proxy_argument(args) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 29ed140e..6e60b884 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -351,7 +351,7 @@ def parse_omit_fields_arg(args: Any) -> list[str]: def prepare_account(args: Any): - hrp = _get_address_hrp(args) + hrp = get_address_hrp_with_fallback(args) if args.pem: return Account.new_from_pem(file_path=Path(args.pem), index=args.sender_wallet_index, hrp=hrp) @@ -426,7 +426,7 @@ def _load_wallet_from_wallet_config(wallet: dict[str, str], hrp: str) -> Account raise WalletError(f"Unsupported wallet file type: [{path.suffix}]. Supported types are: `.pem` and `.json`.") -def _get_address_hrp(args: Any) -> str: +def get_address_hrp_with_fallback(args: Any) -> str: """Use hrp provided by the user. If not provided, fetch from network. If proxy not provided, get hrp from config.""" hrp: str = "" @@ -462,7 +462,7 @@ def _get_hrp_from_api(args: Any) -> str: def load_guardian_account(args: Any) -> Union[IAccount, None]: - hrp = _get_address_hrp(args) + hrp = get_address_hrp_with_fallback(args) if args.guardian_pem: return Account.new_from_pem(file_path=Path(args.guardian_pem), index=args.guardian_wallet_index, hrp=hrp) @@ -599,7 +599,7 @@ def _is_matching_address(account_address: Union[Address, None], args_address: Un def load_relayer_account(args: Any) -> Union[IAccount, None]: - hrp = _get_address_hrp(args) + hrp = get_address_hrp_with_fallback(args) if args.relayer_pem: return Account.new_from_pem(file_path=Path(args.relayer_pem), index=args.relayer_wallet_index, hrp=hrp) diff --git a/multiversx_sdk_cli/multisig.py b/multiversx_sdk_cli/multisig.py deleted file mode 100644 index 12c8f6c7..00000000 --- a/multiversx_sdk_cli/multisig.py +++ /dev/null @@ -1,922 +0,0 @@ -import logging -from pathlib import Path -from typing import Any, Optional, Union - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - MultisigTransactionsFactory, - TokenTransfer, - Transaction, - TransactionsFactoryConfig, -) -from multiversx_sdk.abi import Abi - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -logger = logging.getLogger("multisig") - - -class MultisigWrapper(BaseTransactionsController): - def __init__( - self, - config: TransactionsFactoryConfig, - abi: Abi, - gas_limit_estimator: Optional[GasLimitEstimator] = None, - ): - self._factory = MultisigTransactionsFactory(config=config, abi=abi, gas_limit_estimator=gas_limit_estimator) - - def prepare_deploy_transaction( - self, - owner: IAccount, - nonce: int, - bytecode: Path, - quorum: int, - board_members: list[Address], - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_deploy( - sender=owner.address, - bytecode=bytecode, - quorum=quorum, - board=board_members, - gas_limit=gas_limit, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_deposit_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - native_amount: Optional[int] = None, - token_transfers: Optional[list[TokenTransfer]] = None, - ) -> Transaction: - tx = self._factory.create_transaction_for_deposit( - sender=owner.address, - contract=contract, - gas_limit=gas_limit, - native_token_amount=native_amount, - token_transfers=token_transfers, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_discard_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_discard_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_discard_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_ids: list[int], - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_discard_batch( - sender=owner.address, - contract=contract, - action_ids=action_ids, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_add_board_member_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - board_member: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_add_board_member( - sender=owner.address, - contract=contract, - board_member=board_member, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_add_proposer_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - proposer: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_add_proposer( - sender=owner.address, - contract=contract, - proposer=proposer, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_remove_user_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - user: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_remove_user( - sender=owner.address, - contract=contract, - user=user, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_change_quorum_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - quorum: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_propose_change_quorum( - sender=owner.address, - contract=contract, - quorum=quorum, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transfer_execute_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - receiver: Address, - native_token_amount: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - opt_gas_limit: Optional[int] = None, - abi: Optional[Abi] = None, - function: Optional[str] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_transfer_execute( - sender=owner.address, - contract=contract, - receiver=receiver, - native_token_amount=native_token_amount, - gas_limit=gas_limit, - opt_gas_limit=opt_gas_limit, - abi=abi, - function=function, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_transfer_execute_esdt_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - receiver: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - token_transfers: list[TokenTransfer], - opt_gas_limit: Optional[int] = None, - abi: Optional[Abi] = None, - function: Optional[str] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_transfer_esdt_execute( - sender=owner.address, - contract=contract, - receiver=receiver, - token_transfers=token_transfers, - gas_limit=gas_limit, - opt_gas_limit=opt_gas_limit, - abi=abi, - function=function, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_async_call_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - receiver: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - native_token_amount: int = 0, - token_transfers: Optional[list[TokenTransfer]] = None, - opt_gas_limit: Optional[int] = None, - abi: Optional[Abi] = None, - function: Optional[str] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_async_call( - sender=owner.address, - contract=contract, - receiver=receiver, - gas_limit=gas_limit, - native_token_amount=native_token_amount, - token_transfers=token_transfers, - opt_gas_limit=opt_gas_limit, - abi=abi, - function=function, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_contract_deploy_from_source_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - contract_to_copy: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - native_token_amount: int = 0, - abi: Optional[Abi] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_contract_deploy_from_source( - sender=owner.address, - contract=contract, - gas_limit=gas_limit, - contract_to_copy=contract_to_copy, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - native_token_amount=native_token_amount, - abi=abi, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_contract_upgrade_from_source_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - contract_to_upgrade: Address, - contract_to_copy: Address, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - upgradeable: bool, - readable: bool, - payable: bool, - payable_by_sc: bool, - should_prepare_args_for_factory: bool, - guardian_and_relayer_data: GuardianRelayerData, - native_token_amount: int = 0, - abi: Optional[Abi] = None, - arguments: Optional[list[Any]] = None, - ) -> Transaction: - args = arguments if arguments else [] - if should_prepare_args_for_factory: - args = self._convert_args_to_typed_values(args) - - tx = self._factory.create_transaction_for_propose_contract_upgrade_from_source( - sender=owner.address, - contract=contract, - contract_to_upgrade=contract_to_upgrade, - contract_to_copy=contract_to_copy, - gas_limit=gas_limit, - is_upgradeable=upgradeable, - is_readable=readable, - is_payable=payable, - is_payable_by_sc=payable_by_sc, - native_token_amount=native_token_amount, - abi=abi, - arguments=args, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_batch( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_and_perform_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_and_perform( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_sign_batch_and_perform_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_sign_batch_and_perform( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_unsign_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unsign_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_unsign_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unsign_batch( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_unsign_for_outdated_board_members_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - outdated_board_members: list[int], - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_unsign_for_outdated_board_members( - sender=owner.address, - contract=contract, - action_id=action_id, - outdated_board_members=outdated_board_members, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_perform_action_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - action_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_perform_action( - sender=owner.address, - contract=contract, - action_id=action_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx - - def prepare_perform_batch_transaction( - self, - owner: IAccount, - nonce: int, - contract: Address, - batch_id: int, - gas_limit: Union[int, None], - gas_price: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - tx = self._factory.create_transaction_for_perform_batch( - sender=owner.address, - contract=contract, - batch_id=batch_id, - gas_limit=gas_limit, - ) - tx.nonce = nonce - tx.version = version - tx.options = options - tx.gas_price = gas_price - tx.guardian = guardian_and_relayer_data.guardian_address - tx.relayer = guardian_and_relayer_data.relayer_address - - self.sign_transaction( - transaction=tx, - sender=owner, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return tx From e8f0f4688bb9a0add8a1b613e351e8e468cc1522 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 18 Sep 2025 16:21:19 +0300 Subject: [PATCH 16/33] remove validators wrapper --- multiversx_sdk_cli/cli_validators.py | 194 +++++----- multiversx_sdk_cli/validators.py | 539 --------------------------- 2 files changed, 94 insertions(+), 639 deletions(-) delete mode 100644 multiversx_sdk_cli/validators.py diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index f28e0814..7981b3c7 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -1,7 +1,13 @@ from pathlib import Path from typing import Any -from multiversx_sdk import Address, ValidatorPublicKey, ValidatorsSigners +from multiversx_sdk import ( + Address, + Transaction, + ValidatorPublicKey, + ValidatorsController, + ValidatorsSigners, +) from multiversx_sdk_cli import cli_shared, utils from multiversx_sdk_cli.args_validation import ( @@ -10,7 +16,9 @@ validate_nonce_args, validate_receiver_args, ) -from multiversx_sdk_cli.validators import ValidatorsController +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -151,8 +159,18 @@ def validate_args(args: Any) -> None: validate_chain_id_args(args) +def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): + signer = SigningWrapper() + signer.sign_transaction( + transaction=transaction, + sender=sender, + guardian_and_relayer=guardian_and_relayer_data, + ) + + def do_stake(args: Any): 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(), @@ -167,37 +185,35 @@ def do_stake(args: Any): if args.top_up: tx = controller.create_transaction_for_topping_up( sender=sender, - native_amount=native_amount, + nonce=sender.nonce, + amount=native_amount, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) else: validators_signers = _load_validators_signers(args.validators_pem) tx = controller.create_transaction_for_staking( sender=sender, - validators=validators_signers, - native_amount=native_amount, - gas_limit=args.gas_limit, - gas_price=args.gas_price, nonce=sender.nonce, - version=args.version, - options=args.options, + validators_file=validators_signers, + amount=native_amount, rewards_address=rewards_address, - guardian_and_relayer_data=guardian_and_relayer_data, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + gas_limit=args.gas_limit, + gas_price=args.gas_price, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) -def _get_validators_controller(args: Any): +def _get_validators_controller(args: Any) -> ValidatorsController: chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - validators = ValidatorsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) - return validators + return ValidatorsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) def _load_validators_signers(validators_pem: str) -> ValidatorsSigners: @@ -224,22 +240,20 @@ def do_unstake(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unstaking( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -258,16 +272,16 @@ def do_unjail(args: Any): controller = _get_validators_controller(args) tx = controller.create_transaction_for_unjailing( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + amount=native_amount, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -280,22 +294,20 @@ def do_unbond(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unbonding( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -308,22 +320,20 @@ def change_reward_address(args: Any): args=args, ) - native_amount = int(args.value) rewards_address = Address.new_from_bech32(args.reward_address) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_changing_rewards_address( sender=sender, + nonce=sender.nonce, rewards_address=rewards_address, - native_amount=native_amount, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -336,20 +346,17 @@ def do_claim(args: Any): args=args, ) - native_amount = int(args.value) - controller = _get_validators_controller(args) tx = controller.create_transaction_for_claiming( sender=sender, - native_amount=native_amount, + nonce=sender.nonce, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -362,22 +369,20 @@ def do_unstake_nodes(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unstaking_nodes( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -390,22 +395,20 @@ def do_unstake_tokens(args: Any): args=args, ) - native_amount = int(args.value) value = int(args.unstake_value) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unstaking_tokens( sender=sender, - value=value, - native_amount=native_amount, + nonce=sender.nonce, + amount=value, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -418,22 +421,20 @@ def do_unbond_nodes(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unbonding_nodes( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -446,22 +447,20 @@ def do_unbond_tokens(args: Any): args=args, ) - native_amount = int(args.value) value = int(args.unbond_value) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_unbonding_tokens( sender=sender, - value=value, - native_amount=native_amount, + nonce=sender.nonce, + amount=value, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -474,20 +473,17 @@ def do_clean_registered_data(args: Any): args=args, ) - native_amount = int(args.value) - controller = _get_validators_controller(args) tx = controller.create_transaction_for_cleaning_registered_data( sender=sender, - native_amount=native_amount, + nonce=sender.nonce, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -500,20 +496,18 @@ def do_restake_unstaked_nodes(args: Any): args=args, ) - native_amount = int(args.value) keys = _parse_public_bls_keys(args.nodes_public_keys) - controller = _get_validators_controller(args) + tx = controller.create_transaction_for_restaking_unstaked_nodes( sender=sender, - keys=keys, - native_amount=native_amount, + nonce=sender.nonce, + public_keys=keys, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - guardian_and_relayer_data=guardian_and_relayer_data, ) + _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/validators.py b/multiversx_sdk_cli/validators.py deleted file mode 100644 index 05eb9871..00000000 --- a/multiversx_sdk_cli/validators.py +++ /dev/null @@ -1,539 +0,0 @@ -from typing import Optional - -from multiversx_sdk import ( - Address, - GasLimitEstimator, - Transaction, - TransactionsFactoryConfig, - ValidatorPublicKey, - ValidatorsSigners, - ValidatorsTransactionsFactory, -) - -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - - -class ValidatorsController(BaseTransactionsController): - def __init__(self, chain_id: str, gas_limit_estimator: Optional[GasLimitEstimator] = None) -> None: - self.factory = ValidatorsTransactionsFactory( - config=TransactionsFactoryConfig(chain_id), - gas_limit_estimator=gas_limit_estimator, - ) - - def create_transaction_for_staking( - self, - sender: IAccount, - validators: ValidatorsSigners, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - rewards_address: Optional[Address] = None, - ) -> Transaction: - transaction = self.factory.create_transaction_for_staking( - sender=sender.address, - validators_file=validators, - amount=native_amount, - rewards_address=rewards_address, - ) - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_topping_up( - self, - sender: IAccount, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_topping_up( - sender=sender.address, - amount=native_amount, - ) - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unstaking( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unstaking( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unjailing( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unjailing( - sender=sender.address, - public_keys=keys, - amount=native_amount, - ) - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unbonding( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unbonding( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_changing_rewards_address( - self, - sender: IAccount, - rewards_address: Address, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_changing_rewards_address( - sender=sender.address, - rewards_address=rewards_address, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_claiming( - self, - sender: IAccount, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_claiming( - sender=sender.address, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unstaking_nodes( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unstaking_nodes( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unstaking_tokens( - self, - sender: IAccount, - value: int, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unstaking_tokens( - sender=sender.address, - amount=value, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unbonding_nodes( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unbonding_nodes( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_unbonding_tokens( - self, - sender: IAccount, - value: int, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_unbonding_tokens( - sender=sender.address, - amount=value, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_cleaning_registered_data( - self, - sender: IAccount, - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_cleaning_registered_data( - sender=sender.address, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def create_transaction_for_restaking_unstaked_nodes( - self, - sender: IAccount, - keys: list[ValidatorPublicKey], - native_amount: int, - gas_limit: int, - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - ) -> Transaction: - transaction = self.factory.create_transaction_for_restaking_unstaked_nodes( - sender=sender.address, - public_keys=keys, - ) - transaction.value = native_amount - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction From d07f659c2cf8d24a4963834dadfd2259ec052aae Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 18 Sep 2025 16:26:39 +0300 Subject: [PATCH 17/33] fix for guardian and relayer addresses --- multiversx_sdk_cli/cli_delegation.py | 80 ++++++++++++++-------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 941f3407..50b30e1f 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -438,8 +438,8 @@ def do_create_delegation_contract(args: Any): amount=int(args.value), total_delegation_cap=int(args.total_delegation_cap), service_fee=int(args.service_fee), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -483,8 +483,8 @@ def add_new_nodes(args: Any): delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, signed_messages=signed_messages, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -529,8 +529,8 @@ def remove_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -576,8 +576,8 @@ def stake_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -612,8 +612,8 @@ def unbond_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -640,8 +640,8 @@ def unstake_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -669,8 +669,8 @@ def unjail_nodes(args: Any): delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, amount=int(args.value), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -694,8 +694,8 @@ def delegate(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), amount=int(args.value), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -718,8 +718,8 @@ def claim_rewards(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -742,8 +742,8 @@ def redelegate_rewards(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -767,8 +767,8 @@ def undelegate(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), amount=int(args.value), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -791,8 +791,8 @@ def withdraw(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -816,8 +816,8 @@ def change_service_fee(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), service_fee=int(args.service_fee), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -841,8 +841,8 @@ def modify_delegation_cap(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), delegation_cap=int(args.delegation_cap), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -870,8 +870,8 @@ def automatic_activation(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -880,8 +880,8 @@ def automatic_activation(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -910,8 +910,8 @@ def redelegate_cap(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -920,8 +920,8 @@ def redelegate_cap(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -949,8 +949,8 @@ def set_metadata(args: Any): name=args.name, website=args.website, identifier=args.identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -977,8 +977,8 @@ def make_new_contract_from_validator_data(args: Any): nonce=sender.nonce, max_cap=args.max_cap, fee=args.fee, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, + relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, gas_limit=args.gas_limit, gas_price=args.gas_price, ) From 17c5ff5f265a769ecd18ce059fb5e4242a75b152 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 19 Sep 2025 15:01:25 +0300 Subject: [PATCH 18/33] refactoring and fixes --- multiversx_sdk_cli/cli_delegation.py | 91 ++++++------ multiversx_sdk_cli/cli_shared.py | 33 ++++- multiversx_sdk_cli/constants.py | 1 + multiversx_sdk_cli/interfaces.py | 1 + multiversx_sdk_cli/signing_wrapper.py | 101 ++++++++++++++ .../tests/test_cli_staking_provider.py | 131 ++++++++++++++++++ 6 files changed, 307 insertions(+), 51 deletions(-) create mode 100644 multiversx_sdk_cli/signing_wrapper.py diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 50b30e1f..519f57e5 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -20,10 +20,10 @@ validate_proxy_argument, validate_receiver_args, ) -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController from multiversx_sdk_cli.config import get_config_for_network_providers from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -411,14 +411,11 @@ def _get_delegation_controller(args: Any): def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): - base = BaseTransactionsController() - base.sign_transaction( + signer = SigningWrapper() + signer.sign_transaction( transaction=transaction, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, + guardian_and_relayer=guardian_and_relayer_data, ) @@ -438,8 +435,8 @@ def do_create_delegation_contract(args: Any): amount=int(args.value), total_delegation_cap=int(args.total_delegation_cap), service_fee=int(args.service_fee), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -483,8 +480,8 @@ def add_new_nodes(args: Any): delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, signed_messages=signed_messages, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -529,8 +526,8 @@ def remove_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -576,8 +573,8 @@ def stake_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -612,8 +609,8 @@ def unbond_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -640,8 +637,8 @@ def unstake_nodes(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -669,8 +666,8 @@ def unjail_nodes(args: Any): delegation_contract=Address.new_from_bech32(args.delegation_contract), public_keys=public_keys, amount=int(args.value), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -694,8 +691,8 @@ def delegate(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), amount=int(args.value), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -718,8 +715,8 @@ def claim_rewards(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -742,8 +739,8 @@ def redelegate_rewards(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -767,8 +764,8 @@ def undelegate(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), amount=int(args.value), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -791,8 +788,8 @@ def withdraw(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -816,8 +813,8 @@ def change_service_fee(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), service_fee=int(args.service_fee), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -841,8 +838,8 @@ def modify_delegation_cap(args: Any): nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), delegation_cap=int(args.delegation_cap), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -870,8 +867,8 @@ def automatic_activation(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -880,8 +877,8 @@ def automatic_activation(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -910,8 +907,8 @@ def redelegate_cap(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -920,8 +917,8 @@ def redelegate_cap(args: Any): sender=sender, nonce=sender.nonce, delegation_contract=Address.new_from_bech32(args.delegation_contract), - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -949,8 +946,8 @@ def set_metadata(args: Any): name=args.name, website=args.website, identifier=args.identifier, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -977,8 +974,8 @@ def make_new_contract_from_validator_data(args: Any): nonce=sender.nonce, max_cap=args.max_cap, fee=args.fee, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 29ed140e..7b2ab390 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -39,6 +39,7 @@ DEFAULT_GAS_PRICE, DEFAULT_TX_VERSION, TCS_SERVICE_ID, + TRANSACTION_OPTIONS_TX_HASH_SIGN, ) from multiversx_sdk_cli.errors import ( AddressConfigFileError, @@ -350,17 +351,31 @@ def parse_omit_fields_arg(args: Any) -> list[str]: return cast(list[str], parsed) +def _options_set_for_hash_signing(args: Any) -> bool: + if hasattr(args, "options") and args.options: + if args.options & TRANSACTION_OPTIONS_TX_HASH_SIGN == TRANSACTION_OPTIONS_TX_HASH_SIGN: + return True + + return False + + def prepare_account(args: Any): hrp = _get_address_hrp(args) if args.pem: - return Account.new_from_pem(file_path=Path(args.pem), index=args.sender_wallet_index, hrp=hrp) + acc = Account.new_from_pem(file_path=Path(args.pem), index=args.sender_wallet_index, hrp=hrp) + if _options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc elif args.keyfile: password = load_password(args) index = args.sender_wallet_index if args.sender_wallet_index != 0 else None try: - return Account.new_from_keystore(Path(args.keyfile), password=password, address_index=index, hrp=hrp) + acc = Account.new_from_keystore(Path(args.keyfile), password=password, address_index=index, hrp=hrp) + if _options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc except Exception as e: raise WalletError(str(e)) elif args.ledger: @@ -369,9 +384,15 @@ def prepare_account(args: Any): except Exception as e: raise LedgerError(str(e)) elif args.sender: - return load_wallet_by_alias(alias=args.sender, hrp=hrp) + acc = load_wallet_by_alias(alias=args.sender, hrp=hrp) + if _options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc else: - return load_default_wallet(hrp=hrp) + acc = load_default_wallet(hrp=hrp) + if _options_set_for_hash_signing(args): + acc.use_hash_signing = True + return acc def load_wallet_by_alias(alias: str, hrp: str) -> Account: @@ -800,6 +821,10 @@ def set_proxy_from_config_if_not_provided(args: Any) -> None: def initialize_gas_limit_estimator(args: Any) -> Union[GasLimitEstimator, None]: + # if gas limit is provided, we don't need GasLimitEstimator + if hasattr(args, "gas_limit") and args.gas_limit: + return None + # if proxy is not provided, we can't use GasLimitEstimator if hasattr(args, "proxy") and not args.proxy: return None diff --git a/multiversx_sdk_cli/constants.py b/multiversx_sdk_cli/constants.py index 803889fe..54135562 100644 --- a/multiversx_sdk_cli/constants.py +++ b/multiversx_sdk_cli/constants.py @@ -7,6 +7,7 @@ SC_HEX_PUBKEY_PREFIX_WASM_VM = SC_HEX_PUBKEY_PREFIX + VM_TYPE_WASM_VM DEFAULT_CARGO_TARGET_DIR_NAME = "default_cargo_target" TRANSACTION_OPTIONS_TX_GUARDED = 0b0010 +TRANSACTION_OPTIONS_TX_HASH_SIGN = 0b0001 ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365 DEFAULT_TX_VERSION = 2 diff --git a/multiversx_sdk_cli/interfaces.py b/multiversx_sdk_cli/interfaces.py index 8a533e7c..d9518f65 100644 --- a/multiversx_sdk_cli/interfaces.py +++ b/multiversx_sdk_cli/interfaces.py @@ -6,6 +6,7 @@ # fmt: off class IAccount(Protocol): address: Address + use_hash_signing: bool def sign_transaction(self, transaction: Transaction) -> bytes: ... diff --git a/multiversx_sdk_cli/signing_wrapper.py b/multiversx_sdk_cli/signing_wrapper.py new file mode 100644 index 00000000..70a1d62a --- /dev/null +++ b/multiversx_sdk_cli/signing_wrapper.py @@ -0,0 +1,101 @@ +from typing import Optional, Union + +from multiversx_sdk import LedgerAccount, Transaction, TransactionComputer + +from multiversx_sdk_cli.cosign_transaction import cosign_transaction +from multiversx_sdk_cli.errors import TransactionSigningError +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.interfaces import IAccount + + +class SigningWrapper: + def __init__(self): + pass + + def sign_transaction( + self, + transaction: Transaction, + sender: Optional[IAccount] = None, + guardian_and_relayer: GuardianRelayerData = GuardianRelayerData(), + ): + """Signs the transaction using the sender's account and, if required, additionally signs with the guardian's and relayer's accounts. Ensures the appropriate transaction options are set as needed.""" + self._set_options_for_guarded_transaction_if_needed(transaction) + + guardian = guardian_and_relayer.guardian + relayer = guardian_and_relayer.relayer + guardian_service_url = guardian_and_relayer.guardian_service_url + guardian_2fa_code = guardian_and_relayer.guardian_2fa_code + + self._set_options_for_hash_signing_if_needed(transaction, sender, guardian, relayer) + + if sender: + try: + transaction.signature = sender.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") + + self._sign_guarded_transaction_if_guardian( + transaction, + guardian, + guardian_service_url, + guardian_2fa_code, + ) + self._sign_relayed_transaction_if_relayer(transaction, relayer) + + def _set_options_for_guarded_transaction_if_needed(self, transaction: Transaction): + if transaction.guardian: + transaction_computer = TransactionComputer() + transaction_computer.apply_guardian(transaction, transaction.guardian) + + def _set_options_for_hash_signing_if_needed( + self, + transaction: Transaction, + sender: Union[IAccount, None], + guardian: Union[IAccount, None], + relayer: Union[IAccount, None], + ): + transaction_computer = TransactionComputer() + + if ( + isinstance(sender, LedgerAccount) + or isinstance(guardian, LedgerAccount) + or isinstance(relayer, LedgerAccount) + ): + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if sender and sender.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if guardian and guardian.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if relayer and relayer.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + + def _sign_guarded_transaction_if_guardian( + self, + transaction: Transaction, + guardian: Union[IAccount, None], + guardian_service_url: Union[str, None], + guardian_2fa_code: Union[str, None], + ) -> Transaction: + # If the guardian account is provided, we sign locally. Otherwise, we reach for the trusted cosign service. + if guardian: + try: + transaction.guardian_signature = guardian.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") + elif transaction.guardian and guardian_service_url and guardian_2fa_code: + cosign_transaction(transaction, guardian_service_url, guardian_2fa_code) + + return transaction + + def _sign_relayed_transaction_if_relayer(self, transaction: Transaction, relayer: Union[IAccount, None]): + if relayer and transaction.relayer: + try: + transaction.relayer_signature = relayer.sign_transaction(transaction) + except Exception as e: + raise TransactionSigningError(f"Could not sign transaction: {str(e)}") diff --git a/multiversx_sdk_cli/tests/test_cli_staking_provider.py b/multiversx_sdk_cli/tests/test_cli_staking_provider.py index c5fd219f..7eeaa2e7 100644 --- a/multiversx_sdk_cli/tests/test_cli_staking_provider.py +++ b/multiversx_sdk_cli/tests/test_cli_staking_provider.py @@ -6,6 +6,8 @@ parent = Path(__file__).parent alice = parent / "testdata" / "alice.pem" +guardian = parent / "testdata" / "testUser.pem" +relayer = parent / "testdata" / "testUser2.pem" first_bls_key = "f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d" second_bls_key = "1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d" @@ -41,12 +43,141 @@ def test_create_new_delegation_contract(capsys: Any): assert transaction["chainID"] == "T" assert transaction["gasLimit"] == 60126500 assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 0 + assert transaction["version"] == 2 assert ( transaction["signature"] == "0a6d7249c671b1db00f1b8807770bb64eac51e2e2779e426f35439c6cb7b00dadd023392a061ba1b6ee35d235ac2c0ad87283413b1d5558d8526bc5712588702" ) +def test_create_new_delegation_contract_sign_by_hash(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--options", + "1", + ] + ) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "createNewDelegationContract@021e19e0c9bab2400000@64" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" + assert transaction["chainID"] == "T" + assert transaction["gasLimit"] == 60126500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 1 + assert transaction["version"] == 2 + assert ( + transaction["signature"] + == "16cfcdeb6cd7e72b0c332793c0498448665427bb992efed17f873f4917bcd000857d0babb7799dcd97933a060b0e5e4b3edbf248db3f78e74f9b71710adbdf08" + ) + + +def test_create_new_delegation_contract_with_guardian_and_relayer(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--guardian-pem", + str(guardian), + "--relayer-pem", + str(relayer), + ] + ) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "createNewDelegationContract@021e19e0c9bab2400000@64" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" + assert transaction["chainID"] == "T" + assert transaction["gasLimit"] == 60226500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 2 + assert transaction["version"] == 2 + assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" + assert ( + transaction["signature"] + == "2138154667f573451ecb7ca9bd280f12e8240d5a689886f69b9159be6c0207297a3216b8868e2bf1040f435b3bc8208ed7f124674a20976033787c4ee0ff7907" + ) + + +def test_create_new_delegation_contract_with_guardian_and_relayer_and_sign_by_hash(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--guardian-pem", + str(guardian), + "--relayer-pem", + str(relayer), + "--options", + "1", + ] + ) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "createNewDelegationContract@021e19e0c9bab2400000@64" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" + assert transaction["chainID"] == "T" + assert transaction["gasLimit"] == 60226500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 3 + assert transaction["version"] == 2 + assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" + assert ( + transaction["signature"] + == "ec43c0d6e208614821ba2db22a1af56f29a613f9656c169b742f52e9925212cb0809a49dc4bba833e2e54977cc0128388cca490eb7e6fe0dbbe6311c5f078a02" + ) + + def test_create_new_delegation_contract_with_provided_gas_limit(capsys: Any): main( [ From 5ceaed0c5148028cf5524572c0f28fc005130541 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Fri, 19 Sep 2025 17:06:11 +0300 Subject: [PATCH 19/33] more refactoring --- multiversx_sdk_cli/cli_delegation.py | 141 ++++++++++++++++++ multiversx_sdk_cli/cli_shared.py | 25 ++++ multiversx_sdk_cli/signing_wrapper.py | 34 +---- .../tests/test_cli_staking_provider.py | 47 +++++- 4 files changed, 212 insertions(+), 35 deletions(-) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 519f57e5..c0145a88 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -21,6 +21,7 @@ validate_receiver_args, ) from multiversx_sdk_cli.config import get_config_for_network_providers +from multiversx_sdk_cli.constants import DEFAULT_TX_VERSION from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount from multiversx_sdk_cli.signing_wrapper import SigningWrapper @@ -440,6 +441,13 @@ def do_create_delegation_contract(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -485,6 +493,13 @@ def add_new_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -531,6 +546,13 @@ def remove_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -578,6 +600,13 @@ def stake_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -614,6 +643,13 @@ def unbond_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -642,6 +678,13 @@ def unstake_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -650,6 +693,8 @@ def unstake_nodes(args: Any): def unjail_nodes(args: Any): _check_if_either_bls_keys_or_validators_file_are_provided(args) validate_arguments(args) + if not args.value or int(args.value) <= 0: + raise errors.BadUsage("Value must be provided for unjailing nodes") sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -671,6 +716,13 @@ def unjail_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -678,6 +730,8 @@ def unjail_nodes(args: Any): def delegate(args: Any): validate_arguments(args) + if not args.value or int(args.value) <= 0: + raise errors.BadUsage("Value must be provided for delegating") sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -696,6 +750,13 @@ def delegate(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -720,6 +781,13 @@ def claim_rewards(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -744,6 +812,13 @@ def redelegate_rewards(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -751,6 +826,8 @@ def redelegate_rewards(args: Any): def undelegate(args: Any): validate_arguments(args) + if not args.value or int(args.value) <= 0: + raise errors.BadUsage("Value must be provided for undelegating") sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( @@ -769,6 +846,13 @@ def undelegate(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -793,6 +877,13 @@ def withdraw(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -818,6 +909,13 @@ def change_service_fee(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -843,6 +941,13 @@ def modify_delegation_cap(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -885,6 +990,13 @@ def automatic_activation(args: Any): else: raise errors.BadUsage("Both set and unset automatic activation are False") + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -925,6 +1037,13 @@ def redelegate_cap(args: Any): else: raise errors.BadUsage("Either set or unset should be True") + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -951,6 +1070,13 @@ def set_metadata(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -979,6 +1105,21 @@ def make_new_contract_from_validator_data(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) + _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( + transaction=tx, + sender=sender, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) + + +def _alter_version_and_options_if_provided(args: Any, transaction: Transaction): + if args.options: + transaction.options = args.options + + if args.version != DEFAULT_TX_VERSION: + transaction.version = args.version diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 7b2ab390..8aaeb226 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -20,6 +20,7 @@ TokenComputer, TokenTransfer, Transaction, + TransactionComputer, ) from multiversx_sdk_cli import config, utils @@ -837,3 +838,27 @@ def initialize_gas_limit_estimator(args: Any) -> Union[GasLimitEstimator, None]: network_provider_config = config.get_config_for_network_providers() proxy = ProxyNetworkProvider(url=args.proxy, config=network_provider_config) return GasLimitEstimator(network_provider=proxy, gas_multiplier=multiplier) + + +def set_options_for_hash_signing_if_needed( + transaction: Transaction, + sender: Union[IAccount, None], + guardian: Union[IAccount, None], + relayer: Union[IAccount, None], +): + transaction_computer = TransactionComputer() + + if isinstance(sender, LedgerAccount) or isinstance(guardian, LedgerAccount) or isinstance(relayer, LedgerAccount): + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if sender and sender.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if guardian and guardian.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) + return + + if relayer and relayer.use_hash_signing: + transaction_computer.apply_options_for_hash_signing(transaction) diff --git a/multiversx_sdk_cli/signing_wrapper.py b/multiversx_sdk_cli/signing_wrapper.py index 70a1d62a..b9f834ee 100644 --- a/multiversx_sdk_cli/signing_wrapper.py +++ b/multiversx_sdk_cli/signing_wrapper.py @@ -1,6 +1,6 @@ from typing import Optional, Union -from multiversx_sdk import LedgerAccount, Transaction, TransactionComputer +from multiversx_sdk import Transaction, TransactionComputer from multiversx_sdk_cli.cosign_transaction import cosign_transaction from multiversx_sdk_cli.errors import TransactionSigningError @@ -19,15 +19,11 @@ def sign_transaction( guardian_and_relayer: GuardianRelayerData = GuardianRelayerData(), ): """Signs the transaction using the sender's account and, if required, additionally signs with the guardian's and relayer's accounts. Ensures the appropriate transaction options are set as needed.""" - self._set_options_for_guarded_transaction_if_needed(transaction) - guardian = guardian_and_relayer.guardian relayer = guardian_and_relayer.relayer guardian_service_url = guardian_and_relayer.guardian_service_url guardian_2fa_code = guardian_and_relayer.guardian_2fa_code - self._set_options_for_hash_signing_if_needed(transaction, sender, guardian, relayer) - if sender: try: transaction.signature = sender.sign_transaction(transaction) @@ -47,34 +43,6 @@ def _set_options_for_guarded_transaction_if_needed(self, transaction: Transactio transaction_computer = TransactionComputer() transaction_computer.apply_guardian(transaction, transaction.guardian) - def _set_options_for_hash_signing_if_needed( - self, - transaction: Transaction, - sender: Union[IAccount, None], - guardian: Union[IAccount, None], - relayer: Union[IAccount, None], - ): - transaction_computer = TransactionComputer() - - if ( - isinstance(sender, LedgerAccount) - or isinstance(guardian, LedgerAccount) - or isinstance(relayer, LedgerAccount) - ): - transaction_computer.apply_options_for_hash_signing(transaction) - return - - if sender and sender.use_hash_signing: - transaction_computer.apply_options_for_hash_signing(transaction) - return - - if guardian and guardian.use_hash_signing: - transaction_computer.apply_options_for_hash_signing(transaction) - return - - if relayer and relayer.use_hash_signing: - transaction_computer.apply_options_for_hash_signing(transaction) - def _sign_guarded_transaction_if_guardian( self, transaction: Transaction, diff --git a/multiversx_sdk_cli/tests/test_cli_staking_provider.py b/multiversx_sdk_cli/tests/test_cli_staking_provider.py index 7eeaa2e7..b14756a6 100644 --- a/multiversx_sdk_cli/tests/test_cli_staking_provider.py +++ b/multiversx_sdk_cli/tests/test_cli_staking_provider.py @@ -133,6 +133,49 @@ def test_create_new_delegation_contract_with_guardian_and_relayer(capsys: Any): ) +def test_create_new_delegation_contract_with_guardian_and_relayer_and_provided_version_and_options(capsys: Any): + main( + [ + "staking-provider", + "create-new-delegation-contract", + "--pem", + str(alice), + "--nonce", + "7", + "--value", + "1250000000000000000000", + "--total-delegation-cap", + "10000000000000000000000", + "--service-fee", + "100", + "--chain", + "T", + "--guardian-pem", + str(guardian), + "--relayer-pem", + str(relayer), + "--version", + "7", + "--options", + "77", + ] + ) + tx = get_transaction(capsys) + data = tx["emittedTransactionData"] + transaction = tx["emittedTransaction"] + + assert data == "createNewDelegationContract@021e19e0c9bab2400000@64" + assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" + assert transaction["chainID"] == "T" + assert transaction["gasLimit"] == 60226500 + assert transaction["value"] == "1250000000000000000000" + assert transaction["options"] == 77 + assert transaction["version"] == 7 + assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" + assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" + + def test_create_new_delegation_contract_with_guardian_and_relayer_and_sign_by_hash(capsys: Any): main( [ @@ -168,13 +211,13 @@ def test_create_new_delegation_contract_with_guardian_and_relayer_and_sign_by_ha assert transaction["chainID"] == "T" assert transaction["gasLimit"] == 60226500 assert transaction["value"] == "1250000000000000000000" - assert transaction["options"] == 3 + assert transaction["options"] == 1 assert transaction["version"] == 2 assert transaction["guardian"] == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" assert transaction["relayer"] == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" assert ( transaction["signature"] - == "ec43c0d6e208614821ba2db22a1af56f29a613f9656c169b742f52e9925212cb0809a49dc4bba833e2e54977cc0128388cca490eb7e6fe0dbbe6311c5f078a02" + == "2eecebb89627b4f60431a515bc9bce12bc58a7c864654634556a9d03cec9f85bde667f60fb6a0a773faf4560343a447e38d0adea836c8cc421aaf07c11e39d03" ) From 8e5ef9c8bcdf428fdf577e9b26563bf9488363d7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 22 Sep 2025 10:45:05 +0300 Subject: [PATCH 20/33] skip re-signing for ledger device when options are not set --- multiversx_sdk_cli/cli_delegation.py | 75 ++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 22 deletions(-) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index c0145a88..3c0c7728 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Any +from typing import Any, Optional from multiversx_sdk import ( Address, @@ -411,7 +411,11 @@ def _get_delegation_controller(args: Any): ) -def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): +def _sign_transaction( + transaction: Transaction, + sender: Optional[IAccount] = None, + guardian_and_relayer_data: GuardianRelayerData = GuardianRelayerData(), +): signer = SigningWrapper() signer.sign_transaction( transaction=transaction, @@ -441,7 +445,7 @@ def do_create_delegation_contract(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -449,7 +453,11 @@ def do_create_delegation_contract(args: Any): relayer=guardian_and_relayer_data.relayer, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + altered = _alter_version_and_options_if_provided(args, tx) + if altered: # sign only if something was altered + _sign_transaction(tx, sender, guardian_and_relayer_data) + else: + _sign_transaction(tx, None, guardian_and_relayer_data) # sign only with guardian/relayer if needed cli_shared.send_or_simulate(tx, args) @@ -493,7 +501,7 @@ def add_new_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -501,6 +509,7 @@ def add_new_nodes(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -546,7 +555,7 @@ def remove_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -554,6 +563,7 @@ def remove_nodes(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -600,7 +610,6 @@ def stake_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -608,6 +617,7 @@ def stake_nodes(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -643,7 +653,7 @@ def unbond_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -651,6 +661,7 @@ def unbond_nodes(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -678,7 +689,7 @@ def unstake_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -686,6 +697,7 @@ def unstake_nodes(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -716,7 +728,7 @@ def unjail_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -724,6 +736,7 @@ def unjail_nodes(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -750,7 +763,7 @@ def delegate(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -758,6 +771,7 @@ def delegate(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -781,7 +795,7 @@ def claim_rewards(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -789,6 +803,7 @@ def claim_rewards(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -812,7 +827,7 @@ def redelegate_rewards(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -820,6 +835,7 @@ def redelegate_rewards(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -846,7 +862,7 @@ def undelegate(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -854,6 +870,7 @@ def undelegate(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -877,7 +894,7 @@ def withdraw(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -885,6 +902,7 @@ def withdraw(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -909,7 +927,7 @@ def change_service_fee(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -917,6 +935,7 @@ def change_service_fee(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -941,7 +960,7 @@ def modify_delegation_cap(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -949,6 +968,7 @@ def modify_delegation_cap(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -990,13 +1010,14 @@ def automatic_activation(args: Any): else: raise errors.BadUsage("Both set and unset automatic activation are False") - _alter_version_and_options_if_provided(args, tx) cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, guardian=guardian_and_relayer_data.guardian, relayer=guardian_and_relayer_data.relayer, ) + + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1037,13 +1058,14 @@ def redelegate_cap(args: Any): else: raise errors.BadUsage("Either set or unset should be True") - _alter_version_and_options_if_provided(args, tx) cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, guardian=guardian_and_relayer_data.guardian, relayer=guardian_and_relayer_data.relayer, ) + + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1070,7 +1092,7 @@ def set_metadata(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -1078,6 +1100,7 @@ def set_metadata(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1105,7 +1128,7 @@ def make_new_contract_from_validator_data(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _alter_version_and_options_if_provided(args, tx) + cli_shared.set_options_for_hash_signing_if_needed( transaction=tx, sender=sender, @@ -1113,13 +1136,21 @@ def make_new_contract_from_validator_data(args: Any): relayer=guardian_and_relayer_data.relayer, ) + _alter_version_and_options_if_provided(args, tx) _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) -def _alter_version_and_options_if_provided(args: Any, transaction: Transaction): +def _alter_version_and_options_if_provided(args: Any, transaction: Transaction) -> bool: + """Alters the transaction version and options if they are provided in args. Returns True if any alteration was made, False otherwise.""" + altered = False + if args.options: transaction.options = args.options + altered = True if args.version != DEFAULT_TX_VERSION: transaction.version = args.version + altered = True + + return altered From 58e966316a4534514ac88e24aa15d3faafc76d2d Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 22 Sep 2025 16:25:57 +0300 Subject: [PATCH 21/33] continued refactoring for delegation commands --- multiversx_sdk_cli/cli_delegation.py | 219 +++++++++------------------ multiversx_sdk_cli/cli_shared.py | 76 ++++++++-- 2 files changed, 136 insertions(+), 159 deletions(-) diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index 3c0c7728..845e1bab 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -1,12 +1,11 @@ from pathlib import Path -from typing import Any, Optional +from typing import Any from multiversx_sdk import ( Address, DelegationController, DelegationTransactionsOutcomeParser, ProxyNetworkProvider, - Transaction, ValidatorPublicKey, ValidatorsController, ValidatorsSigners, @@ -21,10 +20,6 @@ validate_receiver_args, ) from multiversx_sdk_cli.config import get_config_for_network_providers -from multiversx_sdk_cli.constants import DEFAULT_TX_VERSION -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount -from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -411,19 +406,6 @@ def _get_delegation_controller(args: Any): ) -def _sign_transaction( - transaction: Transaction, - sender: Optional[IAccount] = None, - guardian_and_relayer_data: GuardianRelayerData = GuardianRelayerData(), -): - signer = SigningWrapper() - signer.sign_transaction( - transaction=transaction, - sender=sender, - guardian_and_relayer=guardian_and_relayer_data, - ) - - def do_create_delegation_contract(args: Any): validate_arguments(args) @@ -446,18 +428,13 @@ def do_create_delegation_contract(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - altered = _alter_version_and_options_if_provided(args, tx) - if altered: # sign only if something was altered - _sign_transaction(tx, sender, guardian_and_relayer_data) - else: - _sign_transaction(tx, None, guardian_and_relayer_data) # sign only with guardian/relayer if needed cli_shared.send_or_simulate(tx, args) @@ -502,15 +479,13 @@ def add_new_nodes(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -556,15 +531,13 @@ def remove_nodes(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -610,15 +583,14 @@ def stake_nodes(args: Any): gas_limit=args.gas_limit, gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -654,15 +626,13 @@ def unbond_nodes(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -690,15 +660,13 @@ def unstake_nodes(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -729,15 +697,13 @@ def unjail_nodes(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -764,15 +730,13 @@ def delegate(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -796,15 +760,13 @@ def claim_rewards(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -828,15 +790,13 @@ def redelegate_rewards(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -863,15 +823,13 @@ def undelegate(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -895,15 +853,13 @@ def withdraw(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -928,15 +884,13 @@ def change_service_fee(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -961,15 +915,13 @@ def modify_delegation_cap(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1010,15 +962,13 @@ def automatic_activation(args: Any): else: raise errors.BadUsage("Both set and unset automatic activation are False") - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1058,15 +1008,13 @@ def redelegate_cap(args: Any): else: raise errors.BadUsage("Either set or unset should be True") - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1093,15 +1041,13 @@ def set_metadata(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) @@ -1129,28 +1075,11 @@ def make_new_contract_from_validator_data(args: Any): gas_price=args.gas_price, ) - cli_shared.set_options_for_hash_signing_if_needed( - transaction=tx, + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, + guardian_and_relayer_data=guardian_and_relayer_data, ) - _alter_version_and_options_if_provided(args, tx) - _sign_transaction(tx, sender, guardian_and_relayer_data) cli_shared.send_or_simulate(tx, args) - - -def _alter_version_and_options_if_provided(args: Any, transaction: Transaction) -> bool: - """Alters the transaction version and options if they are provided in args. Returns True if any alteration was made, False otherwise.""" - altered = False - - if args.options: - transaction.options = args.options - altered = True - - if args.version != DEFAULT_TX_VERSION: - transaction.version = args.version - altered = True - - return altered diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 8aaeb226..0dd67fdc 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -54,6 +54,7 @@ ) from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData from multiversx_sdk_cli.interfaces import IAccount +from multiversx_sdk_cli.signing_wrapper import SigningWrapper 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 @@ -352,7 +353,7 @@ def parse_omit_fields_arg(args: Any) -> list[str]: return cast(list[str], parsed) -def _options_set_for_hash_signing(args: Any) -> bool: +def _has_options_set_for_hash_signing(args: Any) -> bool: if hasattr(args, "options") and args.options: if args.options & TRANSACTION_OPTIONS_TX_HASH_SIGN == TRANSACTION_OPTIONS_TX_HASH_SIGN: return True @@ -365,7 +366,7 @@ def prepare_account(args: Any): if args.pem: acc = Account.new_from_pem(file_path=Path(args.pem), index=args.sender_wallet_index, hrp=hrp) - if _options_set_for_hash_signing(args): + if _has_options_set_for_hash_signing(args): acc.use_hash_signing = True return acc elif args.keyfile: @@ -374,7 +375,7 @@ def prepare_account(args: Any): try: acc = Account.new_from_keystore(Path(args.keyfile), password=password, address_index=index, hrp=hrp) - if _options_set_for_hash_signing(args): + if _has_options_set_for_hash_signing(args): acc.use_hash_signing = True return acc except Exception as e: @@ -386,12 +387,12 @@ def prepare_account(args: Any): raise LedgerError(str(e)) elif args.sender: acc = load_wallet_by_alias(alias=args.sender, hrp=hrp) - if _options_set_for_hash_signing(args): + if _has_options_set_for_hash_signing(args): acc.use_hash_signing = True return acc else: acc = load_default_wallet(hrp=hrp) - if _options_set_for_hash_signing(args): + if _has_options_set_for_hash_signing(args): acc.use_hash_signing = True return acc @@ -842,23 +843,70 @@ def initialize_gas_limit_estimator(args: Any) -> Union[GasLimitEstimator, None]: def set_options_for_hash_signing_if_needed( transaction: Transaction, - sender: Union[IAccount, None], guardian: Union[IAccount, None], relayer: Union[IAccount, None], ): transaction_computer = TransactionComputer() - if isinstance(sender, LedgerAccount) or isinstance(guardian, LedgerAccount) or isinstance(relayer, LedgerAccount): - transaction_computer.apply_options_for_hash_signing(transaction) - return - - if sender and sender.use_hash_signing: - transaction_computer.apply_options_for_hash_signing(transaction) - return - if guardian and guardian.use_hash_signing: transaction_computer.apply_options_for_hash_signing(transaction) return if relayer and relayer.use_hash_signing: transaction_computer.apply_options_for_hash_signing(transaction) + + +def alter_transaction_and_sign_again_if_needed( + args: Any, + tx: Transaction, + sender: IAccount, + guardian_and_relayer_data: GuardianRelayerData, +): + set_options_for_hash_signing_if_needed( + transaction=tx, + guardian=guardian_and_relayer_data.guardian, + relayer=guardian_and_relayer_data.relayer, + ) + + altered = _alter_version_and_options_if_provided( + args=args, + final_transaction=tx, + ) + + if altered: # sign only if something was altered + _sign_transaction(tx, sender, guardian_and_relayer_data) + else: + _sign_transaction(tx, None, guardian_and_relayer_data) # sign only with guardian/relayer if needed + + +def _alter_version_and_options_if_provided( + args: Any, + final_transaction: Transaction, +) -> bool: + """Alters the transaction version and options if they are provided in args. + Returns True if any alteration was made, False otherwise. + """ + altered = False + + if args.version != DEFAULT_TX_VERSION and final_transaction.version != args.version: + final_transaction.version = args.version + altered = True + + if args.options and final_transaction.options != args.options: + final_transaction.options = args.options + altered = True + + return altered + + +def _sign_transaction( + transaction: Transaction, + sender: Optional[IAccount] = None, + guardian_and_relayer_data: GuardianRelayerData = GuardianRelayerData(), +): + signer = SigningWrapper() + signer.sign_transaction( + transaction=transaction, + sender=sender, + guardian_and_relayer=guardian_and_relayer_data, + ) From da6288a0494cd49348ab790afcd610a641031430 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 22 Sep 2025 17:01:47 +0300 Subject: [PATCH 22/33] used shared method --- multiversx_sdk_cli/cli_contracts.py | 43 +++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index c819285c..7216222b 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -30,9 +30,7 @@ from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS from multiversx_sdk_cli.contract_verification import trigger_contract_verification from multiversx_sdk_cli.docker import is_docker_installed, run_docker -from multiversx_sdk_cli.errors import DockerMissingError, QueryContractError -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.signing_wrapper import SigningWrapper +from multiversx_sdk_cli.errors import BadUsage, DockerMissingError, QueryContractError from multiversx_sdk_cli.ux import show_warning logger = logging.getLogger("cli.contracts") @@ -334,13 +332,9 @@ def _initialize_controller(args: Any) -> SmartContractController: ) -def _sign_transaction(transaction: Transaction, sender: Any, guardian_and_relayer_data: GuardianRelayerData): - signer = SigningWrapper() - signer.sign_transaction( - transaction=transaction, - sender=sender, - guardian_and_relayer=guardian_and_relayer_data, - ) +def _ensure_args_for_gas_estimation(args: Any): + if not args.proxy and not args.gas_limit: + raise BadUsage("To estimate the gas limit, you need to provide `--proxy` or set a value using `--gas-limit`") def deploy(args: Any): @@ -350,6 +344,8 @@ def deploy(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + _ensure_args_for_gas_estimation(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -384,12 +380,17 @@ def deploy(args: Any): cli_config = MxpyEnv.from_active_env() utils.log_explorer_contract_address( - chain=controller.factory.config.chain_id, + chain=cli_shared.get_chain_id(args.proxy, args.chain), address=contract_address.to_bech32(), explorer_url=cli_config.explorer_url, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -400,6 +401,8 @@ def call(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + _ensure_args_for_gas_estimation(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -431,7 +434,12 @@ def call(args: Any): gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -442,6 +450,8 @@ def upgrade(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + _ensure_args_for_gas_estimation(args) + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), @@ -472,7 +482,12 @@ def upgrade(args: Any): gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) From bada96051b7bcd268977827039ef32bc22d7244c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 11:28:37 +0300 Subject: [PATCH 23/33] remove field --- multiversx_sdk_cli/errors.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/multiversx_sdk_cli/errors.py b/multiversx_sdk_cli/errors.py index d03c7983..ee5ca246 100644 --- a/multiversx_sdk_cli/errors.py +++ b/multiversx_sdk_cli/errors.py @@ -2,8 +2,6 @@ class KnownError(Exception): - inner = None - def __init__(self, message: str, inner: Union[Any, None] = None): super().__init__(message) self.inner = inner From 4e27533151e2757498cbbe0c8b3632e8d4b5b2f3 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 13:44:55 +0300 Subject: [PATCH 24/33] alter version and options and re-sign if needed --- multiversx_sdk_cli/cli_contracts.py | 12 ++--- multiversx_sdk_cli/cli_governance.py | 79 +++++++++++++++++----------- multiversx_sdk_cli/cli_shared.py | 18 ++++--- 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/multiversx_sdk_cli/cli_contracts.py b/multiversx_sdk_cli/cli_contracts.py index 7216222b..539c9238 100644 --- a/multiversx_sdk_cli/cli_contracts.py +++ b/multiversx_sdk_cli/cli_contracts.py @@ -367,8 +367,8 @@ def deploy(args: Any): is_readable=args.metadata_readable, is_payable=args.metadata_payable, is_payable_by_sc=args.metadata_payable_by_sc, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -428,8 +428,8 @@ def call(args: Any): arguments=arguments, native_transfer_amount=int(args.value), token_transfers=token_transfers, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -476,8 +476,8 @@ def upgrade(args: Any): is_readable=args.metadata_readable, is_payable=args.metadata_payable, is_payable_by_sc=args.metadata_payable_by_sc, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index 453af433..0cf95f00 100644 --- a/multiversx_sdk_cli/cli_governance.py +++ b/multiversx_sdk_cli/cli_governance.py @@ -7,7 +7,6 @@ GovernanceController, ProposalInfo, ProxyNetworkProvider, - Transaction, VoteType, ) @@ -20,9 +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.config_env import get_address_hrp -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount -from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -216,15 +212,6 @@ def _initialize_controller(args: Any) -> GovernanceController: ) -def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): - signer = SigningWrapper() - signer.sign_transaction( - transaction=transaction, - sender=sender, - guardian_and_relayer=guardian_and_relayer_data, - ) - - def create_proposal(args: Any): _ensure_args(args) @@ -242,13 +229,18 @@ def create_proposal(args: Any): start_vote_epoch=args.start_vote_epoch, end_vote_epoch=args.end_vote_epoch, native_token_amount=args.value, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -269,13 +261,18 @@ def vote(args: Any): nonce=sender.nonce, proposal_nonce=args.proposal_nonce, vote=vote_value, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -293,13 +290,18 @@ def close_proposal(args: Any): sender=sender, nonce=sender.nonce, proposal_nonce=args.proposal_nonce, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -319,13 +321,18 @@ def clear_ended_proposals(args: Any): sender=sender, nonce=sender.nonce, proposers=proposers, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -342,13 +349,18 @@ def claim_accumulated_fees(args: Any): transaction = controller.create_transaction_for_claiming_accumulated_fees( sender=sender, nonce=sender.nonce, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -370,13 +382,18 @@ def change_config(args: Any): min_quorum=args.min_quorum, min_veto_threshold=args.min_veto_threshold, min_pass_threshold=args.min_pass_threshold, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/cli_shared.py b/multiversx_sdk_cli/cli_shared.py index 0dd67fdc..8d3113f9 100644 --- a/multiversx_sdk_cli/cli_shared.py +++ b/multiversx_sdk_cli/cli_shared.py @@ -870,30 +870,32 @@ def alter_transaction_and_sign_again_if_needed( altered = _alter_version_and_options_if_provided( args=args, - final_transaction=tx, + transaction=tx, ) - if altered: # sign only if something was altered + if altered: + # sign only if something was altered _sign_transaction(tx, sender, guardian_and_relayer_data) else: - _sign_transaction(tx, None, guardian_and_relayer_data) # sign only with guardian/relayer if needed + # sign only with guardian/relayer if needed + _sign_transaction(tx, None, guardian_and_relayer_data) def _alter_version_and_options_if_provided( args: Any, - final_transaction: Transaction, + transaction: Transaction, ) -> bool: """Alters the transaction version and options if they are provided in args. Returns True if any alteration was made, False otherwise. """ altered = False - if args.version != DEFAULT_TX_VERSION and final_transaction.version != args.version: - final_transaction.version = args.version + if args.version != DEFAULT_TX_VERSION and transaction.version != args.version: + transaction.version = args.version altered = True - if args.options and final_transaction.options != args.options: - final_transaction.options = args.options + if args.options and transaction.options != args.options: + transaction.options = args.options altered = True return altered From 84c17bbfa0d1ef4e5cf97599848598804cd90d0b Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 14:01:41 +0300 Subject: [PATCH 25/33] use guardian and relayer address instead of accounts --- multiversx_sdk_cli/cli_tokens.py | 172 +++++++++++++++---------------- 1 file changed, 86 insertions(+), 86 deletions(-) diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index e8a2dfd0..ca8dbc34 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -872,8 +872,8 @@ def issue_fungible(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -904,8 +904,8 @@ def issue_semi_fungible(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -936,8 +936,8 @@ def issue_non_fungible(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -969,8 +969,8 @@ def register_meta_esdt(args: Any): can_change_owner=args.can_change_owner, can_upgrade=args.can_upgrade, can_add_special_roles=args.can_add_special_roles, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -998,8 +998,8 @@ def register_and_set_all_roles(args: Any): token_ticker=args.token_ticker, num_decimals=args.num_decimals, token_type=token_type, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1022,8 +1022,8 @@ def set_burn_role_globally(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1046,8 +1046,8 @@ def unset_burn_role_globally(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1074,8 +1074,8 @@ def set_special_role_on_fungible(args: Any): add_role_local_mint=args.local_mint, add_role_local_burn=args.local_burn, add_role_esdt_transfer_role=args.esdt_transfer_role, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1102,8 +1102,8 @@ def unset_special_role_on_fungible(args: Any): remove_role_local_mint=args.local_mint, remove_role_local_burn=args.local_burn, remove_role_esdt_transfer_role=args.esdt_transfer_role, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1136,8 +1136,8 @@ def set_special_role_on_semi_fungible(args: Any): add_role_esdt_set_new_uri=args.esdt_set_new_uri, add_role_esdt_modify_creator=args.esdt_modify_creator, add_role_nft_recreate=args.nft_recreate, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1169,8 +1169,8 @@ def unset_special_role_on_semi_fungible(args: Any): remove_role_esdt_set_new_uri=args.esdt_set_new_uri, remove_role_esdt_modify_creator=args.esdt_modify_creator, remove_role_nft_recreate=args.nft_recreate, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1198,8 +1198,8 @@ def set_special_role_on_meta_esdt(args: Any): add_role_nft_burn=args.nft_burn, add_role_nft_add_quantity=args.nft_add_quantity, add_role_esdt_transfer_role=args.esdt_transfer_role, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1226,8 +1226,8 @@ def unset_special_role_on_meta_esdt(args: Any): remove_role_nft_burn=args.nft_burn, remove_role_nft_add_quantity=args.nft_add_quantity, remove_role_esdt_transfer_role=args.esdt_transfer_role, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1261,8 +1261,8 @@ def set_special_role_on_nft(args: Any): add_role_esdt_set_new_uri=args.esdt_set_new_uri, add_role_esdt_modify_creator=args.esdt_modify_creator, add_role_nft_recreate=args.nft_recreate, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1295,8 +1295,8 @@ def unset_special_role_on_nft(args: Any): remove_role_esdt_set_new_uri=args.esdt_set_new_uri, remove_role_esdt_modify_creator=args.esdt_modify_creator, remove_role_nft_recreate=args.nft_recreate, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1325,8 +1325,8 @@ def create_nft(args: Any): hash=args.hash, attributes=bytes.fromhex(args.attributes), uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1349,8 +1349,8 @@ def pause_token(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1373,8 +1373,8 @@ def unpause_token(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1398,8 +1398,8 @@ def freeze_token(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1423,8 +1423,8 @@ def unfreeze_token(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1448,8 +1448,8 @@ def wipe_token(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1473,8 +1473,8 @@ def local_mint(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, supply_to_mint=args.supply_to_mint, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1498,8 +1498,8 @@ def local_burn(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, supply_to_burn=args.supply_to_burn, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1524,8 +1524,8 @@ def update_attributes(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, attributes=bytes.fromhex(args.attributes), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1550,8 +1550,8 @@ def add_quantity(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, quantity_to_add=args.quantity, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1576,8 +1576,8 @@ def burn_quantity(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, quantity_to_burn=args.quantity, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1602,8 +1602,8 @@ def modify_royalties(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, new_royalties=args.royalties, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1628,8 +1628,8 @@ def set_new_uris(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, new_uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1653,8 +1653,8 @@ def modify_creator(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, token_nonce=args.token_nonce, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1683,8 +1683,8 @@ def update_metadata(args: Any): new_hash=args.hash, new_attributes=bytes.fromhex(args.attributes), new_uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1713,8 +1713,8 @@ def nft_metadata_recreate(args: Any): new_hash=args.hash, new_attributes=bytes.fromhex(args.attributes), new_uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1737,8 +1737,8 @@ def change_to_dynamic(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1761,8 +1761,8 @@ def update_token_id(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1790,8 +1790,8 @@ def register_dynamic_token(args: Any): token_ticker=args.token_ticker, token_type=token_type, denominator=args.denominator, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1819,8 +1819,8 @@ def register_dynamic_and_set_all_roles(args: Any): token_ticker=args.token_ticker, token_type=token_type, denominator=args.denominator, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1844,8 +1844,8 @@ def transfer_ownership(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, new_owner=Address.new_from_bech32(args.new_owner), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1870,8 +1870,8 @@ def freeze_single_nft(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1896,8 +1896,8 @@ def unfreeze_single_nft(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1921,8 +1921,8 @@ def change_sft_to_meta_esdt(args: Any): nonce=sender.nonce, collection=args.collection, num_decimals=args.decimals, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1946,8 +1946,8 @@ def transfer_nft_create_role(args: Any): nonce=sender.nonce, token_identifier=args.token_identifier, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1970,8 +1970,8 @@ def stop_nft_creation(args: Any): sender=sender, nonce=sender.nonce, token_identifier=args.token_identifier, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -1996,8 +1996,8 @@ def wipe_single_nft(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, user=Address.new_from_bech32(args.user), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -2022,8 +2022,8 @@ def add_uris(args: Any): token_identifier=args.token_identifier, token_nonce=args.token_nonce, uris=args.uris, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) From 00f909791d57413b10dcc1e09d0b5853074146d8 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 14:25:21 +0300 Subject: [PATCH 26/33] remove localnet smoke test --- .github/workflows/test-localnet-tests.yml | 8 +-- .github/workflows/test-localnet.yml | 84 ----------------------- 2 files changed, 4 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/test-localnet.yml diff --git a/.github/workflows/test-localnet-tests.yml b/.github/workflows/test-localnet-tests.yml index 5ba77048..5f64fcc8 100644 --- a/.github/workflows/test-localnet-tests.yml +++ b/.github/workflows/test-localnet-tests.yml @@ -52,7 +52,7 @@ jobs: nohup python3 -m multiversx_sdk_cli.cli localnet start --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml > localnet.log 2>&1 & echo $! > localnet.pid sleep 120 - # - name: Test localnet dependent tests - # run: | - # pytest -m require_localnet . - # python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml + - name: Test localnet dependent tests + run: | + pytest -m require_localnet . + python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml diff --git a/.github/workflows/test-localnet.yml b/.github/workflows/test-localnet.yml deleted file mode 100644 index 9f3f063d..00000000 --- a/.github/workflows/test-localnet.yml +++ /dev/null @@ -1,84 +0,0 @@ -name: Test localnet - -on: - pull_request: - branches: [main, feat/*] - workflow_dispatch: - -permissions: - contents: read - -env: - BRANCH_NAME: ${{ github.head_ref || github.ref_name }} - -jobs: - localnet: - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-latest, macos-latest] - python-version: [3.11] - - steps: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - uses: actions/checkout@v2 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - python3 -m pip install --upgrade pip - pip3 install -r requirements.txt - - - name: Smoke test (with resolution == remote) - run: | - mkdir -p ~/multiversx-sdk - export PYTHONPATH=. - python3 -m multiversx_sdk_cli.cli config set github_api_token ${{ secrets.GITHUB_TOKEN }} - python3 -m multiversx_sdk_cli.cli localnet prerequisites --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - python3 -m multiversx_sdk_cli.cli localnet build --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - - # "Go" and artifacts from "GOPATH/pkg/mod" are not needed anymore. - sudo rm -rf ~/multiversx-sdk/golang - - python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - python3 -m multiversx_sdk_cli.cli localnet config --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml - python3 -m multiversx_sdk_cli.cli localnet start --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_remote.toml --stop-after-seconds=120 - - if grep -r --include=\*.log "started committing block" ./localnet; then - echo "The localnet processed blocks successfully." - else - echo "The localnet failed to process blocks." - exit 1 - fi - - - name: Smoke test (with resolution == local) - run: | - mkdir -p ~/multiversx-sdk/sandbox - export PYTHONPATH=. - - git clone https://github.com/multiversx/mx-chain-go --branch=master --single-branch ~/multiversx-sdk/sandbox/mx-chain-go - git clone https://github.com/multiversx/mx-chain-proxy-go --branch=master --single-branch ~/multiversx-sdk/sandbox/mx-chain-proxy-go - - python3 -m multiversx_sdk_cli.cli localnet prerequisites --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml - python3 -m multiversx_sdk_cli.cli localnet build --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml - - # "Go" and artifacts from "GOPATH/pkg/mod" are not needed anymore. - sudo rm -rf ~/multiversx-sdk/golang - - python3 -m multiversx_sdk_cli.cli localnet clean --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml - python3 -m multiversx_sdk_cli.cli localnet config --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml - python3 -m multiversx_sdk_cli.cli localnet start --configfile=./multiversx_sdk_cli/tests/testdata/localnet_with_resolution_local.toml --stop-after-seconds=120 - - if grep -r --include=\*.log "started committing block" ./localnet; then - echo "The localnet processed blocks successfully." - else - echo "The localnet failed to process blocks." - exit 1 - fi From b2776e3df05d6ed521bb9d119519efccfc766ecb Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 14:25:39 +0300 Subject: [PATCH 27/33] set gas limit for tests --- .../tests/test_cli_validators_localnet.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/multiversx_sdk_cli/tests/test_cli_validators_localnet.py b/multiversx_sdk_cli/tests/test_cli_validators_localnet.py index c54a2545..18758752 100644 --- a/multiversx_sdk_cli/tests/test_cli_validators_localnet.py +++ b/multiversx_sdk_cli/tests/test_cli_validators_localnet.py @@ -32,6 +32,8 @@ def test_stake(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -54,6 +56,8 @@ def test_stake(): "--proxy", "http://127.0.0.1:7950", "--nonce=0", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -75,6 +79,8 @@ def test_stake_top_up(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -95,6 +101,8 @@ def test_unstake(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -115,6 +123,8 @@ def test_unbond(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -137,6 +147,8 @@ def test_unjail(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -157,6 +169,8 @@ def test_change_reward_address(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -177,6 +191,8 @@ def test_unstake_nodes(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -197,6 +213,8 @@ def test_unstake_tokens(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -217,6 +235,8 @@ def test_unbond_nodes(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -237,6 +257,8 @@ def test_unbond_tokens(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -255,6 +277,8 @@ def test_clean_registration_data(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 @@ -275,6 +299,8 @@ def test_re_stake_unstaked_nodes(): "localnet", "--proxy", "http://127.0.0.1:7950", + "--gas-limit", + "60000000", ] ) assert return_code == 0 From 7d081d6246cf68a52fa54275a8d8fa419a62269c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 16:05:43 +0300 Subject: [PATCH 28/33] fixes after merge --- multiversx_sdk_cli/cli_get.py | 8 +- multiversx_sdk_cli/cli_governance.py | 2 +- multiversx_sdk_cli/cli_multisig.py | 258 ++++++++++++++++++--------- 3 files changed, 183 insertions(+), 85 deletions(-) diff --git a/multiversx_sdk_cli/cli_get.py b/multiversx_sdk_cli/cli_get.py index 45bd6d3a..d1b275a2 100644 --- a/multiversx_sdk_cli/cli_get.py +++ b/multiversx_sdk_cli/cli_get.py @@ -107,7 +107,7 @@ def get_account(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -128,7 +128,7 @@ def get_storage(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -146,7 +146,7 @@ def get_key(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -167,7 +167,7 @@ def get_token(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared._get_address_hrp(args) + hrp = cli_shared.get_address_hrp(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) diff --git a/multiversx_sdk_cli/cli_governance.py b/multiversx_sdk_cli/cli_governance.py index c8843c36..4d31c650 100644 --- a/multiversx_sdk_cli/cli_governance.py +++ b/multiversx_sdk_cli/cli_governance.py @@ -196,7 +196,7 @@ def _ensure_args(args: Any): def _initialize_controller(args: Any) -> GovernanceController: - chain = args.chain if hasattr(args, "chain") else None + chain = getattr(args, "chain", None) chain_id = cli_shared.get_chain_id(args.proxy, chain) config = get_config_for_network_providers() proxy_url = args.proxy if args.proxy else "" diff --git a/multiversx_sdk_cli/cli_multisig.py b/multiversx_sdk_cli/cli_multisig.py index f44294cb..a3a55db4 100644 --- a/multiversx_sdk_cli/cli_multisig.py +++ b/multiversx_sdk_cli/cli_multisig.py @@ -37,9 +37,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.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount -from multiversx_sdk_cli.signing_wrapper import SigningWrapper logger = logging.getLogger("cli.multisig") @@ -664,7 +661,7 @@ def _ensure_args(args: Any): def _initialize_multisig_controller(args: Any) -> MultisigController: abi = Abi.load(Path(args.abi)) - chain = args.chain if hasattr(args, "chain") else None + chain = getattr(args, "chain", None) chain_id = cli_shared.get_chain_id(args.proxy, chain) config = get_config_for_network_providers() @@ -681,15 +678,6 @@ def _initialize_multisig_controller(args: Any) -> MultisigController: ) -def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): - signer = SigningWrapper() - signer.sign_transaction( - transaction=transaction, - sender=sender, - guardian_and_relayer=guardian_and_relayer_data, - ) - - def deploy(args: Any): logger.debug("multisig.deploy") _ensure_args(args) @@ -714,8 +702,8 @@ def deploy(args: Any): is_readable=args.metadata_readable, is_payable=args.metadata_payable, is_payable_by_sc=args.metadata_payable_by_sc, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -724,9 +712,14 @@ 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(multisig._factory._sc_factory.config.chain_id, contract_address.to_bech32()) + utils.log_explorer_contract_address(cli_shared.get_chain_id(args.proxy, args.chain), contract_address.to_bech32()) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract_address, args) @@ -753,13 +746,18 @@ def deposit(args: Any): contract=contract, native_token_amount=native_amount, token_transfers=token_transfers, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -781,13 +779,18 @@ def discard_action(args: Any): nonce=sender.nonce, contract=contract, action_id=action_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -809,13 +812,18 @@ def discard_batch(args: Any): nonce=sender.nonce, contract=contract, actions_ids=actions, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -837,13 +845,18 @@ def add_board_member(args: Any): nonce=sender.nonce, contract=contract, board_member=board_member, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -865,13 +878,18 @@ def add_proposer(args: Any): nonce=sender.nonce, contract=contract, proposer=proposer, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -893,13 +911,18 @@ def remove_user(args: Any): nonce=sender.nonce, contract=contract, user=user, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -921,13 +944,18 @@ def change_quorum(args: Any): nonce=sender.nonce, contract=contract, new_quorum=quorum, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -961,13 +989,18 @@ def transfer_and_execute(args: Any): abi=contract_abi, arguments=arguments, native_token_amount=int(args.value), - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1008,13 +1041,18 @@ def transfer_and_execute_esdt(args: Any): function=function, abi=contract_abi, arguments=arguments, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1053,13 +1091,18 @@ def async_call(args: Any): function=function, abi=contract_abi, arguments=arguments, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1093,13 +1136,18 @@ def deploy_from_source(args: Any): native_token_amount=int(args.value), abi=contract_abi, arguments=arguments, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1135,13 +1183,18 @@ def upgrade_from_source(args: Any): native_token_amount=int(args.value), abi=contract_abi, arguments=arguments, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1163,13 +1216,18 @@ def sign_action(args: Any): nonce=sender.nonce, contract=contract, action_id=action_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1191,13 +1249,18 @@ def sign_batch(args: Any): nonce=sender.nonce, contract=contract, batch_id=batch_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1219,13 +1282,18 @@ def sign_and_perform(args: Any): nonce=sender.nonce, contract=contract, action_id=action_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1247,13 +1315,18 @@ def sign_batch_and_perform(args: Any): nonce=sender.nonce, contract=contract, batch_id=batch_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1275,13 +1348,18 @@ def unsign_action(args: Any): nonce=sender.nonce, contract=contract, action_id=action_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1303,13 +1381,18 @@ def unsign_batch(args: Any): nonce=sender.nonce, contract=contract, batch_id=batch_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1332,13 +1415,18 @@ def unsign_for_outdated_board_members(args: Any): contract=contract, action_id=action_id, outdated_board_members=args.outdated_members, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1360,13 +1448,18 @@ def perform_action(args: Any): nonce=sender.nonce, contract=contract, action_id=action_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) @@ -1388,13 +1481,18 @@ def perform_batch(args: Any): nonce=sender.nonce, contract=contract, batch_id=batch_id, - guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None, - relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) _send_or_simulate(tx, contract, args) From 7f3fcc7621d224abfdab8125547e44b8f072472c Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 23 Sep 2025 16:37:22 +0300 Subject: [PATCH 29/33] fixes after merge --- multiversx_sdk_cli/cli_validators.py | 149 ++++++++++++++++++--------- 1 file changed, 98 insertions(+), 51 deletions(-) diff --git a/multiversx_sdk_cli/cli_validators.py b/multiversx_sdk_cli/cli_validators.py index 7981b3c7..fdbcb681 100644 --- a/multiversx_sdk_cli/cli_validators.py +++ b/multiversx_sdk_cli/cli_validators.py @@ -3,7 +3,6 @@ from multiversx_sdk import ( Address, - Transaction, ValidatorPublicKey, ValidatorsController, ValidatorsSigners, @@ -16,9 +15,6 @@ validate_nonce_args, validate_receiver_args, ) -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount -from multiversx_sdk_cli.signing_wrapper import SigningWrapper def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -159,15 +155,6 @@ def validate_args(args: Any) -> None: validate_chain_id_args(args) -def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): - signer = SigningWrapper() - signer.sign_transaction( - transaction=transaction, - sender=sender, - guardian_and_relayer=guardian_and_relayer_data, - ) - - def do_stake(args: Any): validate_args(args) @@ -187,8 +174,8 @@ def do_stake(args: Any): sender=sender, nonce=sender.nonce, amount=native_amount, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) @@ -200,13 +187,18 @@ def do_stake(args: Any): validators_file=validators_signers, amount=native_amount, rewards_address=rewards_address, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -247,13 +239,18 @@ def do_unstake(args: Any): sender=sender, nonce=sender.nonce, public_keys=keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -275,13 +272,18 @@ def do_unjail(args: Any): nonce=sender.nonce, public_keys=keys, amount=native_amount, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -301,13 +303,18 @@ def do_unbond(args: Any): sender=sender, nonce=sender.nonce, public_keys=keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -327,13 +334,18 @@ def change_reward_address(args: Any): sender=sender, nonce=sender.nonce, rewards_address=rewards_address, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -350,13 +362,18 @@ def do_claim(args: Any): tx = controller.create_transaction_for_claiming( sender=sender, nonce=sender.nonce, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -376,13 +393,18 @@ def do_unstake_nodes(args: Any): sender=sender, nonce=sender.nonce, public_keys=keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -402,13 +424,18 @@ def do_unstake_tokens(args: Any): sender=sender, nonce=sender.nonce, amount=value, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -428,13 +455,18 @@ def do_unbond_nodes(args: Any): sender=sender, nonce=sender.nonce, public_keys=keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -454,13 +486,18 @@ def do_unbond_tokens(args: Any): sender=sender, nonce=sender.nonce, amount=value, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -477,13 +514,18 @@ def do_clean_registered_data(args: Any): tx = controller.create_transaction_for_cleaning_registered_data( sender=sender, nonce=sender.nonce, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) @@ -503,11 +545,16 @@ def do_restake_unstaked_nodes(args: Any): sender=sender, nonce=sender.nonce, public_keys=keys, - guardian=guardian_and_relayer_data.guardian_address if guardian_and_relayer_data.guardian_address else None, - relayer=guardian_and_relayer_data.relayer_address if guardian_and_relayer_data.relayer_address else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, gas_limit=args.gas_limit, gas_price=args.gas_price, ) - _sign_transaction(tx, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) From 23a0c6d1cc8bfe363653be792b8a5802ae4340d0 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 24 Sep 2025 09:19:31 +0300 Subject: [PATCH 30/33] transactions refactoring --- multiversx_sdk_cli/cli_transactions.py | 88 ++++-- multiversx_sdk_cli/dns.py | 21 +- .../tests/test_cli_transactions.py | 22 ++ multiversx_sdk_cli/tests/test_transactions.py | 256 ------------------ multiversx_sdk_cli/transactions.py | 76 +----- 5 files changed, 95 insertions(+), 368 deletions(-) delete mode 100644 multiversx_sdk_cli/tests/test_transactions.py diff --git a/multiversx_sdk_cli/cli_transactions.py b/multiversx_sdk_cli/cli_transactions.py index 1249cafd..fd97ae51 100644 --- a/multiversx_sdk_cli/cli_transactions.py +++ b/multiversx_sdk_cli/cli_transactions.py @@ -2,7 +2,12 @@ from pathlib import Path from typing import Any -from multiversx_sdk import Address, ProxyNetworkProvider, TransactionComputer +from multiversx_sdk import ( + Address, + ProxyNetworkProvider, + TransactionComputer, + TransfersController, +) from multiversx_sdk_cli import cli_shared, utils from multiversx_sdk_cli.args_validation import ( @@ -13,14 +18,12 @@ validate_proxy_argument, validate_receiver_args, ) -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.errors import BadUsage, IncorrectWalletError, NoWalletProvided -from multiversx_sdk_cli.transactions import ( - TransactionsController, - load_transaction_from_file, -) +from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData +from multiversx_sdk_cli.signing_wrapper import SigningWrapper +from multiversx_sdk_cli.transactions import load_transaction_from_file logger = logging.getLogger("cli.transactions") @@ -101,38 +104,59 @@ def create_transaction(args: Any): validate_broadcast_args(args) validate_chain_id_args(args) + if args.data_file: + args.data = Path(args.data_file).read_text() + + transfers = getattr(args, "token_transfers", None) + + if transfers and args.data: + raise BadUsage("You cannot provide both data and token transfers") + sender = cli_shared.prepare_sender(args) guardian_and_relayer_data = cli_shared.get_guardian_and_relayer_data( sender=sender.address.to_bech32(), args=args, ) - if args.data_file: - args.data = Path(args.data_file).read_text() - native_amount = int(args.value) - - transfers = getattr(args, "token_transfers", None) + receiver = Address.new_from_bech32(args.receiver) transfers = cli_shared.prepare_token_transfers(transfers) if transfers else None chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - tx_controller = TransactionsController(chain_id, gas_estimator) - - tx = tx_controller.create_transaction( + controller = TransfersController(chain_id=chain_id, gas_limit_estimator=gas_estimator) + + if not transfers: + tx = controller.create_transaction_for_native_token_transfer( + sender=sender, + nonce=sender.nonce, + receiver=receiver, + native_transfer_amount=native_amount, + data=args.data.encode() if args.data else None, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + else: + tx = controller.create_transaction_for_transfer( + sender=sender, + nonce=sender.nonce, + receiver=receiver, + native_transfer_amount=native_amount, + token_transfers=transfers, + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, + gas_limit=args.gas_limit, + gas_price=args.gas_price, + ) + + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, sender=sender, - receiver=Address.new_from_bech32(args.receiver), - native_amount=native_amount, - gas_limit=args.gas_limit, - gas_price=args.gas_price, - nonce=sender.nonce, - version=args.version, - options=args.options, - token_transfers=transfers, - data=args.data, guardian_and_relayer_data=guardian_and_relayer_data, ) - cli_shared.send_or_simulate(tx, args) @@ -180,18 +204,24 @@ def sign_transaction(args: Any): tx_computer = TransactionComputer() if tx.guardian and not tx_computer.has_options_set_for_guarded_transaction(tx): - raise BadUsage("Guardian wallet provided but the transaction has incorrect options.") + raise BadUsage("Guardian wallet provided but the transaction has incorrect options") - tx_controller = BaseTransactionsController() - tx_controller.sign_transaction( - transaction=tx, - sender=sender, + guardian_and_relayer = GuardianRelayerData( guardian=guardian, + guardian_address=tx.guardian, relayer=relayer, + relayer_address=tx.relayer, guardian_service_url=args.guardian_service_url, guardian_2fa_code=args.guardian_2fa_code, ) + signer = SigningWrapper() + signer.sign_transaction( + transaction=tx, + sender=sender, + guardian_and_relayer=guardian_and_relayer, + ) + cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/dns.py b/multiversx_sdk_cli/dns.py index c1a70277..486ce0d6 100644 --- a/multiversx_sdk_cli/dns.py +++ b/multiversx_sdk_cli/dns.py @@ -6,6 +6,7 @@ AddressComputer, SmartContractQuery, SmartContractQueryResponse, + TransfersController, ) from multiversx_sdk_cli import cli_shared @@ -16,7 +17,6 @@ ) from multiversx_sdk_cli.config_env import get_address_hrp from multiversx_sdk_cli.constants import ADDRESS_ZERO_HEX -from multiversx_sdk_cli.transactions import TransactionsController MaxNumShards = 256 ShardIdentiferLen = 2 @@ -77,21 +77,26 @@ def register(args: Any): chain_id = cli_shared.get_chain_id(args.proxy, args.chain) gas_estimator = cli_shared.initialize_gas_limit_estimator(args) - controller = TransactionsController(chain_id=chain_id, gas_limit_estimator=gas_estimator) + controller = TransfersController(chain_id=chain_id, gas_limit_estimator=gas_estimator) - tx = controller.create_transaction( + tx = controller.create_transaction_for_native_token_transfer( sender=sender, receiver=receiver, - native_amount=native_amount, + native_transfer_amount=native_amount, gas_limit=args.gas_limit, gas_price=args.gas_price, nonce=sender.nonce, - version=args.version, - options=args.options, - data=data, - guardian_and_relayer_data=guardian_and_relayer_data, + data=data.encode(), + guardian=guardian_and_relayer_data.guardian_address, + relayer=guardian_and_relayer_data.relayer_address, ) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=tx, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(tx, args) diff --git a/multiversx_sdk_cli/tests/test_cli_transactions.py b/multiversx_sdk_cli/tests/test_cli_transactions.py index 128cf63a..fb522b58 100644 --- a/multiversx_sdk_cli/tests/test_cli_transactions.py +++ b/multiversx_sdk_cli/tests/test_cli_transactions.py @@ -463,6 +463,28 @@ def test_estimate_gas_with_multiplier(capsys: Any): assert tx_json["gasLimit"] == 75000 +def test_raise_error_when_data_and_transfers_provided(capsys: Any): + return_code = main( + [ + "tx", + "new", + "--pem", + str(testdata_path / "alice.pem"), + "--receiver", + "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + "--nonce", + "7", + "--chain", + "D", + "--data", + "hello", + "--token-transfers", + "TEST-123456", + ] + ) + assert return_code == 1 + + def _read_stdout(capsys: Any) -> str: stdout: str = capsys.readouterr().out.strip() return stdout diff --git a/multiversx_sdk_cli/tests/test_transactions.py b/multiversx_sdk_cli/tests/test_transactions.py deleted file mode 100644 index 8a8c4e4c..00000000 --- a/multiversx_sdk_cli/tests/test_transactions.py +++ /dev/null @@ -1,256 +0,0 @@ -from pathlib import Path - -from multiversx_sdk import Account, Address - -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.transactions import TransactionsController - -testdata = Path(__file__).parent / "testdata" - - -class TestTransactionsController: - controller = TransactionsController("D") - alice = Account.new_from_pem(testdata / "alice.pem") - - def test_create_transaction_without_data_and_value(self): - guardian_relayer_data = GuardianRelayerData() - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=50000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 50000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert not transaction.data - assert not transaction.guardian - assert not transaction.relayer - assert not transaction.guardian_signature - assert not transaction.relayer_signature - assert ( - transaction.signature.hex() - == "ecf9e9f8d395741c0fbb61eaba74295448ba380dd00a228463e29a278d4e3c9219b2fa54133e32510837e03d7cc9f17738b99b701e148ce098b8340064a5f409" - ) - - def test_create_transfer_transaction(self): - guardian_relayer_data = GuardianRelayerData() - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=123456789, - gas_limit=50000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 123456789 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 50000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert not transaction.data - assert not transaction.guardian - assert not transaction.relayer - assert not transaction.guardian_signature - assert not transaction.relayer_signature - assert ( - transaction.signature.hex() - == "fe0ff59c06c453eed882db562f98c0684a32763a79580a33e269af6edbebc150007118b298f34d17c54b90d55cee76ed1e5254832db8acb2c34ef12f14b8b40d" - ) - - def test_create_transaction_with_data(self): - guardian_relayer_data = GuardianRelayerData() - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=50000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 50000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert transaction.data == b"testdata" - assert not transaction.guardian - assert not transaction.relayer - assert not transaction.guardian_signature - assert not transaction.relayer_signature - assert ( - transaction.signature.hex() - == "74bb3bd0c4e87ed64a01456f888236a74b5672cf194a33a2225d868f5f43d65e9149f3145b9431075828ff842f70b977b778895925f37037db979e71563c540c" - ) - - def test_create_guarded_transaction(self): - guardian_relayer_data = GuardianRelayerData( - guardian=Account.new_from_pem(testdata / "testUser2.pem"), - guardian_address=Address.new_from_bech32("erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4"), - ) - - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=200000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 200000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 2 - assert transaction.data == b"testdata" - assert not transaction.relayer - assert not transaction.relayer_signature - assert ( - transaction.guardian - and transaction.guardian.to_bech32() == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" - ) - assert ( - transaction.guardian_signature.hex() - == "c8b186f85c6e79e157aac48ec55d3f915abbc396e257d30aff193135485395c4b026e7921853366a16bcbbb8dbe5f6cf98a917a8ca11ccdc3f29f5a5a7d7af0c" - ) - assert ( - transaction.signature.hex() - == "8e9338de8f1d66bc6cd2f8e42cb62b5456d82ba66fdf9b8ace750ab3fa697f348084b41996b19d172b627b0b0a312ef76d29191d627b4d9959a3bf17409f780b" - ) - - def test_create_relayed_transaction(self): - guardian_relayer_data = GuardianRelayerData( - relayer=Account.new_from_pem(testdata / "testUser2.pem"), - relayer_address=Address.new_from_bech32("erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4"), - ) - - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=200000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 200000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 0 - assert transaction.data == b"testdata" - assert not transaction.guardian - assert not transaction.guardian_signature - assert ( - transaction.relayer - and transaction.relayer.to_bech32() == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" - ) - assert ( - transaction.relayer_signature.hex() - == "385fb15816d52118b97a20451c2b225a81ce9be130ad13987453cab36e858f79af0473effc845bef1537ad9f878001e6fcdfeefa36c46c5e8bb6aab83c9b2a0b" - ) - assert ( - transaction.signature.hex() - == "89c2de2939bdd4ed2bdaf8f859f9020b6f7510b3a7298daaebdef53ce1de588181e1c27f8933745927e610ebfe6c41a8875e2b052a48fa22464903f3821b830e" - ) - - def test_create_guarded_relayed_transaction(self): - guardian_relayer_data = GuardianRelayerData( - guardian=Account.new_from_pem(testdata / "testUser.pem"), - guardian_address=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - relayer=Account.new_from_pem(testdata / "testUser2.pem"), - relayer_address=Address.new_from_bech32("erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4"), - ) - - transaction = self.controller.create_transaction( - sender=self.alice, - receiver=Address.new_from_bech32("erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5"), - native_amount=0, - gas_limit=200000, - gas_price=1000000000, - nonce=7, - version=2, - options=0, - data="testdata", - guardian_and_relayer_data=guardian_relayer_data, - ) - - assert transaction.sender == self.alice.address - assert transaction.receiver.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - assert transaction.value == 0 - assert transaction.chain_id == "D" - assert transaction.gas_limit == 200000 - assert transaction.gas_price == 1000000000 - assert transaction.nonce == 7 - assert transaction.version == 2 - assert transaction.options == 2 - assert transaction.data == b"testdata" - - assert ( - transaction.guardian - and transaction.guardian.to_bech32() == "erd1cqqxak4wun7508e0yj9ng843r6hv4mzd0hhpjpsejkpn9wa9yq8sj7u2u5" - ) - assert ( - transaction.guardian_signature.hex() - == "06bc457b510cae975e1cc6ab863ed765aadbd948ad23cbd204d66a2b92bee683922d308148af47e28d186bceba13474c79f16b26803c65c908f1d4a2e2ac6a0e" - ) - - assert ( - transaction.relayer - and transaction.relayer.to_bech32() == "erd1ssmsc9022udc8pdw7wk3hxw74jr900xg28vwpz3z60gep66fasasl2nkm4" - ) - assert ( - transaction.relayer_signature.hex() - == "86e2460a6045ac3142c23f06c3b31fc132f38227faa25ffc8f7e9ce32c4542f6ed37d740d3c83c4454f2390befd223b968d4767c28991f574689b36faa978209" - ) - - assert ( - transaction.signature.hex() - == "b0bce606f2cfd52d6641f8e96aa29dcfd334af4707d88f81dba01dac67e72a99d7143dccadc8d120b387c4eaac84dc01865e57488a2162480a0f15acf50b6306" - ) diff --git a/multiversx_sdk_cli/transactions.py b/multiversx_sdk_cli/transactions.py index d5f9503f..f4229b51 100644 --- a/multiversx_sdk_cli/transactions.py +++ b/multiversx_sdk_cli/transactions.py @@ -2,22 +2,9 @@ import logging from typing import Optional, Protocol, TextIO, Union -from multiversx_sdk import ( - Address, - AwaitingOptions, - GasLimitEstimator, - TokenTransfer, - Transaction, - TransactionOnNetwork, - TransactionsFactoryConfig, - TransferTransactionsFactory, -) +from multiversx_sdk import AwaitingOptions, Transaction, TransactionOnNetwork from multiversx_sdk_cli import errors -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.constants import MIN_GAS_LIMIT -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount logger = logging.getLogger("transactions") @@ -38,67 +25,6 @@ def await_transaction_completed(self, transaction_hash: Union[bytes, str], optio # fmt: on -class TransactionsController(BaseTransactionsController): - def __init__(self, chain_id: str, gas_limit_estimator: Optional[GasLimitEstimator] = None) -> None: - config = TransactionsFactoryConfig(chain_id) - self.chain_id = chain_id - self.factory = TransferTransactionsFactory(config, gas_limit_estimator) - - def create_transaction( - self, - sender: IAccount, - receiver: Address, - native_amount: int, - gas_limit: Union[int, None], - gas_price: int, - nonce: int, - version: int, - options: int, - guardian_and_relayer_data: GuardianRelayerData, - token_transfers: Optional[list[TokenTransfer]] = None, - data: Optional[str] = None, - ) -> Transaction: - # if no value, token transfers or data provided, create plain transaction - if not native_amount and not token_transfers and not data: - transaction = Transaction( - sender=sender.address, - receiver=receiver, - gas_limit=MIN_GAS_LIMIT, - chain_id=self.chain_id, - ) - else: - transaction = self.factory.create_transaction_for_transfer( - sender=sender.address, - receiver=receiver, - native_amount=native_amount, - token_transfers=token_transfers, - data=data.encode() if data else None, - ) - - transaction.gas_price = gas_price - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address - - self.add_extra_gas_limit_if_required(transaction) - - if gas_limit: - transaction.gas_limit = gas_limit - - self.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - return transaction - - def send_and_wait_for_result(transaction: Transaction, proxy: INetworkProvider, timeout: int) -> TransactionOnNetwork: if not transaction.signature: raise errors.TransactionIsNotSigned() From 6d4d23b7106a52f02ed62650bd2c9223f60a4412 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 25 Sep 2025 10:32:07 +0300 Subject: [PATCH 31/33] fixes from previous PR --- multiversx_sdk_cli/cli_get.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/multiversx_sdk_cli/cli_get.py b/multiversx_sdk_cli/cli_get.py index d1b275a2..9daffffe 100644 --- a/multiversx_sdk_cli/cli_get.py +++ b/multiversx_sdk_cli/cli_get.py @@ -107,7 +107,7 @@ def get_account(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared.get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -128,7 +128,7 @@ def get_storage(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared.get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -146,7 +146,7 @@ def get_key(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared.get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) @@ -167,7 +167,7 @@ def get_token(args: Any): if args.address: address = Address.new_from_bech32(args.address) else: - hrp = cli_shared.get_address_hrp(args) + hrp = cli_shared.get_address_hrp_with_fallback(args) address = _get_address_from_alias_or_config(args.alias, hrp) proxy = _get_proxy(args) From 6f1ce4002be0bacb2bd306027bd740a634100814 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 25 Sep 2025 11:24:36 +0300 Subject: [PATCH 32/33] cleanup --- .../base_transactions_controller.py | 172 ---------- multiversx_sdk_cli/cli_tokens.py | 317 ++++++++++++++---- multiversx_sdk_cli/transactions.py | 3 - 3 files changed, 258 insertions(+), 234 deletions(-) delete mode 100644 multiversx_sdk_cli/base_transactions_controller.py diff --git a/multiversx_sdk_cli/base_transactions_controller.py b/multiversx_sdk_cli/base_transactions_controller.py deleted file mode 100644 index 8db775a6..00000000 --- a/multiversx_sdk_cli/base_transactions_controller.py +++ /dev/null @@ -1,172 +0,0 @@ -import logging -from typing import Any, Optional, Union - -from multiversx_sdk import Address, LedgerAccount, Transaction, TransactionComputer -from multiversx_sdk.abi import ( - AddressValue, - BigUIntValue, - BoolValue, - BytesValue, - StringValue, -) - -from multiversx_sdk_cli.config_env import get_address_hrp -from multiversx_sdk_cli.constants import ( - ADDRESS_PREFIX, - EXTRA_GAS_LIMIT_FOR_GUARDED_TRANSACTIONS, - EXTRA_GAS_LIMIT_FOR_RELAYED_TRANSACTIONS, - FALSE_STR_LOWER, - HEX_PREFIX, - MAINCHAIN_ADDRESS_HRP, - STR_PREFIX, - TRUE_STR_LOWER, -) -from multiversx_sdk_cli.cosign_transaction import cosign_transaction -from multiversx_sdk_cli.errors import BadUserInput, TransactionSigningError -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount - -logger = logging.getLogger("base_controller") - - -class BaseTransactionsController: - def __init__(self) -> None: - pass - - def sign_transaction( - self, - transaction: Transaction, - sender: Optional[IAccount] = None, - guardian: Optional[IAccount] = None, - relayer: Optional[IAccount] = None, - guardian_service_url: Optional[str] = None, - guardian_2fa_code: Optional[str] = None, - ): - """Signs the transaction using the sender's account and, if required, additionally signs with the guardian's and relayer's accounts. Ensures the appropriate transaction options are set as needed.""" - self._set_options_for_guarded_transaction_if_needed(transaction) - self._set_options_for_hash_signing_if_needed(transaction, sender, guardian, relayer) - - if sender: - try: - transaction.signature = sender.sign_transaction(transaction) - except Exception as e: - raise TransactionSigningError(f"Could not sign transaction: {str(e)}") - - self._sign_guarded_transaction_if_guardian( - transaction, - guardian, - guardian_service_url, - guardian_2fa_code, - ) - self._sign_relayed_transaction_if_relayer(transaction, relayer) - - def add_extra_gas_limit_if_required(self, transaction: Transaction): - """In case of guarded or relayed transactions, extra gas limit is added.""" - if transaction.guardian: - transaction.gas_limit += EXTRA_GAS_LIMIT_FOR_GUARDED_TRANSACTIONS - - if transaction.relayer: - transaction.gas_limit += EXTRA_GAS_LIMIT_FOR_RELAYED_TRANSACTIONS - - def _set_options_for_guarded_transaction_if_needed(self, transaction: Transaction): - if transaction.guardian: - transaction_computer = TransactionComputer() - transaction_computer.apply_guardian(transaction, transaction.guardian) - - def _set_options_for_hash_signing_if_needed( - self, - transaction: Transaction, - sender: Union[IAccount, None], - guardian: Union[IAccount, None], - relayer: Union[IAccount, None], - ): - if ( - isinstance(sender, LedgerAccount) - or isinstance(guardian, LedgerAccount) - or isinstance(relayer, LedgerAccount) - ): - transaction_computer = TransactionComputer() - transaction_computer.apply_options_for_hash_signing(transaction) - - def _sign_guarded_transaction_if_guardian( - self, - transaction: Transaction, - guardian: Union[IAccount, None], - guardian_service_url: Union[str, None], - guardian_2fa_code: Union[str, None], - ) -> Transaction: - # If the guardian account is provided, we sign locally. Otherwise, we reach for the trusted cosign service. - if guardian: - try: - transaction.guardian_signature = guardian.sign_transaction(transaction) - except Exception as e: - raise TransactionSigningError(f"Could not sign transaction: {str(e)}") - elif transaction.guardian and guardian_service_url and guardian_2fa_code: - cosign_transaction(transaction, guardian_service_url, guardian_2fa_code) - - return transaction - - def _sign_relayed_transaction_if_relayer(self, transaction: Transaction, relayer: Union[IAccount, None]): - if relayer and transaction.relayer: - try: - transaction.relayer_signature = relayer.sign_transaction(transaction) - except Exception as e: - raise TransactionSigningError(f"Could not sign transaction: {str(e)}") - - def _convert_args_to_typed_values(self, arguments: list[str]) -> list[Any]: - args: list[Any] = [] - - for arg in arguments: - if arg.startswith(HEX_PREFIX): - args.append(BytesValue(self._hex_to_bytes(arg))) - elif arg.isnumeric(): - args.append(BigUIntValue(int(arg))) - elif arg.startswith(ADDRESS_PREFIX): - args.append(AddressValue.new_from_address(Address.new_from_bech32(arg[len(ADDRESS_PREFIX) :]))) - elif arg.startswith(MAINCHAIN_ADDRESS_HRP): - # this flow will be removed in the future - logger.warning( - "Address argument has no prefix. This flow will be removed in the future. Please provide each address using the `addr:` prefix. (e.g. --arguments addr:erd1...)" - ) - args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) - elif arg.startswith(get_address_hrp()): - args.append(AddressValue.new_from_address(Address.new_from_bech32(arg))) - elif arg.lower() == FALSE_STR_LOWER: - args.append(BoolValue(False)) - elif arg.lower() == TRUE_STR_LOWER: - args.append(BoolValue(True)) - elif arg.startswith(STR_PREFIX): - args.append(StringValue(arg[len(STR_PREFIX) :])) - else: - raise BadUserInput( - f"Unknown argument type for argument: `{arg}`. Use `mxpy contract --help` to check all supported arguments" - ) - - return args - - def _hex_to_bytes(self, arg: str): - argument = arg[len(HEX_PREFIX) :] - argument = argument.upper() - argument = self.ensure_even_length(argument) - return bytes.fromhex(argument) - - def ensure_even_length(self, string: str) -> str: - if len(string) % 2 == 1: - return "0" + string - return string - - def _set_transaction_fields( - self, - transaction: Transaction, - nonce: int, - version: int, - options: int, - gas_price: int, - guardian_and_relayer_data: GuardianRelayerData, - ): - transaction.nonce = nonce - transaction.version = version - transaction.options = options - transaction.gas_price = gas_price - transaction.guardian = guardian_and_relayer_data.guardian_address - transaction.relayer = guardian_and_relayer_data.relayer_address diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index ca8dbc34..c083d706 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -5,7 +5,6 @@ ProxyNetworkProvider, TokenManagementController, TokenType, - Transaction, ) from multiversx_sdk_cli import cli_shared @@ -13,9 +12,6 @@ validate_broadcast_args, validate_chain_id_args, ) -from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController -from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData -from multiversx_sdk_cli.interfaces import IAccount def setup_parser(args: list[str], subparsers: Any) -> Any: @@ -837,18 +833,6 @@ def _initialize_controller(args: Any) -> TokenManagementController: ) -def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData): - base = BaseTransactionsController() - base.sign_transaction( - transaction=transaction, - sender=sender, - guardian=guardian_and_relayer_data.guardian, - relayer=guardian_and_relayer_data.relayer, - guardian_service_url=guardian_and_relayer_data.guardian_service_url, - guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code, - ) - - def issue_fungible(args: Any): _ensure_args(args) @@ -878,7 +862,12 @@ def issue_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -910,7 +899,12 @@ def issue_semi_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -942,7 +936,12 @@ def issue_non_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -975,7 +974,12 @@ def register_meta_esdt(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1004,7 +1008,12 @@ def register_and_set_all_roles(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1028,7 +1037,12 @@ def set_burn_role_globally(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1052,7 +1066,12 @@ def unset_burn_role_globally(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1080,7 +1099,12 @@ def set_special_role_on_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1108,7 +1132,12 @@ def unset_special_role_on_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1142,7 +1171,12 @@ def set_special_role_on_semi_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1175,7 +1209,12 @@ def unset_special_role_on_semi_fungible(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1204,7 +1243,12 @@ def set_special_role_on_meta_esdt(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1232,7 +1276,12 @@ def unset_special_role_on_meta_esdt(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1267,7 +1316,12 @@ def set_special_role_on_nft(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1301,7 +1355,12 @@ def unset_special_role_on_nft(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1331,7 +1390,12 @@ def create_nft(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1355,7 +1419,12 @@ def pause_token(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1379,7 +1448,12 @@ def unpause_token(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1404,7 +1478,12 @@ def freeze_token(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1429,7 +1508,12 @@ def unfreeze_token(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1454,7 +1538,12 @@ def wipe_token(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1479,7 +1568,12 @@ def local_mint(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1504,7 +1598,12 @@ def local_burn(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1530,7 +1629,12 @@ def update_attributes(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1556,7 +1660,12 @@ def add_quantity(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1582,7 +1691,12 @@ def burn_quantity(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1608,7 +1722,12 @@ def modify_royalties(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1634,7 +1753,12 @@ def set_new_uris(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1659,7 +1783,12 @@ def modify_creator(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1689,7 +1818,12 @@ def update_metadata(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1719,7 +1853,12 @@ def nft_metadata_recreate(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1743,7 +1882,12 @@ def change_to_dynamic(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1767,7 +1911,12 @@ def update_token_id(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1796,7 +1945,12 @@ def register_dynamic_token(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1825,7 +1979,12 @@ def register_dynamic_and_set_all_roles(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1850,7 +2009,12 @@ def transfer_ownership(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1876,7 +2040,12 @@ def freeze_single_nft(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1902,7 +2071,12 @@ def unfreeze_single_nft(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1927,7 +2101,12 @@ def change_sft_to_meta_esdt(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1952,7 +2131,12 @@ def transfer_nft_create_role(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -1976,7 +2160,12 @@ def stop_nft_creation(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -2002,7 +2191,12 @@ def wipe_single_nft(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) @@ -2028,5 +2222,10 @@ def add_uris(args: Any): gas_price=args.gas_price, ) - _sign_transaction(transaction, sender, guardian_and_relayer_data) + cli_shared.alter_transaction_and_sign_again_if_needed( + args=args, + tx=transaction, + sender=sender, + guardian_and_relayer_data=guardian_and_relayer_data, + ) cli_shared.send_or_simulate(transaction, args) diff --git a/multiversx_sdk_cli/transactions.py b/multiversx_sdk_cli/transactions.py index f4229b51..327ffff4 100644 --- a/multiversx_sdk_cli/transactions.py +++ b/multiversx_sdk_cli/transactions.py @@ -17,9 +17,6 @@ class INetworkProvider(Protocol): def send_transaction(self, transaction: Transaction) -> bytes: ... - def get_transaction(self, transaction_hash: Union[bytes, str]) -> TransactionOnNetwork: - ... - def await_transaction_completed(self, transaction_hash: Union[bytes, str], options: Optional[AwaitingOptions] = None) -> TransactionOnNetwork: ... # fmt: on From 3d0f64b1da771ab2672bc06600623f0518727992 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Mon, 29 Sep 2025 11:19:03 +0300 Subject: [PATCH 33/33] bump version and CLI.md update --- CLI.md | 2814 +++++++++++++++++++++++++++++- CLI.md.sh | 44 + multiversx_sdk_cli/cli_tokens.py | 2 +- pyproject.toml | 2 +- 4 files changed, 2857 insertions(+), 5 deletions(-) diff --git a/CLI.md b/CLI.md index e27952f1..c05b48da 100644 --- a/CLI.md +++ b/CLI.md @@ -23,7 +23,7 @@ See: COMMAND GROUPS: - {config-wallet,contract,tx,validator,ledger,wallet,validator-wallet,deps,config,localnet,data,staking-provider,dns,faucet,multisig,governance,config-env,get} + {config-wallet,contract,tx,validator,ledger,wallet,validator-wallet,deps,config,localnet,data,staking-provider,dns,faucet,multisig,governance,config-env,get,token} TOP-LEVEL OPTIONS: -h, --help show this help message and exit @@ -53,6 +53,7 @@ multisig Deploy and interact with the Multisig Smart Contr governance Propose, vote and interact with the governance contract. config-env Configure MultiversX CLI to use specific environment values. get Get info from the network. +token Perform token management operations (issue tokens, create NFTs, set roles, etc.) ``` ## Group **Contract** @@ -144,6 +145,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -237,6 +240,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -340,6 +345,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -551,6 +558,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --data DATA the payload, or 'memo' of the transaction (default: ) --chain CHAIN the chain identifier @@ -771,6 +780,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -827,6 +838,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -881,6 +894,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -935,6 +950,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -989,6 +1006,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1043,6 +1062,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1096,6 +1117,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1150,6 +1173,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1204,6 +1229,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1258,6 +1285,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1312,6 +1341,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1365,6 +1396,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1458,6 +1491,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1530,6 +1565,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1586,6 +1623,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1642,6 +1681,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1698,6 +1739,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1754,6 +1797,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1810,6 +1855,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1864,6 +1911,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1918,6 +1967,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -1972,6 +2023,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2026,6 +2079,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2080,6 +2135,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2135,6 +2192,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2190,6 +2249,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2246,6 +2307,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2302,6 +2365,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2359,6 +2424,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -2416,6 +2483,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3189,6 +3258,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3264,6 +3335,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3337,6 +3410,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3409,6 +3484,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3481,6 +3558,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3553,6 +3632,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3625,6 +3706,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3698,6 +3781,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3779,6 +3864,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3863,6 +3950,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -3948,6 +4037,8 @@ options: --receiver-username RECEIVER_USERNAME 🖄 the username of the receiver --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4031,6 +4122,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4114,6 +4207,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4186,6 +4281,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4258,6 +4355,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4330,6 +4429,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4402,6 +4503,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4474,6 +4577,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4546,6 +4651,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4620,6 +4727,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4693,6 +4802,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -4765,6 +4876,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5163,6 +5276,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5234,6 +5349,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5304,6 +5421,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5375,6 +5494,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5444,6 +5565,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5518,6 +5641,8 @@ options: network. --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) --value VALUE the value to transfer (default: 0) --chain CHAIN the chain identifier --version VERSION the transaction version (default: 2) @@ -5657,7 +5782,7 @@ dump Dumps the active environment. delete Deletes an env value from the specified environment. switch Switch to a different environment. list List available environments -remove Deletes an environment from the env file. Use `mxpy config-env switch` to move to another env. +remove Deletes an environment from the env file. Use `mxpy config-env switch` to switch to another env. reset Deletes the environment file. Default env will be used. ``` @@ -5761,7 +5886,7 @@ options: $ mxpy config-env remove --help usage: mxpy config-env remove [-h] ... -Deletes an environment from the env file. Use `mxpy config-env switch` to move to another env. +Deletes an environment from the env file. Use `mxpy config-env switch` to switch to another env. options: -h, --help show this help message and exit @@ -6055,3 +6180,2686 @@ options: --hash HASH the transaction hash ``` +## Group **Token** + + +``` +$ mxpy token --help +usage: mxpy token COMMAND [-h] ... + +Perform token management operations (issue tokens, create NFTs, set roles, etc.) + +COMMANDS: + {issue-fungible,issue-semi-fungible,issue-non-fungible,register-meta-esdt,register-and-set-all-roles,set-burn-role-globally,unset-burn-role-globally,set-special-role-fungible,unset-special-role-fungible,set-special-role-semi-fungible,unset-special-role-semi-fungible,set-special-role-meta-esdt,unset-special-role-meta-esdt,set-special-role-nft,unset-special-role-nft,create-nft,pause,unpause,freeze,unfreeze,wipe,local-mint,local-burn,update-attributes,add-quantity,burn-quantity,modify-royalties,set-new-uris,modify-creator,update-metadata,nft-metadata-recreate,change-to-dynamic,update-token-id,register-dynamic,register-dynamic-and-set-all-roles,transfer-ownership,freeze-single-nft,unfreeze-single-nft,change-sft-to-meta-esdt,transfer-nft-create-role,stop-nft-creation,wipe-single-nft,add-uris} + +OPTIONS: + -h, --help show this help message and exit + +---------------- +COMMANDS summary +---------------- +issue-fungible Issue a new fungible ESDT token. +issue-semi-fungible Issue a new semi-fungible ESDT token. +issue-non-fungible Issue a new non-fungible ESDT token (NFT). +register-meta-esdt Register a MetaESDT token. +register-and-set-all-roles Register a token and set all roles. +set-burn-role-globally Set the burn role globally for a token. +unset-burn-role-globally Unset the burn role globally for a token. +set-special-role-fungible Set special roles on a fungible token for a user. +unset-special-role-fungible Unset special roles on a fungible token for a user. +set-special-role-semi-fungible Set special roles on a semi-fungible token for a user. +unset-special-role-semi-fungible Unset special roles on a semi-fungible token for a user. +set-special-role-meta-esdt Set special roles on a meta-esdt token for a user. +unset-special-role-meta-esdt Unset special roles on a meta-esdt token for a user. +set-special-role-nft Set special roles on a non-fungible token for a user. +unset-special-role-nft Unset special roles on a non-fungible token for a user. +create-nft Create a non-fungible token. +pause Pause a token. +unpause Unpause a token. +freeze Freeze a token for a user. +unfreeze Unfreeze a token for a user. +wipe Wipe a token for a user. +local-mint Mint new tokens. +local-burn Burn tokens. +update-attributes Update token attributes. +add-quantity Increase token quantity. +burn-quantity Burn token quantity. +modify-royalties Modify token royalties. +set-new-uris Set new uris. +modify-creator Modify the creator of the token. +update-metadata Update the metadata of the token. +nft-metadata-recreate Recreate the metadata of the token. +change-to-dynamic Change a token to a dynamic token. +update-token-id Update token id. +register-dynamic Register a dynamic token. +register-dynamic-and-set-all-roles Register a dynamic token and set all roles. +transfer-ownership Transfer the ownership of a token to another user. +freeze-single-nft Freeze the NFT of a user. +unfreeze-single-nft Unfreeze the NFT of a user. +change-sft-to-meta-esdt Change a semi fungible token to a Meta ESDT. +transfer-nft-create-role Transfer the nft create role to a user. +stop-nft-creation Stop the creation of new NFTs. +wipe-single-nft Wipe the NFT of a user. +add-uris Add uris for a token. + +``` +### Token.IssueFungbile + + +``` +$ mxpy token issue-fungible --help +usage: mxpy token issue-fungible [-h] ... + +Issue a new fungible ESDT token. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --initial-supply INITIAL_SUPPLY the initial supply of the token to be issued + --num-decimals NUM_DECIMALS a numerical value between 0 and 18 representing number of decimals + --cannot-freeze make token not freezable + --cannot-wipe make token not wipeable + --cannot-pause make token not pausable + --cannot-change-owner don't allow changing the token's owner + --cannot-upgrade don't allow upgrading the token + --cannot-add-special-roles don't allow special roles to be added for the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.IssueNonFungbile + + +``` +$ mxpy token issue-non-fungible --help +usage: mxpy token issue-non-fungible [-h] ... + +Issue a new non-fungible ESDT token (NFT). + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --cannot-freeze make token not freezable + --cannot-wipe make token not wipeable + --cannot-pause make token not pausable + --cannot-change-owner don't allow changing the token's owner + --cannot-upgrade don't allow upgrading the token + --cannot-add-special-roles don't allow special roles to be added for the token + --cannot-transfer-nft-create-role don't allow for nft create roles to be transferred for the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterMetaEsdt + + +``` +$ mxpy token register-meta-esdt --help +usage: mxpy token register-meta-esdt [-h] ... + +Register a MetaESDT token. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --num-decimals NUM_DECIMALS a numerical value between 0 and 18 representing number of decimals + --cannot-freeze make token not freezable + --cannot-wipe make token not wipeable + --cannot-pause make token not pausable + --cannot-change-owner don't allow changing the token's owner + --cannot-upgrade don't allow upgrading the token + --cannot-add-special-roles don't allow special roles to be added for the token + --cannot-transfer-nft-create-role don't allow for nft create roles to be transferred for the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterAndSetAllRoles + + +``` +$ mxpy token register-and-set-all-roles --help +usage: mxpy token register-and-set-all-roles [-h] ... + +Register a token and set all roles. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME the name of the token to be issued: 3-20 alphanumerical characters + --token-ticker TOKEN_TICKER the ticker of the token to be issued: 3-10 UPPERCASE alphanumerical + characters + --num-decimals NUM_DECIMALS a numerical value between 0 and 18 representing number of decimals + --token-type {NFT,SFT,META,FNG} the token type + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetBurnRoleGlobally + + +``` +$ mxpy token set-burn-role-globally --help +usage: mxpy token set-burn-role-globally [-h] ... + +Set the burn role globally for a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetBurnRoleGlobally + + +``` +$ mxpy token unset-burn-role-globally --help +usage: mxpy token unset-burn-role-globally [-h] ... + +Unset the burn role globally for a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleFungible + + +``` +$ mxpy token set-special-role-fungible --help +usage: mxpy token set-special-role-fungible [-h] ... + +Set special roles on a fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --local-mint role for local minting + --local-burn role for local burning + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleFungible + + +``` +$ mxpy token unset-special-role-fungible --help +usage: mxpy token unset-special-role-fungible [-h] ... + +Unset special roles on a fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --local-mint role for local minting + --local-burn role for local burning + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleSemiFungible + + +``` +$ mxpy token set-special-role-semi-fungible --help +usage: mxpy token set-special-role-semi-fungible [-h] ... + +Set special roles on a semi-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleSemiFungible + + +``` +$ mxpy token unset-special-role-semi-fungible --help +usage: mxpy token unset-special-role-semi-fungible [-h] ... + +Unset special roles on a semi-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleMetaEsdt + + +``` +$ mxpy token set-special-role-meta-esdt --help +usage: mxpy token set-special-role-meta-esdt [-h] ... + +Set special roles on a meta-esdt token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleMetaEsdt + + +``` +$ mxpy token unset-special-role-meta-esdt --help +usage: mxpy token unset-special-role-meta-esdt [-h] ... + +Unset special roles on a meta-esdt token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-burn role for nft burn + --nft-add-quantity role for adding quantity + --esdt-transfer-role role for esdt transfer + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetSpecialRoleNft + + +``` +$ mxpy token set-special-role-nft --help +usage: mxpy token set-special-role-nft [-h] ... + +Set special roles on a non-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-update-attributes role for updating attributes + --nft-add-uri role for adding uri + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnsetSpecialRoleNft + + +``` +$ mxpy token unset-special-role-nft --help +usage: mxpy token unset-special-role-nft [-h] ... + +Unset special roles on a non-fungible token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --nft-create role for nft create + --nft-burn role for nft burn + --nft-update-attributes role for updating attributes + --nft-add-uri role for adding uri + --esdt-transfer-role role for esdt transfer + --nft-update role for updating nft + --esdt-modify-royalties role for modifying royalties + --esdt-set-new-uri role for setting new uri + --esdt-modify-creator role for modifying creator + --nft-recreate role for recreating nft + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.CreateNft + + +``` +$ mxpy token create-nft --help +usage: mxpy token create-nft [-h] ... + +Create a non-fungible token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --initial-quantity INITIAL_QUANTITY The initial quantity of the token. + --name NAME The name of the token. + --royalties ROYALTIES The royalties of the token. + --hash HASH The hash of the token. + --attributes ATTRIBUTES The hex-string attributes of the token. + --uris URIS [URIS ...] The uris of the token. + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Pause + + +``` +$ mxpy token pause --help +usage: mxpy token pause [-h] ... + +Pause a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Unpause + + +``` +$ mxpy token unpause --help +usage: mxpy token unpause [-h] ... + +Unpause a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Freeze + + +``` +$ mxpy token freeze --help +usage: mxpy token freeze [-h] ... + +Freeze a token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Unfreeze + + +``` +$ mxpy token unfreeze --help +usage: mxpy token unfreeze [-h] ... + +Unfreeze a token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.Wipe + + +``` +$ mxpy token wipe --help +usage: mxpy token wipe [-h] ... + +Wipe a token for a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.LocalMint + + +``` +$ mxpy token local-mint --help +usage: mxpy token local-mint [-h] ... + +Mint new tokens. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --supply-to-mint SUPPLY_TO_MINT The amount of new tokens to mint + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.LocalBurn + + +``` +$ mxpy token local-burn --help +usage: mxpy token local-burn [-h] ... + +Burn tokens. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --supply-to-burn SUPPLY_TO_BURN The amount of tokens to burn + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UpdateAttributes + + +``` +$ mxpy token update-attributes --help +usage: mxpy token update-attributes [-h] ... + +Update token attributes. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --attributes ATTRIBUTES The hex-string attributes of the token + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.AddQuantity + + +``` +$ mxpy token add-quantity --help +usage: mxpy token add-quantity [-h] ... + +Increase token quantity. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --quantity QUANTITY The quantity to add + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.BurnQuantity + + +``` +$ mxpy token burn-quantity --help +usage: mxpy token burn-quantity [-h] ... + +Burn token quantity. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --quantity QUANTITY The quantity to burn + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ModifyRolaties + + +``` +$ mxpy token modify-royalties --help +usage: mxpy token modify-royalties [-h] ... + +Modify token royalties. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --royalties ROYALTIES The new token royalties (e.g. 1234 for 12.34%) + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.SetNewUris + + +``` +$ mxpy token set-new-uris --help +usage: mxpy token set-new-uris [-h] ... + +Set new uris. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --uris URIS [URIS ...] The new uris + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ModifyCreator + + +``` +$ mxpy token modify-creator --help +usage: mxpy token modify-creator [-h] ... + +Modify the creator of the token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UpdateMetadata + + +``` +$ mxpy token update-metadata --help +usage: mxpy token update-metadata [-h] ... + +Update the metadata of the token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --token-name TOKEN_NAME The new name of the token + --royalties ROYALTIES The new token royalties (e.g. 1234 for 12.34%) + --hash HASH The new hash of the token + --attributes ATTRIBUTES The new attributes of the token as a hex-encoded string + --uris URIS [URIS ...] The new uris + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.NftMetadataRecreate + + +``` +$ mxpy token nft-metadata-recreate --help +usage: mxpy token nft-metadata-recreate [-h] ... + +Recreate the metadata of the token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --token-name TOKEN_NAME The new name of the token + --royalties ROYALTIES The new token royalties (e.g. 1234 for 12.34%) + --hash HASH The new hash of the token + --attributes ATTRIBUTES The new attributes of the token as a hex-encoded string + --uris URIS [URIS ...] The new uris + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ChangeToDynamic + + +``` +$ mxpy token change-to-dynamic --help +usage: mxpy token change-to-dynamic [-h] ... + +Change a token to a dynamic token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UpdateTokenId + + +``` +$ mxpy token update-token-id --help +usage: mxpy token update-token-id [-h] ... + +Update token id. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterDynamic + + +``` +$ mxpy token register-dynamic --help +usage: mxpy token register-dynamic [-h] ... + +Register a dynamic token. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME The token name + --token-ticker TOKEN_TICKER The token ticker + --token-type {NFT,SFT,FNG,META} The token type + --denominator DENOMINATOR The number of decimals, only needed when token type is META ESDT + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.RegisterDynamicAndSetAllRoles + + +``` +$ mxpy token register-dynamic-and-set-all-roles --help +usage: mxpy token register-dynamic-and-set-all-roles [-h] ... + +Register a dynamic token and set all roles. + +options: + -h, --help show this help message and exit + --token-name TOKEN_NAME The token name + --token-ticker TOKEN_TICKER The token ticker + --token-type {NFT,SFT,FNG,META} The token type + --denominator DENOMINATOR The number of decimals, only needed when token type is META ESDT + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.TransferOwnership + + +``` +$ mxpy token transfer-ownership --help +usage: mxpy token transfer-ownership [-h] ... + +Transfer the ownership of a token to another user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --new-owner NEW_OWNER The new token owner + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.FreezeSingleNft + + +``` +$ mxpy token freeze-single-nft --help +usage: mxpy token freeze-single-nft [-h] ... + +Freeze the NFT of a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.UnfreezeSingleNft + + +``` +$ mxpy token unfreeze-single-nft --help +usage: mxpy token unfreeze-single-nft [-h] ... + +Unfreeze the NFT of a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the token as decimal value + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.ChangeSftToMetaEsdt + + +``` +$ mxpy token change-sft-to-meta-esdt --help +usage: mxpy token change-sft-to-meta-esdt [-h] ... + +Change a semi fungible token to a Meta ESDT. + +options: + -h, --help show this help message and exit + --collection COLLECTION The collection identifier + --decimals DECIMALS The number of decimals the meta esdt will have + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.TransferNftCreateRole + + +``` +$ mxpy token transfer-nft-create-role --help +usage: mxpy token transfer-nft-create-role [-h] ... + +Transfer the nft create role to a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.StopNftCreation + + +``` +$ mxpy token stop-nft-creation --help +usage: mxpy token stop-nft-creation [-h] ... + +Stop the creation of new NFTs. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.WipeSingleNft + + +``` +$ mxpy token wipe-single-nft --help +usage: mxpy token wipe-single-nft [-h] ... + +Wipe the NFT of a user. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the NFT as a decimal number + --user USER the bech32 address of the user + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` +### Token.AddUris + + +``` +$ mxpy token add-uris --help +usage: mxpy token add-uris [-h] ... + +Add uris for a token. + +options: + -h, --help show this help message and exit + --token-identifier TOKEN_IDENTIFIER the token identifier + --token-nonce TOKEN_NONCE The nonce of the NFT as a decimal number + --uris URIS [URIS ...] The new uris to be added to the token. + --sender SENDER the alias of the wallet set in the address config + --pem PEM 🔑 the PEM file, if keyfile not provided + --keyfile KEYFILE 🔑 a JSON keyfile, if PEM not provided + --passfile PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --ledger 🔐 bool flag for signing transaction using ledger + --sender-wallet-index SENDER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic 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 + --nonce NONCE # the nonce for the transaction. If not provided, is fetched from the + network. + --gas-price GAS_PRICE ⛽ the gas price (default: 1000000000) + --gas-limit GAS_LIMIT ⛽ the gas limit + --gas-limit-multiplier GAS_LIMIT_MULTIPLIER if `--gas-limit` is not provided, the estimated value will be + multiplied by this multiplier (e.g 1.1) + --value VALUE the value to transfer (default: 0) + --chain CHAIN the chain identifier + --version VERSION the transaction version (default: 2) + --options OPTIONS the transaction options (default: 0) + --relayer RELAYER the bech32 address of the relayer + --guardian GUARDIAN the bech32 address of the guardian + --proxy PROXY 🔗 the URL of the proxy + --send ✓ whether to broadcast the transaction (default: False) + --simulate whether to simulate the transaction (default: False) + --wait-result signal to wait for the transaction result - only valid if --send is set + --timeout TIMEOUT max num of seconds to wait for result - only valid if --wait-result is + set + --guardian-service-url GUARDIAN_SERVICE_URL the url of the guardian service + --guardian-2fa-code GUARDIAN_2FA_CODE the 2fa code for the guardian + --guardian-pem GUARDIAN_PEM 🔑 the PEM file, if keyfile not provided + --guardian-keyfile GUARDIAN_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --guardian-passfile GUARDIAN_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --guardian-ledger 🔐 bool flag for signing transaction using ledger + --guardian-wallet-index GUARDIAN_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --relayer-pem RELAYER_PEM 🔑 the PEM file, if keyfile not provided + --relayer-keyfile RELAYER_KEYFILE 🔑 a JSON keyfile, if PEM not provided + --relayer-passfile RELAYER_PASSFILE DEPRECATED, do not use it anymore. Instead, you'll be prompted to enter + the password. + --relayer-ledger 🔐 bool flag for signing transaction using ledger + --relayer-wallet-index RELAYER_WALLET_INDEX 🔑 the address index; can be used for PEM files, keyfiles of type + mnemonic or Ledger devices (default: 0) + --outfile OUTFILE where to save the output (default: stdout) + +``` diff --git a/CLI.md.sh b/CLI.md.sh index 9c7dc806..2c9a3b65 100755 --- a/CLI.md.sh +++ b/CLI.md.sh @@ -212,6 +212,50 @@ generate() { command "Get.StorageEntry" "get storage-entry" command "Get.Token" "get token" command "Get.Transaction" "get transaction" + + group "Token" "token" + command "Token.IssueFungbile" "token issue-fungible" + command "Token.IssueNonFungbile" "token issue-non-fungible" + command "Token.RegisterMetaEsdt" "token register-meta-esdt" + command "Token.RegisterAndSetAllRoles" "token register-and-set-all-roles" + command "Token.SetBurnRoleGlobally" "token set-burn-role-globally" + command "Token.UnsetBurnRoleGlobally" "token unset-burn-role-globally" + command "Token.SetSpecialRoleFungible" "token set-special-role-fungible" + command "Token.UnsetSpecialRoleFungible" "token unset-special-role-fungible" + command "Token.SetSpecialRoleSemiFungible" "token set-special-role-semi-fungible" + command "Token.UnsetSpecialRoleSemiFungible" "token unset-special-role-semi-fungible" + command "Token.SetSpecialRoleMetaEsdt" "token set-special-role-meta-esdt" + command "Token.UnsetSpecialRoleMetaEsdt" "token unset-special-role-meta-esdt" + command "Token.SetSpecialRoleNft" "token set-special-role-nft" + command "Token.UnsetSpecialRoleNft" "token unset-special-role-nft" + command "Token.CreateNft" "token create-nft" + command "Token.Pause" "token pause" + command "Token.Unpause" "token unpause" + command "Token.Freeze" "token freeze" + command "Token.Unfreeze" "token unfreeze" + command "Token.Wipe" "token wipe" + command "Token.LocalMint" "token local-mint" + command "Token.LocalBurn" "token local-burn" + command "Token.UpdateAttributes" "token update-attributes" + command "Token.AddQuantity" "token add-quantity" + command "Token.BurnQuantity" "token burn-quantity" + command "Token.ModifyRolaties" "token modify-royalties" + command "Token.SetNewUris" "token set-new-uris" + command "Token.ModifyCreator" "token modify-creator" + command "Token.UpdateMetadata" "token update-metadata" + command "Token.NftMetadataRecreate" "token nft-metadata-recreate" + command "Token.ChangeToDynamic" "token change-to-dynamic" + command "Token.UpdateTokenId" "token update-token-id" + command "Token.RegisterDynamic" "token register-dynamic" + command "Token.RegisterDynamicAndSetAllRoles" "token register-dynamic-and-set-all-roles" + command "Token.TransferOwnership" "token transfer-ownership" + command "Token.FreezeSingleNft" "token freeze-single-nft" + command "Token.UnfreezeSingleNft" "token unfreeze-single-nft" + command "Token.ChangeSftToMetaEsdt" "token change-sft-to-meta-esdt" + command "Token.TransferNftCreateRole" "token transfer-nft-create-role" + command "Token.StopNftCreation" "token stop-nft-creation" + command "Token.WipeSingleNft" "token wipe-single-nft" + command "Token.AddUris" "token add-uris" } generate diff --git a/multiversx_sdk_cli/cli_tokens.py b/multiversx_sdk_cli/cli_tokens.py index c083d706..a81987f4 100644 --- a/multiversx_sdk_cli/cli_tokens.py +++ b/multiversx_sdk_cli/cli_tokens.py @@ -319,7 +319,7 @@ def setup_parser(args: list[str], subparsers: Any) -> Any: ) _add_token_identifier_arg(sub) sub.add_argument("--token-nonce", required=True, type=int, help="The nonce of the token as decimal value") - sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%)") + sub.add_argument("--royalties", required=True, type=int, help="The new token royalties (e.g. 1234 for 12.34%%)") add_common_args(args, sub) sub.set_defaults(func=modify_royalties) diff --git a/pyproject.toml b/pyproject.toml index 8b78dfe8..b62d8f27 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "multiversx-sdk-cli" -version = "11.1.1" +version = "11.2.0" authors = [ { name="MultiversX" }, ]