Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrated the SmartContractFactory #361

Merged
merged 6 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
91 changes: 40 additions & 51 deletions multiversx_sdk_cli/cli_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
from pathlib import Path
from typing import Any, List

from multiversx_sdk_core import Address, Transaction
from multiversx_sdk_core import Address, AddressComputer, Transaction
from multiversx_sdk_core.transaction_factories import TransactionsFactoryConfig
from multiversx_sdk_network_providers.proxy_network_provider import \
ProxyNetworkProvider

from multiversx_sdk_cli import cli_shared, errors, projects, utils
from multiversx_sdk_cli.accounts import Account, LedgerAccount
from multiversx_sdk_cli.cli_output import CLIOutputBuilder
from multiversx_sdk_cli.cli_password import load_password
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 CodeMetadata, SmartContract
from multiversx_sdk_cli.contracts import SmartContract, query_contract
from multiversx_sdk_cli.cosign_transaction import cosign_transaction
from multiversx_sdk_cli.docker import is_docker_installed, run_docker
from multiversx_sdk_cli.errors import DockerMissingError, NoWalletProvided
from multiversx_sdk_cli.interfaces import IAddress
from multiversx_sdk_cli.projects.core import get_project_paths_recursively
from multiversx_sdk_cli.projects.templates import Contract
from multiversx_sdk_cli.ux import show_message
Expand Down Expand Up @@ -299,32 +302,22 @@ def deploy(args: Any):
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)

arguments = args.arguments
gas_price = args.gas_price
gas_limit = args.gas_limit
value = args.value
version = args.version

contract = _prepare_contract(args)
sender = _prepare_sender(args)
cli_shared.prepare_chain_id_in_args(args)

tx = contract.deploy(sender, arguments, gas_price, gas_limit, value, args.chain, version, args.guardian, args.options)
tx = _sign_guarded_tx(args, tx)

logger.info("Contract address: %s", contract.address.to_bech32())
utils.log_explorer_contract_address(args.chain, contract.address.to_bech32())
config = TransactionsFactoryConfig(args.chain)
contract = SmartContract(config)

_send_or_simulate(tx, contract, args)
address_computer = AddressComputer(NUMBER_OF_SHARDS)
contract_address = address_computer.compute_contract_address(deployer=sender.address, deployment_nonce=sender.nonce)

tx = contract.get_deploy_transaction(sender, args)
tx = _sign_guarded_tx(args, tx)

def _prepare_contract(args: Any) -> SmartContract:
bytecode = utils.read_binary_file(Path(args.bytecode)).hex()
logger.info("Contract address: %s", contract_address.to_bech32())
utils.log_explorer_contract_address(args.chain, contract_address.to_bech32())

metadata = CodeMetadata(upgradeable=args.metadata_upgradeable, readable=args.metadata_readable,
payable=args.metadata_payable, payable_by_sc=args.metadata_payable_by_sc)
contract = SmartContract(bytecode=bytecode, metadata=metadata)
return contract
_send_or_simulate(tx, contract_address, args)


def _prepare_sender(args: Any) -> Account:
Expand Down Expand Up @@ -383,61 +376,57 @@ def call(args: Any):
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)

contract_address = args.contract
function = args.function
arguments = args.arguments
gas_price = args.gas_price
gas_limit = args.gas_limit
value = args.value
version = args.version

contract = SmartContract(Address.from_bech32(contract_address))
sender = _prepare_sender(args)
cli_shared.prepare_chain_id_in_args(args)
sender = _prepare_sender(args)

config = TransactionsFactoryConfig(args.chain)
contract = SmartContract(config)
contract_address = Address.new_from_bech32(args.contract)

tx = contract.execute(sender, function, arguments, gas_price, gas_limit, value, args.chain, version, args.guardian, args.options)
tx = contract.get_execute_transaction(sender, args)
tx = _sign_guarded_tx(args, tx)

_send_or_simulate(tx, contract, args)
_send_or_simulate(tx, contract_address, args)


def upgrade(args: Any):
logger.debug("upgrade")
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)

contract_address = args.contract
arguments = args.arguments
gas_price = args.gas_price
gas_limit = args.gas_limit
value = args.value
version = args.version

contract = _prepare_contract(args)
contract.address = Address.from_bech32(contract_address)
sender = _prepare_sender(args)
cli_shared.prepare_chain_id_in_args(args)
sender = _prepare_sender(args)

