tronpytool.main API documentation
Description: tronpytool.main …

# Module `tronpytool.main`

# tronpytool.main

Connect to the Tron network.

:copyright: © 2019 by the iEXBase. :license: MIT License

Expand source code

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # --------------------------------------------------------------------
    # Copyright (c) iEXBase. All rights reserved.
    # Licensed under the MIT License.
    # See License.txt in the project root for license information.
    # --------------------------------------------------------------------

    """
        tronpytool.main
        ===============

        Connect to the Tron network.

        :copyright: © 2019 by the iEXBase.
        :license: MIT License
    """

    from urllib.parse import urlencode

    from eth_account.datastructures import AttributeDict
    from eth_utils import (
        apply_to_return_value,
        keccak as tron_keccak,
    )
    from hexbytes import HexBytes
    from trx_utils import (
        to_sun,
        from_sun,
        is_integer,
        add_0x_prefix,
        remove_0x_prefix,
        is_address,
        to_hex
    )

    from tronpytool import constants
    from tronpytool.common.abi import map_abi_data
    from tronpytool.common.account import Address, PrivateKey, Account
    from tronpytool.common.encoding import (
        to_bytes,
        to_int,
        to_text,
        to_json,
        hex_encode_abi_type
    )
    from tronpytool.common.key import PrivateKey as PrivateKeyFactory
    from tronpytool.common.normalizers import abi_resolver
    from tronpytool.exceptions import (
        InvalidTronError,
        TronError
    )
    from tronpytool.manager import TronManager
    from tronpytool.transactionbuilder import TransactionBuilder
    from tronpytool.trx import Trx

    DEFAULT_MODULES = {
        'trx': Trx
    }

    class Tron:
        # Providers
        # SolcWrap = SolcWrap

        _default_block = None
        _private_key = None
        _default_address = AttributeDict({})

        # Encoding and Decoding
        toBytes = staticmethod(to_bytes)
        toInt = staticmethod(to_int)
        toHex = staticmethod(to_hex)
        toText = staticmethod(to_text)
        toJSON = staticmethod(to_json)

        # Currency Utility
        toSun = staticmethod(to_sun)
        fromSun = staticmethod(from_sun)

        # Validate address
        isAddress = staticmethod(is_address)

        def __init__(self, **kwargs):
            """Connect to the Tron network.

            Args:
                kwargs (Any): We fill the most necessary parameters
                for working with blockchain Tron

            """

            # We check the obtained nodes, if the necessary parameters
            # are not specified, then we take the default
            kwargs.setdefault('full_node', constants.DEFAULT_NODES['full_node'])
            kwargs.setdefault('solidity_node', constants.DEFAULT_NODES['solidity_node'])
            kwargs.setdefault('event_server', constants.DEFAULT_NODES['event_server'])

            # The node manager allows you to automatically determine the node
            # on the router or manually refer to a specific node.
            # solidity_node, full_node or event_server
            self.manager = TronManager(self, dict(
                full_node=kwargs.get('full_node'),
                solidity_node=kwargs.get('solidity_node'),
                event_server=kwargs.get('event_server')
            ))

            # If the parameter of the private key is not empty,
            # then write to the variable
            if 'private_key' in kwargs:
                self.private_key = kwargs.get('private_key')

            # We check whether the default wallet address is set when
            # defining the class, and then written to the variable
            if 'default_address' in kwargs:
                self.default_address = kwargs.get('default_address')

            # If custom methods are not declared,
            # we take the default from the list
            modules = kwargs.setdefault('modules', DEFAULT_MODULES)
            for module_name, module_class in modules.items():
                module_class.attach(self, module_name)

            self.transaction_builder = TransactionBuilder(self)

        def setNetwork(self, networkname="nile"):
            group = constants.conf_for_name(networkname)
            self.manager = TronManager(self, constants.to_providers_set(group))
            return self

        @property
        def default_block(self):
            return self._default_block

        @default_block.setter
        def default_block(self, block_id):
            """Sets the default block used as a reference for all future calls."""
            if block_id in ('latest', 'earliest', 0):
                self._default_block = block_id
                return

            if not is_integer(block_id) or not block_id:
                raise ValueError('Invalid block ID provided')

            self._default_block = abs(block_id)

        @property
        def providers(self):
            """List providers"""
            return self.manager.providers

        @property
        def private_key(self) -> str:
            """Get a private key"""
            return self._private_key

        def getKey(self) -> "PrivateKey":
            return self.private_key_class

        @private_key.setter
        def private_key(self, value: str) -> None:
            """Set a private key used with the TronAPI instance,
            used for obtaining the address, signing transactions etc...

            Args:
                value (str): Private key
            """
            try:
                private_key = PrivateKey(value)
            except ValueError:
                raise TronError('Invalid private key provided')
            self.private_key_class = private_key
            self._private_key = str(private_key).lower()

        @property
        def default_address(self) -> AttributeDict:
            """Get a TRON Address"""
            return self._default_address

        @default_address.setter
        def default_address(self, address: str) -> None:
            """Sets the address used with all Tron API.
            Will not sign any transactions.

            Args:
                 address (str) Tron Address

            """

            if not self.isAddress(address):
                raise InvalidTronError('Invalid address provided')

            _hex = self.address.to_hex(address)
            _base58 = self.address.from_hex(address)
            _private_base58 = self.address.from_private_key(self._private_key).base58

            # check the addresses
            if self._private_key and _private_base58 != _base58:
                self._private_key = None

            self._default_address = AttributeDict({
                'hex': _hex,
                'base58': _base58
            })

        def get_event_result(self, **kwargs):
            """Will return all events matching the filters.

            Args:
                kwargs (any): List parameters
            """

            # Check the most necessary parameters
            since_timestamp = kwargs.setdefault('since_timestamp', 0)
            event_name = kwargs.setdefault('event_name', 'Notify')
            block_number = kwargs.setdefault('block_number', '')
            size = kwargs.setdefault('size', 20)
            page = kwargs.setdefault('page', 1)
            only_confirmed = kwargs.setdefault('only_confirmed', None)
            only_unconfirmed = kwargs.setdefault('only_unconfirmed', None)
            previous_last = kwargs.setdefault('previous_last_event_fingerprint', None)
            contract_address = kwargs.setdefault('contract_address', self.default_address.hex)
            sort = kwargs.setdefault('sort', None)
            from_timestamp = kwargs.setdefault('from_timestamp', None)

            if not self.isAddress(contract_address):
                raise InvalidTronError('Invalid contract address provided')

            if event_name and not contract_address:
                raise TronError('Usage of event name filtering requires a contract address')

            if block_number and event_name is None:
                raise TronError('Usage of block number filtering requires an event name')

            if not is_integer(page):
                raise ValueError('Invalid size provided')

            if not is_integer(since_timestamp):
                raise ValueError('Invalid sinceTimestamp provided')

            # If the size exceeds 200, displays an error
            if size > 200:
                raise ValueError('Defaulting to maximum accepted size: 200')

            # We collect all parameters in one array
            route_params = []
            if contract_address:
                route_params.append(contract_address)
            if event_name:
                route_params.append(event_name)
            if block_number:
                route_params.append(block_number)

            route = '/'.join(route_params)

            qs = {
                'since': since_timestamp,
                'page': page,
                'size': size
            }

            if only_confirmed is not None:
                qs.update({'onlyConfirmed': only_confirmed})

            if only_unconfirmed is not None and not only_confirmed:
                qs.update({'onlyUnconfirmed': only_unconfirmed})

            if previous_last is not None:
                qs.update({'previousLastEventFingerprint': previous_last})

            if from_timestamp is not None:
                qs.update({'fromTimestamp': from_timestamp})

            if sort is not None:
                qs.update({'sort': sort})

            return self.manager.request("/event/contract/{0}?{1}"
                                        .format(route, urlencode(qs)), method='get')

        def get_event_transaction_id(self, tx_id):
            """Will return all events within a transactionID.

            Args:
                tx_id (str): TransactionID to query for events.
            """
            response = self.manager.request('/event/transaction/' + tx_id, method='get')
            return response

        @property
        def address(self) -> Address:
            """Helper object that allows you to convert
            between hex/base58 and private key representations of a TRON address.

            Note:
                If you wish to convert generic data to hexadecimal strings,
                please use the function tron.to_hex.
                return a static class
            """
            return Address()

        # Address utilities
        @staticmethod
        def generate_address(priv_key=None) -> dict:
            """Address utilities Generate a random address."""
            if priv_key is None:
                priv_key = PrivateKeyFactory.random()
            return {
                "base58check_address": priv_key.public_key.to_base58check_address(),
                "hex_address": priv_key.public_key.to_hex_address(),
                "private_key": priv_key.hex(),
                "public_key": priv_key.public_key.hex(),
            }

        def get_address_from_passphrase(self, passphrase: str) -> dict:
            """Get an address from a passphrase, compatiable with `wallet/createaddress`."""
            priv_key = PrivateKeyFactory.from_passphrase(passphrase.encode())
            return self.generate_address(priv_key)

        @staticmethod
        def create_account() -> PrivateKey:
            """Create account

            Warning: Please control risks when using this API.
            To ensure environmental security, please do not invoke APIs
            provided by other or invoke this very API on a public network.

            """
            return Account.create()

        def solidity_sha3(self, abi_types, values):
            """
                Executes keccak256 exactly as Solidity does.
                Takes list of abi_types as inputs -- `[uint24, int8[], bool]`
                and list of corresponding values  -- `[20, [-1, 5, 0], True]`

                Args:
                    abi_types (any): types abi
                    values (any): values

                Examples:
                    >>> tron = Tron()
                    >>> sol = tron.solidity_sha3(['uint8[]'], [[1, 2, 3, 4, 5]])
                    >>> assert sol.hex() == '0x5917e5a395fb9b454434de59651d36822a9e29c5ec57474df3e67937b969460c'

            """
            if len(abi_types) != len(values):
                raise ValueError(
                    "Length mismatch between provided abi types and values.  Got "
                    "{0} types and {1} values.".format(len(abi_types), len(values))
                )

            normalized_values = map_abi_data([abi_resolver()], abi_types, values)

            hex_string = add_0x_prefix(''.join(
                remove_0x_prefix(hex_encode_abi_type(abi_type, value))
                for abi_type, value
                in zip(abi_types, normalized_values)
            ))
            return self.keccak(hexstr=hex_string)

        @staticmethod
        @apply_to_return_value(HexBytes)
        def keccak(primitive=None, text=None, hexstr=None):
            if isinstance(primitive, (bytes, int, type(None))):
                input_bytes = to_bytes(primitive, hexstr=hexstr, text=text)
                return tron_keccak(input_bytes)

            raise TypeError(
                "You called keccak with first arg %r and keywords %r. You must call it with one of "
                "these approaches: keccak(text='txt'), keccak(hexstr='0x747874'), "
                "keccak(b'\\x74\\x78\\x74'), or keccak(0x747874)." % (
                    primitive,
                    {'text': text, 'hexstr': hexstr}
                )
            )

        def is_connected(self):
            """List of available providers"""
            return self.manager.is_connected()

