def list_tokens(self, limit=0, offset=0): """Query the list of Tokens with pagination Args: limit (int): index of the starting Token offset (int): number of Tokens expected to be returned Returns: List of Tokens """ if not is_integer(limit) or (limit and offset < 1): raise InvalidTronError('Invalid limit provided') if not is_integer(offset) or offset < 0: raise InvalidTronError('Invalid offset provided') if not limit: return self.tron.manager.request('/wallet/getassetissuelist').get( 'assetIssue') return self.tron.manager.request('/wallet/getpaginatedassetissuelist', { 'limit': int(limit), 'offset': int(offset) })
def 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) )
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')
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 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 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")
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 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 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 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)
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})
def get_block_range(self, start, end): """Query a range of blocks by block height Args: start (int): starting block height, including this block end (int): ending block height, excluding that block """ if not is_integer(start) or start < 0: raise InvalidTronError('Invalid start of range provided') if not is_integer(end) or end <= start: raise InvalidTronError('Invalid end of range provided') response = self.tron.manager.request('/wallet/getblockbylimitnext', { 'startNum': int(start), 'endNum': int(end) + 1 }, 'post') return response.get('block')
def 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))
def get_latest_blocks(self, num=1): """Query the latest blocks Args: num (int): the number of blocks to query """ if not is_integer(num) or num <= 0: raise InvalidTronError('Invalid limit provided') response = self.tron.manager.request('/wallet/getblockbylatestnum', {'num': num}) return response.get('block')
def 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.")
def to_bytes(primitive=None, hexstr=None, text=None): assert_one_val(primitive, hexstr=hexstr, text=text) if is_boolean(primitive): return b'\x01' if primitive else b'\x00' elif isinstance(primitive, bytes): return primitive elif is_integer(primitive): return to_bytes(hexstr=to_hex(primitive)) elif hexstr is not None: if len(hexstr) % 2: hexstr = '0x0' + remove_0x_prefix(hexstr) return decode_hex(hexstr) elif text is not None: return text.encode('utf-8') raise TypeError("expected an int in first arg, or keyword of hexstr or text")
def get_transaction_from_block(self, block: Any, index: int = 0): """Get transaction details from Block Args: block (Any): Number or Hash Block index (int) Position """ if not is_integer(index) or index < 0: raise InvalidTronError('Invalid transaction index provided') transactions = self.get_block(block).get('transactions') if not transactions or len(transactions) < index: raise TronError('Transaction not found in block') return transactions[index]
def 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 })
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')
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 })
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)
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 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)