diff --git a/docs/conf.py b/docs/conf.py index 0adc30bc..614e6e1f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,7 +14,7 @@ project = 'multiversx-sdk' copyright = '2024, MultiversX' author = 'MultiversX' -release = '0.11.0' +release = '0.19.0' # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/docs/multiversx_sdk.abi.rst b/docs/multiversx_sdk.abi.rst index a1a0cf32..0b61e614 100644 --- a/docs/multiversx_sdk.abi.rst +++ b/docs/multiversx_sdk.abi.rst @@ -68,6 +68,14 @@ multiversx\_sdk.abi.bytes\_value module :undoc-members: :show-inheritance: +multiversx\_sdk.abi.code\_metadata\_value module +------------------------------------------------ + +.. automodule:: multiversx_sdk.abi.code_metadata_value + :members: + :undoc-members: + :show-inheritance: + multiversx\_sdk.abi.codec module -------------------------------- @@ -92,6 +100,14 @@ multiversx\_sdk.abi.enum\_value module :undoc-members: :show-inheritance: +multiversx\_sdk.abi.explicit\_enum\_value module +------------------------------------------------ + +.. automodule:: multiversx_sdk.abi.explicit_enum_value + :members: + :undoc-members: + :show-inheritance: + multiversx\_sdk.abi.fields module --------------------------------- diff --git a/docs/multiversx_sdk.core.rst b/docs/multiversx_sdk.core.rst index e225cf6a..f164ad2f 100644 --- a/docs/multiversx_sdk.core.rst +++ b/docs/multiversx_sdk.core.rst @@ -56,6 +56,14 @@ multiversx\_sdk.core.codec module :undoc-members: :show-inheritance: +multiversx\_sdk.core.config module +---------------------------------- + +.. automodule:: multiversx_sdk.core.config + :members: + :undoc-members: + :show-inheritance: + multiversx\_sdk.core.contract\_query module ------------------------------------------- diff --git a/docs/multiversx_sdk.network_providers.rst b/docs/multiversx_sdk.network_providers.rst index 60b116d2..651d7f9b 100644 --- a/docs/multiversx_sdk.network_providers.rst +++ b/docs/multiversx_sdk.network_providers.rst @@ -188,6 +188,14 @@ multiversx\_sdk.network\_providers.transactions module :undoc-members: :show-inheritance: +multiversx\_sdk.network\_providers.user\_agent module +----------------------------------------------------- + +.. automodule:: multiversx_sdk.network_providers.user_agent + :members: + :undoc-members: + :show-inheritance: + multiversx\_sdk.network\_providers.utils module ----------------------------------------------- diff --git a/examples/Cookbook.ipynb b/examples/Cookbook.ipynb index 264230b5..c6eea953 100644 --- a/examples/Cookbook.ipynb +++ b/examples/Cookbook.ipynb @@ -184,6 +184,47 @@ "print(\"Is contract:\", address.is_smart_contract())" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Changing the default hrp\n", + "\n", + "We have a configuration class, called `LibraryConfig`, that only stores (for the moment) the **default hrp** of the addresses. The default value is `erd`. The hrp can be changed when instantiating an address, or it can be changed in the `LibraryConfig` class, and all the addresses created will have the newly set hrp. " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "erd\n", + "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\n", + "test1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ss5hqhtr\n" + ] + } + ], + "source": [ + "from multiversx_sdk import Address\n", + "from multiversx_sdk import LibraryConfig\n", + "\n", + "\n", + "print(LibraryConfig.default_address_hrp)\n", + "address = Address.new_from_hex(\"0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\")\n", + "print(address.to_bech32())\n", + "\n", + "LibraryConfig.default_address_hrp = \"test\"\n", + "address = Address.new_from_hex(\"0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\")\n", + "print(address.to_bech32())\n", + "\n", + "# setting back the default value\n", + "LibraryConfig.default_address_hrp = \"erd\"" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -2249,7 +2290,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.12.3" }, "orig_nbformat": 4, "vscode": { diff --git a/multiversx_sdk/__init__.py b/multiversx_sdk/__init__.py index 6768a1e0..2e53e346 100644 --- a/multiversx_sdk/__init__.py +++ b/multiversx_sdk/__init__.py @@ -5,6 +5,7 @@ from multiversx_sdk.core.address import (Address, AddressComputer, AddressFactory) from multiversx_sdk.core.code_metadata import CodeMetadata +from multiversx_sdk.core.config import LibraryConfig from multiversx_sdk.core.contract_query import ContractQuery from multiversx_sdk.core.contract_query_builder import ContractQueryBuilder from multiversx_sdk.core.message import Message, MessageComputer @@ -84,5 +85,6 @@ "UserWallet", "UserPEM", "QueryRunnerAdapter", "TransactionsConverter", "DelegationTransactionsOutcomeParser", "find_events_by_identifier", "find_events_by_first_topic", "SmartContractTransactionsOutcomeParser", "TransactionAwaiter", "SmartContractQueriesController", "SmartContractQuery", "SmartContractQueryResponse", - "TransactionDecoder", "TransactionMetadata", "TransactionEventsParser", "NetworkProviderConfig" + "TransactionDecoder", "TransactionMetadata", "TransactionEventsParser", "NetworkProviderConfig", + "LibraryConfig" ] diff --git a/multiversx_sdk/core/__init__.py b/multiversx_sdk/core/__init__.py index ea91361c..85a59643 100644 --- a/multiversx_sdk/core/__init__.py +++ b/multiversx_sdk/core/__init__.py @@ -2,6 +2,7 @@ from multiversx_sdk.core.address import (Address, AddressComputer, AddressFactory) from multiversx_sdk.core.code_metadata import CodeMetadata +from multiversx_sdk.core.config import LibraryConfig from multiversx_sdk.core.contract_query import ContractQuery from multiversx_sdk.core.contract_query_builder import ContractQueryBuilder from multiversx_sdk.core.message import Message, MessageComputer @@ -54,5 +55,6 @@ "SmartContractTransactionsFactory", "TransferTransactionsFactory", "RelayedTransactionsFactory", "AccountTransactionsFactory", "DelegationTransactionsOutcomeParser", "find_events_by_identifier", "find_events_by_first_topic", "SmartContractTransactionsOutcomeParser", - "SmartContractQueriesController", "SmartContractQuery", "SmartContractQueryResponse", "TransactionEventsParser" + "SmartContractQueriesController", "SmartContractQuery", "SmartContractQueryResponse", "TransactionEventsParser", + "LibraryConfig" ] diff --git a/multiversx_sdk/core/address.py b/multiversx_sdk/core/address.py index e7452614..65ca3994 100644 --- a/multiversx_sdk/core/address.py +++ b/multiversx_sdk/core/address.py @@ -1,10 +1,11 @@ import logging -from typing import Protocol, Tuple +from typing import Optional, Protocol, Tuple from Cryptodome.Hash import keccak from multiversx_sdk.core import bech32 -from multiversx_sdk.core.constants import DEFAULT_HRP, METACHAIN_ID +from multiversx_sdk.core.config import LibraryConfig +from multiversx_sdk.core.constants import METACHAIN_ID from multiversx_sdk.core.errors import ErrBadAddress, ErrBadPubkeyLength SC_HEX_PUBKEY_PREFIX = "0" * 16 @@ -26,7 +27,7 @@ def get_hrp(self) -> str: class Address: """An Address, as an immutable object.""" - def __init__(self, pubkey: bytes, hrp: str) -> None: + def __init__(self, pubkey: bytes, hrp: Optional[str] = None) -> None: """Creates an address object, given a sequence of bytes and the human readable part(hrp). Args: @@ -36,7 +37,7 @@ def __init__(self, pubkey: bytes, hrp: str) -> None: raise ErrBadPubkeyLength(len(pubkey), PUBKEY_LENGTH) self.pubkey = bytes(pubkey) - self.hrp = hrp + self.hrp = hrp if hrp else LibraryConfig.default_address_hrp @classmethod def new_from_bech32(cls, value: str) -> 'Address': @@ -53,7 +54,7 @@ def from_bech32(cls, value: str) -> 'Address': return Address.new_from_bech32(value) @classmethod - def new_from_hex(cls, value: str, hrp: str) -> 'Address': + def new_from_hex(cls, value: str, hrp: Optional[str] = None) -> 'Address': """Creates an address object from the hexed sequence of bytes and the human readable part(hrp). Args: @@ -110,12 +111,12 @@ def __bytes__(self) -> bytes: class AddressFactory: """A factory used to create address objects.""" - def __init__(self, hrp: str = DEFAULT_HRP) -> None: + def __init__(self, hrp: Optional[str] = None) -> None: """All the addresses created with the factory have the same human readable part Args: hrp (str): the human readable part of the address (default: erd)""" - self.hrp = hrp + self.hrp = hrp if hrp else LibraryConfig.default_address_hrp def create_from_bech32(self, value: str) -> Address: """Creates an address object from the bech32 representation of an address""" diff --git a/multiversx_sdk/core/address_test.py b/multiversx_sdk/core/address_test.py index 77d309c8..09ab38fe 100644 --- a/multiversx_sdk/core/address_test.py +++ b/multiversx_sdk/core/address_test.py @@ -3,6 +3,7 @@ from multiversx_sdk.core.address import (Address, AddressComputer, AddressFactory, is_valid_bech32) +from multiversx_sdk.core.config import LibraryConfig from multiversx_sdk.core.errors import ErrBadAddress, ErrBadPubkeyLength @@ -71,3 +72,13 @@ def test_compute_contract_address(): contract_address = address_computer.compute_contract_address(deployer, deployment_nonce=1) assert contract_address.to_hex() == "000000000000000005006e4f90488e27342f9a46e1809452c85ee7186566bd5e" assert contract_address.to_bech32() == "erd1qqqqqqqqqqqqqpgqde8eqjywyu6zlxjxuxqfg5kgtmn3setxh40qen8egy" + + +def test_address_with_library_config_hrp(): + address = Address(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")) + assert address.to_bech32() == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" + + LibraryConfig.default_address_hrp = "test" + address = Address(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")) + assert address.to_bech32() == "test1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ss5hqhtr" + LibraryConfig.default_address_hrp = "erd" diff --git a/multiversx_sdk/core/config.py b/multiversx_sdk/core/config.py new file mode 100644 index 00000000..6edc1fd0 --- /dev/null +++ b/multiversx_sdk/core/config.py @@ -0,0 +1,17 @@ +from dataclasses import dataclass + + +@dataclass +class LibraryConfig: + """ + Global configuration of the library. + + Generally speaking, this configuration should only be altered in exotic use cases. + It can be seen as a collection of constants or, more precisely, variables that are rarely changed and used throughout the library. + + Never alter the configuration within a library! + Only alter the configuration, if needed, within a final application that uses this library. + """ + + # The human-readable part of the bech32 addresses + default_address_hrp: str = "erd" diff --git a/multiversx_sdk/core/constants.py b/multiversx_sdk/core/constants.py index 0b75805f..84049578 100644 --- a/multiversx_sdk/core/constants.py +++ b/multiversx_sdk/core/constants.py @@ -11,9 +11,19 @@ EGLD_TOKEN_IDENTIFIER = "EGLD" EGLD_NUM_DECIMALS = 18 +# left it for compatibility reasons, will be deleted in the future DELEGATION_MANAGER_SC_ADDRESS = "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqylllslmq6y6" + +# left it for compatibility reasons, will be deleted in the future DEFAULT_HRP = "erd" + +# left it for compatibility reasons, will be deleted in the future CONTRACT_DEPLOY_ADDRESS = "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu" + +DELEGATION_MANAGER_SC_ADDRESS_HEX = "000000000000000000010000000000000000000000000000000000000004ffff" +CONTRACT_DEPLOY_ADDRESS_HEX = "0000000000000000000000000000000000000000000000000000000000000000" +ESDT_CONTRACT_ADDRESS_HEX = "000000000000000000010000000000000000000000000000000000000002ffff" + TRANSACTION_OPTIONS_TX_GUARDED = 0b0010 TRANSACTION_OPTIONS_TX_HASH_SIGN = 0b0001 diff --git a/multiversx_sdk/core/transaction_builders/default_configuration.py b/multiversx_sdk/core/transaction_builders/default_configuration.py index 94fe4191..5ada89fc 100644 --- a/multiversx_sdk/core/transaction_builders/default_configuration.py +++ b/multiversx_sdk/core/transaction_builders/default_configuration.py @@ -4,6 +4,8 @@ from multiversx_sdk.core.interfaces import (IAddress, IChainID, IGasPrice, ITransactionValue) +from multiversx_sdk.core.constants import CONTRACT_DEPLOY_ADDRESS_HEX, ESDT_CONTRACT_ADDRESS_HEX + @dataclass class DefaultTransactionBuildersConfiguration: @@ -19,5 +21,5 @@ class DefaultTransactionBuildersConfiguration: additional_gas_for_esdt_transfer = 100000 additional_gas_for_esdt_nft_transfer = 800000 - esdt_contract_address: IAddress = Address.new_from_bech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u") - deployment_address: IAddress = Address.new_from_bech32("erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu") + esdt_contract_address: IAddress = Address.new_from_hex(ESDT_CONTRACT_ADDRESS_HEX) + deployment_address: IAddress = Address.new_from_hex(CONTRACT_DEPLOY_ADDRESS_HEX) diff --git a/multiversx_sdk/core/transaction_builders/relayed_v1_builder.py b/multiversx_sdk/core/transaction_builders/relayed_v1_builder.py index 7cf7a3ed..fcee8ffc 100644 --- a/multiversx_sdk/core/transaction_builders/relayed_v1_builder.py +++ b/multiversx_sdk/core/transaction_builders/relayed_v1_builder.py @@ -131,7 +131,6 @@ def _prepare_inner_transaction(self) -> str: tx["sndUserName"] = base64.b64encode(self.inner_transaction.sender_username.encode()).decode() if self.inner_transaction.receiver_username: - tx[f"rcvUserName"] = base64.b64encode(self.inner_transaction.receiver_username.encode()).decode() + tx["rcvUserName"] = base64.b64encode(self.inner_transaction.receiver_username.encode()).decode() return json.dumps(tx, separators=(",", ":")) - diff --git a/multiversx_sdk/core/transactions_factories/delegation_transactions_factory.py b/multiversx_sdk/core/transactions_factories/delegation_transactions_factory.py index a189704c..fa87680c 100644 --- a/multiversx_sdk/core/transactions_factories/delegation_transactions_factory.py +++ b/multiversx_sdk/core/transactions_factories/delegation_transactions_factory.py @@ -1,7 +1,7 @@ from typing import Protocol, Sequence from multiversx_sdk.core.address import Address -from multiversx_sdk.core.constants import DELEGATION_MANAGER_SC_ADDRESS +from multiversx_sdk.core.constants import DELEGATION_MANAGER_SC_ADDRESS_HEX from multiversx_sdk.core.errors import ErrListsLengthMismatch from multiversx_sdk.core.interfaces import IAddress, IValidatorPublicKey from multiversx_sdk.core.serializer import arg_to_string @@ -41,7 +41,7 @@ def create_transaction_for_new_delegation_contract(self, transaction = TransactionBuilder( config=self.config, sender=sender, - receiver=Address.new_from_bech32(DELEGATION_MANAGER_SC_ADDRESS), + receiver=Address.new_from_hex(DELEGATION_MANAGER_SC_ADDRESS_HEX), data_parts=parts, gas_limit=self.config.gas_limit_create_delegation_contract + self.config.additional_gas_for_delegation_operations, add_data_movement_gas=True, diff --git a/multiversx_sdk/core/transactions_factories/delegation_transactions_factory_test.py b/multiversx_sdk/core/transactions_factories/delegation_transactions_factory_test.py index 4da77d2e..ffc262c8 100644 --- a/multiversx_sdk/core/transactions_factories/delegation_transactions_factory_test.py +++ b/multiversx_sdk/core/transactions_factories/delegation_transactions_factory_test.py @@ -1,5 +1,5 @@ from multiversx_sdk.core.address import Address -from multiversx_sdk.core.constants import DELEGATION_MANAGER_SC_ADDRESS +from multiversx_sdk.core.constants import DELEGATION_MANAGER_SC_ADDRESS_HEX from multiversx_sdk.core.transactions_factories.delegation_transactions_factory import \ DelegationTransactionsFactory from multiversx_sdk.core.transactions_factories.transactions_factory_config import \ @@ -20,7 +20,7 @@ def test_create_transaction_for_new_delegation_contract(self): ) assert transaction.sender == "erd18s6a06ktr2v6fgxv4ffhauxvptssnaqlds45qgsrucemlwc8rawq553rt2" - assert transaction.receiver == DELEGATION_MANAGER_SC_ADDRESS + assert transaction.receiver == Address.new_from_hex(DELEGATION_MANAGER_SC_ADDRESS_HEX).to_bech32() assert transaction.data assert transaction.data.decode() == "createNewDelegationContract@010f0cf064dd59200000@0a" assert transaction.gas_limit == 60126500 diff --git a/multiversx_sdk/core/transactions_factories/smart_contract_transaction_factory_test.py b/multiversx_sdk/core/transactions_factories/smart_contract_transaction_factory_test.py index 517e48ab..56a85230 100644 --- a/multiversx_sdk/core/transactions_factories/smart_contract_transaction_factory_test.py +++ b/multiversx_sdk/core/transactions_factories/smart_contract_transaction_factory_test.py @@ -4,7 +4,7 @@ from multiversx_sdk.abi.biguint_value import BigUIntValue from multiversx_sdk.abi.small_int_values import U32Value from multiversx_sdk.core.address import Address -from multiversx_sdk.core.constants import CONTRACT_DEPLOY_ADDRESS +from multiversx_sdk.core.constants import CONTRACT_DEPLOY_ADDRESS_HEX from multiversx_sdk.core.tokens import Token, TokenTransfer from multiversx_sdk.core.transactions_factories.smart_contract_transactions_factory import \ SmartContractTransactionsFactory @@ -55,7 +55,7 @@ def test_create_transaction_for_deploy(self): ) assert transaction.sender == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th" - assert transaction.receiver == CONTRACT_DEPLOY_ADDRESS + assert transaction.receiver == Address.new_from_hex(CONTRACT_DEPLOY_ADDRESS_HEX).to_bech32() assert transaction.data == f"{self.bytecode.hex()}@0500@0504@01".encode() assert transaction.gas_limit == gas_limit assert transaction.value == 0 diff --git a/multiversx_sdk/core/transactions_factories/smart_contract_transactions_factory.py b/multiversx_sdk/core/transactions_factories/smart_contract_transactions_factory.py index 69920cf6..7e588aec 100644 --- a/multiversx_sdk/core/transactions_factories/smart_contract_transactions_factory.py +++ b/multiversx_sdk/core/transactions_factories/smart_contract_transactions_factory.py @@ -6,7 +6,7 @@ from multiversx_sdk.core.address import Address from multiversx_sdk.core.code_metadata import CodeMetadata from multiversx_sdk.core.constants import (ARGS_SEPARATOR, - CONTRACT_DEPLOY_ADDRESS, + CONTRACT_DEPLOY_ADDRESS_HEX, VM_TYPE_WASM_VM) from multiversx_sdk.core.interfaces import IAddress from multiversx_sdk.core.serializer import arg_to_string, args_to_buffers @@ -72,7 +72,7 @@ def create_transaction_for_deploy(self, return TransactionBuilder( config=self.config, sender=sender, - receiver=Address.new_from_bech32(CONTRACT_DEPLOY_ADDRESS), + receiver=Address.new_from_hex(CONTRACT_DEPLOY_ADDRESS_HEX), data_parts=parts, gas_limit=gas_limit, add_data_movement_gas=False, diff --git a/multiversx_sdk/core/transactions_factories/transactions_factory_config.py b/multiversx_sdk/core/transactions_factories/transactions_factory_config.py index 966681ac..6152c7b2 100644 --- a/multiversx_sdk/core/transactions_factories/transactions_factory_config.py +++ b/multiversx_sdk/core/transactions_factories/transactions_factory_config.py @@ -1,5 +1,6 @@ from multiversx_sdk.core.address import Address -from multiversx_sdk.core.constants import DEFAULT_HRP +from multiversx_sdk.core.config import LibraryConfig +from multiversx_sdk.core.constants import ESDT_CONTRACT_ADDRESS_HEX from multiversx_sdk.core.interfaces import IAddress @@ -7,7 +8,7 @@ class TransactionsFactoryConfig: def __init__(self, chain_id: str) -> None: # General-purpose configuration self.chain_id = chain_id - self.address_hrp = DEFAULT_HRP + self.address_hrp = LibraryConfig.default_address_hrp self.min_gas_limit = 50_000 self.gas_limit_per_byte = 1_500 @@ -34,7 +35,7 @@ def __init__(self, chain_id: str) -> None: self.gas_limit_update_token_id = 60_000_000 self.gas_limit_register_dynamic = 60_000_000 self.issue_cost = 50_000_000_000_000_000 - self.esdt_contract_address: IAddress = Address.new_from_bech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u") + self.esdt_contract_address: IAddress = Address.new_from_hex(ESDT_CONTRACT_ADDRESS_HEX, self.address_hrp) # Configuration for delegation operations self.gas_limit_stake = 5_000_000 diff --git a/multiversx_sdk/core/transactions_outcome_parsers/delegation_transactions_outcome_parser.py b/multiversx_sdk/core/transactions_outcome_parsers/delegation_transactions_outcome_parser.py index a072d8b7..92232c82 100644 --- a/multiversx_sdk/core/transactions_outcome_parsers/delegation_transactions_outcome_parser.py +++ b/multiversx_sdk/core/transactions_outcome_parsers/delegation_transactions_outcome_parser.py @@ -1,12 +1,12 @@ from typing import List from multiversx_sdk.core.address import Address +from multiversx_sdk.core.config import LibraryConfig from multiversx_sdk.core.errors import ParseTransactionOutcomeError from multiversx_sdk.core.transactions_outcome_parsers.delegation_transactions_outcome_parser_types import \ CreateNewDelegationContractOutcome from multiversx_sdk.core.transactions_outcome_parsers.resources import ( TransactionEvent, TransactionOutcome, find_events_by_identifier) -from multiversx_sdk.network_providers.constants import DEFAULT_ADDRESS_HRP class DelegationTransactionsOutcomeParser: @@ -34,4 +34,4 @@ def _extract_contract_address(self, event: TransactionEvent) -> str: if not event.topics[0]: return "" - return Address(event.topics[0], DEFAULT_ADDRESS_HRP).to_bech32() + return Address(event.topics[0], LibraryConfig.default_address_hrp).to_bech32() diff --git a/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser.py b/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser.py index 8291ad9d..5052feb4 100644 --- a/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser.py +++ b/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser.py @@ -1,9 +1,9 @@ from multiversx_sdk.core.address import Address +from multiversx_sdk.core.config import LibraryConfig from multiversx_sdk.core.transactions_outcome_parsers.resources import ( TransactionEvent, TransactionOutcome, find_events_by_identifier) from multiversx_sdk.core.transactions_outcome_parsers.smart_contract_transactions_outcome_parser_types import ( DeployedSmartContract, SmartContractDeployOutcome) -from multiversx_sdk.network_providers.constants import DEFAULT_ADDRESS_HRP class SmartContractTransactionsOutcomeParser: @@ -22,8 +22,8 @@ def _parse_sc_deploy_event(self, event: TransactionEvent) -> DeployedSmartContra owner_address_topic = event.topics[1] if event.topics[1] else b'' code_hash_topic = event.topics[2] if event.topics[2] else b'' - contract_address = Address(contract_address_topic, DEFAULT_ADDRESS_HRP).to_bech32() if len(contract_address_topic) else "" - owner_address = Address(owner_address_topic, DEFAULT_ADDRESS_HRP).to_bech32() if len(owner_address_topic) else "" + contract_address = Address(contract_address_topic, LibraryConfig.default_address_hrp).to_bech32() if len(contract_address_topic) else "" + owner_address = Address(owner_address_topic, LibraryConfig.default_address_hrp).to_bech32() if len(owner_address_topic) else "" code_hash = code_hash_topic return DeployedSmartContract(contract_address, owner_address, code_hash) diff --git a/multiversx_sdk/core/transactions_outcome_parsers/token_management_transactions_outcome_parser.py b/multiversx_sdk/core/transactions_outcome_parsers/token_management_transactions_outcome_parser.py index ce21700a..f2748624 100644 --- a/multiversx_sdk/core/transactions_outcome_parsers/token_management_transactions_outcome_parser.py +++ b/multiversx_sdk/core/transactions_outcome_parsers/token_management_transactions_outcome_parser.py @@ -2,7 +2,7 @@ from multiversx_sdk.core.address import Address from multiversx_sdk.core.codec import decode_unsigned_number -from multiversx_sdk.core.constants import DEFAULT_HRP +from multiversx_sdk.core.config import LibraryConfig from multiversx_sdk.core.errors import ParseTransactionOutcomeError from multiversx_sdk.core.transactions_outcome_parsers.resources import ( TransactionEvent, TransactionOutcome, find_events_by_identifier) @@ -247,4 +247,4 @@ def _extract_address(self, event: TransactionEvent) -> str: if not event.topics[3]: return "" - return Address(event.topics[3], DEFAULT_HRP).to_bech32() + return Address(event.topics[3], LibraryConfig.default_address_hrp).to_bech32() diff --git a/multiversx_sdk/network_providers/api_network_provider.py b/multiversx_sdk/network_providers/api_network_provider.py index 9b5ff48b..ad414514 100644 --- a/multiversx_sdk/network_providers/api_network_provider.py +++ b/multiversx_sdk/network_providers/api_network_provider.py @@ -3,14 +3,11 @@ import requests from requests.auth import AuthBase -from multiversx_sdk.converters.transactions_converter import \ - TransactionsConverter from multiversx_sdk.network_providers.accounts import (AccountOnNetwork, GuardianData) from multiversx_sdk.network_providers.config import (DefaultPagination, NetworkProviderConfig) -from multiversx_sdk.network_providers.constants import (BASE_USER_AGENT, - DEFAULT_ADDRESS_HRP) +from multiversx_sdk.network_providers.constants import BASE_USER_AGENT from multiversx_sdk.network_providers.contract_query_requests import \ ContractQueryRequest from multiversx_sdk.network_providers.contract_query_response import \ @@ -33,7 +30,8 @@ from multiversx_sdk.network_providers.transaction_status import \ TransactionStatus from multiversx_sdk.network_providers.transactions import ( - ITransaction, TransactionInMempool, TransactionOnNetwork) + ITransaction, TransactionInMempool, TransactionOnNetwork, + transaction_to_dictionary) from multiversx_sdk.network_providers.user_agent import extend_user_agent from multiversx_sdk.network_providers.utils import decimal_to_padded_hex @@ -43,7 +41,7 @@ def __init__( self, url: str, auth: Union[AuthBase, None] = None, - address_hrp: str = DEFAULT_ADDRESS_HRP, + address_hrp: Optional[str] = None, config: Optional[NetworkProviderConfig] = None ) -> None: self.url = url @@ -173,8 +171,7 @@ def get_transaction_status(self, tx_hash: str) -> TransactionStatus: def send_transaction(self, transaction: ITransaction) -> str: url = 'transactions' - transactions_converter = TransactionsConverter() - response = self.do_post_generic(url, transactions_converter.transaction_to_dictionary(transaction)) + response = self.do_post_generic(url, transaction_to_dictionary(transaction)) tx_hash: str = response.get('txHash', '') return tx_hash diff --git a/multiversx_sdk/network_providers/constants.py b/multiversx_sdk/network_providers/constants.py index fbbbe0cb..c6e00bde 100644 --- a/multiversx_sdk/network_providers/constants.py +++ b/multiversx_sdk/network_providers/constants.py @@ -1,8 +1,12 @@ from multiversx_sdk.core.address import Address +# left for compatibility reasons; will be deleted in the future ESDT_CONTRACT_ADDRESS = Address.new_from_bech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u") + METACHAIN_ID = 4294967295 MAX_UINT64 = 18446744073709551615 + +# left for compatibility reasons; will be deleted in the future DEFAULT_ADDRESS_HRP = "erd" DEFAULT_TRANSACTION_AWAITING_POLLING_TIMEOUT_IN_MILLISECONDS = 6000 diff --git a/multiversx_sdk/network_providers/proxy_network_provider.py b/multiversx_sdk/network_providers/proxy_network_provider.py index 53deab4d..fbf3725c 100644 --- a/multiversx_sdk/network_providers/proxy_network_provider.py +++ b/multiversx_sdk/network_providers/proxy_network_provider.py @@ -4,14 +4,13 @@ import requests from requests.auth import AuthBase -from multiversx_sdk.converters.transactions_converter import \ - TransactionsConverter +from multiversx_sdk.core.address import Address +from multiversx_sdk.core.config import LibraryConfig +from multiversx_sdk.core.constants import ESDT_CONTRACT_ADDRESS_HEX from multiversx_sdk.network_providers.accounts import (AccountOnNetwork, GuardianData) from multiversx_sdk.network_providers.config import NetworkProviderConfig from multiversx_sdk.network_providers.constants import (BASE_USER_AGENT, - DEFAULT_ADDRESS_HRP, - ESDT_CONTRACT_ADDRESS, METACHAIN_ID) from multiversx_sdk.network_providers.contract_query_requests import \ ContractQueryRequest @@ -30,7 +29,7 @@ from multiversx_sdk.network_providers.transaction_status import \ TransactionStatus from multiversx_sdk.network_providers.transactions import ( - ITransaction, TransactionOnNetwork) + ITransaction, TransactionOnNetwork, transaction_to_dictionary) from multiversx_sdk.network_providers.user_agent import extend_user_agent @@ -39,13 +38,12 @@ def __init__( self, url: str, auth: Union[AuthBase, None] = None, - address_hrp: str = DEFAULT_ADDRESS_HRP, + address_hrp: Optional[str] = None, config: Optional[NetworkProviderConfig] = None ) -> None: self.url = url self.auth = auth - self.address_hrp = address_hrp - self.address_hrp = address_hrp or DEFAULT_ADDRESS_HRP + self.address_hrp = address_hrp or LibraryConfig.default_address_hrp self.config = config if config is not None else NetworkProviderConfig() self.user_agent_prefix = f"{BASE_USER_AGENT}/proxy" @@ -128,13 +126,11 @@ def get_transaction_status(self, tx_hash: str) -> TransactionStatus: return status def send_transaction(self, transaction: ITransaction) -> str: - transactions_converter = TransactionsConverter() - response = self.do_post_generic('transaction/send', transactions_converter.transaction_to_dictionary(transaction)) + response = self.do_post_generic('transaction/send', transaction_to_dictionary(transaction)) return response.get('txHash', '') def send_transactions(self, transactions: Sequence[ITransaction]) -> Tuple[int, Dict[str, str]]: - transactions_converter = TransactionsConverter() - transactions_as_dictionaries = [transactions_converter.transaction_to_dictionary(transaction) for transaction in transactions] + transactions_as_dictionaries = [transaction_to_dictionary(transaction) for transaction in transactions] response = self.do_post_generic('transaction/send-multiple', transactions_as_dictionaries) # Proxy and Observers have different response format: num_sent = response.get("numOfSentTxs", 0) or response.get("txsSent", 0) @@ -153,7 +149,7 @@ def get_definition_of_fungible_token(self, token_identifier: str) -> DefinitionO def __get_token_properties(self, identifier: str) -> List[bytes]: encoded_identifier = identifier.encode() - query = ContractQuery(ESDT_CONTRACT_ADDRESS, 'getTokenProperties', 0, [encoded_identifier]) + query = ContractQuery(Address.new_from_hex(ESDT_CONTRACT_ADDRESS_HEX, self.address_hrp), 'getTokenProperties', 0, [encoded_identifier]) query_response = self.query_contract(query) properties = query_response.get_return_data_parts() return properties @@ -165,8 +161,7 @@ def get_definition_of_token_collection(self, collection: str) -> DefinitionOfTok def simulate_transaction(self, transaction: ITransaction) -> SimulateResponse: url = "transaction/simulate" - transactions_converter = TransactionsConverter() - response = self.do_post_generic(url, transactions_converter.transaction_to_dictionary(transaction)) + response = self.do_post_generic(url, transaction_to_dictionary(transaction)) return SimulateResponse(response) def get_hyperblock(self, key: Union[int, str]) -> Dict[str, Any]: diff --git a/multiversx_sdk/network_providers/transactions.py b/multiversx_sdk/network_providers/transactions.py index 87ba3093..c1c94b10 100644 --- a/multiversx_sdk/network_providers/transactions.py +++ b/multiversx_sdk/network_providers/transactions.py @@ -1,5 +1,5 @@ import base64 -from typing import Any, Dict, Optional, Protocol +from typing import Any, Dict, Optional, Protocol, Union from multiversx_sdk.core.address import Address from multiversx_sdk.network_providers.contract_results import ContractResults @@ -202,3 +202,41 @@ def to_dictionary(self) -> Dict[str, Any]: "gasPrice": self.gas_price, "data": self.data } + + +# this is duplicated code, added here to get rid of a circular dependency +# will be removed in V1 +def transaction_to_dictionary(transaction: ITransaction) -> Dict[str, Any]: + return { + "nonce": transaction.nonce, + "value": str(transaction.value), + "receiver": transaction.receiver, + "sender": transaction.sender, + "senderUsername": _value_to_b64_or_empty(transaction.sender_username), + "receiverUsername": _value_to_b64_or_empty(transaction.receiver_username), + "gasPrice": transaction.gas_price, + "gasLimit": transaction.gas_limit, + "data": _value_to_b64_or_empty(transaction.data), + "chainID": transaction.chain_id, + "version": transaction.version, + "options": transaction.options, + "guardian": transaction.guardian, + "signature": _value_to_hex_or_empty(transaction.signature), + "guardianSignature": _value_to_hex_or_empty(transaction.guardian_signature), + "relayer": transaction.relayer, + "relayerSignature": _value_to_hex_or_empty(transaction.relayer_signature) + } + + +def _value_to_b64_or_empty(value: Union[str, bytes]) -> str: + value_as_bytes = value.encode() if isinstance(value, str) else value + + if len(value): + return base64.b64encode(value_as_bytes).decode() + return "" + + +def _value_to_hex_or_empty(value: bytes) -> str: + if len(value): + return value.hex() + return "" diff --git a/multiversx_sdk/wallet/user_keys.py b/multiversx_sdk/wallet/user_keys.py index 4a1bb3a3..ad7cf1c4 100644 --- a/multiversx_sdk/wallet/user_keys.py +++ b/multiversx_sdk/wallet/user_keys.py @@ -1,3 +1,5 @@ +from typing import Optional + import nacl.signing from multiversx_sdk.core.address import Address @@ -62,7 +64,7 @@ def verify(self, data: bytes, signature: ISignature) -> bool: except Exception: return False - def to_address(self, hrp: str) -> Address: + def to_address(self, hrp: Optional[str] = None) -> Address: return Address(self.buffer, hrp) def hex(self) -> str: diff --git a/multiversx_sdk/wallet/user_wallet.py b/multiversx_sdk/wallet/user_wallet.py index 4be3220d..6633f1e8 100644 --- a/multiversx_sdk/wallet/user_wallet.py +++ b/multiversx_sdk/wallet/user_wallet.py @@ -112,13 +112,11 @@ def to_json(self, address_hrp: Optional[str] = None) -> str: def to_dict(self, address_hrp: Optional[str] = None) -> Dict[str, Any]: if self.kind == UserWalletKind.SECRET_KEY.value: - if not address_hrp: - raise Exception("address_hrp must be provided when kind == 'secretKey'") return self._to_dict_when_kind_is_secret_key(address_hrp) return self._to_dict_when_kind_is_mnemonic() - def _to_dict_when_kind_is_secret_key(self, address_hrp: str) -> Dict[str, Any]: + def _to_dict_when_kind_is_secret_key(self, address_hrp: Optional[str] = None) -> Dict[str, Any]: if self.public_key_when_kind_is_secret_key is None: raise Exception("Public key isn't available") diff --git a/pyproject.toml b/pyproject.toml index ed92d33a..d7c8b60c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ allow-direct-references = true [project] name = "multiversx-sdk" -version = "0.18.0" +version = "0.19.0" authors = [ { name="MultiversX" }, ]