Skip to content

Commit baf60bb

Browse files
authored
Merge pull request #478 from multiversx/transaction-refactoring
Transactions creation refactoring & fixes
2 parents cc22308 + 6df2e3e commit baf60bb

15 files changed

+702
-147
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from typing import Optional, Union
2+
3+
from multiversx_sdk import LedgerAccount, Transaction, TransactionComputer
4+
5+
from multiversx_sdk_cli.cosign_transaction import cosign_transaction
6+
from multiversx_sdk_cli.interfaces import IAccount
7+
8+
9+
class BaseTransactionsController:
10+
def __init__(self) -> None:
11+
pass
12+
13+
def sign_transaction(
14+
self,
15+
transaction: Transaction,
16+
sender: Optional[IAccount] = None,
17+
guardian: Optional[IAccount] = None,
18+
relayer: Optional[IAccount] = None,
19+
guardian_service_url: str = "",
20+
guardian_2fa_code: str = "",
21+
):
22+
"""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."""
23+
self._set_options_for_guarded_transaction_if_needed(transaction)
24+
self._set_options_for_hash_signing_if_needed(transaction, sender, guardian, relayer)
25+
26+
if sender:
27+
transaction.signature = sender.sign_transaction(transaction)
28+
29+
self._sign_guarded_transaction_if_guardian(
30+
transaction,
31+
guardian,
32+
guardian_service_url,
33+
guardian_2fa_code,
34+
)
35+
self._sign_relayed_transaction_if_relayer(transaction, relayer)
36+
37+
def _set_options_for_guarded_transaction_if_needed(self, transaction: Transaction):
38+
if transaction.guardian:
39+
transaction_computer = TransactionComputer()
40+
transaction_computer.apply_guardian(transaction, transaction.guardian)
41+
42+
def _set_options_for_hash_signing_if_needed(
43+
self,
44+
transaction: Transaction,
45+
sender: Union[IAccount, None],
46+
guardian: Union[IAccount, None],
47+
relayer: Union[IAccount, None],
48+
):
49+
if (
50+
isinstance(sender, LedgerAccount)
51+
or isinstance(guardian, LedgerAccount)
52+
or isinstance(relayer, LedgerAccount)
53+
):
54+
transaction_computer = TransactionComputer()
55+
transaction_computer.apply_options_for_hash_signing(transaction)
56+
57+
def _sign_guarded_transaction_if_guardian(
58+
self,
59+
transaction: Transaction,
60+
guardian: Union[IAccount, None],
61+
guardian_service_url: str,
62+
guardian_2fa_code: str,
63+
) -> Transaction:
64+
# If the guardian account is provided, we sign locally. Otherwise, we reach for the trusted cosign service.
65+
if guardian:
66+
transaction.guardian_signature = guardian.sign_transaction(transaction)
67+
elif transaction.guardian and guardian_service_url and guardian_2fa_code:
68+
cosign_transaction(transaction, guardian_service_url, guardian_2fa_code)
69+
70+
return transaction
71+
72+
def _sign_relayed_transaction_if_relayer(self, transaction: Transaction, relayer: Union[IAccount, None]):
73+
if relayer and transaction.relayer:
74+
transaction.relayer_signature = relayer.sign_transaction(transaction)

multiversx_sdk_cli/cli_contracts.py

+25-35
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import logging
33
import os
44
from pathlib import Path
5-
from typing import Any, Union
5+
from typing import Any
66

77
from multiversx_sdk import (
88
Address,
@@ -19,10 +19,8 @@
1919
from multiversx_sdk_cli.constants import NUMBER_OF_SHARDS
2020
from multiversx_sdk_cli.contract_verification import trigger_contract_verification
2121
from multiversx_sdk_cli.contracts import SmartContract
22-
from multiversx_sdk_cli.cosign_transaction import cosign_transaction
2322
from multiversx_sdk_cli.docker import is_docker_installed, run_docker
2423
from multiversx_sdk_cli.errors import DockerMissingError
25-
from multiversx_sdk_cli.interfaces import IAccount
2624
from multiversx_sdk_cli.ux import show_warning
2725

2826
logger = logging.getLogger("cli.contracts")
@@ -338,13 +336,13 @@ def build(args: Any):
338336

339337
def deploy(args: Any):
340338
logger.debug("deploy")
341-
cli_shared.check_guardian_and_options_args(args)
339+
cli_shared.check_guardian_args(args)
342340
cli_shared.check_broadcast_args(args)
343341
cli_shared.prepare_chain_id_in_args(args)
344342

345343
sender = cli_shared.prepare_account(args)
346344

347-
if not args.nonce:
345+
if args.nonce is None:
348346
nonce = cli_shared.get_current_nonce_for_address(sender.address, args.proxy)
349347
else:
350348
nonce = int(args.nonce)
@@ -375,11 +373,13 @@ def deploy(args: Any):
375373
nonce=nonce,
376374
version=int(args.version),
377375
options=int(args.options),
378-
guardian=guardian_address,
379-
relayer=relayer_address,
376+
guardian_account=guardian,
377+
guardian_address=guardian_address,
378+
relayer_account=relayer,
379+
relayer_address=relayer_address,
380+
guardian_service_url=args.guardian_service_url,
381+
guardian_2fa_code=args.guardian_2fa_code,
380382
)
381-
tx = _sign_guarded_tx_if_guardian(guardian, args, tx)
382-
_sign_relayed_tx_if_relayer(relayer, tx)
383383

