Skip to content

Commit ccb1102

Browse files
committed
refactoring contracts to remove wrapper
1 parent 64763e5 commit ccb1102

7 files changed

Lines changed: 286 additions & 327 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import logging
2+
from typing import Any
3+
4+
from multiversx_sdk import Address
5+
from multiversx_sdk.abi import (
6+
AddressValue,
7+
BigUIntValue,
8+
BoolValue,
9+
BytesValue,
10+
StringValue,
11+
)
12+
13+
from multiversx_sdk_cli.config_env import get_address_hrp
14+
from multiversx_sdk_cli.constants import (
15+
ADDRESS_PREFIX,
16+
FALSE_STR_LOWER,
17+
HEX_PREFIX,
18+
MAINCHAIN_ADDRESS_HRP,
19+
STR_PREFIX,
20+
TRUE_STR_LOWER,
21+
)
22+
from multiversx_sdk_cli.errors import BadUserInput
23+
24+
logger = logging.getLogger("args_converter")
25+
26+
27+
def convert_args_to_typed_values(arguments: list[str]) -> list[Any]:
28+
args: list[Any] = []
29+
30+
for arg in arguments:
31+
if arg.startswith(HEX_PREFIX):
32+
args.append(BytesValue(_hex_to_bytes(arg)))
33+
elif arg.isnumeric():
34+
args.append(BigUIntValue(int(arg)))
35+
elif arg.startswith(ADDRESS_PREFIX):
36+
args.append(AddressValue.new_from_address(Address.new_from_bech32(arg[len(ADDRESS_PREFIX) :])))
37+
elif arg.startswith(MAINCHAIN_ADDRESS_HRP):
38+
# this flow will be removed in the future
39+
logger.warning(
40+
"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...)"
41+
)
42+
args.append(AddressValue.new_from_address(Address.new_from_bech32(arg)))
43+
elif arg.startswith(get_address_hrp()):
44+
args.append(AddressValue.new_from_address(Address.new_from_bech32(arg)))
45+
elif arg.lower() == FALSE_STR_LOWER:
46+
args.append(BoolValue(False))
47+
elif arg.lower() == TRUE_STR_LOWER:
48+
args.append(BoolValue(True))
49+
elif arg.startswith(STR_PREFIX):
50+
args.append(StringValue(arg[len(STR_PREFIX) :]))
51+
else:
52+
raise BadUserInput(
53+
f"Unknown argument type for argument: `{arg}`. Use `mxpy contract <sub-command> --help` to check all supported arguments"
54+
)
55+
56+
return args
57+
58+
59+
def _hex_to_bytes(arg: str):
60+
argument = arg[len(HEX_PREFIX) :]
61+
argument = argument.upper()
62+
argument = _ensure_even_length(argument)
63+
return bytes.fromhex(argument)
64+
65+
66+
def _ensure_even_length(string: str) -> str:
67+
if len(string) % 2 == 1:
68+
return "0" + string
69+
return string

multiversx_sdk_cli/cli_contracts.py

Lines changed: 99 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111
AddressComputer,
1212
Message,
1313
ProxyNetworkProvider,
14+
SmartContractController,
1415
Transaction,
15-
TransactionsFactoryConfig,
1616
)
1717
from multiversx_sdk.abi import Abi
1818

