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 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)