384384
address_computer = AddressComputer(NUMBER_OF_SHARDS)
385385
contract_address = address_computer.compute_contract_address(deployer=sender.address, deployment_nonce=tx.nonce)
@@ -390,29 +390,15 @@ def deploy(args: Any):
390390
_send_or_simulate(tx, contract_address, args)
391391

392392

393-
def _sign_guarded_tx_if_guardian(guardian: Union[IAccount, None], args: Any, tx: Transaction) -> Transaction:
394-
if guardian:
395-
tx.guardian_signature = guardian.sign_transaction(tx)
396-
elif tx.guardian and args.guardian_service_url and args.guardian_2fa_code:
397-
tx = cosign_transaction(tx, args.guardian_service_url, args.guardian_2fa_code)
398-
399-
return tx
400-
401-
402-
def _sign_relayed_tx_if_relayer(relayer: Union[IAccount, None], tx: Transaction):
403-
if relayer and tx.relayer:
404-
tx.relayer_signature = relayer.sign_transaction(tx)
405-
406-
407393
def call(args: Any):
408394
logger.debug("call")
409-
cli_shared.check_guardian_and_options_args(args)
395+
cli_shared.check_guardian_args(args)
410396
cli_shared.check_broadcast_args(args)
411397
cli_shared.prepare_chain_id_in_args(args)
412398

413399
sender = cli_shared.prepare_account(args)
414400

415-
if not args.nonce:
401+
if args.nonce is None:
416402
nonce = cli_shared.get_current_nonce_for_address(sender.address, args.proxy)
417403
else:
418404
nonce = int(args.nonce)
@@ -442,24 +428,26 @@ def call(args: Any):
442428
nonce=nonce,
443429
version=int(args.version),
444430
options=int(args.options),
445-
guardian=guardian_address,
446-
relayer=relayer_address,
431+
guardian_account=guardian,
432+
guardian_address=guardian_address,
433+
relayer_account=relayer,
434+
relayer_address=relayer_address,
435+
guardian_service_url=args.guardian_service_url,
436+
guardian_2fa_code=args.guardian_2fa_code,
447437
)
448-
tx = _sign_guarded_tx_if_guardian(guardian, args, tx)
449-
_sign_relayed_tx_if_relayer(relayer, tx)
450438

451439
_send_or_simulate(tx, contract_address, args)
452440

453441

454442
def upgrade(args: Any):
455443
logger.debug("upgrade")
456-
cli_shared.check_guardian_and_options_args(args)
444+
cli_shared.check_guardian_args(args)
457445
cli_shared.check_broadcast_args(args)
458446
cli_shared.prepare_chain_id_in_args(args)
459447

460448
sender = cli_shared.prepare_account(args)
461449

462-
if not args.nonce:
450+
if args.nonce is None:
463451
nonce = cli_shared.get_current_nonce_for_address(sender.address, args.proxy)
464452
else:
465453
nonce = int(args.nonce)
@@ -492,11 +480,13 @@ def upgrade(args: Any):
492480
nonce=nonce,
493481
version=int(args.version),
494482
options=int(args.options),
495-
guardian=guardian_address,
496-
relayer=relayer_address,
483+
guardian_account=guardian,
484+
guardian_address=guardian_address,
485+
relayer_account=relayer,
486+
relayer_address=relayer_address,
487+
guardian_service_url=args.guardian_service_url,
488+
guardian_2fa_code=args.guardian_2fa_code,
497489
)
498-
tx = _sign_guarded_tx_if_guardian(guardian, args, tx)
499-
_sign_relayed_tx_if_relayer(relayer, tx)
500490

501491
_send_or_simulate(tx, contract_address, args)
502492

multiversx_sdk_cli/cli_delegation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ def _add_common_arguments(args: List[str], sub: Any):
363363

364364

365365
def ensure_arguments_are_provided_and_prepared(args: Any):
366-
cli_shared.check_guardian_and_options_args(args)
366+
cli_shared.check_guardian_args(args)
367367
cli_shared.check_broadcast_args(args)
368368
cli_shared.prepare_chain_id_in_args(args)
369369
cli_shared.prepare_nonce_in_args(args)

0 commit comments

Comments
 (0)