1919
from multiversx_sdk_cli import cli_shared, utils
20+
from multiversx_sdk_cli.args_converter import convert_args_to_typed_values
2021
from multiversx_sdk_cli.args_validation import (
2122
validate_broadcast_args,
2223
validate_chain_id_args,
@@ -28,9 +29,10 @@
2829
from multiversx_sdk_cli.config_env import MxpyEnv
2930
from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS
3031
from multiversx_sdk_cli.contract_verification import trigger_contract_verification
31-
from multiversx_sdk_cli.contracts import SmartContract
3232
from multiversx_sdk_cli.docker import is_docker_installed, run_docker
33-
from multiversx_sdk_cli.errors import DockerMissingError
33+
from multiversx_sdk_cli.errors import DockerMissingError, QueryContractError
34+
from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData
35+
from multiversx_sdk_cli.signing_wrapper import SigningWrapper
3436
from multiversx_sdk_cli.ux import show_warning
3537

3638
logger = logging.getLogger("cli.contracts")
@@ -295,6 +297,7 @@ def _add_arguments_arg(sub: Any):
295297
sub.add_argument(
296298
"--arguments",
297299
nargs="+",
300+
default=[],
298301
help="arguments for the contract transaction, as [number, bech32-address, ascii string, "
299302
"boolean] or hex-encoded. E.g. --arguments 42 0x64 1000 0xabba str:TOK-a1c2ef true addr:erd1[..]",
300303
)
@@ -315,6 +318,31 @@ def build(args: Any):
315318
show_warning(message)
316319

317320

321+
def _initialize_controller(args: Any) -> SmartContractController:
322+
chain_id = cli_shared.get_chain_id(args.proxy, args.chain)
323+
config = get_config_for_network_providers()
324+
proxy_url = args.proxy if args.proxy else ""
325+
proxy = ProxyNetworkProvider(url=proxy_url, config=config)
326+
abi = Abi.load(Path(args.abi)) if args.abi else None
327+
gas_estimator = cli_shared.initialize_gas_limit_estimator(args)
328+
329+
return SmartContractController(
330+
chain_id=chain_id,
331+
network_provider=proxy,
332+
abi=abi,
333+
gas_limit_estimator=gas_estimator,
334+
)
335+
336+
337+
def _sign_transaction(transaction: Transaction, sender: Any, guardian_and_relayer_data: GuardianRelayerData):
338+
signer = SigningWrapper()
339+
signer.sign_transaction(
340+
transaction=transaction,
341+
sender=sender,
342+
guardian_and_relayer=guardian_and_relayer_data,
343+
)
344+
345+
318346
def deploy(args: Any):
319347
logger.debug("deploy")
320348

@@ -328,31 +356,25 @@ def deploy(args: Any):
328356
args=args,
329357
)
330358

331-
chain_id = cli_shared.get_chain_id(args.proxy, args.chain)
332-
config = TransactionsFactoryConfig(chain_id)
333-
334-
abi = Abi.load(Path(args.abi)) if args.abi else None
335-
gas_estimator = cli_shared.initialize_gas_limit_estimator(args)
336-
contract = SmartContract(config, abi, gas_estimator)
337-
338359
arguments, should_prepare_args = _get_contract_arguments(args)
360+
if should_prepare_args:
361+
arguments = convert_args_to_typed_values(arguments)
339362

340-
tx = contract.prepare_deploy_transaction(
341-
owner=sender,
363+
controller = _initialize_controller(args)
364+
tx = controller.create_transaction_for_deploy(
365+
sender=sender,
366+
nonce=sender.nonce,
342367
bytecode=Path(args.bytecode),
343368
arguments=arguments,
344-
should_prepare_args=should_prepare_args,
345-
upgradeable=args.metadata_upgradeable,
346-
readable=args.metadata_readable,
347-
payable=args.metadata_payable,
348-
payable_by_sc=args.metadata_payable_by_sc,
369+
native_transfer_amount=int(args.value),
370+
is_upgradeable=args.metadata_upgradeable,
371+
is_readable=args.metadata_readable,
372+
is_payable=args.metadata_payable,
373+
is_payable_by_sc=args.metadata_payable_by_sc,
374+
guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None,
375+
relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None,
349376
gas_limit=args.gas_limit,
350-
gas_price=int(args.gas_price),
351-
value=int(args.value),
352-
nonce=sender.nonce,
353-
version=int(args.version),
354-
options=int(args.options),
355-
guardian_and_relayer_data=guardian_and_relayer_data,
377+
gas_price=args.gas_price,
356378
)
357379

358380
address_computer = AddressComputer(NUMBER_OF_SHARDS)
@@ -361,8 +383,13 @@ def deploy(args: Any):
361383
logger.info("Contract address: %s", contract_address.to_bech32())
362384

363385
cli_config = MxpyEnv.from_active_env()
364-
utils.log_explorer_contract_address(args.chain, contract_address.to_bech32(), cli_config.explorer_url)
386+
utils.log_explorer_contract_address(
387+
chain=controller.factory.config.chain_id,
388+
address=contract_address.to_bech32(),
389+
explorer_url=cli_config.explorer_url,
390+
)
365391

392+
_sign_transaction(tx, sender, guardian_and_relayer_data)
366393
_send_or_simulate(tx, contract_address, args)
367394

368395

@@ -379,36 +406,32 @@ def call(args: Any):
379406
args=args,
380407
)
381408