tx = contract.upgrade(sender, arguments, gas_price, gas_limit, value, args.chain, version, args.guardian, args.options)
config = TransactionsFactoryConfig(args.chain)
contract = SmartContract(config)
contract_address = Address.new_from_bech32(args.contract)

tx = contract.get_upgrade_transaction(sender, args)
tx = _sign_guarded_tx(args, tx)

_send_or_simulate(tx, contract, args)
_send_or_simulate(tx, contract_address, args)


def query(args: Any):
logger.debug("query")

contract_address = args.contract
# workaround so we can use the function bellow
args.chain = ""
cli_shared.prepare_chain_id_in_args(args)

contract_address = Address.new_from_bech32(args.contract)

proxy = ProxyNetworkProvider(args.proxy)
function = args.function
arguments = args.arguments
arguments = args.arguments or []

contract = SmartContract(address=Address.from_bech32(contract_address))
result = contract.query(ProxyNetworkProvider(args.proxy), function, arguments)
result = query_contract(contract_address, proxy, function, arguments)
utils.dump_out_json(result)


def _send_or_simulate(tx: Transaction, contract: SmartContract, args: Any):
def _send_or_simulate(tx: Transaction, contract_address: IAddress, args: Any):
output_builder = cli_shared.send_or_simulate(tx, args, dump_output=False)
output_builder.set_contract_address(contract.address)
output_builder.set_contract_address(contract_address)
utils.dump_out_json(output_builder.build(), outfile=args.outfile)


Expand Down
7 changes: 3 additions & 4 deletions multiversx_sdk_cli/cli_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@
from collections import OrderedDict
from typing import Any, Dict, List, Optional, Union

from multiversx_sdk_core import Address
from multiversx_sdk_network_providers.transactions import \
transaction_to_dictionary

from multiversx_sdk_cli import utils
from multiversx_sdk_cli.interfaces import ITransaction
from multiversx_sdk_cli.interfaces import IAddress, ITransaction
from multiversx_sdk_cli.utils import ISerializable

logger = logging.getLogger("cli.output")
Expand All @@ -19,7 +18,7 @@ def __init__(self) -> None:
self.emitted_transaction_hash: Optional[str] = None
self.emitted_transaction: Union[ITransaction, None] = None
self.emitted_transaction_omitted_fields: List[str] = []
self.contract_address: Union[Address, None] = None
self.contract_address: Union[IAddress, None] = None
self.transaction_on_network: Union[ISerializable, None] = None
self.transaction_on_network_omitted_fields: List[str] = []
self.simulation_results: Union[ISerializable, None] = None
Expand All @@ -33,7 +32,7 @@ def set_emitted_transaction(self, emitted_transaction: ITransaction, omitted_fie
self.emitted_transaction_omitted_fields = omitted_fields
return self

def set_contract_address(self, contract_address: Address):
def set_contract_address(self, contract_address: IAddress):
self.contract_address = contract_address
return self

Expand Down
6 changes: 3 additions & 3 deletions multiversx_sdk_cli/cli_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ def add_tx_args(args: List[str], sub: Any, with_nonce: bool = True, with_receive


def add_guardian_args(sub: Any):
sub.add_argument("--guardian", type=str, help="the address of the guradian")
sub.add_argument("--guardian-service-url", type=str, help="the url of the guardian service")
sub.add_argument("--guardian-2fa-code", type=str, help="the 2fa code for the guardian")
sub.add_argument("--guardian", type=str, help="the address of the guradian", default="")
sub.add_argument("--guardian-service-url", type=str, help="the url of the guardian service", default="")
sub.add_argument("--guardian-2fa-code", type=str, help="the 2fa code for the guardian", default="")


def add_wallet_args(args: List[str], sub: Any):
Expand Down
2 changes: 2 additions & 0 deletions multiversx_sdk_cli/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@

DEFAULT_HRP = "erd"
ADDRESS_ZERO_BECH32 = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu"

NUMBER_OF_SHARDS = 3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see it was set to 3 before, as well (hardcoded).

But it seems there were no issues when performing deploys on localnet (2 shards, by default)?

Indeed, the contract address computation algorithm does not depend on the number of shards:

https://github.com/multiversx/mx-sdk-py-core/blob/main/multiversx_sdk_core/address.py#L109

Thus, we have a slightly unfortunate design (specs) of the AddressComputer. It requires the number of shards as a parameter, but that isn't required in all circumstances.

Can stay as it is 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed the number_of_shards is not used to compute the contract address, added it to be more explicit, but it can be deleted since the default value is already 3. Let me know what you think.

Loading
Loading