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

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

        Returns:
            List of Tokens

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

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

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

        return self.tron.manager.request('/wallet/getpaginatedassetissuelist',
                                         {
                                             'limit': int(limit),
                                             'offset': int(offset)
                                         })
Esempio n. 2
0
def validate_abi_value(abi_type, value):
    """
    Helper function for validating a value against the expected abi_type
    Note: abi_type 'bytes' must either be python3 'bytes' object or ''
    """
    if is_array_type(abi_type) and is_list_like(value):
        # validate length
        specified_length = length_of_array_type(abi_type)
        if specified_length is not None:
            if specified_length < 1:
                raise TypeError(
                    "Invalid abi-type: {abi_type}. Length of fixed sized arrays"
                    "must be greater than 0."
                        .format(abi_type=abi_type)
                )
            if specified_length != len(value):
                raise TypeError(
                    "The following array length does not the length specified"
                    "by the abi-type, {abi_type}: {value}"
                        .format(abi_type=abi_type, value=value)
                )

        # validate sub_types
        sub_type = sub_type_of_array_type(abi_type)
        for v in value:
            validate_abi_value(sub_type, v)
        return
    elif is_bool_type(abi_type) and is_boolean(value):
        return
    elif is_uint_type(abi_type) and is_integer(value) and value >= 0:
        return
    elif is_int_type(abi_type) and is_integer(value):
        return
    elif is_address_type(abi_type):
        validate_address(value)
        return
    elif is_bytes_type(abi_type):
        if is_bytes(value):
            return
        elif is_string(value):
            if is_0x_prefixed(value):
                return
            else:
                raise TypeError(
                    "ABI values of abi-type 'bytes' must be either"
                    "a python3 'bytes' object or an '0x' prefixed string."
                )
    elif is_string_type(abi_type) and is_string(value):
        return

    raise TypeError(
        "The following abi value is not a '{abi_type}': {value}".format(abi_type=abi_type, value=value)
    )
Esempio n. 3
0
    def get_event_result(self, **kwargs):
        """Will return all events matching the filters.

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

        # Check the most necessary parameters
        contract_address = kwargs.setdefault('contract_address',
                                             self.default_address.hex)
        event_name = kwargs.setdefault('event_name', 'Notify')
        since_timestamp = kwargs.setdefault('since_timestamp', 0)
        block_number = kwargs.setdefault('block_number', '')
        size = kwargs.setdefault('size', 20)
        page = kwargs.setdefault('page', 1)

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

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

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

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

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

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

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

        route = '/'.join(route_params)
        return self.manager.request(
            "/event/contract/{0}?since={1}&size={2}&page={3}".format(
                route, since_timestamp, size, page),
            method='get')
Esempio n. 4
0
    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)
            })
Esempio n. 5
0
    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
            })
Esempio n. 6
0
    def inject(self, element, name=None, layer=None):
        """
        Inject a named element to an arbitrary layer in the onion.

        The current implementation only supports insertion at the innermost layer,
        or at the outermost layer. Note that inserting to the outermost is equivalent
        to calling :meth:`add` .
        """
        if not is_integer(layer):
            raise TypeError("The layer for insertion must be an int.")
        elif layer != 0 and layer != len(self._queue):
            raise NotImplementedError(
                "You can only insert to the beginning or end of a %s, currently. "
                "You tried to insert to %d, but only 0 and %d are permitted. " % (
                    type(self),
                    layer,
                    len(self._queue),
                )
            )

        self.add(element, name=name)

        if layer == 0:
            if name is None:
                name = element
            self._queue.move_to_end(name, last=False)
        elif layer == len(self._queue):
            return
        else:
            raise AssertionError("Impossible to reach: earlier validation raises an error")
Esempio n. 7
0
    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
            })
Esempio n. 8
0
    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
Esempio n. 9
0
    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
Esempio n. 10
0
    def default_block(self, block_id):
        """Sets the default block used as a reference for all future calls."""
        if block_id in ('latest', 'earliest', 0):
            self._default_block = block_id
            return

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

        self._default_block = abs(block_id)
Esempio n. 11
0
    def get_transaction_count_by_blocknum(self, num: int):
        """Query transaction's count on a specified block by height

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

        return self.tron.manager.request(
            '/wallet/gettransactioncountbyblocknum', {'num': num})