382-
chain_id = cli_shared.get_chain_id(args.proxy, args.chain)
383-
config = TransactionsFactoryConfig(chain_id)
384-
385-
abi = Abi.load(Path(args.abi)) if args.abi else None
386-
gas_estimator = cli_shared.initialize_gas_limit_estimator(args)
387-
contract = SmartContract(config, abi, gas_estimator)
388-
389409
arguments, should_prepare_args = _get_contract_arguments(args)
390-
contract_address = Address.new_from_bech32(args.contract)
410+
if should_prepare_args:
411+
arguments = convert_args_to_typed_values(arguments)
391412

392-
token_transfers = None
413+
token_transfers = []
393414
if args.token_transfers:
394415
token_transfers = cli_shared.prepare_token_transfers(args.token_transfers)
395416

396-
tx = contract.prepare_execute_transaction(
397-
caller=sender,
417+
contract_address = Address.new_from_bech32(args.contract)
418+
controller = _initialize_controller(args)
419+
420+
tx = controller.create_transaction_for_execute(
421+
sender=sender,
422+
nonce=sender.nonce,
398423
contract=contract_address,
399424
function=args.function,
400425
arguments=arguments,
401-
should_prepare_args=should_prepare_args,
402-
gas_limit=args.gas_limit,
403-
gas_price=int(args.gas_price),
404-
value=int(args.value),
426+
native_transfer_amount=int(args.value),
405427
token_transfers=token_transfers,
406-
nonce=sender.nonce,
407-
version=int(args.version),
408-
options=int(args.options),
409-
guardian_and_relayer_data=guardian_and_relayer_data,
428+
guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None,
429+
relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None,
430+
gas_limit=args.gas_limit,
431+
gas_price=args.gas_price,
410432
)
411433

434+
_sign_transaction(tx, sender, guardian_and_relayer_data)
412435
_send_or_simulate(tx, contract_address, args)
413436

414437

@@ -425,35 +448,31 @@ def upgrade(args: Any):
425448
args=args,
426449
)
427450

428-
chain_id = cli_shared.get_chain_id(args.proxy, args.chain)
429-
config = TransactionsFactoryConfig(chain_id)
430-
431-
abi = Abi.load(Path(args.abi)) if args.abi else None
432-
gas_estimator = cli_shared.initialize_gas_limit_estimator(args)
433-
contract = SmartContract(config, abi, gas_estimator)
434-
435451
arguments, should_prepare_args = _get_contract_arguments(args)
452+
if should_prepare_args:
453+
arguments = convert_args_to_typed_values(arguments)
454+
436455
contract_address = Address.new_from_bech32(args.contract)
456+
controller = _initialize_controller(args)
437457

