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 0x7fa470627310> = None, text: str = None) ‑> .new_type at 0x7fa470627310>

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 addressAddress

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)