tronpytool.trx API documentation
Description: tronpytool.trx …

# Module `tronpytool.trx`

# tronpytool.trx

Work with basic methods

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

Expand source code

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

    """
        tronpytool.trx
        ===============

        Work with basic methods

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

    import math
    from typing import Any

    from trx_utils import is_integer, is_hex
    from trx_utils.types import is_object, is_string, is_list

    from tronpytool.common import key
    from tronpytool.common.account import Account
    from tronpytool.common.blocks import select_method_for_block
    from tronpytool.common.toolz import (
        assoc
    )
    from tronpytool.common.transactions import wait_for_transaction_id
    from tronpytool.contract import Contract
    from tronpytool.exceptions import InvalidTronError, TronError, TimeExhausted, AssetNotFound
    from tronpytool.module import Module

    TRX_MESSAGE_HEADER = '\x19TRON Signed Message:\n'
    ETH_MESSAGE_HEADER = '\x19Ethereum Signed Message:\n'

    class Trx(Module):
        default_contract_factory = Contract

        def get_current_block(self):
            """Query the latest block"""
            return self.tron.manager.request(url='/wallet/getnowblock')

        def get_confirmed_current_block(self):
            """Query the confirmed latest block"""
            return self.tron.manager.request('/walletsolidity/getnowblock')

        def get_block(self, block: Any = None):
            """Get block details using HashString or blockNumber

            Args:
                block (Any): ID or height for the block

            """

            # If the block identifier is not specified,
            # we take the default
            if block is None:
                block = self.tron.default_block

            if block == 'latest':
                return self.get_current_block()
            elif block == 'earliest':
                return self.get_block(0)

            method = select_method_for_block(
                block,
                if_hash={'url': '/wallet/getblockbyid', 'field': 'value'},
                if_number={'url': '/wallet/getblockbynum', 'field': 'num'},
            )

            result = self.tron.manager.request(method['url'], {
                method['field']: block
            })

            if result:
                return result
            return ValueError("The call to {method['url']} did not return a value.")

        def get_transaction_count_by_blocknum(self, num: int):
            """Query transaction's count on a specified block by height

            Args:
                num (int): block number
            """
            if not is_integer(num) or num < 0:
                raise ValueError('Invalid num provider')

            return self.tron.manager.request('/wallet/gettransactioncountbyblocknum', {
                'num': num
            })

        def get_block_transaction_count(self, block: Any):
            """Total number of transactions in a block

            Args:
                block (Any): Number or Hash Block

            """
            transaction = self.get_block(block)
            if 'transactions' not in transaction:
                raise TronError('Parameter "transactions" not found')

            return len(transaction)

        def get_transaction_from_block(self, block: Any, index: int = 0):
            """Get transaction details from Block

            Args:
                block (Any): Number or Hash Block
                index (int) Position

            """
            if not is_integer(index) or index < 0:
                raise InvalidTronError('Invalid transaction index provided')

            transactions = self.get_block(block).get('transactions')
            if not transactions or len(transactions) < index:
                raise TronError('Transaction not found in block')

            return transactions[index]

        def wait_for_transaction_id(self,
                                    transaction_hash: str,
                                    timeout=120,
                                    poll_latency=0.2):
            """
            Waits for the transaction specified by transaction_hash
            to be included in a block, then returns its transaction receipt.

            Optionally, specify a timeout in seconds.
            If timeout elapses before the transaction is added to a block,
            then wait_for_transaction_id() raises a Timeout exception.

            Args:
                transaction_hash (str): Transaction Hash
                timeout (int): TimeOut
                poll_latency (any):  between subsequent requests

            """
            try:
                if poll_latency > timeout:
                    poll_latency = timeout

                return wait_for_transaction_id(self.tron, transaction_hash, timeout, poll_latency)
            except TimeoutError:
                raise TimeExhausted(
                    "Transaction {} is not in the chain, after {} seconds".format(
                        transaction_hash,
                        timeout,
                    )
                )

        def get_transaction(self, transaction_id: str,
                            is_confirm: bool = False):
            """Query transaction based on id

            Args:
                transaction_id (str): transaction id
                is_confirm (bool):
            """

            method = 'walletsolidity' if is_confirm else 'wallet'
            response = self.tron.manager.request('/{}/gettransactionbyid'.format(method), {
                'value': transaction_id
            })

            if 'txID' not in response:
                raise ValueError('Transaction not found')

            return response

        def get_account_by_id(self, account_id: str, options: object):
            return self.get_account_info_by_id(account_id, options)

        def get_account_info_by_id(self, account_id: str, options: object):

            if account_id.startswith('0x'):
                account_id = id[2:]

            if 'confirmed' in options:
                return self.tron.manager.request('/walletsolidity/getaccountbyid', {
                    'account_id': self.tron.toHex(text=account_id)
                })

            return self.tron.manager.request('/wallet/getaccountbyid', {
                'account_id': self.tron.toHex(text=account_id)
            })

        def get_unconfirmed_account_by_id(self, account_id: str):

            return self.get_account_info_by_id(account_id, {
                'confirmed': True
            })

        def get_account_resource(self, address=None):
            """Query the resource information of the account

            Args:
                address (str): Address

            Results:
                Resource information of the account

            """

            if address is None:
                address = self.tron.default_address.hex

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

            return self.tron.manager.request('/wallet/getaccountresource', {
                'address': self.tron.address.to_hex(address)
            })

        def get_account(self, address=None):
            """Query information about an account

            Args:
                address (str): Address

            """

            if address is None:
                address = self.tron.default_address.hex

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

            return self.tron.manager.request('/walletsolidity/getaccount', {
                'address': self.tron.address.to_hex(address)
            })

        def get_balance(self, address=None, is_float=False):
            """Getting a balance

            Args:
                address (str): Address
                is_float (bool): Convert to float format

            """
            response = self.get_account(address)
            if 'balance' not in response:
                return 0

            if is_float:
                return self.tron.fromSun(response['balance'])

            return response['balance']

        def get_transactions_related(self, address, direction='all', limit=30, offset=0):
            """Getting data in the "from", "to" and "all" directions

            Args:
                address (str): Address
                direction (str): Type direction
                address (str): address
                limit (int): number of transactions expected to be returned
                offset (int): index of the starting transaction

            """

            if direction not in ['from', 'to', 'all']:
                raise InvalidTronError('Invalid direction provided: Expected "to", "from" or "all"')

            if direction == 'all':
                _from = self.get_transactions_related(address, 'from', limit, offset)
                _to = self.get_transactions_related(address, 'to', limit, offset)

                filter_from = [{**i, 'direction': 'from'} for i in _from]
                filter_to = [{**i, 'direction': 'to'} for i in _to]

                callback = filter_from
                callback.extend(filter_to)
                return callback

            if address is None:
                address = self.tron.default_address.hex

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

            if not isinstance(limit, int) or limit < 0 or (offset and limit < 1):
                raise InvalidTronError('Invalid limit provided')

            if not isinstance(offset, int) or offset < 0:
                raise InvalidTronError('Invalid offset provided')

            path = '/walletextension/gettransactions{0}this'.format(direction)
            response = self.tron.manager.request(path, {
                'account': {
                    'address': self.tron.address.to_hex(address)
                },
                'limit': limit,
                'offset': offset
            }, 'get')

            if 'transaction' in response:
                return response['transaction']
            return response

        def get_transactions_to_address(self, address=None, limit=30, offset=0):
            """Query the list of transactions received by an address

            Args:
                address (str): address
                limit (int): number of transactions expected to be returned
                offset (int): index of the starting transaction

            Returns:
                Transactions list

            """
            return self.get_transactions_related(address, 'to', limit, offset)

        def get_transactions_from_address(self, address=None, limit=30, offset=0):
            """Query the list of transactions sent by an address

            Args:
                address (str): address
                limit (int): number of transactions expected to be returned
                offset (int): index of the starting transaction

            Returns:
                Transactions list

            """
            return self.get_transactions_related(address, 'from', limit, offset)

        def get_transaction_info(self, tx_id):
            """Query transaction fee based on id

            Args:
                tx_id (str): Transaction Id

            Returns:
                Transaction fee，block height and block creation time

            """
            response = self.tron.manager.request('/walletsolidity/gettransactioninfobyid', {
                'value': tx_id
            })

            return response

        def get_band_width(self, address=None):
            """Query bandwidth information.

            Args:
                address (str): address

            Returns:
                Bandwidth information for the account.
                If a field doesn't appear, then the corresponding value is 0.
                {
                    "freeNetUsed": 557,
                    "freeNetLimit": 5000,
                    "NetUsed": 353,
                    "NetLimit": 5239157853,
                    "TotalNetLimit": 43200000000,
                    "TotalNetWeight": 41228
                }

            """

            if address is None:
                address = self.tron.default_address.hex

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

            response = self.tron.manager.request('/wallet/getaccountnet', {
                'address': self.tron.address.to_hex(address)
            })

            free_net_limit = 0 if 'freeNetLimit' not in response else response['freeNetLimit']
            free_net_used = 0 if 'freeNetUsed' not in response else response['freeNetUsed']
            net_limit = 0 if 'NetLimit' not in response else response['NetLimit']
            net_used = 0 if 'NetUsed' not in response else response['NetUsed']

            return (free_net_limit - free_net_used) + (net_limit - net_used)

        def get_transaction_count(self):
            """Count all transactions on the network
            Note: Possible delays

            Returns:
                Total number of transactions.

            """
            response = self.tron.manager.request('/wallet/totaltransaction')
            return response.get('num')

        def send(self, to, amount, options=None):
            """Send funds to the Tron account (option 2)"""
            return self.send_transaction(to, amount, options)

        def send_trx(self, to, amount, options=None):
            """Send funds to the Tron account (option 3)"""
            return self.send_transaction(to, amount, options)

        def send_transaction(self, to, amount, options=None):
            """Send an asset to another account.
            Will create and broadcast the transaction if a private key is provided.

            Args:
                to (str): Address to send TRX to.
                amount (float): Amount of TRX to send.
                options (Any, optional): Options

            """

            if options is None:
                options = {}

            if 'from' not in options:
                options = assoc(options, 'from', self.tron.default_address.hex)

            tx = self.tron.transaction_builder.send_transaction(
                to,
                amount,
                options['from']
            )
            # If a comment is attached to the transaction,
            # in this case adding to the object
            if 'message' in options:
                tx['raw_data']['data'] = self.tron.toHex(text=str(options['message']))

            sign = self.sign(tx)
            result = self.broadcast(sign)

            return result

        def send_token(self, to, amount, token_id=None, account=None):
            """Transfer Token

            Args:
                to (str): is the recipient address
                amount (float): is the amount of token to transfer
                token_id (str): Token Name(NOT SYMBOL)
                account: (str): is the address of the withdrawal account

            Returns:
                Token transfer Transaction raw data

            """
            if account is None:
                account = self.tron.default_address.hex

            tx = self.tron.transaction_builder.send_token(
                to,
                amount,
                token_id,
                account
            )
            sign = self.sign(tx)
            result = self.broadcast(sign)

            return result

        def freeze_balance(self, amount=0, duration=3, resource='BANDWIDTH', account=None):
            """
            Freezes an amount of TRX.
            Will give bandwidth OR Energy and TRON Power(voting rights)
            to the owner of the frozen tokens.

            Args:
                amount (int): number of frozen trx
                duration (int): duration in days to be frozen
                resource (str): type of resource, must be either "ENERGY" or "BANDWIDTH"
                account (str): address that is freezing trx account

            """

            if account is None:
                account = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.freeze_balance(
                amount,
                duration,
                resource,
                account
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

        def unfreeze_balance(self, resource='BANDWIDTH', account=None):
            """
            Unfreeze TRX that has passed the minimum freeze duration.
            Unfreezing will remove bandwidth and TRON Power.

            Args:
                resource (str): type of resource, must be either "ENERGY" or "BANDWIDTH"
                account (str): address that is freezing trx account

            """

            if account is None:
                account = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.unfreeze_balance(
                resource,
                account
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

        def online_sign(self, transaction: dict):
            """Online transaction signature
            Sign the transaction, the api has the risk of leaking the private key,
            please make sure to call the api in a secure environment

            Warnings:
                Do not use this in any web / user-facing applications.
                This will expose the private key.

            Args:
                transaction (dict): transaction details

            """

            if 'signature' in transaction:
                raise TronError('Transaction is already signed')

            address = self.tron.address.from_private_key(self.tron.private_key).hex.lower()
            owner_address = transaction['raw_data']['contract'][0]['parameter']['value']['owner_address']

            if address != owner_address:
                raise ValueError('Private key does not match address in transaction')

            return self.tron.manager.request('/wallet/gettransactionsign', {
                'transaction': transaction,
                'privateKey': self.tron.private_key
            })

        def sign(self, transaction: Any, private_key=None, use_tron: bool = True, multisig: bool = False,
                 is_message_hex=False):
            """Safe method for signing your transaction

            Warnings:
                method: online_sign() - Use only in extreme cases.

            Args:
                transaction (Any): transaction details
                use_tron (bool): is Tron header
                multisig (bool): multi sign

            """

            if is_string(transaction):
                if not is_hex(transaction):
                    raise TronError('Expected hex message input')

                # Determine which header to attach to the message
                # before encrypting or decrypting
                header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
                header += str(len(transaction))

                if is_message_hex:
                    from eth_hash.auto import keccak as keccak_256
                    message_hash = keccak_256(header.encode('utf-8') + bytes.fromhex(transaction))
                else:
                    message_hash = self.tron.keccak(text=header + transaction)

                signed_message = Account.sign_hash(self.tron.toHex(message_hash), private_key or self.tron.private_key)
                return signed_message

            if not multisig and 'signature' in transaction:
                raise TronError('Transaction is already signed')

            try:
                if transaction.get('transaction', ''):
                    transaction = transaction['transaction']

                if not multisig:
                    address = self.tron.address.from_private_key(private_key or self.tron.private_key).hex.lower()
                    owner_address = transaction['raw_data']['contract'][0]['parameter']['value']['owner_address']

                    if address != owner_address:
                        raise ValueError('Private key does not match address in transaction')

                # This option deals with signing of transactions, and writing to the array
                signed_tx = Account.sign_hash(
                    transaction['txID'], private_key or self.tron.private_key
                )
                signature = signed_tx['signature'].hex()[2:]

                # support multi sign
                if 'signature' in transaction and is_list(transaction['signature']):
                    if not transaction['signature'].index(signature):
                        transaction['signature'].append(signature)
                else:
                    transaction['signature'] = [signature]

                return transaction
            except ValueError as err:
                raise InvalidTronError(err)

        def broadcast(self, signed_transaction):
            """Broadcast the signed transaction

            Args:
                signed_transaction (object): signed transaction contract data

            """
            if not is_object(signed_transaction):
                raise InvalidTronError('Invalid transaction provided')

            if 'signature' not in signed_transaction:
                raise TronError('Transaction is not signed')

            response = self.tron.manager.request('/wallet/broadcasttransaction',
                                                 signed_transaction)

            if 'result' in response:
                response.update({
                    'transaction': signed_transaction
                })
            return response

        def sign_and_broadcast(self, transaction: Any):
            """Sign and send to the network

            Args:
                transaction (Any): transaction details
            """
            if not is_object(transaction):
                raise TronError('Invalid transaction provided')

            signed_tx = self.sign(transaction)
            return self.broadcast(signed_tx)

        def verify_message(self, message, signed_message=None, address=None, use_tron: bool = True, is_message_hex=False):
            """ Get the address of the account that signed the message with the given hash.
            You must specify exactly one of: vrs or signature

            Args:
                message (str): The message in the format "hex"
                signed_message (AttributeDict): Signature
                address (str): is Address
                use_tron (bool): is Tron header

            """
            if address is None:
                address = self.tron.default_address.base58

            if not is_hex(message):
                raise TronError('Expected hex message input')

            # Determine which header to attach to the message
            # before encrypting or decrypting
            header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
            header += str(len(message))

            if is_message_hex:
                from eth_hash.auto import keccak as keccak_256
                message_hash = keccak_256(header.encode('utf-8') + bytes.fromhex(message))
            else:
                message_hash = self.tron.keccak(text=header + message)
            recovered = Account.recover_hash(self.tron.toHex(message_hash), signed_message.signature)

            tron_address = '41' + recovered[2:]
            base58address = self.tron.address.from_hex(tron_address).decode()

            if base58address == address:
                return True

            raise ValueError('Signature does not match')

        def update_account(self, account_name, address=None):
            """Modify account name
            Note: Username is allowed to edit only once.

            Args:
                account_name (str): name of the account
                address (str): address

            """
            if address is None:
                address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.update_account(
                account_name,
                address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

        def apply_for_sr(self, url, address):
            """Apply to become a super representative
            Note: Applied to become a super representative. Cost 9999 TRX.

            Args:
                url (str): official website address
                address (str): address

            """

            if address is None:
                address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.apply_for_sr(
                url,
                address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

        def list_nodes(self):
            """List the nodes which the api fullnode is connecting on the network"""
            response = self.tron.manager.request('/wallet/listnodes')
            callback = map(lambda x: {
                'address': '{}:{}'.format(self.tron.toText(x['address']['host']),
                                          str(x['address']['port']))
            }, response['nodes'])

            return list(callback)

        def get_tokens_issued_by_address(self, address):
            """List the tokens issued by an account.

            Args:
                address (str): address

            Returns:
                The token issued by the account.
                An account can issue only one token.

            """

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

            address = self.tron.address.to_hex(address)

            return self.tron.manager.request('/wallet/getassetissuebyaccount', {
                'address': address
            })

        def get_token_from_id(self, token_id: str):
            """Query token by name.

            Args:
                token_id (str): The name of the token

            """
            if not isinstance(token_id, str) or not len(token_id):
                raise InvalidTronError('Invalid token ID provided')

            return self.tron.manager.request('/wallet/getassetissuebyname', {
                'value': self.tron.toHex(text=token_id)
            })

        def get_block_range(self, start, end):
            """Query a range of blocks by block height

            Args:
                start (int): starting block height, including this block
                end (int): ending block height, excluding that block

            """
            if not is_integer(start) or start < 0:
                raise InvalidTronError('Invalid start of range provided')

            if not is_integer(end) or end <= start:
                raise InvalidTronError('Invalid end of range provided')

            response = self.tron.manager.request('/wallet/getblockbylimitnext', {
                'startNum': int(start),
                'endNum': int(end) + 1
            }, 'post')

            return response.get('block')

        def get_latest_blocks(self, num=1):
            """Query the latest blocks

            Args:
                num (int): the number of blocks to query

            """
            if not is_integer(num) or num <= 0:
                raise InvalidTronError('Invalid limit provided')

            response = self.tron.manager.request('/wallet/getblockbylatestnum', {
                'num': num
            })

            return response.get('block')

        def list_super_representatives(self):
            """Query the list of Super Representatives"""
            response = self.tron.manager.request('/wallet/listwitnesses')
            return response.get('witnesses')

        def list_tokens(self, limit=0, offset=0):
            """Query the list of Tokens with pagination

            Args:
                limit (int): index of the starting Token
                offset (int): number of Tokens expected to be returned

            Returns:
                List of Tokens

            """
            if not is_integer(limit) or (limit and offset < 1):
                raise InvalidTronError('Invalid limit provided')

            if not is_integer(offset) or offset < 0:
                raise InvalidTronError('Invalid offset provided')

            if not limit:
                return self.tron.manager.request('/wallet/getassetissuelist').get('assetIssue')

            return self.tron.manager.request('/wallet/getpaginatedassetissuelist', {
                'limit': int(limit),
                'offset': int(offset)
            })

        def get_asset_from_name(self, name: str) -> dict:
            """Get asset info from its abbr name, might fail if there're duplicates."""
            assets = [asset for asset in self.list_assets(1000, 0) if asset['abbr'] == name]
            if assets:
                if len(assets) == 1:
                    return assets[0]
                raise ValueError("duplicated assets with the same name", [asset['id'] for asset in assets])
            raise AssetNotFound

        def list_assets(self, limit=0, offset=0) -> list:
            """List all TRC10 tokens(assets)."""
            assets = self.list_tokens(limit, offset)
            for asset in assets:
                asset["id"] = int(asset["id"])
                asset["owner_address"] = key.to_base58check_address(asset["owner_address"])
                asset["name"] = bytes.fromhex(asset["name"]).decode()
                if "abbr" in asset:
                    asset["abbr"] = bytes.fromhex(asset["abbr"]).decode()
                else:
                    asset["abbr"] = ""
                asset["description"] = bytes.fromhex(asset["description"]).decode("utf8", "replace")
                asset["url"] = bytes.fromhex(asset["url"]).decode()
            return assets

        def time_until_next_vote_cycle(self):
            """Get the time of the next Super Representative vote

            Returns:
                Number of milliseconds until the next voting time.

            """
            num = self.tron.manager.request('/wallet/getnextmaintenancetime').get('num')

            if num == -1:
                raise Exception('Failed to get time until next vote cycle')

            return math.floor(num / 1000)

        def get_contract(self, contract_address):
            """Queries a contract's information from the blockchain.

            Args:
                contract_address (str): contract address

            Returns:
                SmartContract object. JSON

            """

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

            return self.tron.manager.request('/wallet/getcontract', {
                'value': self.tron.address.to_hex(contract_address)
            })

        def contract(self, address=None, **kwargs):
            """Work with a contract

            Args:
                address (str): TRON Address
                **kwargs (any): details (bytecode, abi)
            """
            factory_class = kwargs.pop('contract_factory_class', self.default_contract_factory)

            contract_factory = factory_class.factory(self.tron, **kwargs)

            if address:
                return contract_factory(address)
            return contract_factory

        def validate_address(self, address, _is_hex=False):
            """Validate address

            Args:
                address (str): The address, should be in base58checksum
                _is_hex (bool): hexString or base64 format

            """
            if _is_hex:
                address = self.tron.address.to_hex(address)

            return self.tron.manager.request('/wallet/validateaddress', {
                'address': address
            })

        def get_chain_parameters(self):
            """Getting chain parameters"""
            return self.tron.manager.request('/wallet/getchainparameters')

        def get_exchange_by_id(self, exchange_id):
            """Find exchange by id

            Args:
                 exchange_id (str): ID Exchange

            """

            if not isinstance(exchange_id, int) or exchange_id < 0:
                raise InvalidTronError('Invalid exchangeID provided')

            return self.tron.manager.request('/wallet/getexchangebyid', {
                'id': exchange_id
            })

        def get_list_exchangers(self):
            """Get list exchangers"""
            return self.tron.manager.request('/wallet/listexchanges')

        def get_proposal(self, proposal_id):
            """Query proposal based on id

            Args:
                proposal_id (int): ID

            """
            if not isinstance(proposal_id, int) or proposal_id < 0:
                raise InvalidTronError('Invalid proposalID provided')

            return self.tron.manager.request('/wallet/getproposalbyid', {
                'id': int(proposal_id)
            })

        def list_proposals(self):
            """Query all proposals

            Returns:
                Proposal list information

            """
            return self.tron.manager.request('/wallet/listproposals')

        def vote_proposal(self, proposal_id, has_approval, voter_address):
            """Proposal approval

            Args:
                proposal_id (int): proposal id
                has_approval (bool): Approved
                voter_address (str): Approve address

            Returns:
                 Approval of the proposed transaction

            """

            if voter_address is None:
                voter_address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.vote_proposal(
                proposal_id,
                has_approval,
                voter_address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

        def proposal_delete(self, proposal_id: int, issuer_address: str):
            """Delete proposal

            Args:
                proposal_id (int): proposal id
                issuer_address (str): delete the person's address

            Results:
                Delete the proposal's transaction

            """
            if issuer_address is None:
                issuer_address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.delete_proposal(
                proposal_id,
                issuer_address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

        def list_exchanges_paginated(self, limit=10, offset=0):
            """Paged query transaction pair list

            Args:
                limit (int): number of trading pairs  expected to be returned.
                offset (int): index of the starting trading pair

            """
            return self.tron.manager.request('/wallet/listexchangespaginated', {
                'limit': limit,
                'offset': offset
            })

        def get_node_info(self):
            """Get info about thre node"""
            return self.tron.manager.request('/wallet/getnodeinfo')

        def get_token_list_name(self, token_id: str) -> any:
            """Query token list by name.

                Args:
                    token_id (str): The name of the token
            """
            if not is_string(token_id):
                raise ValueError('Invalid token ID provided')

            return self.tron.manager.request('/wallet/getassetissuelistbyname', {
                'value': self.tron.toHex(text=token_id)
            })

        def get_token_by_id(self, token_id: str) -> any:
            """Query token by id.

                Args:
                    token_id (str): The id of the token, it's a string
            """
            if not is_string(token_id):
                raise ValueError('Invalid token ID provided')

            return self.tron.manager.request('/wallet/getassetissuebyid', {
                'value': token_id
            })

## Classes

`class Trx (tron)`

  Module Class

  Expand source code

      class Trx(Module):
          default_contract_factory = Contract

          def get_current_block(self):
              """Query the latest block"""
              return self.tron.manager.request(url='/wallet/getnowblock')

          def get_confirmed_current_block(self):
              """Query the confirmed latest block"""
              return self.tron.manager.request('/walletsolidity/getnowblock')

          def get_block(self, block: Any = None):
              """Get block details using HashString or blockNumber

              Args:
                  block (Any): ID or height for the block

              """

              # If the block identifier is not specified,
              # we take the default
              if block is None:
                  block = self.tron.default_block

              if block == 'latest':
                  return self.get_current_block()
              elif block == 'earliest':
                  return self.get_block(0)

              method = select_method_for_block(
                  block,
                  if_hash={'url': '/wallet/getblockbyid', 'field': 'value'},
                  if_number={'url': '/wallet/getblockbynum', 'field': 'num'},
              )

              result = self.tron.manager.request(method['url'], {
                  method['field']: block
              })

              if result:
                  return result
              return ValueError("The call to {method['url']} did not return a value.")

          def get_transaction_count_by_blocknum(self, num: int):
              """Query transaction's count on a specified block by height

              Args:
                  num (int): block number
              """
              if not is_integer(num) or num < 0:
                  raise ValueError('Invalid num provider')

              return self.tron.manager.request('/wallet/gettransactioncountbyblocknum', {
                  'num': num
              })

          def get_block_transaction_count(self, block: Any):
              """Total number of transactions in a block

              Args:
                  block (Any): Number or Hash Block

              """
              transaction = self.get_block(block)
              if 'transactions' not in transaction:
                  raise TronError('Parameter "transactions" not found')

              return len(transaction)

          def get_transaction_from_block(self, block: Any, index: int = 0):
              """Get transaction details from Block

              Args:
                  block (Any): Number or Hash Block
                  index (int) Position

              """
              if not is_integer(index) or index < 0:
                  raise InvalidTronError('Invalid transaction index provided')

              transactions = self.get_block(block).get('transactions')
              if not transactions or len(transactions) < index:
                  raise TronError('Transaction not found in block')

              return transactions[index]

          def wait_for_transaction_id(self,
                                      transaction_hash: str,
                                      timeout=120,
                                      poll_latency=0.2):
              """
              Waits for the transaction specified by transaction_hash
              to be included in a block, then returns its transaction receipt.

              Optionally, specify a timeout in seconds.
              If timeout elapses before the transaction is added to a block,
              then wait_for_transaction_id() raises a Timeout exception.

              Args:
                  transaction_hash (str): Transaction Hash
                  timeout (int): TimeOut
                  poll_latency (any):  between subsequent requests

              """
              try:
                  if poll_latency > timeout:
                      poll_latency = timeout

                  return wait_for_transaction_id(self.tron, transaction_hash, timeout, poll_latency)
              except TimeoutError:
                  raise TimeExhausted(
                      "Transaction {} is not in the chain, after {} seconds".format(
                          transaction_hash,
                          timeout,
                      )
                  )

          def get_transaction(self, transaction_id: str,
                              is_confirm: bool = False):
              """Query transaction based on id

              Args:
                  transaction_id (str): transaction id
                  is_confirm (bool):
              """

              method = 'walletsolidity' if is_confirm else 'wallet'
              response = self.tron.manager.request('/{}/gettransactionbyid'.format(method), {
                  'value': transaction_id
              })

              if 'txID' not in response:
                  raise ValueError('Transaction not found')

              return response

          def get_account_by_id(self, account_id: str, options: object):
              return self.get_account_info_by_id(account_id, options)

          def get_account_info_by_id(self, account_id: str, options: object):

              if account_id.startswith('0x'):
                  account_id = id[2:]

              if 'confirmed' in options:
                  return self.tron.manager.request('/walletsolidity/getaccountbyid', {
                      'account_id': self.tron.toHex(text=account_id)
                  })

              return self.tron.manager.request('/wallet/getaccountbyid', {
                  'account_id': self.tron.toHex(text=account_id)
              })

          def get_unconfirmed_account_by_id(self, account_id: str):

              return self.get_account_info_by_id(account_id, {
                  'confirmed': True
              })

          def get_account_resource(self, address=None):
              """Query the resource information of the account

              Args:
                  address (str): Address

              Results:
                  Resource information of the account

              """

              if address is None:
                  address = self.tron.default_address.hex

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

              return self.tron.manager.request('/wallet/getaccountresource', {
                  'address': self.tron.address.to_hex(address)
              })

          def get_account(self, address=None):
              """Query information about an account

              Args:
                  address (str): Address

              """

              if address is None:
                  address = self.tron.default_address.hex

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

              return self.tron.manager.request('/walletsolidity/getaccount', {
                  'address': self.tron.address.to_hex(address)
              })

          def get_balance(self, address=None, is_float=False):
              """Getting a balance

              Args:
                  address (str): Address
                  is_float (bool): Convert to float format

              """
              response = self.get_account(address)
              if 'balance' not in response:
                  return 0

              if is_float:
                  return self.tron.fromSun(response['balance'])

              return response['balance']

          def get_transactions_related(self, address, direction='all', limit=30, offset=0):
              """Getting data in the "from", "to" and "all" directions

              Args:
                  address (str): Address
                  direction (str): Type direction
                  address (str): address
                  limit (int): number of transactions expected to be returned
                  offset (int): index of the starting transaction

              """

              if direction not in ['from', 'to', 'all']:
                  raise InvalidTronError('Invalid direction provided: Expected "to", "from" or "all"')

              if direction == 'all':
                  _from = self.get_transactions_related(address, 'from', limit, offset)
                  _to = self.get_transactions_related(address, 'to', limit, offset)

                  filter_from = [{**i, 'direction': 'from'} for i in _from]
                  filter_to = [{**i, 'direction': 'to'} for i in _to]

                  callback = filter_from
                  callback.extend(filter_to)
                  return callback

              if address is None:
                  address = self.tron.default_address.hex

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

              if not isinstance(limit, int) or limit < 0 or (offset and limit < 1):
                  raise InvalidTronError('Invalid limit provided')

              if not isinstance(offset, int) or offset < 0:
                  raise InvalidTronError('Invalid offset provided')

              path = '/walletextension/gettransactions{0}this'.format(direction)
              response = self.tron.manager.request(path, {
                  'account': {
                      'address': self.tron.address.to_hex(address)
                  },
                  'limit': limit,
                  'offset': offset
              }, 'get')

              if 'transaction' in response:
                  return response['transaction']
              return response

          def get_transactions_to_address(self, address=None, limit=30, offset=0):
              """Query the list of transactions received by an address

              Args:
                  address (str): address
                  limit (int): number of transactions expected to be returned
                  offset (int): index of the starting transaction

              Returns:
                  Transactions list

              """
              return self.get_transactions_related(address, 'to', limit, offset)

          def get_transactions_from_address(self, address=None, limit=30, offset=0):
              """Query the list of transactions sent by an address

              Args:
                  address (str): address
                  limit (int): number of transactions expected to be returned
                  offset (int): index of the starting transaction

              Returns:
                  Transactions list

              """
              return self.get_transactions_related(address, 'from', limit, offset)

          def get_transaction_info(self, tx_id):
              """Query transaction fee based on id

              Args:
                  tx_id (str): Transaction Id

              Returns:
                  Transaction fee，block height and block creation time

              """
              response = self.tron.manager.request('/walletsolidity/gettransactioninfobyid', {
                  'value': tx_id
              })

              return response

          def get_band_width(self, address=None):
              """Query bandwidth information.

              Args:
                  address (str): address

              Returns:
                  Bandwidth information for the account.
                  If a field doesn't appear, then the corresponding value is 0.
                  {
                      "freeNetUsed": 557,
                      "freeNetLimit": 5000,
                      "NetUsed": 353,
                      "NetLimit": 5239157853,
                      "TotalNetLimit": 43200000000,
                      "TotalNetWeight": 41228
                  }

              """

              if address is None:
                  address = self.tron.default_address.hex

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

              response = self.tron.manager.request('/wallet/getaccountnet', {
                  'address': self.tron.address.to_hex(address)
              })

              free_net_limit = 0 if 'freeNetLimit' not in response else response['freeNetLimit']
              free_net_used = 0 if 'freeNetUsed' not in response else response['freeNetUsed']
              net_limit = 0 if 'NetLimit' not in response else response['NetLimit']
              net_used = 0 if 'NetUsed' not in response else response['NetUsed']

              return (free_net_limit - free_net_used) + (net_limit - net_used)

          def get_transaction_count(self):
              """Count all transactions on the network
              Note: Possible delays

              Returns:
                  Total number of transactions.

              """
              response = self.tron.manager.request('/wallet/totaltransaction')
              return response.get('num')

          def send(self, to, amount, options=None):
              """Send funds to the Tron account (option 2)"""
              return self.send_transaction(to, amount, options)

          def send_trx(self, to, amount, options=None):
              """Send funds to the Tron account (option 3)"""
              return self.send_transaction(to, amount, options)

          def send_transaction(self, to, amount, options=None):
              """Send an asset to another account.
              Will create and broadcast the transaction if a private key is provided.

              Args:
                  to (str): Address to send TRX to.
                  amount (float): Amount of TRX to send.
                  options (Any, optional): Options

              """

              if options is None:
                  options = {}

              if 'from' not in options:
                  options = assoc(options, 'from', self.tron.default_address.hex)

              tx = self.tron.transaction_builder.send_transaction(
                  to,
                  amount,
                  options['from']
              )
              # If a comment is attached to the transaction,
              # in this case adding to the object
              if 'message' in options:
                  tx['raw_data']['data'] = self.tron.toHex(text=str(options['message']))

              sign = self.sign(tx)
              result = self.broadcast(sign)

              return result

          def send_token(self, to, amount, token_id=None, account=None):
              """Transfer Token

              Args:
                  to (str): is the recipient address
                  amount (float): is the amount of token to transfer
                  token_id (str): Token Name(NOT SYMBOL)
                  account: (str): is the address of the withdrawal account

              Returns:
                  Token transfer Transaction raw data

              """
              if account is None:
                  account = self.tron.default_address.hex

              tx = self.tron.transaction_builder.send_token(
                  to,
                  amount,
                  token_id,
                  account
              )
              sign = self.sign(tx)
              result = self.broadcast(sign)

              return result

          def freeze_balance(self, amount=0, duration=3, resource='BANDWIDTH', account=None):
              """
              Freezes an amount of TRX.
              Will give bandwidth OR Energy and TRON Power(voting rights)
              to the owner of the frozen tokens.

              Args:
                  amount (int): number of frozen trx
                  duration (int): duration in days to be frozen
                  resource (str): type of resource, must be either "ENERGY" or "BANDWIDTH"
                  account (str): address that is freezing trx account

              """

              if account is None:
                  account = self.tron.default_address.hex

              transaction = self.tron.transaction_builder.freeze_balance(
                  amount,
                  duration,
                  resource,
                  account
              )
              sign = self.sign(transaction)
              response = self.broadcast(sign)

              return response

          def unfreeze_balance(self, resource='BANDWIDTH', account=None):
              """
              Unfreeze TRX that has passed the minimum freeze duration.
              Unfreezing will remove bandwidth and TRON Power.

              Args:
                  resource (str): type of resource, must be either "ENERGY" or "BANDWIDTH"
                  account (str): address that is freezing trx account

              """

              if account is None:
                  account = self.tron.default_address.hex

              transaction = self.tron.transaction_builder.unfreeze_balance(
                  resource,
                  account
              )
              sign = self.sign(transaction)
              response = self.broadcast(sign)

              return response

          def online_sign(self, transaction: dict):
              """Online transaction signature
              Sign the transaction, the api has the risk of leaking the private key,
              please make sure to call the api in a secure environment

              Warnings:
                  Do not use this in any web / user-facing applications.
                  This will expose the private key.

              Args:
                  transaction (dict): transaction details

              """

              if 'signature' in transaction:
                  raise TronError('Transaction is already signed')

              address = self.tron.address.from_private_key(self.tron.private_key).hex.lower()
              owner_address = transaction['raw_data']['contract'][0]['parameter']['value']['owner_address']

              if address != owner_address:
                  raise ValueError('Private key does not match address in transaction')

              return self.tron.manager.request('/wallet/gettransactionsign', {
                  'transaction': transaction,
                  'privateKey': self.tron.private_key
              })

          def sign(self, transaction: Any, private_key=None, use_tron: bool = True, multisig: bool = False,
                   is_message_hex=False):
              """Safe method for signing your transaction

              Warnings:
                  method: online_sign() - Use only in extreme cases.

              Args:
                  transaction (Any): transaction details
                  use_tron (bool): is Tron header
                  multisig (bool): multi sign

              """

              if is_string(transaction):
                  if not is_hex(transaction):
                      raise TronError('Expected hex message input')

                  # Determine which header to attach to the message
                  # before encrypting or decrypting
                  header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
                  header += str(len(transaction))

                  if is_message_hex:
                      from eth_hash.auto import keccak as keccak_256
                      message_hash = keccak_256(header.encode('utf-8') + bytes.fromhex(transaction))
                  else:
                      message_hash = self.tron.keccak(text=header + transaction)

                  signed_message = Account.sign_hash(self.tron.toHex(message_hash), private_key or self.tron.private_key)
                  return signed_message

              if not multisig and 'signature' in transaction:
                  raise TronError('Transaction is already signed')

              try:
                  if transaction.get('transaction', ''):
                      transaction = transaction['transaction']

                  if not multisig:
                      address = self.tron.address.from_private_key(private_key or self.tron.private_key).hex.lower()
                      owner_address = transaction['raw_data']['contract'][0]['parameter']['value']['owner_address']

                      if address != owner_address:
                          raise ValueError('Private key does not match address in transaction')

                  # This option deals with signing of transactions, and writing to the array
                  signed_tx = Account.sign_hash(
                      transaction['txID'], private_key or self.tron.private_key
                  )
                  signature = signed_tx['signature'].hex()[2:]

                  # support multi sign
                  if 'signature' in transaction and is_list(transaction['signature']):
                      if not transaction['signature'].index(signature):
                          transaction['signature'].append(signature)
                  else:
                      transaction['signature'] = [signature]

                  return transaction
              except ValueError as err:
                  raise InvalidTronError(err)

          def broadcast(self, signed_transaction):
              """Broadcast the signed transaction

              Args:
                  signed_transaction (object): signed transaction contract data

              """
              if not is_object(signed_transaction):
                  raise InvalidTronError('Invalid transaction provided')

              if 'signature' not in signed_transaction:
                  raise TronError('Transaction is not signed')

              response = self.tron.manager.request('/wallet/broadcasttransaction',
                                                   signed_transaction)

              if 'result' in response:
                  response.update({
                      'transaction': signed_transaction
                  })
              return response

          def sign_and_broadcast(self, transaction: Any):
              """Sign and send to the network

              Args:
                  transaction (Any): transaction details
              """
              if not is_object(transaction):
                  raise TronError('Invalid transaction provided')

              signed_tx = self.sign(transaction)
              return self.broadcast(signed_tx)

          def verify_message(self, message, signed_message=None, address=None, use_tron: bool = True, is_message_hex=False):
              """ Get the address of the account that signed the message with the given hash.
              You must specify exactly one of: vrs or signature

              Args:
                  message (str): The message in the format "hex"
                  signed_message (AttributeDict): Signature
                  address (str): is Address
                  use_tron (bool): is Tron header

              """
              if address is None:
                  address = self.tron.default_address.base58

              if not is_hex(message):
                  raise TronError('Expected hex message input')

              # Determine which header to attach to the message
              # before encrypting or decrypting
              header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
              header += str(len(message))

              if is_message_hex:
                  from eth_hash.auto import keccak as keccak_256
                  message_hash = keccak_256(header.encode('utf-8') + bytes.fromhex(message))
              else:
                  message_hash = self.tron.keccak(text=header + message)
              recovered = Account.recover_hash(self.tron.toHex(message_hash), signed_message.signature)

              tron_address = '41' + recovered[2:]
              base58address = self.tron.address.from_hex(tron_address).decode()

              if base58address == address:
                  return True

              raise ValueError('Signature does not match')

          def update_account(self, account_name, address=None):
              """Modify account name
              Note: Username is allowed to edit only once.

              Args:
                  account_name (str): name of the account
                  address (str): address

              """
              if address is None:
                  address = self.tron.default_address.hex

              transaction = self.tron.transaction_builder.update_account(
                  account_name,
                  address
              )
              sign = self.sign(transaction)
              response = self.broadcast(sign)

              return response

          def apply_for_sr(self, url, address):
              """Apply to become a super representative
              Note: Applied to become a super representative. Cost 9999 TRX.

              Args:
                  url (str): official website address
                  address (str): address

              """

              if address is None:
                  address = self.tron.default_address.hex

              transaction = self.tron.transaction_builder.apply_for_sr(
                  url,
                  address
              )
              sign = self.sign(transaction)
              response = self.broadcast(sign)

              return response

          def list_nodes(self):
              """List the nodes which the api fullnode is connecting on the network"""
              response = self.tron.manager.request('/wallet/listnodes')
              callback = map(lambda x: {
                  'address': '{}:{}'.format(self.tron.toText(x['address']['host']),
                                            str(x['address']['port']))
              }, response['nodes'])

              return list(callback)

          def get_tokens_issued_by_address(self, address):
              """List the tokens issued by an account.

              Args:
                  address (str): address

              Returns:
                  The token issued by the account.
                  An account can issue only one token.

              """

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

              address = self.tron.address.to_hex(address)

              return self.tron.manager.request('/wallet/getassetissuebyaccount', {
                  'address': address
              })

          def get_token_from_id(self, token_id: str):
              """Query token by name.

              Args:
                  token_id (str): The name of the token

              """
              if not isinstance(token_id, str) or not len(token_id):
                  raise InvalidTronError('Invalid token ID provided')

              return self.tron.manager.request('/wallet/getassetissuebyname', {
                  'value': self.tron.toHex(text=token_id)
              })

          def get_block_range(self, start, end):
              """Query a range of blocks by block height

              Args:
                  start (int): starting block height, including this block
                  end (int): ending block height, excluding that block

              """
              if not is_integer(start) or start < 0:
                  raise InvalidTronError('Invalid start of range provided')

              if not is_integer(end) or end <= start:
                  raise InvalidTronError('Invalid end of range provided')

              response = self.tron.manager.request('/wallet/getblockbylimitnext', {
                  'startNum': int(start),
                  'endNum': int(end) + 1
              }, 'post')

              return response.get('block')

          def get_latest_blocks(self, num=1):
              """Query the latest blocks

              Args:
                  num (int): the number of blocks to query

              """
              if not is_integer(num) or num <= 0:
                  raise InvalidTronError('Invalid limit provided')

              response = self.tron.manager.request('/wallet/getblockbylatestnum', {
                  'num': num
              })

              return response.get('block')

          def list_super_representatives(self):
              """Query the list of Super Representatives"""
              response = self.tron.manager.request('/wallet/listwitnesses')
              return response.get('witnesses')

          def list_tokens(self, limit=0, offset=0):
              """Query the list of Tokens with pagination

              Args:
                  limit (int): index of the starting Token
                  offset (int): number of Tokens expected to be returned

              Returns:
                  List of Tokens

              """
              if not is_integer(limit) or (limit and offset < 1):
                  raise InvalidTronError('Invalid limit provided')

              if not is_integer(offset) or offset < 0:
                  raise InvalidTronError('Invalid offset provided')

              if not limit:
                  return self.tron.manager.request('/wallet/getassetissuelist').get('assetIssue')

              return self.tron.manager.request('/wallet/getpaginatedassetissuelist', {
                  'limit': int(limit),
                  'offset': int(offset)
              })

          def get_asset_from_name(self, name: str) -> dict:
              """Get asset info from its abbr name, might fail if there're duplicates."""
              assets = [asset for asset in self.list_assets(1000, 0) if asset['abbr'] == name]
              if assets:
                  if len(assets) == 1:
                      return assets[0]
                  raise ValueError("duplicated assets with the same name", [asset['id'] for asset in assets])
              raise AssetNotFound

          def list_assets(self, limit=0, offset=0) -> list:
              """List all TRC10 tokens(assets)."""
              assets = self.list_tokens(limit, offset)
              for asset in assets:
                  asset["id"] = int(asset["id"])
                  asset["owner_address"] = key.to_base58check_address(asset["owner_address"])
                  asset["name"] = bytes.fromhex(asset["name"]).decode()
                  if "abbr" in asset:
                      asset["abbr"] = bytes.fromhex(asset["abbr"]).decode()
                  else:
                      asset["abbr"] = ""
                  asset["description"] = bytes.fromhex(asset["description"]).decode("utf8", "replace")
                  asset["url"] = bytes.fromhex(asset["url"]).decode()
              return assets

          def time_until_next_vote_cycle(self):
              """Get the time of the next Super Representative vote

              Returns:
                  Number of milliseconds until the next voting time.

              """
              num = self.tron.manager.request('/wallet/getnextmaintenancetime').get('num')

              if num == -1:
                  raise Exception('Failed to get time until next vote cycle')

              return math.floor(num / 1000)

          def get_contract(self, contract_address):
              """Queries a contract's information from the blockchain.

              Args:
                  contract_address (str): contract address

              Returns:
                  SmartContract object. JSON

              """

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

              return self.tron.manager.request('/wallet/getcontract', {
                  'value': self.tron.address.to_hex(contract_address)
              })

          def contract(self, address=None, **kwargs):
              """Work with a contract

              Args:
                  address (str): TRON Address
                  **kwargs (any): details (bytecode, abi)
              """
              factory_class = kwargs.pop('contract_factory_class', self.default_contract_factory)

              contract_factory = factory_class.factory(self.tron, **kwargs)

              if address:
                  return contract_factory(address)
              return contract_factory

          def validate_address(self, address, _is_hex=False):
              """Validate address

              Args:
                  address (str): The address, should be in base58checksum
                  _is_hex (bool): hexString or base64 format

              """
              if _is_hex:
                  address = self.tron.address.to_hex(address)

              return self.tron.manager.request('/wallet/validateaddress', {
                  'address': address
              })

          def get_chain_parameters(self):
              """Getting chain parameters"""
              return self.tron.manager.request('/wallet/getchainparameters')

          def get_exchange_by_id(self, exchange_id):
              """Find exchange by id

              Args:
                   exchange_id (str): ID Exchange

              """

              if not isinstance(exchange_id, int) or exchange_id < 0:
                  raise InvalidTronError('Invalid exchangeID provided')

              return self.tron.manager.request('/wallet/getexchangebyid', {
                  'id': exchange_id
              })

          def get_list_exchangers(self):
              """Get list exchangers"""
              return self.tron.manager.request('/wallet/listexchanges')

          def get_proposal(self, proposal_id):
              """Query proposal based on id

              Args:
                  proposal_id (int): ID

              """
              if not isinstance(proposal_id, int) or proposal_id < 0:
                  raise InvalidTronError('Invalid proposalID provided')

              return self.tron.manager.request('/wallet/getproposalbyid', {
                  'id': int(proposal_id)
              })

          def list_proposals(self):
              """Query all proposals

              Returns:
                  Proposal list information

              """
              return self.tron.manager.request('/wallet/listproposals')

          def vote_proposal(self, proposal_id, has_approval, voter_address):
              """Proposal approval

              Args:
                  proposal_id (int): proposal id
                  has_approval (bool): Approved
                  voter_address (str): Approve address

              Returns:
                   Approval of the proposed transaction

              """

              if voter_address is None:
                  voter_address = self.tron.default_address.hex

              transaction = self.tron.transaction_builder.vote_proposal(
                  proposal_id,
                  has_approval,
                  voter_address
              )
              sign = self.sign(transaction)
              response = self.broadcast(sign)

              return response

          def proposal_delete(self, proposal_id: int, issuer_address: str):
              """Delete proposal

              Args:
                  proposal_id (int): proposal id
                  issuer_address (str): delete the person's address

              Results:
                  Delete the proposal's transaction

              """
              if issuer_address is None:
                  issuer_address = self.tron.default_address.hex

              transaction = self.tron.transaction_builder.delete_proposal(
                  proposal_id,
                  issuer_address
              )
              sign = self.sign(transaction)
              response = self.broadcast(sign)

              return response

          def list_exchanges_paginated(self, limit=10, offset=0):
              """Paged query transaction pair list

              Args:
                  limit (int): number of trading pairs  expected to be returned.
                  offset (int): index of the starting trading pair

              """
              return self.tron.manager.request('/wallet/listexchangespaginated', {
                  'limit': limit,
                  'offset': offset
              })

          def get_node_info(self):
              """Get info about thre node"""
              return self.tron.manager.request('/wallet/getnodeinfo')

          def get_token_list_name(self, token_id: str) -> any:
              """Query token list by name.

                  Args:
                      token_id (str): The name of the token
              """
              if not is_string(token_id):
                  raise ValueError('Invalid token ID provided')

              return self.tron.manager.request('/wallet/getassetissuelistbyname', {
                  'value': self.tron.toHex(text=token_id)
              })

          def get_token_by_id(self, token_id: str) -> any:
              """Query token by id.

                  Args:
                      token_id (str): The id of the token, it's a string
              """
              if not is_string(token_id):
                  raise ValueError('Invalid token ID provided')

              return self.tron.manager.request('/wallet/getassetissuebyid', {
                  'value': token_id
              })

  ### Ancestors

  - Module

  ### Class variables

  `var default_contract_factory`

  ### Methods

  `def apply_for_sr(self, url, address)`

    Apply to become a super representative Note: Applied to become a super representative. Cost 9999 TRX.

    ## Args

    `url` :`str`
      official website address
    `address` :`str`
      address
    Expand source code

        def apply_for_sr(self, url, address):
            """Apply to become a super representative
            Note: Applied to become a super representative. Cost 9999 TRX.

            Args:
                url (str): official website address
                address (str): address

            """

            if address is None:
                address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.apply_for_sr(
                url,
                address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

  `def broadcast(self, signed_transaction)`

    Broadcast the signed transaction

    ## Args

    `signed_transaction` :`object`
      signed transaction contract data
    Expand source code

        def broadcast(self, signed_transaction):
            """Broadcast the signed transaction

            Args:
                signed_transaction (object): signed transaction contract data

            """
            if not is_object(signed_transaction):
                raise InvalidTronError('Invalid transaction provided')

            if 'signature' not in signed_transaction:
                raise TronError('Transaction is not signed')

            response = self.tron.manager.request('/wallet/broadcasttransaction',
                                                 signed_transaction)

            if 'result' in response:
                response.update({
                    'transaction': signed_transaction
                })
            return response

  `def contract(self, address=None, **kwargs)`

    Work with a contract

    ## Args

    `address` :`str`
      TRON Address
    `**kwargs` :`any`
      details (bytecode, abi)
    Expand source code

        def contract(self, address=None, **kwargs):
            """Work with a contract

            Args:
                address (str): TRON Address
                **kwargs (any): details (bytecode, abi)
            """
            factory_class = kwargs.pop('contract_factory_class', self.default_contract_factory)

            contract_factory = factory_class.factory(self.tron, **kwargs)

            if address:
                return contract_factory(address)
            return contract_factory

  `def freeze_balance(self, amount=0, duration=3, resource='BANDWIDTH', account=None)`

    Freezes an amount of TRX. Will give bandwidth OR Energy and TRON Power(voting rights) to the owner of the frozen tokens.

    ## Args

    `amount` :`int`
      number of frozen trx
    `duration` :`int`
      duration in days to be frozen
    `resource` :`str`
      type of resource, must be either "ENERGY" or "BANDWIDTH"
    `account` :`str`
      address that is freezing trx account
    Expand source code

        def freeze_balance(self, amount=0, duration=3, resource='BANDWIDTH', account=None):
            """
            Freezes an amount of TRX.
            Will give bandwidth OR Energy and TRON Power(voting rights)
            to the owner of the frozen tokens.

            Args:
                amount (int): number of frozen trx
                duration (int): duration in days to be frozen
                resource (str): type of resource, must be either "ENERGY" or "BANDWIDTH"
                account (str): address that is freezing trx account

            """

            if account is None:
                account = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.freeze_balance(
                amount,
                duration,
                resource,
                account
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

  `def get_account(self, address=None)`

    Query information about an account

    ## Args

    `address` :`str`
      Address
    Expand source code

        def get_account(self, address=None):
            """Query information about an account

            Args:
                address (str): Address

            """

            if address is None:
                address = self.tron.default_address.hex

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

            return self.tron.manager.request('/walletsolidity/getaccount', {
                'address': self.tron.address.to_hex(address)
            })

  `def get_account_by_id(self, account_id: str, options: object)`
    Expand source code

        def get_account_by_id(self, account_id: str, options: object):
            return self.get_account_info_by_id(account_id, options)

  `def get_account_info_by_id(self, account_id: str, options: object)`
    Expand source code

        def get_account_info_by_id(self, account_id: str, options: object):

            if account_id.startswith('0x'):
                account_id = id[2:]

            if 'confirmed' in options:
                return self.tron.manager.request('/walletsolidity/getaccountbyid', {
                    'account_id': self.tron.toHex(text=account_id)
                })

            return self.tron.manager.request('/wallet/getaccountbyid', {
                'account_id': self.tron.toHex(text=account_id)
            })

  `def get_account_resource(self, address=None)`

    Query the resource information of the account

    ## Args

    `address` :`str`
      Address

    ## Results

    Resource information of the account

    Expand source code

        def get_account_resource(self, address=None):
            """Query the resource information of the account

            Args:
                address (str): Address

            Results:
                Resource information of the account

            """

            if address is None:
                address = self.tron.default_address.hex

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

            return self.tron.manager.request('/wallet/getaccountresource', {
                'address': self.tron.address.to_hex(address)
            })

  `def get_asset_from_name(self, name: str) ‑> dict`

    Get asset info from its abbr name, might fail if there're duplicates.

    Expand source code

        def get_asset_from_name(self, name: str) -> dict:
            """Get asset info from its abbr name, might fail if there're duplicates."""
            assets = [asset for asset in self.list_assets(1000, 0) if asset['abbr'] == name]
            if assets:
                if len(assets) == 1:
                    return assets[0]
                raise ValueError("duplicated assets with the same name", [asset['id'] for asset in assets])
            raise AssetNotFound

  `def get_balance(self, address=None, is_float=False)`

    Getting a balance

    ## Args

    `address` :`str`
      Address
    `is_float` :`bool`
      Convert to float format
    Expand source code

        def get_balance(self, address=None, is_float=False):
            """Getting a balance

            Args:
                address (str): Address
                is_float (bool): Convert to float format

            """
            response = self.get_account(address)
            if 'balance' not in response:
                return 0

            if is_float:
                return self.tron.fromSun(response['balance'])

            return response['balance']

  `def get_band_width(self, address=None)`

    Query bandwidth information.

    ## Args

    `address` :`str`
      address

    ## Returns

    Bandwidth information for the account. If a field doesn't appear, then the corresponding value is 0. { "freeNetUsed": 557, "freeNetLimit": 5000, "NetUsed": 353, "NetLimit": 5239157853, "TotalNetLimit": 43200000000, "TotalNetWeight": 41228 }

    Expand source code

        def get_band_width(self, address=None):
            """Query bandwidth information.

            Args:
                address (str): address

            Returns:
                Bandwidth information for the account.
                If a field doesn't appear, then the corresponding value is 0.
                {
                    "freeNetUsed": 557,
                    "freeNetLimit": 5000,
                    "NetUsed": 353,
                    "NetLimit": 5239157853,
                    "TotalNetLimit": 43200000000,
                    "TotalNetWeight": 41228
                }

            """

            if address is None:
                address = self.tron.default_address.hex

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

            response = self.tron.manager.request('/wallet/getaccountnet', {
                'address': self.tron.address.to_hex(address)
            })

            free_net_limit = 0 if 'freeNetLimit' not in response else response['freeNetLimit']
            free_net_used = 0 if 'freeNetUsed' not in response else response['freeNetUsed']
            net_limit = 0 if 'NetLimit' not in response else response['NetLimit']
            net_used = 0 if 'NetUsed' not in response else response['NetUsed']

            return (free_net_limit - free_net_used) + (net_limit - net_used)

  `def get_block(self, block: Any = None)`

    Get block details using HashString or blockNumber

    ## Args

    `block` :`Any`
      ID or height for the block
    Expand source code

        def get_block(self, block: Any = None):
            """Get block details using HashString or blockNumber

            Args:
                block (Any): ID or height for the block

            """

            # If the block identifier is not specified,
            # we take the default
            if block is None:
                block = self.tron.default_block

            if block == 'latest':
                return self.get_current_block()
            elif block == 'earliest':
                return self.get_block(0)

            method = select_method_for_block(
                block,
                if_hash={'url': '/wallet/getblockbyid', 'field': 'value'},
                if_number={'url': '/wallet/getblockbynum', 'field': 'num'},
            )

            result = self.tron.manager.request(method['url'], {
                method['field']: block
            })

            if result:
                return result
            return ValueError("The call to {method['url']} did not return a value.")

  `def get_block_range(self, start, end)`

    Query a range of blocks by block height

    ## Args

    `start` :`int`
      starting block height, including this block
    `end` :`int`
      ending block height, excluding that block
    Expand source code

        def get_block_range(self, start, end):
            """Query a range of blocks by block height

            Args:
                start (int): starting block height, including this block
                end (int): ending block height, excluding that block

            """
            if not is_integer(start) or start < 0:
                raise InvalidTronError('Invalid start of range provided')

            if not is_integer(end) or end <= start:
                raise InvalidTronError('Invalid end of range provided')

            response = self.tron.manager.request('/wallet/getblockbylimitnext', {
                'startNum': int(start),
                'endNum': int(end) + 1
            }, 'post')

            return response.get('block')

  `def get_block_transaction_count(self, block: Any)`

    Total number of transactions in a block

    ## Args

    `block` :`Any`
      Number or Hash Block
    Expand source code

        def get_block_transaction_count(self, block: Any):
            """Total number of transactions in a block

            Args:
                block (Any): Number or Hash Block

            """
            transaction = self.get_block(block)
            if 'transactions' not in transaction:
                raise TronError('Parameter "transactions" not found')

            return len(transaction)

  `def get_chain_parameters(self)`

    Getting chain parameters

    Expand source code

        def get_chain_parameters(self):
            """Getting chain parameters"""
            return self.tron.manager.request('/wallet/getchainparameters')

  `def get_confirmed_current_block(self)`

    Query the confirmed latest block

    Expand source code

        def get_confirmed_current_block(self):
            """Query the confirmed latest block"""
            return self.tron.manager.request('/walletsolidity/getnowblock')

  `def get_contract(self, contract_address)`

    Queries a contract's information from the blockchain.

    ## Args

    `contract_address` :`str`
      contract address

    ## Returns

    SmartContract object. JSON

    Expand source code

        def get_contract(self, contract_address):
            """Queries a contract's information from the blockchain.

            Args:
                contract_address (str): contract address

            Returns:
                SmartContract object. JSON

            """

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

            return self.tron.manager.request('/wallet/getcontract', {
                'value': self.tron.address.to_hex(contract_address)
            })

  `def get_current_block(self)`

    Query the latest block

    Expand source code

        def get_current_block(self):
            """Query the latest block"""
            return self.tron.manager.request(url='/wallet/getnowblock')

  `def get_exchange_by_id(self, exchange_id)`

    Find exchange by id

    ## Args

    `exchange_id` :`str`
      ID Exchange
    Expand source code

        def get_exchange_by_id(self, exchange_id):
            """Find exchange by id

            Args:
                 exchange_id (str): ID Exchange

            """

            if not isinstance(exchange_id, int) or exchange_id < 0:
                raise InvalidTronError('Invalid exchangeID provided')

            return self.tron.manager.request('/wallet/getexchangebyid', {
                'id': exchange_id
            })

  `def get_latest_blocks(self, num=1)`

    Query the latest blocks

    ## Args

    `num` :`int`
      the number of blocks to query
    Expand source code

        def get_latest_blocks(self, num=1):
            """Query the latest blocks

            Args:
                num (int): the number of blocks to query

            """
            if not is_integer(num) or num <= 0:
                raise InvalidTronError('Invalid limit provided')

            response = self.tron.manager.request('/wallet/getblockbylatestnum', {
                'num': num
            })

            return response.get('block')

  `def get_list_exchangers(self)`

    Get list exchangers

    Expand source code

        def get_list_exchangers(self):
            """Get list exchangers"""
            return self.tron.manager.request('/wallet/listexchanges')

  `def get_node_info(self)`

    Get info about thre node

    Expand source code

        def get_node_info(self):
            """Get info about thre node"""
            return self.tron.manager.request('/wallet/getnodeinfo')

  `def get_proposal(self, proposal_id)`

    Query proposal based on id

    ## Args

    `proposal_id` :`int`
      ID
    Expand source code

        def get_proposal(self, proposal_id):
            """Query proposal based on id

            Args:
                proposal_id (int): ID

            """
            if not isinstance(proposal_id, int) or proposal_id < 0:
                raise InvalidTronError('Invalid proposalID provided')

            return self.tron.manager.request('/wallet/getproposalbyid', {
                'id': int(proposal_id)
            })

  `def get_token_by_id(self, token_id: str) ‑>`

    Query token by id.

    ## Args

    `token_id` :`str`
      The id of the token, it's a string
    Expand source code

        def get_token_by_id(self, token_id: str) -> any:
            """Query token by id.

                Args:
                    token_id (str): The id of the token, it's a string
            """
            if not is_string(token_id):
                raise ValueError('Invalid token ID provided')

            return self.tron.manager.request('/wallet/getassetissuebyid', {
                'value': token_id
            })

  `def get_token_from_id(self, token_id: str)`

    Query token by name.

    ## Args

    `token_id` :`str`
      The name of the token
    Expand source code

        def get_token_from_id(self, token_id: str):
            """Query token by name.

            Args:
                token_id (str): The name of the token

            """
            if not isinstance(token_id, str) or not len(token_id):
                raise InvalidTronError('Invalid token ID provided')

            return self.tron.manager.request('/wallet/getassetissuebyname', {
                'value': self.tron.toHex(text=token_id)
            })

  `def get_token_list_name(self, token_id: str) ‑>`

    Query token list by name.

    ## Args

    `token_id` :`str`
      The name of the token
    Expand source code

        def get_token_list_name(self, token_id: str) -> any:
            """Query token list by name.

                Args:
                    token_id (str): The name of the token
            """
            if not is_string(token_id):
                raise ValueError('Invalid token ID provided')

            return self.tron.manager.request('/wallet/getassetissuelistbyname', {
                'value': self.tron.toHex(text=token_id)
            })

  `def get_tokens_issued_by_address(self, address)`

    List the tokens issued by an account.

    ## Args

    `address` :`str`
      address

    ## Returns

    The token issued by the account. An account can issue only one token.

    Expand source code

        def get_tokens_issued_by_address(self, address):
            """List the tokens issued by an account.

            Args:
                address (str): address

            Returns:
                The token issued by the account.
                An account can issue only one token.

            """

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

            address = self.tron.address.to_hex(address)

            return self.tron.manager.request('/wallet/getassetissuebyaccount', {
                'address': address
            })

  `def get_transaction(self, transaction_id: str, is_confirm: bool = False)`

    Query transaction based on id

    ## Args

    `transaction_id` :`str`
      transaction id

    is_confirm (bool):

    Expand source code

        def get_transaction(self, transaction_id: str,
                            is_confirm: bool = False):
            """Query transaction based on id

            Args:
                transaction_id (str): transaction id
                is_confirm (bool):
            """

            method = 'walletsolidity' if is_confirm else 'wallet'
            response = self.tron.manager.request('/{}/gettransactionbyid'.format(method), {
                'value': transaction_id
            })

            if 'txID' not in response:
                raise ValueError('Transaction not found')

            return response

  `def get_transaction_count(self)`

    Count all transactions on the network Note: Possible delays

    ## Returns

    Total number of transactions.

    Expand source code

        def get_transaction_count(self):
            """Count all transactions on the network
            Note: Possible delays

            Returns:
                Total number of transactions.

            """
            response = self.tron.manager.request('/wallet/totaltransaction')
            return response.get('num')

  `def get_transaction_count_by_blocknum(self, num: int)`

    Query transaction's count on a specified block by height

    ## Args

    `num` :`int`
      block number
    Expand source code

        def get_transaction_count_by_blocknum(self, num: int):
            """Query transaction's count on a specified block by height

            Args:
                num (int): block number
            """
            if not is_integer(num) or num < 0:
                raise ValueError('Invalid num provider')

            return self.tron.manager.request('/wallet/gettransactioncountbyblocknum', {
                'num': num
            })

  `def get_transaction_from_block(self, block: Any, index: int = 0)`

    Get transaction details from Block

    ## Args

    `block` :`Any`
      Number or Hash Block

    index (int) Position

    Expand source code

        def get_transaction_from_block(self, block: Any, index: int = 0):
            """Get transaction details from Block

            Args:
                block (Any): Number or Hash Block
                index (int) Position

            """
            if not is_integer(index) or index < 0:
                raise InvalidTronError('Invalid transaction index provided')

            transactions = self.get_block(block).get('transactions')
            if not transactions or len(transactions) < index:
                raise TronError('Transaction not found in block')

            return transactions[index]

  `def get_transaction_info(self, tx_id)`

    Query transaction fee based on id

    ## Args

    `tx_id` :`str`
      Transaction Id

    ## Returns

    Transaction fee，block height and block creation time

    Expand source code

        def get_transaction_info(self, tx_id):
            """Query transaction fee based on id

            Args:
                tx_id (str): Transaction Id

            Returns:
                Transaction fee，block height and block creation time

            """
            response = self.tron.manager.request('/walletsolidity/gettransactioninfobyid', {
                'value': tx_id
            })

            return response

  `def get_transactions_from_address(self, address=None, limit=30, offset=0)`

    Query the list of transactions sent by an address

    ## Args

    `address` :`str`
      address
    `limit` :`int`
      number of transactions expected to be returned
    `offset` :`int`
      index of the starting transaction

    ## Returns

    Transactions list

    Expand source code

        def get_transactions_from_address(self, address=None, limit=30, offset=0):
            """Query the list of transactions sent by an address

            Args:
                address (str): address
                limit (int): number of transactions expected to be returned
                offset (int): index of the starting transaction

            Returns:
                Transactions list

            """
            return self.get_transactions_related(address, 'from', limit, offset)

  `def get_transactions_related(self, address, direction='all', limit=30, offset=0)`

    Getting data in the "from", "to" and "all" directions

    ## Args

    `address` :`str`
      Address
    `direction` :`str`
      Type direction
    `address` :`str`
      address
    `limit` :`int`
      number of transactions expected to be returned
    `offset` :`int`
      index of the starting transaction
    Expand source code

        def get_transactions_related(self, address, direction='all', limit=30, offset=0):
            """Getting data in the "from", "to" and "all" directions

            Args:
                address (str): Address
                direction (str): Type direction
                address (str): address
                limit (int): number of transactions expected to be returned
                offset (int): index of the starting transaction

            """

            if direction not in ['from', 'to', 'all']:
                raise InvalidTronError('Invalid direction provided: Expected "to", "from" or "all"')

            if direction == 'all':
                _from = self.get_transactions_related(address, 'from', limit, offset)
                _to = self.get_transactions_related(address, 'to', limit, offset)

                filter_from = [{**i, 'direction': 'from'} for i in _from]
                filter_to = [{**i, 'direction': 'to'} for i in _to]

                callback = filter_from
                callback.extend(filter_to)
                return callback

            if address is None:
                address = self.tron.default_address.hex

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

            if not isinstance(limit, int) or limit < 0 or (offset and limit < 1):
                raise InvalidTronError('Invalid limit provided')

            if not isinstance(offset, int) or offset < 0:
                raise InvalidTronError('Invalid offset provided')

            path = '/walletextension/gettransactions{0}this'.format(direction)
            response = self.tron.manager.request(path, {
                'account': {
                    'address': self.tron.address.to_hex(address)
                },
                'limit': limit,
                'offset': offset
            }, 'get')

            if 'transaction' in response:
                return response['transaction']
            return response

  `def get_transactions_to_address(self, address=None, limit=30, offset=0)`

    Query the list of transactions received by an address

    ## Args

    `address` :`str`
      address
    `limit` :`int`
      number of transactions expected to be returned
    `offset` :`int`
      index of the starting transaction

    ## Returns

    Transactions list

    Expand source code

        def get_transactions_to_address(self, address=None, limit=30, offset=0):
            """Query the list of transactions received by an address

            Args:
                address (str): address
                limit (int): number of transactions expected to be returned
                offset (int): index of the starting transaction

            Returns:
                Transactions list

            """
            return self.get_transactions_related(address, 'to', limit, offset)

  `def get_unconfirmed_account_by_id(self, account_id: str)`
    Expand source code

        def get_unconfirmed_account_by_id(self, account_id: str):

            return self.get_account_info_by_id(account_id, {
                'confirmed': True
            })

  `def list_assets(self, limit=0, offset=0) ‑> list`

    List all TRC10 tokens(assets).

    Expand source code

        def list_assets(self, limit=0, offset=0) -> list:
            """List all TRC10 tokens(assets)."""
            assets = self.list_tokens(limit, offset)
            for asset in assets:
                asset["id"] = int(asset["id"])
                asset["owner_address"] = key.to_base58check_address(asset["owner_address"])
                asset["name"] = bytes.fromhex(asset["name"]).decode()
                if "abbr" in asset:
                    asset["abbr"] = bytes.fromhex(asset["abbr"]).decode()
                else:
                    asset["abbr"] = ""
                asset["description"] = bytes.fromhex(asset["description"]).decode("utf8", "replace")
                asset["url"] = bytes.fromhex(asset["url"]).decode()
            return assets

  `def list_exchanges_paginated(self, limit=10, offset=0)`

    Paged query transaction pair list

    ## Args

    `limit` :`int`
      number of trading pairs expected to be returned.
    `offset` :`int`
      index of the starting trading pair
    Expand source code

        def list_exchanges_paginated(self, limit=10, offset=0):
            """Paged query transaction pair list

            Args:
                limit (int): number of trading pairs  expected to be returned.
                offset (int): index of the starting trading pair

            """
            return self.tron.manager.request('/wallet/listexchangespaginated', {
                'limit': limit,
                'offset': offset
            })

  `def list_nodes(self)`

    List the nodes which the api fullnode is connecting on the network

    Expand source code

        def list_nodes(self):
            """List the nodes which the api fullnode is connecting on the network"""
            response = self.tron.manager.request('/wallet/listnodes')
            callback = map(lambda x: {
                'address': '{}:{}'.format(self.tron.toText(x['address']['host']),
                                          str(x['address']['port']))
            }, response['nodes'])

            return list(callback)

  `def list_proposals(self)`

    Query all proposals

    ## Returns

    Proposal list information

    Expand source code

        def list_proposals(self):
            """Query all proposals

            Returns:
                Proposal list information

            """
            return self.tron.manager.request('/wallet/listproposals')

  `def list_super_representatives(self)`

    Query the list of Super Representatives

    Expand source code

        def list_super_representatives(self):
            """Query the list of Super Representatives"""
            response = self.tron.manager.request('/wallet/listwitnesses')
            return response.get('witnesses')

  `def list_tokens(self, limit=0, offset=0)`

    Query the list of Tokens with pagination

    ## Args

    `limit` :`int`
      index of the starting Token
    `offset` :`int`
      number of Tokens expected to be returned

    ## Returns

    List of Tokens

    Expand source code

        def list_tokens(self, limit=0, offset=0):
            """Query the list of Tokens with pagination

            Args:
                limit (int): index of the starting Token
                offset (int): number of Tokens expected to be returned

            Returns:
                List of Tokens

            """
            if not is_integer(limit) or (limit and offset < 1):
                raise InvalidTronError('Invalid limit provided')

            if not is_integer(offset) or offset < 0:
                raise InvalidTronError('Invalid offset provided')

            if not limit:
                return self.tron.manager.request('/wallet/getassetissuelist').get('assetIssue')

            return self.tron.manager.request('/wallet/getpaginatedassetissuelist', {
                'limit': int(limit),
                'offset': int(offset)
            })

  `def online_sign(self, transaction: dict)`

    Online transaction signature Sign the transaction, the api has the risk of leaking the private key, please make sure to call the api in a secure environment

    ## Warnings

    Do not use this in any web / user-facing applications. This will expose the private key.

    ## Args

    `transaction` :`dict`
      transaction details
    Expand source code

        def online_sign(self, transaction: dict):
            """Online transaction signature
            Sign the transaction, the api has the risk of leaking the private key,
            please make sure to call the api in a secure environment

            Warnings:
                Do not use this in any web / user-facing applications.
                This will expose the private key.

            Args:
                transaction (dict): transaction details

            """

            if 'signature' in transaction:
                raise TronError('Transaction is already signed')

            address = self.tron.address.from_private_key(self.tron.private_key).hex.lower()
            owner_address = transaction['raw_data']['contract'][0]['parameter']['value']['owner_address']

            if address != owner_address:
                raise ValueError('Private key does not match address in transaction')

            return self.tron.manager.request('/wallet/gettransactionsign', {
                'transaction': transaction,
                'privateKey': self.tron.private_key
            })

  `def proposal_delete(self, proposal_id: int, issuer_address: str)`

    Delete proposal

    ## Args

    `proposal_id` :`int`
      proposal id
    `issuer_address` :`str`
      delete the person's address

    ## Results

    Delete the proposal's transaction

    Expand source code

        def proposal_delete(self, proposal_id: int, issuer_address: str):
            """Delete proposal

            Args:
                proposal_id (int): proposal id
                issuer_address (str): delete the person's address

            Results:
                Delete the proposal's transaction

            """
            if issuer_address is None:
                issuer_address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.delete_proposal(
                proposal_id,
                issuer_address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

  `def send(self, to, amount, options=None)`

    Send funds to the Tron account (option 2)

    Expand source code

        def send(self, to, amount, options=None):
            """Send funds to the Tron account (option 2)"""
            return self.send_transaction(to, amount, options)

  `def send_token(self, to, amount, token_id=None, account=None)`

    Transfer Token

    ## Args

    `to` :`str`
      is the recipient address
    `amount` :`float`
      is the amount of token to transfer
    `token_id` :`str`
      Token Name(NOT SYMBOL)
    `account`
      (str): is the address of the withdrawal account

    ## Returns

    Token transfer Transaction raw data

    Expand source code

        def send_token(self, to, amount, token_id=None, account=None):
            """Transfer Token

            Args:
                to (str): is the recipient address
                amount (float): is the amount of token to transfer
                token_id (str): Token Name(NOT SYMBOL)
                account: (str): is the address of the withdrawal account

            Returns:
                Token transfer Transaction raw data

            """
            if account is None:
                account = self.tron.default_address.hex

            tx = self.tron.transaction_builder.send_token(
                to,
                amount,
                token_id,
                account
            )
            sign = self.sign(tx)
            result = self.broadcast(sign)

            return result

  `def send_transaction(self, to, amount, options=None)`

    Send an asset to another account. Will create and broadcast the transaction if a private key is provided.

    ## Args

    `to` :`str`
      Address to send TRX to.
    `amount` :`float`
      Amount of TRX to send.
    `options` :`Any`, optional
      Options
    Expand source code

        def send_transaction(self, to, amount, options=None):
            """Send an asset to another account.
            Will create and broadcast the transaction if a private key is provided.

            Args:
                to (str): Address to send TRX to.
                amount (float): Amount of TRX to send.
                options (Any, optional): Options

            """

            if options is None:
                options = {}

            if 'from' not in options:
                options = assoc(options, 'from', self.tron.default_address.hex)

            tx = self.tron.transaction_builder.send_transaction(
                to,
                amount,
                options['from']
            )
            # If a comment is attached to the transaction,
            # in this case adding to the object
            if 'message' in options:
                tx['raw_data']['data'] = self.tron.toHex(text=str(options['message']))

            sign = self.sign(tx)
            result = self.broadcast(sign)

            return result

  `def send_trx(self, to, amount, options=None)`

    Send funds to the Tron account (option 3)

    Expand source code

        def send_trx(self, to, amount, options=None):
            """Send funds to the Tron account (option 3)"""
            return self.send_transaction(to, amount, options)

  `def sign(self, transaction: Any, private_key=None, use_tron: bool = True, multisig: bool = False, is_message_hex=False)`

    Safe method for signing your transaction

    ## Warnings

    method: online_sign() - Use only in extreme cases.

    ## Args

    `transaction` :`Any`
      transaction details
    `use_tron` :`bool`
      is Tron header
    `multisig` :`bool`
      multi sign
    Expand source code

        def sign(self, transaction: Any, private_key=None, use_tron: bool = True, multisig: bool = False,
                 is_message_hex=False):
            """Safe method for signing your transaction

            Warnings:
                method: online_sign() - Use only in extreme cases.

            Args:
                transaction (Any): transaction details
                use_tron (bool): is Tron header
                multisig (bool): multi sign

            """

            if is_string(transaction):
                if not is_hex(transaction):
                    raise TronError('Expected hex message input')

                # Determine which header to attach to the message
                # before encrypting or decrypting
                header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
                header += str(len(transaction))

                if is_message_hex:
                    from eth_hash.auto import keccak as keccak_256
                    message_hash = keccak_256(header.encode('utf-8') + bytes.fromhex(transaction))
                else:
                    message_hash = self.tron.keccak(text=header + transaction)

                signed_message = Account.sign_hash(self.tron.toHex(message_hash), private_key or self.tron.private_key)
                return signed_message

            if not multisig and 'signature' in transaction:
                raise TronError('Transaction is already signed')

            try:
                if transaction.get('transaction', ''):
                    transaction = transaction['transaction']

                if not multisig:
                    address = self.tron.address.from_private_key(private_key or self.tron.private_key).hex.lower()
                    owner_address = transaction['raw_data']['contract'][0]['parameter']['value']['owner_address']

                    if address != owner_address:
                        raise ValueError('Private key does not match address in transaction')

                # This option deals with signing of transactions, and writing to the array
                signed_tx = Account.sign_hash(
                    transaction['txID'], private_key or self.tron.private_key
                )
                signature = signed_tx['signature'].hex()[2:]

                # support multi sign
                if 'signature' in transaction and is_list(transaction['signature']):
                    if not transaction['signature'].index(signature):
                        transaction['signature'].append(signature)
                else:
                    transaction['signature'] = [signature]

                return transaction
            except ValueError as err:
                raise InvalidTronError(err)

  `def sign_and_broadcast(self, transaction: Any)`

    Sign and send to the network

    ## Args

    `transaction` :`Any`
      transaction details
    Expand source code

        def sign_and_broadcast(self, transaction: Any):
            """Sign and send to the network

            Args:
                transaction (Any): transaction details
            """
            if not is_object(transaction):
                raise TronError('Invalid transaction provided')

            signed_tx = self.sign(transaction)
            return self.broadcast(signed_tx)

  `def time_until_next_vote_cycle(self)`

    Get the time of the next Super Representative vote

    ## Returns

    Number of milliseconds until the next voting time.

    Expand source code

        def time_until_next_vote_cycle(self):
            """Get the time of the next Super Representative vote

            Returns:
                Number of milliseconds until the next voting time.

            """
            num = self.tron.manager.request('/wallet/getnextmaintenancetime').get('num')

            if num == -1:
                raise Exception('Failed to get time until next vote cycle')

            return math.floor(num / 1000)

  `def unfreeze_balance(self, resource='BANDWIDTH', account=None)`

    Unfreeze TRX that has passed the minimum freeze duration. Unfreezing will remove bandwidth and TRON Power.

    ## Args

    `resource` :`str`
      type of resource, must be either "ENERGY" or "BANDWIDTH"
    `account` :`str`
      address that is freezing trx account
    Expand source code

        def unfreeze_balance(self, resource='BANDWIDTH', account=None):
            """
            Unfreeze TRX that has passed the minimum freeze duration.
            Unfreezing will remove bandwidth and TRON Power.

            Args:
                resource (str): type of resource, must be either "ENERGY" or "BANDWIDTH"
                account (str): address that is freezing trx account

            """

            if account is None:
                account = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.unfreeze_balance(
                resource,
                account
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

  `def update_account(self, account_name, address=None)`

    Modify account name Note: Username is allowed to edit only once.

    ## Args

    `account_name` :`str`
      name of the account
    `address` :`str`
      address
    Expand source code

        def update_account(self, account_name, address=None):
            """Modify account name
            Note: Username is allowed to edit only once.

            Args:
                account_name (str): name of the account
                address (str): address

            """
            if address is None:
                address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.update_account(
                account_name,
                address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

  `def validate_address(self, address)`

    Validate address

    ## Args

    `address` :`str`
      The address, should be in base58checksum
    `_is_hex` :`bool`
      hexString or base64 format
    Expand source code

        def validate_address(self, address, _is_hex=False):
            """Validate address

            Args:
                address (str): The address, should be in base58checksum
                _is_hex (bool): hexString or base64 format

            """
            if _is_hex:
                address = self.tron.address.to_hex(address)

            return self.tron.manager.request('/wallet/validateaddress', {
                'address': address
            })

  `def verify_message(self, message, signed_message=None, address=None, use_tron: bool = True, is_message_hex=False)`

    Get the address of the account that signed the message with the given hash. You must specify exactly one of: vrs or signature

    ## Args

    `message` :`str`
      The message in the format "hex"
    `signed_message` :`AttributeDict`
      Signature
    `address` :`str`
      is Address
    `use_tron` :`bool`
      is Tron header
    Expand source code

        def verify_message(self, message, signed_message=None, address=None, use_tron: bool = True, is_message_hex=False):
            """ Get the address of the account that signed the message with the given hash.
            You must specify exactly one of: vrs or signature

            Args:
                message (str): The message in the format "hex"
                signed_message (AttributeDict): Signature
                address (str): is Address
                use_tron (bool): is Tron header

            """
            if address is None:
                address = self.tron.default_address.base58

            if not is_hex(message):
                raise TronError('Expected hex message input')

            # Determine which header to attach to the message
            # before encrypting or decrypting
            header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
            header += str(len(message))

            if is_message_hex:
                from eth_hash.auto import keccak as keccak_256
                message_hash = keccak_256(header.encode('utf-8') + bytes.fromhex(message))
            else:
                message_hash = self.tron.keccak(text=header + message)
            recovered = Account.recover_hash(self.tron.toHex(message_hash), signed_message.signature)

            tron_address = '41' + recovered[2:]
            base58address = self.tron.address.from_hex(tron_address).decode()

            if base58address == address:
                return True

            raise ValueError('Signature does not match')

  `def vote_proposal(self, proposal_id, has_approval, voter_address)`

    Proposal approval

    ## Args

    `proposal_id` :`int`
      proposal id
    `has_approval` :`bool`
      Approved
    `voter_address` :`str`
      Approve address

    ## Returns

    Approval of the proposed transaction

    Expand source code

        def vote_proposal(self, proposal_id, has_approval, voter_address):
            """Proposal approval

            Args:
                proposal_id (int): proposal id
                has_approval (bool): Approved
                voter_address (str): Approve address

            Returns:
                 Approval of the proposed transaction

            """

            if voter_address is None:
                voter_address = self.tron.default_address.hex

            transaction = self.tron.transaction_builder.vote_proposal(
                proposal_id,
                has_approval,
                voter_address
            )
            sign = self.sign(transaction)
            response = self.broadcast(sign)

            return response

  `def wait_for_transaction_id(self, transaction_hash: str, timeout=120, poll_latency=0.2)`

    Waits for the transaction specified by transaction_hash to be included in a block, then returns its transaction receipt.

    Optionally, specify a timeout in seconds. If timeout elapses before the transaction is added to a block, then wait_for_transaction_id() raises a Timeout exception.

    ## Args

    `transaction_hash` :`str`
      Transaction Hash
    `timeout` :`int`
      TimeOut
    `poll_latency` :`any`
      between subsequent requests
    Expand source code

        def wait_for_transaction_id(self,
                                    transaction_hash: str,
                                    timeout=120,
                                    poll_latency=0.2):
            """
            Waits for the transaction specified by transaction_hash
            to be included in a block, then returns its transaction receipt.

            Optionally, specify a timeout in seconds.
            If timeout elapses before the transaction is added to a block,
            then wait_for_transaction_id() raises a Timeout exception.

            Args:
                transaction_hash (str): Transaction Hash
                timeout (int): TimeOut
                poll_latency (any):  between subsequent requests

            """
            try:
                if poll_latency > timeout:
                    poll_latency = timeout

                return wait_for_transaction_id(self.tron, transaction_hash, timeout, poll_latency)
            except TimeoutError:
                raise TimeExhausted(
                    "Transaction {} is not in the chain, after {} seconds".format(
                        transaction_hash,
                        timeout,
                    )
                )