438-
tx = contract.prepare_upgrade_transaction(
439-
owner=sender,
458+
tx = controller.create_transaction_for_upgrade(
459+
sender=sender,
460+
nonce=sender.nonce,
440461
contract=contract_address,
441462
bytecode=Path(args.bytecode),
442463
arguments=arguments,
443-
should_prepare_args=should_prepare_args,
444-
upgradeable=args.metadata_upgradeable,
445-
readable=args.metadata_readable,
446-
payable=args.metadata_payable,
447-
payable_by_sc=args.metadata_payable_by_sc,
464+
native_transfer_amount=int(args.value),
465+
is_upgradeable=args.metadata_upgradeable,
466+
is_readable=args.metadata_readable,
467+
is_payable=args.metadata_payable,
468+
is_payable_by_sc=args.metadata_payable_by_sc,
469+
guardian=guardian_and_relayer_data.guardian.address if guardian_and_relayer_data.guardian else None,
470+
relayer=guardian_and_relayer_data.relayer.address if guardian_and_relayer_data.relayer else None,
448471
gas_limit=args.gas_limit,
449-
gas_price=int(args.gas_price),
450-
value=int(args.value),
451-
nonce=sender.nonce,
452-
version=int(args.version),
453-
options=int(args.options),
454-
guardian_and_relayer_data=guardian_and_relayer_data,
472+
gas_price=args.gas_price,
455473
)
456474

475+
_sign_transaction(tx, sender, guardian_and_relayer_data)
457476
_send_or_simulate(tx, contract_address, args)
458477

459478

@@ -462,26 +481,32 @@ def query(args: Any):
462481

463482
validate_proxy_argument(args)
464483

465-
# we don't need chainID to query a contract; we use the provided proxy
466-
factory_config = TransactionsFactoryConfig("")
467484
abi = Abi.load(Path(args.abi)) if args.abi else None
468-
contract = SmartContract(factory_config, abi)
485+
contract_address = Address.new_from_bech32(args.contract)
486+
function = args.function
469487

470488
arguments, should_prepare_args = _get_contract_arguments(args)
471-
contract_address = Address.new_from_bech32(args.contract)
489+
if should_prepare_args:
490+
arguments = convert_args_to_typed_values(arguments)
472491

473492
network_provider_config = get_config_for_network_providers()
474493
proxy = ProxyNetworkProvider(url=args.proxy, config=network_provider_config)
475-
function = args.function
476494

477-
result = contract.query_contract(
478-
contract_address=contract_address,
479-
proxy=proxy,
480-
function=function,
481-
arguments=arguments,
482-
should_prepare_args=should_prepare_args,
495+
controller = SmartContractController(
496+
chain_id="",
497+
network_provider=proxy,
498+
abi=abi,
483499
)
484500

501+
try:
502+
result = controller.query(
503+
contract=contract_address,
504+
function=function,
505+
arguments=arguments,
506+
)
507+
except Exception as e:
508+
raise QueryContractError("Couldn't query contract: ", e)
509+
485510
utils.dump_out_json(result)
486511

487512

multiversx_sdk_cli/cli_delegation.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
validate_proxy_argument,
2121
validate_receiver_args,
2222
)
23-
from multiversx_sdk_cli.base_transactions_controller import BaseTransactionsController
2423
from multiversx_sdk_cli.config import get_config_for_network_providers
2524
from multiversx_sdk_cli.guardian_relayer_data import GuardianRelayerData
2625
from multiversx_sdk_cli.interfaces import IAccount
26+
from multiversx_sdk_cli.signing_wrapper import SigningWrapper
2727

2828

2929
def setup_parser(args: list[str], subparsers: Any) -> Any:
@@ -411,14 +411,11 @@ def _get_delegation_controller(args: Any):
411411

412412

413413
def _sign_transaction(transaction: Transaction, sender: IAccount, guardian_and_relayer_data: GuardianRelayerData):
414-
base = BaseTransactionsController()
415-
base.sign_transaction(
414+
signer = SigningWrapper()
415+
signer.sign_transaction(
416416
transaction=transaction,
417417
sender=sender,
418-
guardian=guardian_and_relayer_data.guardian,
419-
relayer=guardian_and_relayer_data.relayer,
420-
guardian_service_url=guardian_and_relayer_data.guardian_service_url,
421-
guardian_2fa_code=guardian_and_relayer_data.guardian_2fa_code,
418+
guardian_and_relayer=guardian_and_relayer_data,
422419
)
423420

424421

0 commit comments

Comments
 (0)