tronpytool.transactionbuilder API documentation

# Module `tronpytool.transactionbuilder`

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.
    # --------------------------------------------------------------------

    from datetime import datetime
    from typing import (
        Any,
        Tuple,
        List
    )

    from eth_abi import encode_abi
    from trx_utils import (
        is_string,
        is_integer,
        is_boolean,
        is_hex,
        encode_hex
    )

    from tronpytool.common.validation import is_valid_url
    from tronpytool.exceptions import (
        InvalidTronError,
        TronError,
        InvalidAddress
    )

    DEFAULT_TIME = datetime.now()
    START_DATE = int(DEFAULT_TIME.timestamp() * 1000)

    class TransactionBuilder(object):
        debug = True

        def __init__(self, tron):
            self.tron = tron

        def setDebug(self, b: bool) -> None:
            self.debug = b

        def send_transaction(self, to, amount, account=None):
            """Creates a transaction of transfer.
            If the recipient address does not exist, a corresponding account will be created.

            Args:
                to (str): to address
                amount (float): amount
                account (str): from address

            Returns:
                Transaction contract data

            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

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

            if not isinstance(amount, float) or amount <= 0:
                raise InvalidTronError('Invalid amount provided')

            _to = self.tron.address.to_hex(to)
            _from = self.tron.address.to_hex(account)

            if _to == _from:
                raise TronError('Cannot transfer TRX to the same account')

            response = self.tron.manager.request('/wallet/createtransaction', {
                'to_address': _to,
                'owner_address': _from,
                'amount': self.tron.toSun(amount)
            })

            return response

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

            Args:
                to (str): is the recipient address
                amount (int): is the amount of token to transfer. must be integer instead of float
                token_id (any): Token Name and id
                account: (str): is the address of the withdrawal account

            Returns:
                Token transfer Transaction raw data

            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

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

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

            if not token_id:
                raise InvalidTronError('Invalid token ID provided')

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

            _to = self.tron.address.to_hex(to)
            _from = self.tron.address.to_hex(account)
            _token_id = self.tron.toHex(text=str(token_id))

            if _to == _from:
                raise TronError('Cannot transfer TRX to the same account')

            # In case if "TRX" is specified, we redirect to another method.
            if is_string(token_id) and token_id.upper() == 'TRX':
                return self.send_transaction(_to, amount, _from)

            return self.tron.manager.request('/wallet/transferasset', {
                'to_address': _to,
                'owner_address': _from,
                'asset_name': _token_id,
                'amount': amount
            })

        def freeze_balance(self, amount, duration, resource, 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 the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

            if resource not in ('BANDWIDTH', 'ENERGY',):
                raise InvalidTronError('Invalid resource provided: Expected "BANDWIDTH" or "ENERGY"')

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

            if not is_integer(duration) or duration < 3:
                raise InvalidTronError('Invalid duration provided, minimum of 3 days')

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

            response = self.tron.manager.request('/wallet/freezebalance', {
                'owner_address': self.tron.address.to_hex(account),
                'frozen_balance': self.tron.toSun(amount),
                'frozen_duration': int(duration),
                'resource': resource
            })

            if 'Error' in response:
                raise TronError(response['Error'])

            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 the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

            if resource not in ('BANDWIDTH', 'ENERGY',):
                raise InvalidTronError('Invalid resource provided: Expected "BANDWIDTH" or "ENERGY"')

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

            response = self.tron.manager.request('/wallet/unfreezebalance', {
                'owner_address': self.tron.address.to_hex(account),
                'resource': resource
            })

            if 'Error' in response:
                raise ValueError(response['Error'])

            return response

        def purchase_token(self, to: str, token_id: str, amount: int, buyer=None):
            """Purchase a Token
            Creates an unsigned ICO token purchase transaction.

            Args:
                to (str): is the address of the Token issuer
                token_id (str): is the name of the token
                amount (int): is the number of tokens created
                buyer (str): is the address of the Token owner

            """

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

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

            if not len(token_id):
                raise ValueError('Invalid token ID provided')

            if amount <= 0:
                raise ValueError('Invalid amount provided')

            _to = self.tron.address.to_hex(to)
            _from = self.tron.address.to_hex(buyer)

            return self.tron.manager.request('/wallet/participateassetissue', {
                'to_address': _to,
                'owner_address': _from,
                'asset_name': self.tron.toHex(text=token_id),
                'amount': int(amount)
            })

        def withdraw_block_rewards(self, address: str = None):
            """Withdraw block rewards
            Creates an unsigned Super Representative award balance withdraw transaction.

            Args:
                address (str): Optional address to withdraw from.

            """
            if not address:
                address = self.tron.default_address.hex

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

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

        def apply_for_sr(self, url, address=None):
            """Apply to become a super representative

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

            """

            # If the address of the sender is not specified, we prescribe the default
            if address is None:
                address = self.tron.default_address.hex

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

            if not is_valid_url(url):
                raise TronError('Invalid url provided')

            return self.tron.manager.request('/wallet/createwitness', {
                'owner_address': self.tron.address.to_hex(address),
                'url': self.tron.toHex(text=url)
            })

        def vote(self, votes: List[Tuple[str, int]], voter_address: str = None):
            """Vote
            Vote on the super representative

            Args:
                votes (dict): dictionary of SR address : vote count key-value pair
                voter_address: voter address

            Examples:
                >>> from tronpytool import Tron
                >>> data = [
                >>>     ('TRJpw2uqohP7FUmAEJgt57wakRn6aGQU6Z', 1)
                >>> ]
                >>> tron = Tron()
                >>> tron.transaction.vote(data)

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

            _view_vote = []

            # We create a cycle to check all the received data for voting.
            for sr_address, vote_count in votes:
                if not self.tron.isAddress(sr_address):
                    raise InvalidAddress(
                        'Invalid SR address provided: ' + sr_address
                    )

                if not is_integer(vote_count) or vote_count <= 0:
                    raise ValueError(
                        'Invalid vote count provided for SR: ' + sr_address
                    )

                _view_vote.append({
                    'vote_address': self.tron.address.to_hex(sr_address),
                    'vote_count': int(vote_count)
                })

            return self.tron.manager.request('/wallet/votewitnessaccount', {
                'owner_address': self.tron.address.to_hex(voter_address),
                'votes': _view_vote
            })

        def create_proposal(self, parameters: Any, issuer_address=None):
            """Creates a proposal to modify the network.
            Can only be created by a current Super Representative.

            Args:
                parameters (Any): proposal parameters
                issuer_address: owner address

            Examples:
                >>> from tronpytool import Tron
                >>> data = [
                >>>     {'key': 1, 'value': 2},
                >>>     {'key': 1, 'value': 2}
                >>> ]
                >>> tron = Tron()
                >>> tron.transaction.create_proposal(data)

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

            if not self.tron.isAddress(issuer_address):
                raise InvalidAddress('Invalid issuerAddress provided')

            return self.tron.manager.request('/wallet/proposalcreate', {
                'owner_address': self.tron.address.to_hex(issuer_address),
                'parameters': parameters
            })

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

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

            """

            # If the address of the sender is not specified, we prescribe the default
            if voter_address is None:
                voter_address = self.tron.default_address.hex

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

            if not is_integer(proposal_id) or proposal_id < 0:
                raise TronError('Invalid proposal_id provided')

            if not is_boolean(has_approval):
                raise TronError('Invalid has_approval provided')

            return self.tron.manager.request('/wallet/proposalapprove', {
                'owner_address': self.tron.address.to_hex(voter_address),
                'proposal_id': int(proposal_id),
                'is_add_approval': bool(has_approval)
            })

        def delete_proposal(self, proposal_id: int, issuer_address: str = None):
            """Delete proposal

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

            Results:
                Delete the proposal's transaction

            """

            # If the address of the sender is not specified, we prescribe the default
            if issuer_address is None:
                issuer_address = self.tron.default_address.hex

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

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

            return self.tron.manager.request('/wallet/proposaldelete', {
                'owner_address': self.tron.address.to_hex(issuer_address),
                'proposal_id': int(proposal_id)
            })

        def update_account(self, account_name, account: str = None):
            """Modify account name

            Note: Username is allowed to edit only once.

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

            Returns:
                modified Transaction Object

            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

            if not is_string(account_name):
                raise ValueError('Name must be a string')

            if not self.tron.isAddress(account):
                raise TronError('Invalid origin address provided')

            response = self.tron.manager.request('/wallet/updateaccount', {
                'account_name': self.tron.toHex(text=account_name),
                'owner_address': self.tron.address.to_hex(account)
            })

            return response

        def create_smart_contract(self, **kwargs):
            """Deploy Contract

            Deploys a contract.
            Returns TransactionExtention, which contains an unsigned transaction.

            Example:
            .. code-block:: python
                >>> from tronpytool import Tron
                >>>
                >>> tron = Tron()
                >>> tron.transaction_builder.create_smart_contract(
                >>>    fee_limit=10**9,
                >>>    call_value=0,
                >>>    consume_user_resource_percent=10
                >>> )

            Args:
                **kwargs: Transaction parameters for the deployment
                transaction as a dict

            """

            if 'bytecode' not in kwargs:
                raise ValueError(
                    "Cannot deploy a contract that does not have 'bytecode' associated "
                    "with it"
                )

            # Maximum TRX consumption, measured in SUN (1 TRX = 1,000,000 SUN).
            fee_limit = kwargs.setdefault('fee_limit', 0)
            # The same as User Pay Ratio.
            # The percentage of resources specified for users who use this contract.
            # This field accepts integers between [0, 100].
            user_fee_percentage = kwargs.setdefault('consume_user_resource_percent', 0)
            # Amount of TRX transferred with this transaction, measured in SUN (1TRX = 1,000,000 SUN)
            call_value = kwargs.setdefault('call_value', 0)
            # Contract owner address, converted to a hex string
            owner_address = kwargs.setdefault('owner_address', self.tron.default_address.hex)
            # The max energy which will be consumed by the owner
            # in the process of excution or creation of the contract,
            # is an integer which should be greater than 0.
            origin_energy_limit = kwargs.setdefault('origin_energy_limit', 10000000)

            # parameters = kwargs.setdefault('parameters', []).append()
            # parameters = kwargs.setdefault('visible', []).append()
            # parameters = kwargs.setdefault('permission_id', []).append()

            if not is_integer(user_fee_percentage) and not user_fee_percentage:
                user_fee_percentage = 100

            if not is_hex(kwargs.get('bytecode')):
                raise ValueError('Invalid bytecode provided')

            if not is_integer(fee_limit) or fee_limit <= 0 or \
                    fee_limit > 1000000000:
                raise ValueError('Invalid fee limit provided')

            if not is_integer(call_value) or call_value < 0:
                raise ValueError('Invalid call value provided')

            if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                    user_fee_percentage > 100:
                raise ValueError('Invalid user fee percentage provided')

            if not is_integer(origin_energy_limit) or origin_energy_limit < 0:
                return ValueError('Invalid origin_energy_limit provided')

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid issuer address provided')

            # We write all the results in one object
            transaction = dict(**kwargs)
            transaction.setdefault('owner_address', self.tron.address.to_hex(owner_address))

            return self.tron.manager.request('/wallet/deploycontract', transaction)

        def trigger_smart_contract_constant(self, kv: dict):

            contract_address = kv.setdefault('contract_address', None)
            function_selector = kv.setdefault('function_selector', None)

            issuer_address = kv.setdefault('issuer_address', self.tron.default_address.hex)
            call_value = kv.setdefault('call_value', 0)
            fee_limit = kv.setdefault('fee_limit', 1000000000)
            token_value = kv.setdefault('token_value', 0)
            token_id = kv.setdefault('token_id', 0)

            if not is_integer(token_value) or token_value < 0:
                raise ValueError('Invalid options.tokenValue provided')

            if not is_integer(token_id) or token_id < 0:
                raise ValueError('Invalid options.tokenId provided')

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

            if not is_string(function_selector):
                raise ValueError('Invalid function selector provided')

            if not is_integer(call_value) or call_value < 0:
                raise ValueError('Invalid call value provided')

            if not is_integer(fee_limit) or fee_limit <= 0 or fee_limit > 1000000000:
                raise ValueError('Invalid fee limit provided')

            """remove all the spaces"""
            function_selector = function_selector.replace('/\s*/g', '')

            if hasattr(kv, "parameters") and len(kv['parameters']) > 0:
                types = []
                values = []
                parameters = kv['parameters']
                for abi in parameters:
                    if 'type' not in abi or not is_string(abi['type']):
                        raise ValueError('Invalid parameter type provided: ' + abi['type'])

                    if abi['type'] == 'address':
                        abi['value'] = self.tron.address.to_hex(abi['value']).replace('41', '0x', 1)

                    types.append(abi['type'])
                    values.append(abi['value'])

                try:
                    parameters = encode_hex(encode_abi(types, values)).replace('0x', '', 2)
                except ValueError as ex:
                    print(ex)

            else:
                parameters = []

            self.debug_input_kv(kv)

            data = {
                'contract_address': self.tron.address.to_hex(contract_address),
                'owner_address': issuer_address.hex,
                'function_selector': function_selector,
                'fee_limit': int(fee_limit),
                'call_value': int(call_value),
                'parameter': parameters
            }

            if token_value:
                data['call_token_value'] = int(token_value)

            if token_id:
                data['token_id'] = int(token_id)

            self.debug_url_req(data)

            return self.tron.manager.request('/wallet/triggerconstantcontract', kv)

        def trigger_smart_contract(self, kv: dict):

            """Trigger Smart Contract
            Calls a function on a contract

            Args:
                **kv: Fill in the required parameters

            Examples:
                >>> tron = Tron()
                >>> tron.transaction_builder.trigger_smart_contract(
                >>>     contract_address='413c8143e98b3e2fe1b1a8fb82b34557505a752390',
                >>>     function_selector='set(uint256,uint256)',
                >>>     fee_limit=30000,
                >>>     call_value=0,
                >>>     parameters=[
                >>>        {'type': 'int256', 'value': 1},
                >>>        {'type': 'int256', 'value': 1}])

            Returns:
                TransactionExtention, TransactionExtention contains unsigned Transaction
            """

            contract_address = kv.setdefault('contract_address', None)
            function_selector = kv.setdefault('function_selector', None)

            issuer_address = kv.setdefault('issuer_address', self.tron.default_address.hex)
            call_value = kv.setdefault('call_value', 0)
            fee_limit = kv.setdefault('fee_limit', 1000000000)
            token_value = kv.setdefault('token_value', 0)
            token_id = kv.setdefault('token_id', 0)
            parameters = kv.setdefault('parameters', [])

            if not is_integer(token_value) or token_value < 0:
                raise ValueError('Invalid options.tokenValue provided')

            if not is_integer(token_id) or token_id < 0:
                raise ValueError('Invalid options.tokenId provided')

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

            if not is_string(function_selector):
                raise ValueError('Invalid function selector provided')

            if not is_integer(call_value) or call_value < 0:
                raise ValueError('Invalid call value provided')

            if not is_integer(fee_limit) or fee_limit <= 0 or fee_limit > 1000000000:
                raise ValueError('Invalid fee limit provided')

            """remove all the spaces"""
            function_selector = function_selector.replace('/\s*/g', '')
            print(parameters)
            print("-------------- this is the last parameters.. ")
            if len(parameters) > 0:
                types = []
                values = []
                for abi in parameters:
                    if 'type' not in abi or not is_string(abi['type']):
                        raise ValueError('Invalid parameter type provided: ' + abi['type'])
                    if abi['type'] == 'address':
                        abi['value'] = self.tron.address.to_hex(abi['value']).replace('41', '0x', 1)
                    types.append(abi['type'])
                    values.append(abi['value'])

                try:
                    parameters = encode_hex(encode_abi(types, values)).replace('0x', '', 2)
                except ValueError as ex:
                    print(ex)

            else:
                parameters = ''

            data = {
                'contract_address': self.tron.address.to_hex(contract_address),
                'owner_address': issuer_address.hex,
                'function_selector': function_selector,
                'fee_limit': int(fee_limit),
                'call_value': int(call_value),
                'parameter': parameters
            }

            # if parameters is '':
            #    data.pop('parameter')
            self.debug_input_kv(kv)
            if token_value:
                data['call_token_value'] = int(token_value)

            if token_id:
                data['token_id'] = int(token_id)
            self.debug_url_req(data)
            return self.tron.manager.request('/wallet/triggersmartcontract', data)

        def debug_url_req(self, data):
            if self.debug:
                print("==data load on request url")
                print(data)
                print("==end")

        def debug_input_kv(self, data):
            if self.debug:
                print("==checking input data")
                print(data)
                print("==end")

        def create_trx_exchange(self,
                                token_name: str,
                                token_balance: int,
                                trx_balance: int,
                                account: str = None):
            """Create an exchange between a token and TRX.
            Token Name should be a CASE SENSITIVE string.
            Note: PLEASE VERIFY THIS ON TRONSCAN.

            Args:
                token_name (str): Token Name
                token_balance (int): balance of the first token
                trx_balance (int): balance of the second token
                account (str): Owner Address
            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

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

            if token_balance <= 0 or trx_balance <= 0:
                raise TronError('Invalid amount provided')

            return self.tron.manager.request('/wallet/exchangecreate', {
                'owner_address': self.tron.address.to_hex(account),
                'first_token_id': self.tron.toHex(text=token_name),
                'first_token_balance': token_balance,
                'second_token_id': '5f',
                'second_token_balance': trx_balance
            })

        def create_token_exchange(self,
                                  first_token_name: str,
                                  first_token_balance: int,
                                  second_token_name: str,
                                  second_token_balance: int,
                                  owner_address: str = None):
            """Create an exchange between a token and another token.
            DO NOT USE THIS FOR TRX.
            Token Names should be a CASE SENSITIVE string.

            Args:
                first_token_name (str): the id of the first token
                first_token_balance (int): balance of the first token
                second_token_name (str): the id of the second token
                second_token_balance (int): balance of the second token
                owner_address: owner address

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

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

            if second_token_balance <= 0 or first_token_balance <= 0:
                raise ValueError('Invalid amount provided')

            return self.tron.manager.request('/wallet/exchangecreate', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'first_token_id': self.tron.toHex(text=first_token_name),
                'first_token_balance': first_token_balance,
                'second_token_id': self.tron.toHex(text=second_token_name),
                'second_token_balance': second_token_balance
            })

        def inject_exchange_tokens(self,
                                   exchange_id: int,
                                   token_name: str,
                                   token_amount: int = 0,
                                   owner_address: str = None):
            """Adds tokens into a bancor style exchange.
            Will add both tokens at market rate.

            Args:
                exchange_id (int): non-negative integer exchange id
                token_name (str): token name
                token_amount (int): amount of token
                owner_address (str): token owner address in hex

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if exchange_id < 0:
                raise ValueError('Invalid exchange_id provided')

            if token_amount < 1:
                raise ValueError('Invalid token_amount provided')

            return self.tron.manager.request('/wallet/exchangeinject', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'exchange_id': exchange_id,
                'token_id': self.tron.toHex(text=token_name),
                'quant': token_amount
            })

        def create_token(self, **kwargs):
            """Issue Token

            Issuing a token on the TRON Protocol can be done by anyone
            who has at least 1024 TRX in their account.
            When a token is issued it will be shown on the token overview page.
            Users can then participate within the issuing time and exchange their
            TRX for tokens.After issuing the token your account will
            receive the amount of tokens equal to the total supply.
            When other users exchange their TRX for tokens then the tokens
            will be withdrawn from your account and you will receive
            TRX equal to the specified exchange rate.

            Args:
                **kwargs: Fill in the required parameters

            Examples:

                >>> start_func = datetime.now()
                >>> start = int(start_func.timestamp() * 1000)
                >>>
                >>> end_func = datetime.now() + timedelta(days=2)
                >>> end = int(end_func.timestamp() * 1000)
                >>>
                >>> opt = {
                >>>     'name': 'Tron',
                >>>     'abbreviation': 'TRX',
                >>>     'description': 'Hello World',
                >>>     'url': 'https://github.com',
                >>>     'totalSupply': 25000000,
                >>>     'frozenAmount': 1,
                >>>     'frozenDuration': 2,
                >>>     'freeBandwidth': 10000,
                >>>     'freeBandwidthLimit': 10000,
                >>>     'saleStart': start,
                >>>     'saleEnd': end,
                >>>     'voteScore': 1
                >>> }

            """
            issuer_address = kwargs.setdefault(
                'issuer_address', self.tron.default_address.hex
            )

            if not self.tron.isAddress(issuer_address):
                raise TronError('Invalid issuer address provided')

            total_supply = kwargs.setdefault('totalSupply', 0)
            trx_ratio = kwargs.setdefault('trxRatio', 1)
            token_ratio = kwargs.setdefault('tokenRatio', 1)
            sale_start = kwargs.setdefault(
                'saleStart', START_DATE
            )
            free_bandwidth = kwargs.setdefault('freeBandwidth', 0)
            free_bandwidth_limit = kwargs.setdefault('freeBandwidthLimit', 0)
            frozen_amount = kwargs.setdefault('frozenAmount', 0)
            frozen_duration = kwargs.setdefault('frozenDuration', 0)
            vote_score = kwargs.setdefault('voteScore', 0)
            precision = kwargs.setdefault('precision', 0)

            if not is_string(kwargs.get('name')):
                raise ValueError('Invalid token name provided')

            if not is_string(kwargs.get('abbreviation')):
                raise ValueError('Invalid token abbreviation provided')

            if not is_integer(total_supply) or total_supply <= 0:
                raise ValueError('Invalid supply amount provided')

            if not is_integer(trx_ratio) or trx_ratio <= 0:
                raise ValueError('TRX ratio must be a positive integer')

            if not is_integer(token_ratio) or token_ratio <= 0:
                raise ValueError('Token ratio must be a positive integer')

            if not is_integer(vote_score) or vote_score <= 0:
                raise ValueError('voteScore must be a positive integer greater than 0')

            if not is_integer(precision) or precision <= 0 or precision > 6:
                raise ValueError('precision must be a positive integer > 0 and <= 6')

            if not is_integer(sale_start) or sale_start < START_DATE:
                raise ValueError('Invalid sale start timestamp provided')

            if not is_integer(kwargs.get('saleEnd')) or \
                    kwargs.get('saleEnd') <= sale_start:
                raise ValueError('Invalid sale end timestamp provided')

            if not is_string(kwargs.get('description')):
                raise ValueError('Invalid token description provided')

            if not is_valid_url(kwargs.get('url')):
                raise ValueError('Invalid token url provided')

            if not is_integer(free_bandwidth) or free_bandwidth < 0:
                raise ValueError('Invalid free bandwidth amount provided')

            if not is_integer(free_bandwidth_limit) or free_bandwidth_limit < 0 \
                    or (free_bandwidth and not free_bandwidth_limit):
                raise ValueError('Invalid free bandwidth limit provided')

            if not is_integer(frozen_amount) or frozen_amount < 0 \
                    or (not frozen_duration and frozen_amount):
                raise ValueError('Invalid frozen supply provided')

            if not is_integer(frozen_duration) or frozen_duration < 0 \
                    or (frozen_duration and not frozen_amount):
                raise ValueError('Invalid frozen duration provided')

            frozen_supply = {
                'frozen_amount': int(frozen_amount),
                'frozen_days': int(frozen_duration)
            }

            response = self.tron.manager.request('/wallet/createassetissue', {
                'owner_address': self.tron.address.to_hex(issuer_address),
                'name': self.tron.toHex(text=kwargs.get('name')),
                'abbr': self.tron.toHex(text=kwargs.get('abbreviation')),
                'description': self.tron.toHex(text=kwargs.get('description')),
                'url': self.tron.toHex(text=kwargs.get('url')),
                'total_supply': int(total_supply),
                'trx_num': int(trx_ratio),
                'num': int(token_ratio),
                'start_time': int(sale_start),
                'end_time': int(kwargs.get('saleEnd')),
                'free_asset_net_limit': int(free_bandwidth),
                'public_free_asset_net_limit': int(free_bandwidth_limit),
                'frozen_supply': frozen_supply,
                'vote_score': vote_score,
                'precision': precision
            })

            return response

        def withdraw_exchange_tokens(self,
                                     exchange_id: int,
                                     token_name: str,
                                     token_amount: int = 0,
                                     owner_address: str = None):
            """Withdraws tokens from a bancor style exchange.
            Will withdraw at market rate both tokens.

            Args:
                exchange_id (int): non-negative integer exchange id
                token_name (str): token name
                token_amount (int): number of tokens withdraw
                owner_address (str): owner address in hex

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if exchange_id < 0:
                raise ValueError('Invalid exchange_id provided')

            if token_amount < 1:
                raise ValueError('Invalid token_amount provided')

            return self.tron.manager.request('/wallet/exchangewithdraw', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'exchange_id': exchange_id,
                'token_id': self.tron.toHex(text=token_name),
                'quant': token_amount
            })

        def trade_exchange_tokens(self,
                                  exchange_id: int,
                                  token_name: str,
                                  token_amount_sold: int = 0,
                                  token_amount_expected: int = 0,
                                  owner_address: str = None):
            """Trade tokens on a bancor style exchange.
            Expected value is a validation and used to cap the total amt of token 2 spent.

            Args:
                exchange_id (int): non-negative integer exchange id
                token_name (str): token name
                token_amount_sold (int): amount f token actually sold
                token_amount_expected (int): amount of token expected
                owner_address (str): token owner address in hex

            """

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if exchange_id < 0:
                raise ValueError('Invalid exchange_id provided')

            if token_amount_sold < 1:
                raise ValueError('Invalid token_amount_sold provided')

            if token_amount_expected < 1:
                raise ValueError('Invalid token_amount_expected provided')

            return self.tron.manager.request('/wallet/exchangewithdraw', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'exchange_id': exchange_id,
                'token_id': self.tron.toHex(text=token_name),
                'quant': token_amount_sold,
                'expected': token_amount_expected
            })

        def update_setting(self,
                           contract_address,
                           user_fee_percentage,
                           owner_address: str = None):
            """Update userFeePercentage.

            Args:
                contract_address (str): the address of the contract to be modified
                user_fee_percentage (int): the percentage of resources specified for users using this contract
                owner_address (str): is the address of the creator

            Returns:
                Contains unsigned transaction Transaction
            """

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if not self.tron.isAddress(contract_address):
                raise InvalidAddress('Invalid contract_address provided')

            if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                    user_fee_percentage > 100:
                raise ValueError('Invalid user_fee_percentage provided')

            return self.tron.manager.request('wallet/updatesetting', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'contract_address': self.tron.address.to_hex(contract_address),
                'consume_user_resource_percent': user_fee_percentage
            })

        def update_energy_limit(self,
                                contract_address,
                                origin_energy_limit,
                                owner_address: str = None):
            """Update energy limit.

            Args:
                contract_address (str): The address of the contract to be modified
                origin_energy_limit (int): The maximum energy set by the creator that is created
                owner_address (str): Is the address of the creator

            Returns:
                Contains unsigned transaction Transaction
            """

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if not self.tron.isAddress(contract_address):
                raise InvalidAddress('Invalid contractAddress provided')

            if not is_integer(origin_energy_limit) or origin_energy_limit < 0 or \
                    origin_energy_limit > 10000000:
                raise ValueError('Invalid originEnergyLimit  provided')

            return self.tron.manager.request('wallet/updateenergylimit', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'contract_address': self.tron.address.to_hex(contract_address),
                'origin_energy_limit': origin_energy_limit
            })

        def check_permissions(self, permissions, _type):
            if permissions is not None:
                if permissions['type'] != _type or \
                        not permissions['permission_name'] or \
                        not is_string(permissions['permission_name']) or \
                        not is_integer(permissions['threshold']) or \
                        permissions['threshold'] < 1 or not permissions['keys']:
                    return False

            for key in permissions['key']:
                if not self.tron.isAddress(key['address']) or \
                        not is_integer(key['weight']) or \
                        key['weight'] > permissions['threshold'] or \
                        key['weight'] < 1 or _type == 2 and not permissions['operations']:
                    return False

            return True

        def update_account_permissions(self, owner_address=None,
                                       owner_permissions=None,
                                       witness_permissions=None,
                                       actives_permissions=None
                                       ):
            """Role: update user permissions (for multi-signature)

            Args:
                owner_address (str): The address of the account whose permissions are to be modified
                owner_permissions: Modified owner permission
                witness_permissions: Modified witness permission (if it is a witness)
                actives_permissions: Modified actives permission
            """

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

            if not self.check_permissions(owner_permissions, 0):
                raise InvalidTronError('Invalid ownerPermissions provided')

            if not self.check_permissions(witness_permissions, 1):
                raise InvalidTronError('Invalid witnessPermissions provided')

            for actives_permission in actives_permissions:
                if not self.check_permissions(actives_permission, 2):
                    raise InvalidTronError('Invalid activesPermissions provided')

            data = {
                owner_address: owner_address
            }

            if owner_permissions:
                data['owner'] = owner_permissions

            if witness_permissions:
                data['witness'] = witness_permissions

            if actives_permissions:
                if len(actives_permissions) == 1:
                    data['actives'] = actives_permissions[0]
                else:
                    data['actives'] = actives_permissions

            return self.tron.manager.request('wallet/accountpermissionupdate', data)

## Classes

`class TransactionBuilder (tron)`
  Expand source code

      class TransactionBuilder(object):
          debug = True

          def __init__(self, tron):
              self.tron = tron

          def setDebug(self, b: bool) -> None:
              self.debug = b

          def send_transaction(self, to, amount, account=None):
              """Creates a transaction of transfer.
              If the recipient address does not exist, a corresponding account will be created.

              Args:
                  to (str): to address
                  amount (float): amount
                  account (str): from address

              Returns:
                  Transaction contract data

              """

              # If the address of the sender is not specified, we prescribe the default
              if account is None:
                  account = self.tron.default_address.hex

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

              if not isinstance(amount, float) or amount <= 0:
                  raise InvalidTronError('Invalid amount provided')

              _to = self.tron.address.to_hex(to)
              _from = self.tron.address.to_hex(account)

              if _to == _from:
                  raise TronError('Cannot transfer TRX to the same account')

              response = self.tron.manager.request('/wallet/createtransaction', {
                  'to_address': _to,
                  'owner_address': _from,
                  'amount': self.tron.toSun(amount)
              })

              return response

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

              Args:
                  to (str): is the recipient address
                  amount (int): is the amount of token to transfer. must be integer instead of float
                  token_id (any): Token Name and id
                  account: (str): is the address of the withdrawal account

              Returns:
                  Token transfer Transaction raw data

              """

              # If the address of the sender is not specified, we prescribe the default
              if account is None:
                  account = self.tron.default_address.hex

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

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

              if not token_id:
                  raise InvalidTronError('Invalid token ID provided')

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

              _to = self.tron.address.to_hex(to)
              _from = self.tron.address.to_hex(account)
              _token_id = self.tron.toHex(text=str(token_id))

              if _to == _from:
                  raise TronError('Cannot transfer TRX to the same account')

              # In case if "TRX" is specified, we redirect to another method.
              if is_string(token_id) and token_id.upper() == 'TRX':
                  return self.send_transaction(_to, amount, _from)

              return self.tron.manager.request('/wallet/transferasset', {
                  'to_address': _to,
                  'owner_address': _from,
                  'asset_name': _token_id,
                  'amount': amount
              })

          def freeze_balance(self, amount, duration, resource, 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 the address of the sender is not specified, we prescribe the default
              if account is None:
                  account = self.tron.default_address.hex

              if resource not in ('BANDWIDTH', 'ENERGY',):
                  raise InvalidTronError('Invalid resource provided: Expected "BANDWIDTH" or "ENERGY"')

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

              if not is_integer(duration) or duration < 3:
                  raise InvalidTronError('Invalid duration provided, minimum of 3 days')

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

              response = self.tron.manager.request('/wallet/freezebalance', {
                  'owner_address': self.tron.address.to_hex(account),
                  'frozen_balance': self.tron.toSun(amount),
                  'frozen_duration': int(duration),
                  'resource': resource
              })

              if 'Error' in response:
                  raise TronError(response['Error'])

              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 the address of the sender is not specified, we prescribe the default
              if account is None:
                  account = self.tron.default_address.hex

              if resource not in ('BANDWIDTH', 'ENERGY',):
                  raise InvalidTronError('Invalid resource provided: Expected "BANDWIDTH" or "ENERGY"')

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

              response = self.tron.manager.request('/wallet/unfreezebalance', {
                  'owner_address': self.tron.address.to_hex(account),
                  'resource': resource
              })

              if 'Error' in response:
                  raise ValueError(response['Error'])

              return response

          def purchase_token(self, to: str, token_id: str, amount: int, buyer=None):
              """Purchase a Token
              Creates an unsigned ICO token purchase transaction.

              Args:
                  to (str): is the address of the Token issuer
                  token_id (str): is the name of the token
                  amount (int): is the number of tokens created
                  buyer (str): is the address of the Token owner

              """

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

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

              if not len(token_id):
                  raise ValueError('Invalid token ID provided')

              if amount <= 0:
                  raise ValueError('Invalid amount provided')

              _to = self.tron.address.to_hex(to)
              _from = self.tron.address.to_hex(buyer)

              return self.tron.manager.request('/wallet/participateassetissue', {
                  'to_address': _to,
                  'owner_address': _from,
                  'asset_name': self.tron.toHex(text=token_id),
                  'amount': int(amount)
              })

          def withdraw_block_rewards(self, address: str = None):
              """Withdraw block rewards
              Creates an unsigned Super Representative award balance withdraw transaction.

              Args:
                  address (str): Optional address to withdraw from.

              """
              if not address:
                  address = self.tron.default_address.hex

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

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

          def apply_for_sr(self, url, address=None):
              """Apply to become a super representative

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

              """

              # If the address of the sender is not specified, we prescribe the default
              if address is None:
                  address = self.tron.default_address.hex

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

              if not is_valid_url(url):
                  raise TronError('Invalid url provided')

              return self.tron.manager.request('/wallet/createwitness', {
                  'owner_address': self.tron.address.to_hex(address),
                  'url': self.tron.toHex(text=url)
              })

          def vote(self, votes: List[Tuple[str, int]], voter_address: str = None):
              """Vote
              Vote on the super representative

              Args:
                  votes (dict): dictionary of SR address : vote count key-value pair
                  voter_address: voter address

              Examples:
                  >>> from tronpytool import Tron
                  >>> data = [
                  >>>     ('TRJpw2uqohP7FUmAEJgt57wakRn6aGQU6Z', 1)
                  >>> ]
                  >>> tron = Tron()
                  >>> tron.transaction.vote(data)

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

              _view_vote = []

              # We create a cycle to check all the received data for voting.
              for sr_address, vote_count in votes:
                  if not self.tron.isAddress(sr_address):
                      raise InvalidAddress(
                          'Invalid SR address provided: ' + sr_address
                      )

                  if not is_integer(vote_count) or vote_count <= 0:
                      raise ValueError(
                          'Invalid vote count provided for SR: ' + sr_address
                      )

                  _view_vote.append({
                      'vote_address': self.tron.address.to_hex(sr_address),
                      'vote_count': int(vote_count)
                  })

              return self.tron.manager.request('/wallet/votewitnessaccount', {
                  'owner_address': self.tron.address.to_hex(voter_address),
                  'votes': _view_vote
              })

          def create_proposal(self, parameters: Any, issuer_address=None):
              """Creates a proposal to modify the network.
              Can only be created by a current Super Representative.

              Args:
                  parameters (Any): proposal parameters
                  issuer_address: owner address

              Examples:
                  >>> from tronpytool import Tron
                  >>> data = [
                  >>>     {'key': 1, 'value': 2},
                  >>>     {'key': 1, 'value': 2}
                  >>> ]
                  >>> tron = Tron()
                  >>> tron.transaction.create_proposal(data)

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

              if not self.tron.isAddress(issuer_address):
                  raise InvalidAddress('Invalid issuerAddress provided')

              return self.tron.manager.request('/wallet/proposalcreate', {
                  'owner_address': self.tron.address.to_hex(issuer_address),
                  'parameters': parameters
              })

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

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

              """

              # If the address of the sender is not specified, we prescribe the default
              if voter_address is None:
                  voter_address = self.tron.default_address.hex

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

              if not is_integer(proposal_id) or proposal_id < 0:
                  raise TronError('Invalid proposal_id provided')

              if not is_boolean(has_approval):
                  raise TronError('Invalid has_approval provided')

              return self.tron.manager.request('/wallet/proposalapprove', {
                  'owner_address': self.tron.address.to_hex(voter_address),
                  'proposal_id': int(proposal_id),
                  'is_add_approval': bool(has_approval)
              })

          def delete_proposal(self, proposal_id: int, issuer_address: str = None):
              """Delete proposal

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

              Results:
                  Delete the proposal's transaction

              """

              # If the address of the sender is not specified, we prescribe the default
              if issuer_address is None:
                  issuer_address = self.tron.default_address.hex

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

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

              return self.tron.manager.request('/wallet/proposaldelete', {
                  'owner_address': self.tron.address.to_hex(issuer_address),
                  'proposal_id': int(proposal_id)
              })

          def update_account(self, account_name, account: str = None):
              """Modify account name

              Note: Username is allowed to edit only once.

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

              Returns:
                  modified Transaction Object

              """

              # If the address of the sender is not specified, we prescribe the default
              if account is None:
                  account = self.tron.default_address.hex

              if not is_string(account_name):
                  raise ValueError('Name must be a string')

              if not self.tron.isAddress(account):
                  raise TronError('Invalid origin address provided')

              response = self.tron.manager.request('/wallet/updateaccount', {
                  'account_name': self.tron.toHex(text=account_name),
                  'owner_address': self.tron.address.to_hex(account)
              })

              return response

          def create_smart_contract(self, **kwargs):
              """Deploy Contract

              Deploys a contract.
              Returns TransactionExtention, which contains an unsigned transaction.

              Example:
              .. code-block:: python
                  >>> from tronpytool import Tron
                  >>>
                  >>> tron = Tron()
                  >>> tron.transaction_builder.create_smart_contract(
                  >>>    fee_limit=10**9,
                  >>>    call_value=0,
                  >>>    consume_user_resource_percent=10
                  >>> )

              Args:
                  **kwargs: Transaction parameters for the deployment
                  transaction as a dict

              """

              if 'bytecode' not in kwargs:
                  raise ValueError(
                      "Cannot deploy a contract that does not have 'bytecode' associated "
                      "with it"
                  )

              # Maximum TRX consumption, measured in SUN (1 TRX = 1,000,000 SUN).
              fee_limit = kwargs.setdefault('fee_limit', 0)
              # The same as User Pay Ratio.
              # The percentage of resources specified for users who use this contract.
              # This field accepts integers between [0, 100].
              user_fee_percentage = kwargs.setdefault('consume_user_resource_percent', 0)
              # Amount of TRX transferred with this transaction, measured in SUN (1TRX = 1,000,000 SUN)
              call_value = kwargs.setdefault('call_value', 0)
              # Contract owner address, converted to a hex string
              owner_address = kwargs.setdefault('owner_address', self.tron.default_address.hex)
              # The max energy which will be consumed by the owner
              # in the process of excution or creation of the contract,
              # is an integer which should be greater than 0.
              origin_energy_limit = kwargs.setdefault('origin_energy_limit', 10000000)

              # parameters = kwargs.setdefault('parameters', []).append()
              # parameters = kwargs.setdefault('visible', []).append()
              # parameters = kwargs.setdefault('permission_id', []).append()

              if not is_integer(user_fee_percentage) and not user_fee_percentage:
                  user_fee_percentage = 100

              if not is_hex(kwargs.get('bytecode')):
                  raise ValueError('Invalid bytecode provided')

              if not is_integer(fee_limit) or fee_limit <= 0 or \
                      fee_limit > 1000000000:
                  raise ValueError('Invalid fee limit provided')

              if not is_integer(call_value) or call_value < 0:
                  raise ValueError('Invalid call value provided')

              if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                      user_fee_percentage > 100:
                  raise ValueError('Invalid user fee percentage provided')

              if not is_integer(origin_energy_limit) or origin_energy_limit < 0:
                  return ValueError('Invalid origin_energy_limit provided')

              if not self.tron.isAddress(owner_address):
                  raise InvalidAddress('Invalid issuer address provided')

              # We write all the results in one object
              transaction = dict(**kwargs)
              transaction.setdefault('owner_address', self.tron.address.to_hex(owner_address))

              return self.tron.manager.request('/wallet/deploycontract', transaction)

          def trigger_smart_contract_constant(self, kv: dict):

              contract_address = kv.setdefault('contract_address', None)
              function_selector = kv.setdefault('function_selector', None)

              issuer_address = kv.setdefault('issuer_address', self.tron.default_address.hex)
              call_value = kv.setdefault('call_value', 0)
              fee_limit = kv.setdefault('fee_limit', 1000000000)
              token_value = kv.setdefault('token_value', 0)
              token_id = kv.setdefault('token_id', 0)

              if not is_integer(token_value) or token_value < 0:
                  raise ValueError('Invalid options.tokenValue provided')

              if not is_integer(token_id) or token_id < 0:
                  raise ValueError('Invalid options.tokenId provided')

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

              if not is_string(function_selector):
                  raise ValueError('Invalid function selector provided')

              if not is_integer(call_value) or call_value < 0:
                  raise ValueError('Invalid call value provided')

              if not is_integer(fee_limit) or fee_limit <= 0 or fee_limit > 1000000000:
                  raise ValueError('Invalid fee limit provided')

              """remove all the spaces"""
              function_selector = function_selector.replace('/\s*/g', '')

              if hasattr(kv, "parameters") and len(kv['parameters']) > 0:
                  types = []
                  values = []
                  parameters = kv['parameters']
                  for abi in parameters:
                      if 'type' not in abi or not is_string(abi['type']):
                          raise ValueError('Invalid parameter type provided: ' + abi['type'])

                      if abi['type'] == 'address':
                          abi['value'] = self.tron.address.to_hex(abi['value']).replace('41', '0x', 1)

                      types.append(abi['type'])
                      values.append(abi['value'])

                  try:
                      parameters = encode_hex(encode_abi(types, values)).replace('0x', '', 2)
                  except ValueError as ex:
                      print(ex)

              else:
                  parameters = []

              self.debug_input_kv(kv)

              data = {
                  'contract_address': self.tron.address.to_hex(contract_address),
                  'owner_address': issuer_address.hex,
                  'function_selector': function_selector,
                  'fee_limit': int(fee_limit),
                  'call_value': int(call_value),
                  'parameter': parameters
              }

              if token_value:
                  data['call_token_value'] = int(token_value)

              if token_id:
                  data['token_id'] = int(token_id)

              self.debug_url_req(data)

              return self.tron.manager.request('/wallet/triggerconstantcontract', kv)

          def trigger_smart_contract(self, kv: dict):

              """Trigger Smart Contract
              Calls a function on a contract

              Args:
                  **kv: Fill in the required parameters

              Examples:
                  >>> tron = Tron()
                  >>> tron.transaction_builder.trigger_smart_contract(
                  >>>     contract_address='413c8143e98b3e2fe1b1a8fb82b34557505a752390',
                  >>>     function_selector='set(uint256,uint256)',
                  >>>     fee_limit=30000,
                  >>>     call_value=0,
                  >>>     parameters=[
                  >>>        {'type': 'int256', 'value': 1},
                  >>>        {'type': 'int256', 'value': 1}])

              Returns:
                  TransactionExtention, TransactionExtention contains unsigned Transaction
              """

              contract_address = kv.setdefault('contract_address', None)
              function_selector = kv.setdefault('function_selector', None)

              issuer_address = kv.setdefault('issuer_address', self.tron.default_address.hex)
              call_value = kv.setdefault('call_value', 0)
              fee_limit = kv.setdefault('fee_limit', 1000000000)
              token_value = kv.setdefault('token_value', 0)
              token_id = kv.setdefault('token_id', 0)
              parameters = kv.setdefault('parameters', [])

              if not is_integer(token_value) or token_value < 0:
                  raise ValueError('Invalid options.tokenValue provided')

              if not is_integer(token_id) or token_id < 0:
                  raise ValueError('Invalid options.tokenId provided')

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

              if not is_string(function_selector):
                  raise ValueError('Invalid function selector provided')

              if not is_integer(call_value) or call_value < 0:
                  raise ValueError('Invalid call value provided')

              if not is_integer(fee_limit) or fee_limit <= 0 or fee_limit > 1000000000:
                  raise ValueError('Invalid fee limit provided')

              """remove all the spaces"""
              function_selector = function_selector.replace('/\s*/g', '')
              print(parameters)
              print("-------------- this is the last parameters.. ")
              if len(parameters) > 0:
                  types = []
                  values = []
                  for abi in parameters:
                      if 'type' not in abi or not is_string(abi['type']):
                          raise ValueError('Invalid parameter type provided: ' + abi['type'])
                      if abi['type'] == 'address':
                          abi['value'] = self.tron.address.to_hex(abi['value']).replace('41', '0x', 1)
                      types.append(abi['type'])
                      values.append(abi['value'])

                  try:
                      parameters = encode_hex(encode_abi(types, values)).replace('0x', '', 2)
                  except ValueError as ex:
                      print(ex)

              else:
                  parameters = ''

              data = {
                  'contract_address': self.tron.address.to_hex(contract_address),
                  'owner_address': issuer_address.hex,
                  'function_selector': function_selector,
                  'fee_limit': int(fee_limit),
                  'call_value': int(call_value),
                  'parameter': parameters
              }

              # if parameters is '':
              #    data.pop('parameter')
              self.debug_input_kv(kv)
              if token_value:
                  data['call_token_value'] = int(token_value)

              if token_id:
                  data['token_id'] = int(token_id)
              self.debug_url_req(data)
              return self.tron.manager.request('/wallet/triggersmartcontract', data)

          def debug_url_req(self, data):
              if self.debug:
                  print("==data load on request url")
                  print(data)
                  print("==end")

          def debug_input_kv(self, data):
              if self.debug:
                  print("==checking input data")
                  print(data)
                  print("==end")

          def create_trx_exchange(self,
                                  token_name: str,
                                  token_balance: int,
                                  trx_balance: int,
                                  account: str = None):
              """Create an exchange between a token and TRX.
              Token Name should be a CASE SENSITIVE string.
              Note: PLEASE VERIFY THIS ON TRONSCAN.

              Args:
                  token_name (str): Token Name
                  token_balance (int): balance of the first token
                  trx_balance (int): balance of the second token
                  account (str): Owner Address
              """

              # If the address of the sender is not specified, we prescribe the default
              if account is None:
                  account = self.tron.default_address.hex

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

              if token_balance <= 0 or trx_balance <= 0:
                  raise TronError('Invalid amount provided')

              return self.tron.manager.request('/wallet/exchangecreate', {
                  'owner_address': self.tron.address.to_hex(account),
                  'first_token_id': self.tron.toHex(text=token_name),
                  'first_token_balance': token_balance,
                  'second_token_id': '5f',
                  'second_token_balance': trx_balance
              })

          def create_token_exchange(self,
                                    first_token_name: str,
                                    first_token_balance: int,
                                    second_token_name: str,
                                    second_token_balance: int,
                                    owner_address: str = None):
              """Create an exchange between a token and another token.
              DO NOT USE THIS FOR TRX.
              Token Names should be a CASE SENSITIVE string.

              Args:
                  first_token_name (str): the id of the first token
                  first_token_balance (int): balance of the first token
                  second_token_name (str): the id of the second token
                  second_token_balance (int): balance of the second token
                  owner_address: owner address

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

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

              if second_token_balance <= 0 or first_token_balance <= 0:
                  raise ValueError('Invalid amount provided')

              return self.tron.manager.request('/wallet/exchangecreate', {
                  'owner_address': self.tron.address.to_hex(owner_address),
                  'first_token_id': self.tron.toHex(text=first_token_name),
                  'first_token_balance': first_token_balance,
                  'second_token_id': self.tron.toHex(text=second_token_name),
                  'second_token_balance': second_token_balance
              })

          def inject_exchange_tokens(self,
                                     exchange_id: int,
                                     token_name: str,
                                     token_amount: int = 0,
                                     owner_address: str = None):
              """Adds tokens into a bancor style exchange.
              Will add both tokens at market rate.

              Args:
                  exchange_id (int): non-negative integer exchange id
                  token_name (str): token name
                  token_amount (int): amount of token
                  owner_address (str): token owner address in hex

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

              if not self.tron.isAddress(owner_address):
                  raise InvalidAddress('Invalid owner_address provided')

              if exchange_id < 0:
                  raise ValueError('Invalid exchange_id provided')

              if token_amount < 1:
                  raise ValueError('Invalid token_amount provided')

              return self.tron.manager.request('/wallet/exchangeinject', {
                  'owner_address': self.tron.address.to_hex(owner_address),
                  'exchange_id': exchange_id,
                  'token_id': self.tron.toHex(text=token_name),
                  'quant': token_amount
              })

          def create_token(self, **kwargs):
              """Issue Token

              Issuing a token on the TRON Protocol can be done by anyone
              who has at least 1024 TRX in their account.
              When a token is issued it will be shown on the token overview page.
              Users can then participate within the issuing time and exchange their
              TRX for tokens.After issuing the token your account will
              receive the amount of tokens equal to the total supply.
              When other users exchange their TRX for tokens then the tokens
              will be withdrawn from your account and you will receive
              TRX equal to the specified exchange rate.

              Args:
                  **kwargs: Fill in the required parameters

              Examples:

                  >>> start_func = datetime.now()
                  >>> start = int(start_func.timestamp() * 1000)
                  >>>
                  >>> end_func = datetime.now() + timedelta(days=2)
                  >>> end = int(end_func.timestamp() * 1000)
                  >>>
                  >>> opt = {
                  >>>     'name': 'Tron',
                  >>>     'abbreviation': 'TRX',
                  >>>     'description': 'Hello World',
                  >>>     'url': 'https://github.com',
                  >>>     'totalSupply': 25000000,
                  >>>     'frozenAmount': 1,
                  >>>     'frozenDuration': 2,
                  >>>     'freeBandwidth': 10000,
                  >>>     'freeBandwidthLimit': 10000,
                  >>>     'saleStart': start,
                  >>>     'saleEnd': end,
                  >>>     'voteScore': 1
                  >>> }

              """
              issuer_address = kwargs.setdefault(
                  'issuer_address', self.tron.default_address.hex
              )

              if not self.tron.isAddress(issuer_address):
                  raise TronError('Invalid issuer address provided')

              total_supply = kwargs.setdefault('totalSupply', 0)
              trx_ratio = kwargs.setdefault('trxRatio', 1)
              token_ratio = kwargs.setdefault('tokenRatio', 1)
              sale_start = kwargs.setdefault(
                  'saleStart', START_DATE
              )
              free_bandwidth = kwargs.setdefault('freeBandwidth', 0)
              free_bandwidth_limit = kwargs.setdefault('freeBandwidthLimit', 0)
              frozen_amount = kwargs.setdefault('frozenAmount', 0)
              frozen_duration = kwargs.setdefault('frozenDuration', 0)
              vote_score = kwargs.setdefault('voteScore', 0)
              precision = kwargs.setdefault('precision', 0)

              if not is_string(kwargs.get('name')):
                  raise ValueError('Invalid token name provided')

              if not is_string(kwargs.get('abbreviation')):
                  raise ValueError('Invalid token abbreviation provided')

              if not is_integer(total_supply) or total_supply <= 0:
                  raise ValueError('Invalid supply amount provided')

              if not is_integer(trx_ratio) or trx_ratio <= 0:
                  raise ValueError('TRX ratio must be a positive integer')

              if not is_integer(token_ratio) or token_ratio <= 0:
                  raise ValueError('Token ratio must be a positive integer')

              if not is_integer(vote_score) or vote_score <= 0:
                  raise ValueError('voteScore must be a positive integer greater than 0')

              if not is_integer(precision) or precision <= 0 or precision > 6:
                  raise ValueError('precision must be a positive integer > 0 and <= 6')

              if not is_integer(sale_start) or sale_start < START_DATE:
                  raise ValueError('Invalid sale start timestamp provided')

              if not is_integer(kwargs.get('saleEnd')) or \
                      kwargs.get('saleEnd') <= sale_start:
                  raise ValueError('Invalid sale end timestamp provided')

              if not is_string(kwargs.get('description')):
                  raise ValueError('Invalid token description provided')

              if not is_valid_url(kwargs.get('url')):
                  raise ValueError('Invalid token url provided')

              if not is_integer(free_bandwidth) or free_bandwidth < 0:
                  raise ValueError('Invalid free bandwidth amount provided')

              if not is_integer(free_bandwidth_limit) or free_bandwidth_limit < 0 \
                      or (free_bandwidth and not free_bandwidth_limit):
                  raise ValueError('Invalid free bandwidth limit provided')

              if not is_integer(frozen_amount) or frozen_amount < 0 \
                      or (not frozen_duration and frozen_amount):
                  raise ValueError('Invalid frozen supply provided')

              if not is_integer(frozen_duration) or frozen_duration < 0 \
                      or (frozen_duration and not frozen_amount):
                  raise ValueError('Invalid frozen duration provided')

              frozen_supply = {
                  'frozen_amount': int(frozen_amount),
                  'frozen_days': int(frozen_duration)
              }

              response = self.tron.manager.request('/wallet/createassetissue', {
                  'owner_address': self.tron.address.to_hex(issuer_address),
                  'name': self.tron.toHex(text=kwargs.get('name')),
                  'abbr': self.tron.toHex(text=kwargs.get('abbreviation')),
                  'description': self.tron.toHex(text=kwargs.get('description')),
                  'url': self.tron.toHex(text=kwargs.get('url')),
                  'total_supply': int(total_supply),
                  'trx_num': int(trx_ratio),
                  'num': int(token_ratio),
                  'start_time': int(sale_start),
                  'end_time': int(kwargs.get('saleEnd')),
                  'free_asset_net_limit': int(free_bandwidth),
                  'public_free_asset_net_limit': int(free_bandwidth_limit),
                  'frozen_supply': frozen_supply,
                  'vote_score': vote_score,
                  'precision': precision
              })

              return response

          def withdraw_exchange_tokens(self,
                                       exchange_id: int,
                                       token_name: str,
                                       token_amount: int = 0,
                                       owner_address: str = None):
              """Withdraws tokens from a bancor style exchange.
              Will withdraw at market rate both tokens.

              Args:
                  exchange_id (int): non-negative integer exchange id
                  token_name (str): token name
                  token_amount (int): number of tokens withdraw
                  owner_address (str): owner address in hex

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

              if not self.tron.isAddress(owner_address):
                  raise InvalidAddress('Invalid owner_address provided')

              if exchange_id < 0:
                  raise ValueError('Invalid exchange_id provided')

              if token_amount < 1:
                  raise ValueError('Invalid token_amount provided')

              return self.tron.manager.request('/wallet/exchangewithdraw', {
                  'owner_address': self.tron.address.to_hex(owner_address),
                  'exchange_id': exchange_id,
                  'token_id': self.tron.toHex(text=token_name),
                  'quant': token_amount
              })

          def trade_exchange_tokens(self,
                                    exchange_id: int,
                                    token_name: str,
                                    token_amount_sold: int = 0,
                                    token_amount_expected: int = 0,
                                    owner_address: str = None):
              """Trade tokens on a bancor style exchange.
              Expected value is a validation and used to cap the total amt of token 2 spent.

              Args:
                  exchange_id (int): non-negative integer exchange id
                  token_name (str): token name
                  token_amount_sold (int): amount f token actually sold
                  token_amount_expected (int): amount of token expected
                  owner_address (str): token owner address in hex

              """

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

              if not self.tron.isAddress(owner_address):
                  raise InvalidAddress('Invalid owner_address provided')

              if exchange_id < 0:
                  raise ValueError('Invalid exchange_id provided')

              if token_amount_sold < 1:
                  raise ValueError('Invalid token_amount_sold provided')

              if token_amount_expected < 1:
                  raise ValueError('Invalid token_amount_expected provided')

              return self.tron.manager.request('/wallet/exchangewithdraw', {
                  'owner_address': self.tron.address.to_hex(owner_address),
                  'exchange_id': exchange_id,
                  'token_id': self.tron.toHex(text=token_name),
                  'quant': token_amount_sold,
                  'expected': token_amount_expected
              })

          def update_setting(self,
                             contract_address,
                             user_fee_percentage,
                             owner_address: str = None):
              """Update userFeePercentage.

              Args:
                  contract_address (str): the address of the contract to be modified
                  user_fee_percentage (int): the percentage of resources specified for users using this contract
                  owner_address (str): is the address of the creator

              Returns:
                  Contains unsigned transaction Transaction
              """

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

              if not self.tron.isAddress(owner_address):
                  raise InvalidAddress('Invalid owner_address provided')

              if not self.tron.isAddress(contract_address):
                  raise InvalidAddress('Invalid contract_address provided')

              if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                      user_fee_percentage > 100:
                  raise ValueError('Invalid user_fee_percentage provided')

              return self.tron.manager.request('wallet/updatesetting', {
                  'owner_address': self.tron.address.to_hex(owner_address),
                  'contract_address': self.tron.address.to_hex(contract_address),
                  'consume_user_resource_percent': user_fee_percentage
              })

          def update_energy_limit(self,
                                  contract_address,
                                  origin_energy_limit,
                                  owner_address: str = None):
              """Update energy limit.

              Args:
                  contract_address (str): The address of the contract to be modified
                  origin_energy_limit (int): The maximum energy set by the creator that is created
                  owner_address (str): Is the address of the creator

              Returns:
                  Contains unsigned transaction Transaction
              """

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

              if not self.tron.isAddress(owner_address):
                  raise InvalidAddress('Invalid owner_address provided')

              if not self.tron.isAddress(contract_address):
                  raise InvalidAddress('Invalid contractAddress provided')

              if not is_integer(origin_energy_limit) or origin_energy_limit < 0 or \
                      origin_energy_limit > 10000000:
                  raise ValueError('Invalid originEnergyLimit  provided')

              return self.tron.manager.request('wallet/updateenergylimit', {
                  'owner_address': self.tron.address.to_hex(owner_address),
                  'contract_address': self.tron.address.to_hex(contract_address),
                  'origin_energy_limit': origin_energy_limit
              })

          def check_permissions(self, permissions, _type):
              if permissions is not None:
                  if permissions['type'] != _type or \
                          not permissions['permission_name'] or \
                          not is_string(permissions['permission_name']) or \
                          not is_integer(permissions['threshold']) or \
                          permissions['threshold'] < 1 or not permissions['keys']:
                      return False

              for key in permissions['key']:
                  if not self.tron.isAddress(key['address']) or \
                          not is_integer(key['weight']) or \
                          key['weight'] > permissions['threshold'] or \
                          key['weight'] < 1 or _type == 2 and not permissions['operations']:
                      return False

              return True

          def update_account_permissions(self, owner_address=None,
                                         owner_permissions=None,
                                         witness_permissions=None,
                                         actives_permissions=None
                                         ):
              """Role: update user permissions (for multi-signature)

              Args:
                  owner_address (str): The address of the account whose permissions are to be modified
                  owner_permissions: Modified owner permission
                  witness_permissions: Modified witness permission (if it is a witness)
                  actives_permissions: Modified actives permission
              """

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

              if not self.check_permissions(owner_permissions, 0):
                  raise InvalidTronError('Invalid ownerPermissions provided')

              if not self.check_permissions(witness_permissions, 1):
                  raise InvalidTronError('Invalid witnessPermissions provided')

              for actives_permission in actives_permissions:
                  if not self.check_permissions(actives_permission, 2):
                      raise InvalidTronError('Invalid activesPermissions provided')

              data = {
                  owner_address: owner_address
              }

              if owner_permissions:
                  data['owner'] = owner_permissions

              if witness_permissions:
                  data['witness'] = witness_permissions

              if actives_permissions:
                  if len(actives_permissions) == 1:
                      data['actives'] = actives_permissions[0]
                  else:
                      data['actives'] = actives_permissions

              return self.tron.manager.request('wallet/accountpermissionupdate', data)

  ### Class variables

  `var debug`

  ### Methods

  `def apply_for_sr(self, url, address=None)`

    Apply to become a super representative

    ## Args

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

        def apply_for_sr(self, url, address=None):
            """Apply to become a super representative

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

            """

            # If the address of the sender is not specified, we prescribe the default
            if address is None:
                address = self.tron.default_address.hex

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

            if not is_valid_url(url):
                raise TronError('Invalid url provided')

            return self.tron.manager.request('/wallet/createwitness', {
                'owner_address': self.tron.address.to_hex(address),
                'url': self.tron.toHex(text=url)
            })

  `def check_permissions(self, permissions, _type)`
    Expand source code

        def check_permissions(self, permissions, _type):
            if permissions is not None:
                if permissions['type'] != _type or \
                        not permissions['permission_name'] or \
                        not is_string(permissions['permission_name']) or \
                        not is_integer(permissions['threshold']) or \
                        permissions['threshold'] < 1 or not permissions['keys']:
                    return False

            for key in permissions['key']:
                if not self.tron.isAddress(key['address']) or \
                        not is_integer(key['weight']) or \
                        key['weight'] > permissions['threshold'] or \
                        key['weight'] < 1 or _type == 2 and not permissions['operations']:
                    return False

            return True

  `def create_proposal(self, parameters: Any, issuer_address=None)`

    Creates a proposal to modify the network. Can only be created by a current Super Representative.

    ## Args

    `parameters` :`Any`
      proposal parameters
    `issuer_address`
      owner address

    ## Examples

        >>> from tronpytool import Tron
        >>> data = [
        >>>     {'key': 1, 'value': 2},
        >>>     {'key': 1, 'value': 2}
        >>> ]
        >>> tron = Tron()
        >>> tron.transaction.create_proposal(data)

    Expand source code

        def create_proposal(self, parameters: Any, issuer_address=None):
            """Creates a proposal to modify the network.
            Can only be created by a current Super Representative.

            Args:
                parameters (Any): proposal parameters
                issuer_address: owner address

            Examples:
                >>> from tronpytool import Tron
                >>> data = [
                >>>     {'key': 1, 'value': 2},
                >>>     {'key': 1, 'value': 2}
                >>> ]
                >>> tron = Tron()
                >>> tron.transaction.create_proposal(data)

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

            if not self.tron.isAddress(issuer_address):
                raise InvalidAddress('Invalid issuerAddress provided')

            return self.tron.manager.request('/wallet/proposalcreate', {
                'owner_address': self.tron.address.to_hex(issuer_address),
                'parameters': parameters
            })

  `def create_smart_contract(self, **kwargs)`

    Deploy Contract

    Deploys a contract. Returns TransactionExtention, which contains an unsigned transaction.

    Example: .. code-block:: python >>> from tronpytool import Tron >>> >>> tron = Tron() >>> tron.transaction_builder.create_smart_contract( >>> fee_limit=10**9, >>> call_value=0, >>> consume_user_resource_percent=10 >>> )

    ## Args

    `**kwargs`
      Transaction parameters for the deployment

    transaction as a dict

    Expand source code

        def create_smart_contract(self, **kwargs):
            """Deploy Contract

            Deploys a contract.
            Returns TransactionExtention, which contains an unsigned transaction.

            Example:
            .. code-block:: python
                >>> from tronpytool import Tron
                >>>
                >>> tron = Tron()
                >>> tron.transaction_builder.create_smart_contract(
                >>>    fee_limit=10**9,
                >>>    call_value=0,
                >>>    consume_user_resource_percent=10
                >>> )

            Args:
                **kwargs: Transaction parameters for the deployment
                transaction as a dict

            """

            if 'bytecode' not in kwargs:
                raise ValueError(
                    "Cannot deploy a contract that does not have 'bytecode' associated "
                    "with it"
                )

            # Maximum TRX consumption, measured in SUN (1 TRX = 1,000,000 SUN).
            fee_limit = kwargs.setdefault('fee_limit', 0)
            # The same as User Pay Ratio.
            # The percentage of resources specified for users who use this contract.
            # This field accepts integers between [0, 100].
            user_fee_percentage = kwargs.setdefault('consume_user_resource_percent', 0)
            # Amount of TRX transferred with this transaction, measured in SUN (1TRX = 1,000,000 SUN)
            call_value = kwargs.setdefault('call_value', 0)
            # Contract owner address, converted to a hex string
            owner_address = kwargs.setdefault('owner_address', self.tron.default_address.hex)
            # The max energy which will be consumed by the owner
            # in the process of excution or creation of the contract,
            # is an integer which should be greater than 0.
            origin_energy_limit = kwargs.setdefault('origin_energy_limit', 10000000)

            # parameters = kwargs.setdefault('parameters', []).append()
            # parameters = kwargs.setdefault('visible', []).append()
            # parameters = kwargs.setdefault('permission_id', []).append()

            if not is_integer(user_fee_percentage) and not user_fee_percentage:
                user_fee_percentage = 100

            if not is_hex(kwargs.get('bytecode')):
                raise ValueError('Invalid bytecode provided')

            if not is_integer(fee_limit) or fee_limit <= 0 or \
                    fee_limit > 1000000000:
                raise ValueError('Invalid fee limit provided')

            if not is_integer(call_value) or call_value < 0:
                raise ValueError('Invalid call value provided')

            if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                    user_fee_percentage > 100:
                raise ValueError('Invalid user fee percentage provided')

            if not is_integer(origin_energy_limit) or origin_energy_limit < 0:
                return ValueError('Invalid origin_energy_limit provided')

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid issuer address provided')

            # We write all the results in one object
            transaction = dict(**kwargs)
            transaction.setdefault('owner_address', self.tron.address.to_hex(owner_address))

            return self.tron.manager.request('/wallet/deploycontract', transaction)

  `def create_token(self, **kwargs)`

    Issue Token

    Issuing a token on the TRON Protocol can be done by anyone who has at least 1024 TRX in their account. When a token is issued it will be shown on the token overview page. Users can then participate within the issuing time and exchange their TRX for tokens.After issuing the token your account will receive the amount of tokens equal to the total supply. When other users exchange their TRX for tokens then the tokens will be withdrawn from your account and you will receive TRX equal to the specified exchange rate.

    ## Args

    `**kwargs`
      Fill in the required parameters

    ## Examples

        >>> start_func = datetime.now()
        >>> start = int(start_func.timestamp() * 1000)
        >>>
        >>> end_func = datetime.now() + timedelta(days=2)
        >>> end = int(end_func.timestamp() * 1000)
        >>>
        >>> opt = {
        >>>     'name': 'Tron',
        >>>     'abbreviation': 'TRX',
        >>>     'description': 'Hello World',
        >>>     'url': 'https://github.com',
        >>>     'totalSupply': 25000000,
        >>>     'frozenAmount': 1,
        >>>     'frozenDuration': 2,
        >>>     'freeBandwidth': 10000,
        >>>     'freeBandwidthLimit': 10000,
        >>>     'saleStart': start,
        >>>     'saleEnd': end,
        >>>     'voteScore': 1
        >>> }

    Expand source code

        def create_token(self, **kwargs):
            """Issue Token

            Issuing a token on the TRON Protocol can be done by anyone
            who has at least 1024 TRX in their account.
            When a token is issued it will be shown on the token overview page.
            Users can then participate within the issuing time and exchange their
            TRX for tokens.After issuing the token your account will
            receive the amount of tokens equal to the total supply.
            When other users exchange their TRX for tokens then the tokens
            will be withdrawn from your account and you will receive
            TRX equal to the specified exchange rate.

            Args:
                **kwargs: Fill in the required parameters

            Examples:

                >>> start_func = datetime.now()
                >>> start = int(start_func.timestamp() * 1000)
                >>>
                >>> end_func = datetime.now() + timedelta(days=2)
                >>> end = int(end_func.timestamp() * 1000)
                >>>
                >>> opt = {
                >>>     'name': 'Tron',
                >>>     'abbreviation': 'TRX',
                >>>     'description': 'Hello World',
                >>>     'url': 'https://github.com',
                >>>     'totalSupply': 25000000,
                >>>     'frozenAmount': 1,
                >>>     'frozenDuration': 2,
                >>>     'freeBandwidth': 10000,
                >>>     'freeBandwidthLimit': 10000,
                >>>     'saleStart': start,
                >>>     'saleEnd': end,
                >>>     'voteScore': 1
                >>> }

            """
            issuer_address = kwargs.setdefault(
                'issuer_address', self.tron.default_address.hex
            )

            if not self.tron.isAddress(issuer_address):
                raise TronError('Invalid issuer address provided')

            total_supply = kwargs.setdefault('totalSupply', 0)
            trx_ratio = kwargs.setdefault('trxRatio', 1)
            token_ratio = kwargs.setdefault('tokenRatio', 1)
            sale_start = kwargs.setdefault(
                'saleStart', START_DATE
            )
            free_bandwidth = kwargs.setdefault('freeBandwidth', 0)
            free_bandwidth_limit = kwargs.setdefault('freeBandwidthLimit', 0)
            frozen_amount = kwargs.setdefault('frozenAmount', 0)
            frozen_duration = kwargs.setdefault('frozenDuration', 0)
            vote_score = kwargs.setdefault('voteScore', 0)
            precision = kwargs.setdefault('precision', 0)

            if not is_string(kwargs.get('name')):
                raise ValueError('Invalid token name provided')

            if not is_string(kwargs.get('abbreviation')):
                raise ValueError('Invalid token abbreviation provided')

            if not is_integer(total_supply) or total_supply <= 0:
                raise ValueError('Invalid supply amount provided')

            if not is_integer(trx_ratio) or trx_ratio <= 0:
                raise ValueError('TRX ratio must be a positive integer')

            if not is_integer(token_ratio) or token_ratio <= 0:
                raise ValueError('Token ratio must be a positive integer')

            if not is_integer(vote_score) or vote_score <= 0:
                raise ValueError('voteScore must be a positive integer greater than 0')

            if not is_integer(precision) or precision <= 0 or precision > 6:
                raise ValueError('precision must be a positive integer > 0 and <= 6')

            if not is_integer(sale_start) or sale_start < START_DATE:
                raise ValueError('Invalid sale start timestamp provided')

            if not is_integer(kwargs.get('saleEnd')) or \
                    kwargs.get('saleEnd') <= sale_start:
                raise ValueError('Invalid sale end timestamp provided')

            if not is_string(kwargs.get('description')):
                raise ValueError('Invalid token description provided')

            if not is_valid_url(kwargs.get('url')):
                raise ValueError('Invalid token url provided')

            if not is_integer(free_bandwidth) or free_bandwidth < 0:
                raise ValueError('Invalid free bandwidth amount provided')

            if not is_integer(free_bandwidth_limit) or free_bandwidth_limit < 0 \
                    or (free_bandwidth and not free_bandwidth_limit):
                raise ValueError('Invalid free bandwidth limit provided')

            if not is_integer(frozen_amount) or frozen_amount < 0 \
                    or (not frozen_duration and frozen_amount):
                raise ValueError('Invalid frozen supply provided')

            if not is_integer(frozen_duration) or frozen_duration < 0 \
                    or (frozen_duration and not frozen_amount):
                raise ValueError('Invalid frozen duration provided')

            frozen_supply = {
                'frozen_amount': int(frozen_amount),
                'frozen_days': int(frozen_duration)
            }

            response = self.tron.manager.request('/wallet/createassetissue', {
                'owner_address': self.tron.address.to_hex(issuer_address),
                'name': self.tron.toHex(text=kwargs.get('name')),
                'abbr': self.tron.toHex(text=kwargs.get('abbreviation')),
                'description': self.tron.toHex(text=kwargs.get('description')),
                'url': self.tron.toHex(text=kwargs.get('url')),
                'total_supply': int(total_supply),
                'trx_num': int(trx_ratio),
                'num': int(token_ratio),
                'start_time': int(sale_start),
                'end_time': int(kwargs.get('saleEnd')),
                'free_asset_net_limit': int(free_bandwidth),
                'public_free_asset_net_limit': int(free_bandwidth_limit),
                'frozen_supply': frozen_supply,
                'vote_score': vote_score,
                'precision': precision
            })

            return response

  `def create_token_exchange(self, first_token_name: str, first_token_balance: int, second_token_name: str, second_token_balance: int, owner_address: str = None)`

    Create an exchange between a token and another token. DO NOT USE THIS FOR TRX. Token Names should be a CASE SENSITIVE string.

    ## Args

    `first_token_name` :`str`
      the id of the first token
    `first_token_balance` :`int`
      balance of the first token
    `second_token_name` :`str`
      the id of the second token
    `second_token_balance` :`int`
      balance of the second token
    `owner_address`
      owner address
    Expand source code

        def create_token_exchange(self,
                                  first_token_name: str,
                                  first_token_balance: int,
                                  second_token_name: str,
                                  second_token_balance: int,
                                  owner_address: str = None):
            """Create an exchange between a token and another token.
            DO NOT USE THIS FOR TRX.
            Token Names should be a CASE SENSITIVE string.

            Args:
                first_token_name (str): the id of the first token
                first_token_balance (int): balance of the first token
                second_token_name (str): the id of the second token
                second_token_balance (int): balance of the second token
                owner_address: owner address

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

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

            if second_token_balance <= 0 or first_token_balance <= 0:
                raise ValueError('Invalid amount provided')

            return self.tron.manager.request('/wallet/exchangecreate', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'first_token_id': self.tron.toHex(text=first_token_name),
                'first_token_balance': first_token_balance,
                'second_token_id': self.tron.toHex(text=second_token_name),
                'second_token_balance': second_token_balance
            })

  `def create_trx_exchange(self, token_name: str, token_balance: int, trx_balance: int, account: str = None)`

    Create an exchange between a token and TRX. Token Name should be a CASE SENSITIVE string. Note: PLEASE VERIFY THIS ON TRONSCAN.

    ## Args

    `token_name` :`str`
      Token Name
    `token_balance` :`int`
      balance of the first token
    `trx_balance` :`int`
      balance of the second token
    `account` :`str`
      Owner Address
    Expand source code

        def create_trx_exchange(self,
                                token_name: str,
                                token_balance: int,
                                trx_balance: int,
                                account: str = None):
            """Create an exchange between a token and TRX.
            Token Name should be a CASE SENSITIVE string.
            Note: PLEASE VERIFY THIS ON TRONSCAN.

            Args:
                token_name (str): Token Name
                token_balance (int): balance of the first token
                trx_balance (int): balance of the second token
                account (str): Owner Address
            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

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

            if token_balance <= 0 or trx_balance <= 0:
                raise TronError('Invalid amount provided')

            return self.tron.manager.request('/wallet/exchangecreate', {
                'owner_address': self.tron.address.to_hex(account),
                'first_token_id': self.tron.toHex(text=token_name),
                'first_token_balance': token_balance,
                'second_token_id': '5f',
                'second_token_balance': trx_balance
            })

  `def debug_input_kv(self, data)`
    Expand source code

        def debug_input_kv(self, data):
            if self.debug:
                print("==checking input data")
                print(data)
                print("==end")

  `def debug_url_req(self, data)`
    Expand source code

        def debug_url_req(self, data):
            if self.debug:
                print("==data load on request url")
                print(data)
                print("==end")

  `def delete_proposal(self, proposal_id: int, issuer_address: str = None)`

    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 delete_proposal(self, proposal_id: int, issuer_address: str = None):
            """Delete proposal

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

            Results:
                Delete the proposal's transaction

            """

            # If the address of the sender is not specified, we prescribe the default
            if issuer_address is None:
                issuer_address = self.tron.default_address.hex

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

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

            return self.tron.manager.request('/wallet/proposaldelete', {
                'owner_address': self.tron.address.to_hex(issuer_address),
                'proposal_id': int(proposal_id)
            })

  `def freeze_balance(self, amount, duration, resource, 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, duration, resource, 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 the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

            if resource not in ('BANDWIDTH', 'ENERGY',):
                raise InvalidTronError('Invalid resource provided: Expected "BANDWIDTH" or "ENERGY"')

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

            if not is_integer(duration) or duration < 3:
                raise InvalidTronError('Invalid duration provided, minimum of 3 days')

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

            response = self.tron.manager.request('/wallet/freezebalance', {
                'owner_address': self.tron.address.to_hex(account),
                'frozen_balance': self.tron.toSun(amount),
                'frozen_duration': int(duration),
                'resource': resource
            })

            if 'Error' in response:
                raise TronError(response['Error'])

            return response

  `def inject_exchange_tokens(self, exchange_id: int, token_name: str, token_amount: int = 0, owner_address: str = None)`

    Adds tokens into a bancor style exchange. Will add both tokens at market rate.

    ## Args

    `exchange_id` :`int`
      non-negative integer exchange id
    `token_name` :`str`
      token name
    `token_amount` :`int`
      amount of token
    `owner_address` :`str`
      token owner address in hex
    Expand source code

        def inject_exchange_tokens(self,
                                   exchange_id: int,
                                   token_name: str,
                                   token_amount: int = 0,
                                   owner_address: str = None):
            """Adds tokens into a bancor style exchange.
            Will add both tokens at market rate.

            Args:
                exchange_id (int): non-negative integer exchange id
                token_name (str): token name
                token_amount (int): amount of token
                owner_address (str): token owner address in hex

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if exchange_id < 0:
                raise ValueError('Invalid exchange_id provided')

            if token_amount < 1:
                raise ValueError('Invalid token_amount provided')

            return self.tron.manager.request('/wallet/exchangeinject', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'exchange_id': exchange_id,
                'token_id': self.tron.toHex(text=token_name),
                'quant': token_amount
            })

  `def purchase_token(self, to: str, token_id: str, amount: int, buyer=None)`

    Purchase a Token Creates an unsigned ICO token purchase transaction.

    ## Args

    `to` :`str`
      is the address of the Token issuer
    `token_id` :`str`
      is the name of the token
    `amount` :`int`
      is the number of tokens created
    `buyer` :`str`
      is the address of the Token owner
    Expand source code

        def purchase_token(self, to: str, token_id: str, amount: int, buyer=None):
            """Purchase a Token
            Creates an unsigned ICO token purchase transaction.

            Args:
                to (str): is the address of the Token issuer
                token_id (str): is the name of the token
                amount (int): is the number of tokens created
                buyer (str): is the address of the Token owner

            """

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

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

            if not len(token_id):
                raise ValueError('Invalid token ID provided')

            if amount <= 0:
                raise ValueError('Invalid amount provided')

            _to = self.tron.address.to_hex(to)
            _from = self.tron.address.to_hex(buyer)

            return self.tron.manager.request('/wallet/participateassetissue', {
                'to_address': _to,
                'owner_address': _from,
                'asset_name': self.tron.toHex(text=token_id),
                'amount': int(amount)
            })

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

    Transfer Token

    ## Args

    `to` :`str`
      is the recipient address
    `amount` :`int`
      is the amount of token to transfer. must be integer instead of float
    `token_id` :`any`
      Token Name and id
    `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, account=None):
            """Transfer Token

            Args:
                to (str): is the recipient address
                amount (int): is the amount of token to transfer. must be integer instead of float
                token_id (any): Token Name and id
                account: (str): is the address of the withdrawal account

            Returns:
                Token transfer Transaction raw data

            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

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

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

            if not token_id:
                raise InvalidTronError('Invalid token ID provided')

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

            _to = self.tron.address.to_hex(to)
            _from = self.tron.address.to_hex(account)
            _token_id = self.tron.toHex(text=str(token_id))

            if _to == _from:
                raise TronError('Cannot transfer TRX to the same account')

            # In case if "TRX" is specified, we redirect to another method.
            if is_string(token_id) and token_id.upper() == 'TRX':
                return self.send_transaction(_to, amount, _from)

            return self.tron.manager.request('/wallet/transferasset', {
                'to_address': _to,
                'owner_address': _from,
                'asset_name': _token_id,
                'amount': amount
            })

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

    Creates a transaction of transfer. If the recipient address does not exist, a corresponding account will be created.

    ## Args

    `to` :`str`
      to address
    `amount` :`float`
      amount
    `account` :`str`
      from address

    ## Returns

    Transaction contract data

    Expand source code

        def send_transaction(self, to, amount, account=None):
            """Creates a transaction of transfer.
            If the recipient address does not exist, a corresponding account will be created.

            Args:
                to (str): to address
                amount (float): amount
                account (str): from address

            Returns:
                Transaction contract data

            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

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

            if not isinstance(amount, float) or amount <= 0:
                raise InvalidTronError('Invalid amount provided')

            _to = self.tron.address.to_hex(to)
            _from = self.tron.address.to_hex(account)

            if _to == _from:
                raise TronError('Cannot transfer TRX to the same account')

            response = self.tron.manager.request('/wallet/createtransaction', {
                'to_address': _to,
                'owner_address': _from,
                'amount': self.tron.toSun(amount)
            })

            return response

  `def setDebug(self, b: bool) ‑> NoneType`
    Expand source code

        def setDebug(self, b: bool) -> None:
            self.debug = b

  `def trade_exchange_tokens(self, exchange_id: int, token_name: str, token_amount_sold: int = 0, token_amount_expected: int = 0, owner_address: str = None)`

    Trade tokens on a bancor style exchange. Expected value is a validation and used to cap the total amt of token 2 spent.

    ## Args

    `exchange_id` :`int`
      non-negative integer exchange id
    `token_name` :`str`
      token name
    `token_amount_sold` :`int`
      amount f token actually sold
    `token_amount_expected` :`int`
      amount of token expected
    `owner_address` :`str`
      token owner address in hex
    Expand source code

        def trade_exchange_tokens(self,
                                  exchange_id: int,
                                  token_name: str,
                                  token_amount_sold: int = 0,
                                  token_amount_expected: int = 0,
                                  owner_address: str = None):
            """Trade tokens on a bancor style exchange.
            Expected value is a validation and used to cap the total amt of token 2 spent.

            Args:
                exchange_id (int): non-negative integer exchange id
                token_name (str): token name
                token_amount_sold (int): amount f token actually sold
                token_amount_expected (int): amount of token expected
                owner_address (str): token owner address in hex

            """

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if exchange_id < 0:
                raise ValueError('Invalid exchange_id provided')

            if token_amount_sold < 1:
                raise ValueError('Invalid token_amount_sold provided')

            if token_amount_expected < 1:
                raise ValueError('Invalid token_amount_expected provided')

            return self.tron.manager.request('/wallet/exchangewithdraw', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'exchange_id': exchange_id,
                'token_id': self.tron.toHex(text=token_name),
                'quant': token_amount_sold,
                'expected': token_amount_expected
            })

  `def trigger_smart_contract(self, kv: dict)`

    Trigger Smart Contract Calls a function on a contract

    ## Args

    `**kv`
      Fill in the required parameters

    ## Examples

        >>> tron = Tron()
        >>> tron.transaction_builder.trigger_smart_contract(
        >>>     contract_address='413c8143e98b3e2fe1b1a8fb82b34557505a752390',
        >>>     function_selector='set(uint256,uint256)',
        >>>     fee_limit=30000,
        >>>     call_value=0,
        >>>     parameters=[
        >>>        {'type': 'int256', 'value': 1},
        >>>        {'type': 'int256', 'value': 1}])

    ## Returns

    TransactionExtention, TransactionExtention contains unsigned Transaction

    Expand source code

        def trigger_smart_contract(self, kv: dict):

            """Trigger Smart Contract
            Calls a function on a contract

            Args:
                **kv: Fill in the required parameters

            Examples:
                >>> tron = Tron()
                >>> tron.transaction_builder.trigger_smart_contract(
                >>>     contract_address='413c8143e98b3e2fe1b1a8fb82b34557505a752390',
                >>>     function_selector='set(uint256,uint256)',
                >>>     fee_limit=30000,
                >>>     call_value=0,
                >>>     parameters=[
                >>>        {'type': 'int256', 'value': 1},
                >>>        {'type': 'int256', 'value': 1}])

            Returns:
                TransactionExtention, TransactionExtention contains unsigned Transaction
            """

            contract_address = kv.setdefault('contract_address', None)
            function_selector = kv.setdefault('function_selector', None)

            issuer_address = kv.setdefault('issuer_address', self.tron.default_address.hex)
            call_value = kv.setdefault('call_value', 0)
            fee_limit = kv.setdefault('fee_limit', 1000000000)
            token_value = kv.setdefault('token_value', 0)
            token_id = kv.setdefault('token_id', 0)
            parameters = kv.setdefault('parameters', [])

            if not is_integer(token_value) or token_value < 0:
                raise ValueError('Invalid options.tokenValue provided')

            if not is_integer(token_id) or token_id < 0:
                raise ValueError('Invalid options.tokenId provided')

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

            if not is_string(function_selector):
                raise ValueError('Invalid function selector provided')

            if not is_integer(call_value) or call_value < 0:
                raise ValueError('Invalid call value provided')

            if not is_integer(fee_limit) or fee_limit <= 0 or fee_limit > 1000000000:
                raise ValueError('Invalid fee limit provided')

            """remove all the spaces"""
            function_selector = function_selector.replace('/\s*/g', '')
            print(parameters)
            print("-------------- this is the last parameters.. ")
            if len(parameters) > 0:
                types = []
                values = []
                for abi in parameters:
                    if 'type' not in abi or not is_string(abi['type']):
                        raise ValueError('Invalid parameter type provided: ' + abi['type'])
                    if abi['type'] == 'address':
                        abi['value'] = self.tron.address.to_hex(abi['value']).replace('41', '0x', 1)
                    types.append(abi['type'])
                    values.append(abi['value'])

                try:
                    parameters = encode_hex(encode_abi(types, values)).replace('0x', '', 2)
                except ValueError as ex:
                    print(ex)

            else:
                parameters = ''

            data = {
                'contract_address': self.tron.address.to_hex(contract_address),
                'owner_address': issuer_address.hex,
                'function_selector': function_selector,
                'fee_limit': int(fee_limit),
                'call_value': int(call_value),
                'parameter': parameters
            }

            # if parameters is '':
            #    data.pop('parameter')
            self.debug_input_kv(kv)
            if token_value:
                data['call_token_value'] = int(token_value)

            if token_id:
                data['token_id'] = int(token_id)
            self.debug_url_req(data)
            return self.tron.manager.request('/wallet/triggersmartcontract', data)

  `def trigger_smart_contract_constant(self, kv: dict)`
    Expand source code

        def trigger_smart_contract_constant(self, kv: dict):

            contract_address = kv.setdefault('contract_address', None)
            function_selector = kv.setdefault('function_selector', None)

            issuer_address = kv.setdefault('issuer_address', self.tron.default_address.hex)
            call_value = kv.setdefault('call_value', 0)
            fee_limit = kv.setdefault('fee_limit', 1000000000)
            token_value = kv.setdefault('token_value', 0)
            token_id = kv.setdefault('token_id', 0)

            if not is_integer(token_value) or token_value < 0:
                raise ValueError('Invalid options.tokenValue provided')

            if not is_integer(token_id) or token_id < 0:
                raise ValueError('Invalid options.tokenId provided')

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

            if not is_string(function_selector):
                raise ValueError('Invalid function selector provided')

            if not is_integer(call_value) or call_value < 0:
                raise ValueError('Invalid call value provided')

            if not is_integer(fee_limit) or fee_limit <= 0 or fee_limit > 1000000000:
                raise ValueError('Invalid fee limit provided')

            """remove all the spaces"""
            function_selector = function_selector.replace('/\s*/g', '')

            if hasattr(kv, "parameters") and len(kv['parameters']) > 0:
                types = []
                values = []
                parameters = kv['parameters']
                for abi in parameters:
                    if 'type' not in abi or not is_string(abi['type']):
                        raise ValueError('Invalid parameter type provided: ' + abi['type'])

                    if abi['type'] == 'address':
                        abi['value'] = self.tron.address.to_hex(abi['value']).replace('41', '0x', 1)

                    types.append(abi['type'])
                    values.append(abi['value'])

                try:
                    parameters = encode_hex(encode_abi(types, values)).replace('0x', '', 2)
                except ValueError as ex:
                    print(ex)

            else:
                parameters = []

            self.debug_input_kv(kv)

            data = {
                'contract_address': self.tron.address.to_hex(contract_address),
                'owner_address': issuer_address.hex,
                'function_selector': function_selector,
                'fee_limit': int(fee_limit),
                'call_value': int(call_value),
                'parameter': parameters
            }

            if token_value:
                data['call_token_value'] = int(token_value)

            if token_id:
                data['token_id'] = int(token_id)

            self.debug_url_req(data)

            return self.tron.manager.request('/wallet/triggerconstantcontract', kv)

  `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 the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

            if resource not in ('BANDWIDTH', 'ENERGY',):
                raise InvalidTronError('Invalid resource provided: Expected "BANDWIDTH" or "ENERGY"')

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

            response = self.tron.manager.request('/wallet/unfreezebalance', {
                'owner_address': self.tron.address.to_hex(account),
                'resource': resource
            })

            if 'Error' in response:
                raise ValueError(response['Error'])

            return response

  `def update_account(self, account_name, account: str = None)`

    Modify account name

    Note: Username is allowed to edit only once.

    ## Args

    `account_name` :`str`
      name of the account
    `account` :`str`
      address

    ## Returns

    modified Transaction Object

    Expand source code

        def update_account(self, account_name, account: str = None):
            """Modify account name

            Note: Username is allowed to edit only once.

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

            Returns:
                modified Transaction Object

            """

            # If the address of the sender is not specified, we prescribe the default
            if account is None:
                account = self.tron.default_address.hex

            if not is_string(account_name):
                raise ValueError('Name must be a string')

            if not self.tron.isAddress(account):
                raise TronError('Invalid origin address provided')

            response = self.tron.manager.request('/wallet/updateaccount', {
                'account_name': self.tron.toHex(text=account_name),
                'owner_address': self.tron.address.to_hex(account)
            })

            return response

  `def update_account_permissions(self, owner_address=None, owner_permissions=None, witness_permissions=None, actives_permissions=None)`

    Role: update user permissions (for multi-signature)

    ## Args

    `owner_address` :`str`
      The address of the account whose permissions are to be modified
    `owner_permissions`
      Modified owner permission
    `witness_permissions`
      Modified witness permission (if it is a witness)
    `actives_permissions`
      Modified actives permission
    Expand source code

        def update_account_permissions(self, owner_address=None,
                                       owner_permissions=None,
                                       witness_permissions=None,
                                       actives_permissions=None
                                       ):
            """Role: update user permissions (for multi-signature)

            Args:
                owner_address (str): The address of the account whose permissions are to be modified
                owner_permissions: Modified owner permission
                witness_permissions: Modified witness permission (if it is a witness)
                actives_permissions: Modified actives permission
            """

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

            if not self.check_permissions(owner_permissions, 0):
                raise InvalidTronError('Invalid ownerPermissions provided')

            if not self.check_permissions(witness_permissions, 1):
                raise InvalidTronError('Invalid witnessPermissions provided')

            for actives_permission in actives_permissions:
                if not self.check_permissions(actives_permission, 2):
                    raise InvalidTronError('Invalid activesPermissions provided')

            data = {
                owner_address: owner_address
            }

            if owner_permissions:
                data['owner'] = owner_permissions

            if witness_permissions:
                data['witness'] = witness_permissions

            if actives_permissions:
                if len(actives_permissions) == 1:
                    data['actives'] = actives_permissions[0]
                else:
                    data['actives'] = actives_permissions

            return self.tron.manager.request('wallet/accountpermissionupdate', data)

  `def update_energy_limit(self, contract_address, origin_energy_limit, owner_address: str = None)`

    Update energy limit.

    ## Args

    `contract_address` :`str`
      The address of the contract to be modified
    `origin_energy_limit` :`int`
      The maximum energy set by the creator that is created
    `owner_address` :`str`
      Is the address of the creator

    ## Returns

    Contains unsigned transaction Transaction

    Expand source code

        def update_energy_limit(self,
                                contract_address,
                                origin_energy_limit,
                                owner_address: str = None):
            """Update energy limit.

            Args:
                contract_address (str): The address of the contract to be modified
                origin_energy_limit (int): The maximum energy set by the creator that is created
                owner_address (str): Is the address of the creator

            Returns:
                Contains unsigned transaction Transaction
            """

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if not self.tron.isAddress(contract_address):
                raise InvalidAddress('Invalid contractAddress provided')

            if not is_integer(origin_energy_limit) or origin_energy_limit < 0 or \
                    origin_energy_limit > 10000000:
                raise ValueError('Invalid originEnergyLimit  provided')

            return self.tron.manager.request('wallet/updateenergylimit', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'contract_address': self.tron.address.to_hex(contract_address),
                'origin_energy_limit': origin_energy_limit
            })

  `def update_setting(self, contract_address, user_fee_percentage, owner_address: str = None)`

    Update userFeePercentage.

    ## Args

    `contract_address` :`str`
      the address of the contract to be modified
    `user_fee_percentage` :`int`
      the percentage of resources specified for users using this contract
    `owner_address` :`str`
      is the address of the creator

    ## Returns

    Contains unsigned transaction Transaction

    Expand source code

        def update_setting(self,
                           contract_address,
                           user_fee_percentage,
                           owner_address: str = None):
            """Update userFeePercentage.

            Args:
                contract_address (str): the address of the contract to be modified
                user_fee_percentage (int): the percentage of resources specified for users using this contract
                owner_address (str): is the address of the creator

            Returns:
                Contains unsigned transaction Transaction
            """

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if not self.tron.isAddress(contract_address):
                raise InvalidAddress('Invalid contract_address provided')

            if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                    user_fee_percentage > 100:
                raise ValueError('Invalid user_fee_percentage provided')

            return self.tron.manager.request('wallet/updatesetting', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'contract_address': self.tron.address.to_hex(contract_address),
                'consume_user_resource_percent': user_fee_percentage
            })

  `def vote(self, votes: List[Tuple[str, int]], voter_address: str = None)`

    Vote Vote on the super representative

    ## Args

    `votes` :`dict`
      dictionary of SR address : vote count key-value pair
    `voter_address`
      voter address

    ## Examples

        >>> from tronpytool import Tron
        >>> data = [
        >>>     ('TRJpw2uqohP7FUmAEJgt57wakRn6aGQU6Z', 1)
        >>> ]
        >>> tron = Tron()
        >>> tron.transaction.vote(data)

    Expand source code

        def vote(self, votes: List[Tuple[str, int]], voter_address: str = None):
            """Vote
            Vote on the super representative

            Args:
                votes (dict): dictionary of SR address : vote count key-value pair
                voter_address: voter address

            Examples:
                >>> from tronpytool import Tron
                >>> data = [
                >>>     ('TRJpw2uqohP7FUmAEJgt57wakRn6aGQU6Z', 1)
                >>> ]
                >>> tron = Tron()
                >>> tron.transaction.vote(data)

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

            _view_vote = []

            # We create a cycle to check all the received data for voting.
            for sr_address, vote_count in votes:
                if not self.tron.isAddress(sr_address):
                    raise InvalidAddress(
                        'Invalid SR address provided: ' + sr_address
                    )

                if not is_integer(vote_count) or vote_count <= 0:
                    raise ValueError(
                        'Invalid vote count provided for SR: ' + sr_address
                    )

                _view_vote.append({
                    'vote_address': self.tron.address.to_hex(sr_address),
                    'vote_count': int(vote_count)
                })

            return self.tron.manager.request('/wallet/votewitnessaccount', {
                'owner_address': self.tron.address.to_hex(voter_address),
                'votes': _view_vote
            })

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

    Proposal approval

    ## Args

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

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

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

            """

            # If the address of the sender is not specified, we prescribe the default
            if voter_address is None:
                voter_address = self.tron.default_address.hex

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

            if not is_integer(proposal_id) or proposal_id < 0:
                raise TronError('Invalid proposal_id provided')

            if not is_boolean(has_approval):
                raise TronError('Invalid has_approval provided')

            return self.tron.manager.request('/wallet/proposalapprove', {
                'owner_address': self.tron.address.to_hex(voter_address),
                'proposal_id': int(proposal_id),
                'is_add_approval': bool(has_approval)
            })

  `def withdraw_block_rewards(self, address: str = None)`

    Withdraw block rewards Creates an unsigned Super Representative award balance withdraw transaction.

    ## Args

    `address` :`str`
      Optional address to withdraw from.
    Expand source code

        def withdraw_block_rewards(self, address: str = None):
            """Withdraw block rewards
            Creates an unsigned Super Representative award balance withdraw transaction.

            Args:
                address (str): Optional address to withdraw from.

            """
            if not address:
                address = self.tron.default_address.hex

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

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

  `def withdraw_exchange_tokens(self, exchange_id: int, token_name: str, token_amount: int = 0, owner_address: str = None)`

    Withdraws tokens from a bancor style exchange. Will withdraw at market rate both tokens.

    ## Args

    `exchange_id` :`int`
      non-negative integer exchange id
    `token_name` :`str`
      token name
    `token_amount` :`int`
      number of tokens withdraw
    `owner_address` :`str`
      owner address in hex
    Expand source code

        def withdraw_exchange_tokens(self,
                                     exchange_id: int,
                                     token_name: str,
                                     token_amount: int = 0,
                                     owner_address: str = None):
            """Withdraws tokens from a bancor style exchange.
            Will withdraw at market rate both tokens.

            Args:
                exchange_id (int): non-negative integer exchange id
                token_name (str): token name
                token_amount (int): number of tokens withdraw
                owner_address (str): owner address in hex

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

            if not self.tron.isAddress(owner_address):
                raise InvalidAddress('Invalid owner_address provided')

            if exchange_id < 0:
                raise ValueError('Invalid exchange_id provided')

            if token_amount < 1:
                raise ValueError('Invalid token_amount provided')

            return self.tron.manager.request('/wallet/exchangewithdraw', {
                'owner_address': self.tron.address.to_hex(owner_address),
                'exchange_id': exchange_id,
                'token_id': self.tron.toHex(text=token_name),
                'quant': token_amount
            })