## Classes

`class Tron (**kwargs)`

  Connect to the Tron network.

  ## Args

  `kwargs` :`Any`
    We fill the most necessary parameters

  for working with blockchain Tron

  Expand source code

      class Tron:
          # Providers
          # SolcWrap = SolcWrap

          _default_block = None
          _private_key = None
          _default_address = AttributeDict({})

          # Encoding and Decoding
          toBytes = staticmethod(to_bytes)
          toInt = staticmethod(to_int)
          toHex = staticmethod(to_hex)
          toText = staticmethod(to_text)
          toJSON = staticmethod(to_json)

          # Currency Utility
          toSun = staticmethod(to_sun)
          fromSun = staticmethod(from_sun)

          # Validate address
          isAddress = staticmethod(is_address)

          def __init__(self, **kwargs):
              """Connect to the Tron network.

              Args:
                  kwargs (Any): We fill the most necessary parameters
                  for working with blockchain Tron

              """

              # We check the obtained nodes, if the necessary parameters
              # are not specified, then we take the default
              kwargs.setdefault('full_node', constants.DEFAULT_NODES['full_node'])
              kwargs.setdefault('solidity_node', constants.DEFAULT_NODES['solidity_node'])
              kwargs.setdefault('event_server', constants.DEFAULT_NODES['event_server'])

              # The node manager allows you to automatically determine the node
              # on the router or manually refer to a specific node.
              # solidity_node, full_node or event_server
              self.manager = TronManager(self, dict(
                  full_node=kwargs.get('full_node'),
                  solidity_node=kwargs.get('solidity_node'),
                  event_server=kwargs.get('event_server')
              ))

              # If the parameter of the private key is not empty,
              # then write to the variable
              if 'private_key' in kwargs:
                  self.private_key = kwargs.get('private_key')

              # We check whether the default wallet address is set when
              # defining the class, and then written to the variable
              if 'default_address' in kwargs:
                  self.default_address = kwargs.get('default_address')

              # If custom methods are not declared,
              # we take the default from the list
              modules = kwargs.setdefault('modules', DEFAULT_MODULES)
              for module_name, module_class in modules.items():
                  module_class.attach(self, module_name)

              self.transaction_builder = TransactionBuilder(self)

          def setNetwork(self, networkname="nile"):
              group = constants.conf_for_name(networkname)
              self.manager = TronManager(self, constants.to_providers_set(group))
              return self

          @property
          def default_block(self):
              return self._default_block

          @default_block.setter
          def default_block(self, block_id):
              """Sets the default block used as a reference for all future calls."""
              if block_id in ('latest', 'earliest', 0):
                  self._default_block = block_id
                  return

              if not is_integer(block_id) or not block_id:
                  raise ValueError('Invalid block ID provided')

              self._default_block = abs(block_id)

          @property
          def providers(self):
              """List providers"""
              return self.manager.providers

          @property
          def private_key(self) -> str:
              """Get a private key"""
              return self._private_key

          def getKey(self) -> "PrivateKey":
              return self.private_key_class

          @private_key.setter
          def private_key(self, value: str) -> None:
              """Set a private key used with the TronAPI instance,
              used for obtaining the address, signing transactions etc...

              Args:
                  value (str): Private key
              """
              try:
                  private_key = PrivateKey(value)
              except ValueError:
                  raise TronError('Invalid private key provided')
              self.private_key_class = private_key
              self._private_key = str(private_key).lower()

          @property
          def default_address(self) -> AttributeDict:
              """Get a TRON Address"""
              return self._default_address

          @default_address.setter
          def default_address(self, address: str) -> None:
              """Sets the address used with all Tron API.
              Will not sign any transactions.

              Args:
                   address (str) Tron Address

              """

              if not self.isAddress(address):
                  raise InvalidTronError('Invalid address provided')

              _hex = self.address.to_hex(address)
              _base58 = self.address.from_hex(address)
              _private_base58 = self.address.from_private_key(self._private_key).base58

              # check the addresses
              if self._private_key and _private_base58 != _base58:
                  self._private_key = None

              self._default_address = AttributeDict({
                  'hex': _hex,
                  'base58': _base58
              })

          def get_event_result(self, **kwargs):
              """Will return all events matching the filters.

              Args:
                  kwargs (any): List parameters
              """

              # Check the most necessary parameters
              since_timestamp = kwargs.setdefault('since_timestamp', 0)
              event_name = kwargs.setdefault('event_name', 'Notify')
              block_number = kwargs.setdefault('block_number', '')
              size = kwargs.setdefault('size', 20)
              page = kwargs.setdefault('page', 1)
              only_confirmed = kwargs.setdefault('only_confirmed', None)
              only_unconfirmed = kwargs.setdefault('only_unconfirmed', None)
              previous_last = kwargs.setdefault('previous_last_event_fingerprint', None)
              contract_address = kwargs.setdefault('contract_address', self.default_address.hex)
              sort = kwargs.setdefault('sort', None)
              from_timestamp = kwargs.setdefault('from_timestamp', None)

              if not self.isAddress(contract_address):
                  raise InvalidTronError('Invalid contract address provided')

              if event_name and not contract_address:
                  raise TronError('Usage of event name filtering requires a contract address')

              if block_number and event_name is None:
                  raise TronError('Usage of block number filtering requires an event name')

              if not is_integer(page):
                  raise ValueError('Invalid size provided')

              if not is_integer(since_timestamp):
                  raise ValueError('Invalid sinceTimestamp provided')

              # If the size exceeds 200, displays an error
              if size > 200:
                  raise ValueError('Defaulting to maximum accepted size: 200')

              # We collect all parameters in one array
              route_params = []
              if contract_address:
                  route_params.append(contract_address)
              if event_name:
                  route_params.append(event_name)
              if block_number:
                  route_params.append(block_number)

              route = '/'.join(route_params)

              qs = {
                  'since': since_timestamp,
                  'page': page,
                  'size': size
              }

              if only_confirmed is not None:
                  qs.update({'onlyConfirmed': only_confirmed})

              if only_unconfirmed is not None and not only_confirmed:
                  qs.update({'onlyUnconfirmed': only_unconfirmed})

              if previous_last is not None:
                  qs.update({'previousLastEventFingerprint': previous_last})

              if from_timestamp is not None:
                  qs.update({'fromTimestamp': from_timestamp})

              if sort is not None:
                  qs.update({'sort': sort})

              return self.manager.request("/event/contract/{0}?{1}"
                                          .format(route, urlencode(qs)), method='get')

          def get_event_transaction_id(self, tx_id):
              """Will return all events within a transactionID.

              Args:
                  tx_id (str): TransactionID to query for events.
              """
              response = self.manager.request('/event/transaction/' + tx_id, method='get')
              return response

          @property
          def address(self) -> Address:
              """Helper object that allows you to convert
              between hex/base58 and private key representations of a TRON address.

              Note:
                  If you wish to convert generic data to hexadecimal strings,
                  please use the function tron.to_hex.
                  return a static class
              """
              return Address()

          # Address utilities
          @staticmethod
          def generate_address(priv_key=None) -> dict:
              """Address utilities Generate a random address."""
              if priv_key is None:
                  priv_key = PrivateKeyFactory.random()
              return {
                  "base58check_address": priv_key.public_key.to_base58check_address(),
                  "hex_address": priv_key.public_key.to_hex_address(),
                  "private_key": priv_key.hex(),
                  "public_key": priv_key.public_key.hex(),
              }

          def get_address_from_passphrase(self, passphrase: str) -> dict:
              """Get an address from a passphrase, compatiable with `wallet/createaddress`."""
              priv_key = PrivateKeyFactory.from_passphrase(passphrase.encode())
              return self.generate_address(priv_key)

          @staticmethod
          def create_account() -> PrivateKey:
              """Create account

              Warning: Please control risks when using this API.
              To ensure environmental security, please do not invoke APIs
              provided by other or invoke this very API on a public network.

              """
              return Account.create()

          def solidity_sha3(self, abi_types, values):
              """
                  Executes keccak256 exactly as Solidity does.
                  Takes list of abi_types as inputs -- `[uint24, int8[], bool]`
                  and list of corresponding values  -- `[20, [-1, 5, 0], True]`

                  Args:
                      abi_types (any): types abi
                      values (any): values

                  Examples:
                      >>> tron = Tron()
                      >>> sol = tron.solidity_sha3(['uint8[]'], [[1, 2, 3, 4, 5]])
                      >>> assert sol.hex() == '0x5917e5a395fb9b454434de59651d36822a9e29c5ec57474df3e67937b969460c'

              """
              if len(abi_types) != len(values):
                  raise ValueError(
                      "Length mismatch between provided abi types and values.  Got "
                      "{0} types and {1} values.".format(len(abi_types), len(values))
                  )

              normalized_values = map_abi_data([abi_resolver()], abi_types, values)

              hex_string = add_0x_prefix(''.join(
                  remove_0x_prefix(hex_encode_abi_type(abi_type, value))
                  for abi_type, value
                  in zip(abi_types, normalized_values)
              ))
              return self.keccak(hexstr=hex_string)

          @staticmethod
          @apply_to_return_value(HexBytes)
          def keccak(primitive=None, text=None, hexstr=None):
              if isinstance(primitive, (bytes, int, type(None))):
                  input_bytes = to_bytes(primitive, hexstr=hexstr, text=text)
                  return tron_keccak(input_bytes)

              raise TypeError(
                  "You called keccak with first arg %r and keywords %r. You must call it with one of "
                  "these approaches: keccak(text='txt'), keccak(hexstr='0x747874'), "
                  "keccak(b'\\x74\\x78\\x74'), or keccak(0x747874)." % (
                      primitive,
                      {'text': text, 'hexstr': hexstr}
                  )
              )

          def is_connected(self):
              """List of available providers"""
              return self.manager.is_connected()

  ### Static methods

  `def create_account() ‑> PrivateKey`

    Create account

    Warning: Please control risks when using this API. To ensure environmental security, please do not invoke APIs provided by other or invoke this very API on a public network.

    Expand source code

        @staticmethod
        def create_account() -> PrivateKey:
            """Create account

            Warning: Please control risks when using this API.
            To ensure environmental security, please do not invoke APIs
            provided by other or invoke this very API on a public network.

            """
            return Account.create()

  `def fromSun(number: int) ‑> Union[int, decimal.Decimal]`

    Helper function that will convert a value in SUN to TRX.

    ## Args

    `number` :`int`
      Value in SUN to convert to TRX
    Expand source code

        def from_sun(number: int) -> Union[int, decimal.Decimal]:
            """Helper function that will convert a value in SUN to TRX.

            Args:
                number (int): Value in SUN to convert to TRX

            """
            if number == 0:
                return 0

            if number < MIN_SUN or number > MAX_SUN:
                raise ValueError("value must be between 1 and 2**256 - 1")

            unit_value = UNITS['sun']

            with localcontext() as ctx:
                ctx.prec = 999
                d_number = decimal.Decimal(value=number, context=ctx)
                result_value = d_number / unit_value

            return result_value

  `def generate_address(priv_key=None) ‑> dict`

    Address utilities Generate a random address.

    Expand source code

        @staticmethod
        def generate_address(priv_key=None) -> dict:
            """Address utilities Generate a random address."""
            if priv_key is None:
                priv_key = PrivateKeyFactory.random()
            return {
                "base58check_address": priv_key.public_key.to_base58check_address(),
                "hex_address": priv_key.public_key.to_hex_address(),
                "private_key": priv_key.hex(),
                "public_key": priv_key.public_key.hex(),
            }

  `def isAddress(value: str) ‑> bool`

    Checks if the given string in a supported value is an address in any of the known formats.

    ## Args

    `value` :`str`
      Address
    Expand source code

        def is_address(value: str) -> bool:
            """Checks if the given string in a supported value is an address
            in any of the known formats.
            Args:
                value (str): Address
            """
            if is_checksum_address(value):
                return True
            elif is_hex_address(value):
                return True

            return False

  `def keccak(primitive=None, text=None, hexstr=None)`
    Expand source code

        @staticmethod
        @apply_to_return_value(HexBytes)
        def keccak(primitive=None, text=None, hexstr=None):
            if isinstance(primitive, (bytes, int, type(None))):
                input_bytes = to_bytes(primitive, hexstr=hexstr, text=text)
                return tron_keccak(input_bytes)

            raise TypeError(
                "You called keccak with first arg %r and keywords %r. You must call it with one of "
                "these approaches: keccak(text='txt'), keccak(hexstr='0x747874'), "
                "keccak(b'\\x74\\x78\\x74'), or keccak(0x747874)." % (
                    primitive,
                    {'text': text, 'hexstr': hexstr}
                )
            )

  `def toBytes(primitive=None, hexstr=None, text=None)`
    Expand source code

        def to_bytes(primitive=None, hexstr=None, text=None):
            assert_one_val(primitive, hexstr=hexstr, text=text)

            if is_boolean(primitive):
                return b'\x01' if primitive else b'\x00'
            elif isinstance(primitive, bytes):
                return primitive
            elif is_integer(primitive):
                return to_bytes(hexstr=to_hex(primitive))
            elif hexstr is not None:
                if len(hexstr) % 2:
                    hexstr = '0x0' + remove_0x_prefix(hexstr)
                return decode_hex(hexstr)
            elif text is not None:
                return text.encode('utf-8')
            raise TypeError("expected an int in first arg, or keyword of hexstr or text")

  `def toHex(primitive: Union[bytes, int, bool] = None, hexstr: .new_type at 0x7ff648077310> = None, text: str = None) ‑> .new_type at 0x7ff648077310>`

    Auto converts any supported value into its hex representation. Trims leading zeros, as defined in: https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding

    Expand source code

        @validate_conversion_arguments
        def to_hex(
                primitive: Primitives = None, hexstr: HexStr = None, text: str = None
        ) -> HexStr:
            """
            Auto converts any supported value into its hex representation.
            Trims leading zeros, as defined in:
            https://github.com/ethereum/wiki/wiki/JSON-RPC#hex-value-encoding
            """
            if hexstr is not None:
                return HexStr(add_0x_prefix(hexstr.lower()))

            if text is not None:
                return HexStr(encode_hex(text.encode("utf-8")))

            if is_boolean(primitive):
                return HexStr("0x1") if primitive else HexStr("0x0")

            if isinstance(primitive, (bytes, bytearray)):
                return HexStr(encode_hex(primitive))
            elif is_string(primitive):
                raise TypeError(
                    "Unsupported type: The primitive argument must be one of: bytes,"
                    "bytearray, int or bool and not str"
                )

            if is_integer(primitive):
                return HexStr(hex(primitive))

            raise TypeError(
                "Unsupported type: '{0}'.  Must be one of: bool, str, bytes, bytearray"
                "or int.".format(repr(type(primitive)))
            )

  `def toInt(value=None, hexstr=None, text=None)`

    Converts value to it's integer representation.

    Values are converted this way:

    - value:
    - bytes: big-endian integer
    - bool: True => 1, False => 0
    - hexstr: interpret hex as integer
    - text: interpret as string of digits, like '12' => 12
    Expand source code

        def to_int(value=None, hexstr=None, text=None):
            """Converts value to it's integer representation.

            Values are converted this way:

             * value:
               * bytes: big-endian integer
               * bool: True => 1, False => 0
             * hexstr: interpret hex as integer
             * text: interpret as string of digits, like '12' => 12
            """
            assert_one_val(value, hexstr=hexstr, text=text)

            if hexstr is not None:
                return int(hexstr, 16)
            elif text is not None:
                return int(text)
            elif isinstance(value, bytes):
                return big_endian_to_int(value)
            elif isinstance(value, str):
                raise TypeError("Pass in strings with keyword hexstr or text")
            else:
                return int(value)

  `def toJSON(obj: object) ‑> object`

    Convert a complex object (like a transaction object) to a JSON string

    Expand source code

        def to_json(obj: object) -> object:
            """Convert a complex object (like a transaction object) to a JSON string"""
            return FriendlyJsonSerialize().json_encode(obj, cls=TronJsonEncoder)

  `def toSun(number: int) ‑> int`

    Helper function that will convert a value in TRX to SUN.

    ## Args

    `number` :`int`
      Value in TRX to convert to SUN
    Expand source code

        def to_sun(number: int) -> int:
            """Helper function that will convert a value in TRX to SUN.

            Args:
                number (int): Value in TRX to convert to SUN

            """
            if is_integer(number) or is_string(number):
                d_number = decimal.Decimal(value=number)
            elif isinstance(number, float):
                d_number = decimal.Decimal(value=str(number))
            elif isinstance(number, decimal.Decimal):
                d_number = number
            else:
                raise TypeError("Unsupported type.  Must be one of integer, float, or string")

            s_number = str(number)
            unit_value = UNITS['sun']

            if d_number == 0:
                return 0

            if d_number < 1 and '.' in s_number:
                with localcontext() as ctx:
                    multiplier = len(s_number) - s_number.index('.') - 1
                    ctx.prec = multiplier
                    d_number = decimal.Decimal(value=number, context=ctx) * 10 ** multiplier
                unit_value /= 10 ** multiplier

            with localcontext() as ctx:
                ctx.prec = 999
                result_value = decimal.Decimal(value=d_number, context=ctx) * unit_value

            if result_value < MIN_SUN or result_value > MAX_SUN:
                raise ValueError("Resulting wei value must be between 1 and 2**256 - 1")

            return int(result_value)

  `def toText(primitive=None, hexstr=None, text=None)`
    Expand source code

        def to_text(primitive=None, hexstr=None, text=None):
            assert_one_val(primitive, hexstr=hexstr, text=text)

            if hexstr is not None:
                return to_bytes(hexstr=hexstr).decode('utf-8')
            elif text is not None:
                return text
            elif isinstance(primitive, str):
                return to_text(hexstr=primitive)
            elif isinstance(primitive, bytes):
                return primitive.decode('utf-8')
            elif is_integer(primitive):
                byte_encoding = int_to_big_endian(primitive)
                return to_text(byte_encoding)
            raise TypeError("Expected an int, bytes or hexstr.")

  ### Instance variables

  `var address : Address`

    Helper object that allows you to convert between hex/base58 and private key representations of a TRON address.

    ## Note

    If you wish to convert generic data to hexadecimal strings, please use the function tron.to_hex. return a static class

    Expand source code

        @property
        def address(self) -> Address:
            """Helper object that allows you to convert
            between hex/base58 and private key representations of a TRON address.

            Note:
                If you wish to convert generic data to hexadecimal strings,
                please use the function tron.to_hex.
                return a static class
            """
            return Address()

  `var default_address : eth_account.datastructures.AttributeDict`

    Get a TRON Address

    Expand source code

        @property
        def default_address(self) -> AttributeDict:
            """Get a TRON Address"""
            return self._default_address

  `var default_block`
    Expand source code

        @property
        def default_block(self):
            return self._default_block

  `var private_key : str`

    Get a private key

    Expand source code

        @property
        def private_key(self) -> str:
            """Get a private key"""
            return self._private_key

  `var providers`

    List providers

    Expand source code

        @property
        def providers(self):
            """List providers"""
            return self.manager.providers

  ### Methods

  `def getKey(self) ‑> PrivateKey`
    Expand source code

        def getKey(self) -> "PrivateKey":
            return self.private_key_class

  `def get_address_from_passphrase(self, passphrase: str) ‑> dict`

    Get an address from a passphrase, compatiable with `wallet/createaddress`.

    Expand source code

        def get_address_from_passphrase(self, passphrase: str) -> dict:
            """Get an address from a passphrase, compatiable with `wallet/createaddress`."""
            priv_key = PrivateKeyFactory.from_passphrase(passphrase.encode())
            return self.generate_address(priv_key)

  `def get_event_result(self, **kwargs)`

    Will return all events matching the filters.

    ## Args

    `kwargs` :`any`
      List parameters
    Expand source code

        def get_event_result(self, **kwargs):
            """Will return all events matching the filters.

            Args:
                kwargs (any): List parameters
            """

            # Check the most necessary parameters
            since_timestamp = kwargs.setdefault('since_timestamp', 0)
            event_name = kwargs.setdefault('event_name', 'Notify')
            block_number = kwargs.setdefault('block_number', '')
            size = kwargs.setdefault('size', 20)
            page = kwargs.setdefault('page', 1)
            only_confirmed = kwargs.setdefault('only_confirmed', None)
            only_unconfirmed = kwargs.setdefault('only_unconfirmed', None)
            previous_last = kwargs.setdefault('previous_last_event_fingerprint', None)
            contract_address = kwargs.setdefault('contract_address', self.default_address.hex)
            sort = kwargs.setdefault('sort', None)
            from_timestamp = kwargs.setdefault('from_timestamp', None)

            if not self.isAddress(contract_address):
                raise InvalidTronError('Invalid contract address provided')

            if event_name and not contract_address:
                raise TronError('Usage of event name filtering requires a contract address')

            if block_number and event_name is None:
                raise TronError('Usage of block number filtering requires an event name')

            if not is_integer(page):
                raise ValueError('Invalid size provided')

            if not is_integer(since_timestamp):
                raise ValueError('Invalid sinceTimestamp provided')

            # If the size exceeds 200, displays an error
            if size > 200:
                raise ValueError('Defaulting to maximum accepted size: 200')

            # We collect all parameters in one array
            route_params = []
            if contract_address:
                route_params.append(contract_address)
            if event_name:
                route_params.append(event_name)
            if block_number:
                route_params.append(block_number)

            route = '/'.join(route_params)

            qs = {
                'since': since_timestamp,
                'page': page,
                'size': size
            }

            if only_confirmed is not None:
                qs.update({'onlyConfirmed': only_confirmed})

            if only_unconfirmed is not None and not only_confirmed:
                qs.update({'onlyUnconfirmed': only_unconfirmed})

            if previous_last is not None:
                qs.update({'previousLastEventFingerprint': previous_last})

            if from_timestamp is not None:
                qs.update({'fromTimestamp': from_timestamp})

            if sort is not None:
                qs.update({'sort': sort})

            return self.manager.request("/event/contract/{0}?{1}"
                                        .format(route, urlencode(qs)), method='get')

  `def get_event_transaction_id(self, tx_id)`

    Will return all events within a transactionID.

    ## Args

    `tx_id` :`str`
      TransactionID to query for events.
    Expand source code

        def get_event_transaction_id(self, tx_id):
            """Will return all events within a transactionID.

            Args:
                tx_id (str): TransactionID to query for events.
            """
            response = self.manager.request('/event/transaction/' + tx_id, method='get')
            return response

  `def is_connected(self)`

    List of available providers

    Expand source code

        def is_connected(self):
            """List of available providers"""
            return self.manager.is_connected()

  `def setNetwork(self, networkname='nile')`
    Expand source code

        def setNetwork(self, networkname="nile"):
            group = constants.conf_for_name(networkname)
            self.manager = TronManager(self, constants.to_providers_set(group))
            return self

  `def solidity_sha3(self, abi_types, values)`

    Executes keccak256 exactly as Solidity does. Takes list of abi_types as inputs – `[uint24, int8[], bool]` and list of corresponding values – `[20, [-1, 5, 0], True]`

    ## Args

    `abi_types` :`any`
      types abi
    `values` :`any`
      values

    ## Examples

        >>> tron = Tron()
        >>> sol = tron.solidity_sha3(['uint8[]'], [[1, 2, 3, 4, 5]])
        >>> assert sol.hex() == '0x5917e5a395fb9b454434de59651d36822a9e29c5ec57474df3e67937b969460c'

    Expand source code

        def solidity_sha3(self, abi_types, values):
            """
                Executes keccak256 exactly as Solidity does.
                Takes list of abi_types as inputs -- `[uint24, int8[], bool]`
                and list of corresponding values  -- `[20, [-1, 5, 0], True]`

                Args:
                    abi_types (any): types abi
                    values (any): values

                Examples:
                    >>> tron = Tron()
                    >>> sol = tron.solidity_sha3(['uint8[]'], [[1, 2, 3, 4, 5]])
                    >>> assert sol.hex() == '0x5917e5a395fb9b454434de59651d36822a9e29c5ec57474df3e67937b969460c'

            """
            if len(abi_types) != len(values):
                raise ValueError(
                    "Length mismatch between provided abi types and values.  Got "
                    "{0} types and {1} values.".format(len(abi_types), len(values))
                )

            normalized_values = map_abi_data([abi_resolver()], abi_types, values)

            hex_string = add_0x_prefix(''.join(
                remove_0x_prefix(hex_encode_abi_type(abi_type, value))
                for abi_type, value
                in zip(abi_types, normalized_values)
            ))
            return self.keccak(hexstr=hex_string)