diff --git a/multiversx_sdk_cli/accounts.py b/multiversx_sdk_cli/accounts.py index 40adf2f4..bb563ae5 100644 --- a/multiversx_sdk_cli/accounts.py +++ b/multiversx_sdk_cli/accounts.py @@ -2,7 +2,8 @@ from pathlib import Path from typing import Any, Optional, Protocol -from multiversx_sdk_core import Address, Message, MessageComputer +from multiversx_sdk_core import (Address, Message, MessageComputer, + TransactionComputer) from multiversx_sdk_network_providers.accounts import AccountOnNetwork from multiversx_sdk_wallet import UserSigner @@ -69,7 +70,9 @@ def __init__(self, def sign_transaction(self, transaction: ITransaction) -> str: assert self.signer is not None - return self.signer.sign(transaction.serialize_for_signing()).hex() + + transaction_computer = TransactionComputer() + return self.signer.sign(transaction_computer.compute_bytes_for_signing(transaction)).hex() def sign_message(self, data: bytes) -> str: assert self.signer is not None @@ -95,8 +98,10 @@ def sign_transaction(self, transaction: ITransaction) -> str: transaction.version = TX_HASH_SIGN_VERSION transaction.options = TX_HASH_SIGN_OPTIONS + transaction_computer = TransactionComputer() + signature = do_sign_transaction_with_ledger( - transaction.serialize_for_signing(), + transaction_computer.compute_bytes_for_signing(transaction), account_index=self.account_index, address_index=self.address_index, sign_using_hash=should_use_hash_signing diff --git a/multiversx_sdk_cli/cli_delegation.py b/multiversx_sdk_cli/cli_delegation.py index c0728ace..6b781e52 100644 --- a/multiversx_sdk_cli/cli_delegation.py +++ b/multiversx_sdk_cli/cli_delegation.py @@ -159,7 +159,7 @@ def get_contract_address_by_deploy_tx_hash(args: Any): transaction_events = transaction.logs.events if len(transaction_events) == 1: contract_address = transaction_events[0].address - print(contract_address.bech32()) + print(contract_address.to_bech32()) else: raise errors.ProgrammingError("Tx has more than one event. Make sure it's a staking provider SC Deploy transaction.") diff --git a/multiversx_sdk_cli/cli_output.py b/multiversx_sdk_cli/cli_output.py index 4d5abf64..36fb6ffe 100644 --- a/multiversx_sdk_cli/cli_output.py +++ b/multiversx_sdk_cli/cli_output.py @@ -51,12 +51,15 @@ def build(self) -> Dict[str, Any]: output: Dict[str, Any] = OrderedDict() if self.emitted_transaction: - emitted_transaction_dict = self.emitted_transaction.to_dictionary() + emitted_transaction_dict = self.emitted_transaction.__dict__ emitted_transaction_hash = self.emitted_transaction_hash or "" - emitted_transaction_data = str(self.emitted_transaction.data) + emitted_transaction_data = self.emitted_transaction.data.decode() utils.omit_fields(emitted_transaction_dict, self.emitted_transaction_omitted_fields) output["emittedTransaction"] = emitted_transaction_dict + signature: bytes = output["emittedTransaction"]["signature"] + output["emittedTransaction"]["signature"] = signature.hex() if type(signature) is not str else signature + output["emittedTransactionData"] = emitted_transaction_data output["emittedTransactionHash"] = emitted_transaction_hash diff --git a/multiversx_sdk_cli/contracts.py b/multiversx_sdk_cli/contracts.py index 4650c8a3..6575ce77 100644 --- a/multiversx_sdk_cli/contracts.py +++ b/multiversx_sdk_cli/contracts.py @@ -79,19 +79,19 @@ def deploy(self, owner: Account, arguments: List[Any], gas_price: int, gas_limit tx = Transaction( chain_id=chain, - sender=owner.address, - receiver=Address.new_from_bech32(ADDRESS_ZERO_BECH32), + sender=owner.address.to_bech32(), + receiver=ADDRESS_ZERO_BECH32, gas_limit=gas_limit, gas_price=gas_price, nonce=owner.nonce, - value=value, - data=self.prepare_deploy_transaction_data(arguments), + amount=value, + data=self.prepare_deploy_transaction_data(arguments).data, version=version, options=options ) if guardian: - tx.guardian = Address.from_bech32(guardian) + tx.guardian = guardian tx.signature = bytes.fromhex(owner.sign_transaction(tx)) return tx @@ -115,19 +115,19 @@ def execute(self, caller: Account, function: str, arguments: List[str], gas_pric tx = Transaction( chain_id=chain, - sender=caller.address, - receiver=receiver, + sender=caller.address.to_bech32(), + receiver=receiver.to_bech32(), gas_limit=gas_limit, gas_price=gas_price, nonce=caller.nonce, - value=value, - data=self.prepare_execute_transaction_data(function, arguments), + amount=value, + data=self.prepare_execute_transaction_data(function, arguments).data, version=version, options=options ) if guardian: - tx.guardian = Address.from_bech32(guardian) + tx.guardian = guardian tx.signature = bytes.fromhex(caller.sign_transaction(tx)) return tx @@ -151,19 +151,19 @@ def upgrade(self, owner: Account, arguments: List[Any], gas_price: int, gas_limi tx = Transaction( chain_id=chain, - sender=owner.address, - receiver=receiver, + sender=owner.address.to_bech32(), + receiver=receiver.to_bech32(), gas_limit=gas_limit, gas_price=gas_price, nonce=owner.nonce, - value=value, - data=self.prepare_upgrade_transaction_data(arguments), + amount=value, + data=self.prepare_upgrade_transaction_data(arguments).data, version=version, options=options ) if guardian: - tx.guardian = Address.from_bech32(guardian) + tx.guardian = guardian tx.signature = bytes.fromhex(owner.sign_transaction(tx)) return tx diff --git a/multiversx_sdk_cli/cosign_transaction.py b/multiversx_sdk_cli/cosign_transaction.py index 6c5383dc..26aada47 100644 --- a/multiversx_sdk_cli/cosign_transaction.py +++ b/multiversx_sdk_cli/cosign_transaction.py @@ -9,7 +9,7 @@ def cosign_transaction(transaction: ITransaction, service_url: str, guardian_code: str) -> ITransaction: payload = { "code": f"{guardian_code}", - "transaction": transaction.to_dictionary() + "transaction": transaction.__dict__ } url = f"{service_url}/sign-transaction" diff --git a/multiversx_sdk_cli/interfaces.py b/multiversx_sdk_cli/interfaces.py index 7e085b43..9e736b17 100644 --- a/multiversx_sdk_cli/interfaces.py +++ b/multiversx_sdk_cli/interfaces.py @@ -9,32 +9,22 @@ def to_bech32(self) -> str: ... -ITransactionOptions = int -ITransactionVersion = int -ISignature = bytes - - -class ITransactionPayload(Protocol): - data: bytes - def encoded(self) -> str: ... - def length(self) -> int: ... - - class ITransaction(Protocol): - version: ITransactionVersion - options: ITransactionOptions - signature: ISignature - guardian_signature: ISignature - - @property - def data(self) -> ITransactionPayload: - ... - - def serialize_for_signing(self) -> bytes: - ... - - def to_dictionary(self, with_signature: bool = True) -> Dict[str, Any]: - ... + sender: str + receiver: str + gas_limit: int + chain_id: str + nonce: int + amount: int + sender_username: str + receiver_username: str + gas_price: int + data: bytes + version: int + options: int + guardian: str + signature: bytes + guardian_signature: bytes class IAccount(Protocol): diff --git a/multiversx_sdk_cli/tests/test_contracts.py b/multiversx_sdk_cli/tests/test_contracts.py index 2ea5674f..f6eed78d 100644 --- a/multiversx_sdk_cli/tests/test_contracts.py +++ b/multiversx_sdk_cli/tests/test_contracts.py @@ -35,7 +35,7 @@ def test_compute_address(): assert contract.address.bech32() == "erd1qqqqqqqqqqqqqpgqhdjjyq8dr7v5yq9tv6v5vt9tfvd00vg7h40q6779zn" contract.owner.nonce = 1 - contract.address = address_computer.compute_contract_address(contract.owner.address, contract.owner.nonce DEFAULT_HRP) + contract.address = address_computer.compute_contract_address(contract.owner.address, contract.owner.nonce) assert contract.address.hex() == "000000000000000005006e4f90488e27342f9a46e1809452c85ee7186566bd5e" assert contract.address.bech32() == "erd1qqqqqqqqqqqqqpgqde8eqjywyu6zlxjxuxqfg5kgtmn3setxh40qen8egy" diff --git a/multiversx_sdk_cli/transactions.py b/multiversx_sdk_cli/transactions.py index 5b8d2a9f..ba2cceee 100644 --- a/multiversx_sdk_cli/transactions.py +++ b/multiversx_sdk_cli/transactions.py @@ -69,21 +69,21 @@ def do_prepare_transaction(args: Any) -> Transaction: tx = Transaction( chain_id=args.chain, - sender=account.address, - receiver=Address.from_bech32(args.receiver), + sender=account.address.to_bech32(), + receiver=args.receiver, gas_limit=int(args.gas_limit), sender_username=getattr(args, "sender_username", ""), receiver_username=getattr(args, "receiver_username", ""), gas_price=int(args.gas_price), - data=TransactionPayload.from_str(args.data), + data=TransactionPayload.from_str(args.data).data, nonce=int(args.nonce), - value=int(args.value), + amount=int(args.value), version=int(args.version), options=int(args.options) ) if args.guardian: - tx.guardian = Address.from_bech32(args.guardian) + tx.guardian = args.guardian tx.signature = bytes.fromhex(account.sign_transaction(tx)) tx = sign_tx_by_guardian(args, tx) @@ -148,12 +148,12 @@ def _send_transaction_and_wait_for_result(proxy: INetworkProvider, payload: ITra def tx_to_dictionary_as_inner(tx: Transaction) -> Dict[str, Any]: - dictionary = tx.to_dictionary() - dictionary["receiver"] = base64.b64encode(bytes.fromhex(tx.receiver.hex())).decode() # type: ignore - dictionary["sender"] = base64.b64encode(bytes.fromhex(tx.sender.hex())).decode() # type: ignore - dictionary["chainID"] = base64.b64encode(tx.chainID.encode()).decode() + dictionary = tx.__dict__ + dictionary["receiver"] = base64.b64encode(Address.new_from_bech32(tx.receiver).get_public_key()).decode() + dictionary["sender"] = base64.b64encode(Address.new_from_bech32(tx.sender).get_public_key()).decode() + dictionary["chainID"] = base64.b64encode(tx.chain_id.encode()).decode() dictionary["signature"] = base64.b64encode(bytes(bytearray(tx.signature))).decode() - dictionary["value"] = tx.value + dictionary["value"] = tx.amount return dictionary @@ -179,21 +179,21 @@ def load_transaction_from_file(f: TextIO) -> Transaction: loaded_tx = Transaction( chain_id=instance.chainID, - sender=Address.from_bech32(instance.sender), - receiver=Address.from_bech32(instance.receiver), + sender=instance.sender, + receiver=instance.receiver, sender_username=decode_field_value(instance.senderUsername), receiver_username=decode_field_value(instance.receiverUsername), gas_limit=instance.gasLimit, gas_price=instance.gasPrice, - value=int(instance.value), - data=TransactionPayload.from_encoded_str(instance.data), + amount=int(instance.value), + data=TransactionPayload.from_encoded_str(instance.data).data, version=instance.version, options=instance.options, nonce=instance.nonce ) if instance.guardian: - loaded_tx.guardian = Address.from_bech32(instance.guardian) + loaded_tx.guardian = instance.guardian if instance.signature: loaded_tx.signature = bytes.fromhex(instance.signature) diff --git a/multiversx_sdk_cli/utils.py b/multiversx_sdk_cli/utils.py index 89ce3e5c..a4905076 100644 --- a/multiversx_sdk_cli/utils.py +++ b/multiversx_sdk_cli/utils.py @@ -1,3 +1,4 @@ +import base64 import json import logging import os @@ -40,9 +41,12 @@ def to_json(self): class BasicEncoder(json.JSONEncoder): def default(self, o: Any): + if isinstance(o, bytes): + # Encode bytes as a base64 string + return base64.b64encode(o).decode('utf-8') if isinstance(o, ISerializable): return o.to_dictionary() - return json.JSONEncoder.default(self, o) + return super().default(o) def omit_fields(data: Any, fields: List[str] = []):