Esempio n. 12
0
    def get_block_range(self, start, end):
        """Query a range of blocks by block height

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

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

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

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

        return response.get('block')
Esempio n. 13
0
def select_method_for_block(value, if_hash, if_number):
    if isinstance(value, bytes):
        return if_hash
    elif is_hex_encoded_block_hash(value):
        return if_hash
    elif is_integer(value) and (0 <= value < 2**256):
        return if_number
    elif is_hex_encoded_block_number(value):
        return if_number
    else:
        raise ValueError(
            "Value did not match any of the recognized block identifiers: {0}".
            format(value))
Esempio n. 14
0
    def get_latest_blocks(self, num=1):
        """Query the latest blocks

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

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

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

        return response.get('block')
Esempio n. 15
0
def to_text(primitive=None, hexstr=None, text=None):
    assert_one_val(primitive, hexstr=hexstr, text=text)

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

    if is_boolean(primitive):
        return b'\x01' if primitive else b'\x00'
    elif isinstance(primitive, bytes):
        return primitive
    elif is_integer(primitive):
        return to_bytes(hexstr=to_hex(primitive))
    elif hexstr is not None:
        if len(hexstr) % 2:
            hexstr = '0x0' + remove_0x_prefix(hexstr)
        return decode_hex(hexstr)
    elif text is not None:
        return text.encode('utf-8')
    raise TypeError("expected an int in first arg, or keyword of hexstr or text")
Esempio n. 17
0
    def get_transaction_from_block(self, block: Any, index: int = 0):
        """Get transaction details from Block

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

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

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

        return transactions[index]
Esempio n. 18
0
    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 tronapi 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
            })
Esempio n. 19
0
    def get_event_result(self, **kwargs):
        """Will return all events matching the filters.

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

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

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

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

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

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

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

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

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

        route = '/'.join(route_params)

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

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

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

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

        return self.manager.request("/event/contract/{0}?{1}".format(
            route, urlencode(qs)),
                                    method='get')
Esempio n. 20
0
    def trigger_smart_contract(self,
                               contract_address,
                               function_selector,
                               fee_limit: int = 1000000000,
                               call_value: int = 0,
                               parameters=None,
                               issuer_address=None):
        """Trigger Smart Contract (Beta Version)
        Calls a function on a contract

        Args:
            contract_address (str): Contract address, converted to a hex string
            function_selector (str): Function signature. No spaces.
            fee_limit (int): Maximum TRX consumption, measured in SUN(1TRX = 1,000,000SUN)
            call_value (int): Amount of TRX transferred with this transaction, measured in SUN(1TRX = 1,000,000SUN)
            parameters (any): Call the virtual machine format of the parameter [1, 2],
                                use the js tool provided by remix, convert the parameter array [1, 2]
                                called by the contract caller into
                                the parameter format required by the virtual machine.

            issuer_address (str): address that is trigger the contract

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

        Returns:
            TransactionExtention, TransactionExtention contains unsigned Transaction
        """

        if parameters is None:
            parameters = []

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

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

        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', 2)

                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 = ''

        return self.tron.manager.request(
            '/wallet/triggersmartcontract', {
                'contract_address': self.tron.address.to_hex(contract_address),
                'owner_address': self.tron.address.to_hex(issuer_address),
                'function_selector': function_selector,
                'fee_limit': int(fee_limit),
                'call_value': int(call_value),
                'parameter': parameters
            })
Esempio n. 21
0
    def create_smart_contract(self, **kwargs):
        """Deploy Contract

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

        Example:
        .. code-block:: python
            >>> from tronapi 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)

        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)
Esempio n. 22
0
    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
Esempio n. 23
0
    def trigger_smart_contract(self, **kwargs):
        """Trigger Smart Contract
        Calls a function on a contract

        Args:
            **kwargs: 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 = kwargs.setdefault('contract_address', None)
        function_selector = kwargs.setdefault('function_selector', None)
        parameters = kwargs.setdefault('parameters', [])
        issuer_address = kwargs.setdefault('issuer_address',
                                           self.tron.default_address.hex)
        call_value = kwargs.setdefault('call_value', 0)
        fee_limit = kwargs.setdefault('fee_limit', 1000000000)
        token_value = kwargs.setdefault('token_value', 0)
        token_id = kwargs.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')

        function_selector = function_selector.replace('/\s*/g', '')

        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', 2)

                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': self.tron.address.to_hex(issuer_address),
            '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)

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