def get_contract(self, contract_address): """Queries a contract's information from the blockchain. Args: contract_address (str): contract address Returns: SmartContract object. """ if not self.tron.isAddress(contract_address): raise InvalidTronError('Invalid contract address provided') return self.tron.manager.request( '/wallet/getcontract', {'value': self.tron.address.to_hex(contract_address)})
def get_latest_blocks(self, limit=1): """Query the latest blocks Args: limit (int): the number of blocks to query Returns: A list of Block Objects """ if not is_integer(limit) or limit <= 0: raise InvalidTronError('Invalid limit provided') response = self.full_node.request('/wallet/getblockbylatestnum', {'limit': limit}, 'post') return response['block']
def get_account(self, address=None): """Query information about an account Args: address (str): Address """ if address is None: address = self.tron.default_address.hex if not self.tron.isAddress(address): raise InvalidTronError('Invalid address provided') return self.tron.manager.request( '/walletsolidity/getaccount', {'address': self.tron.address.to_hex(address)})
def get_transaction_from_block(self, block=None, index=0): """Get transaction details from Block Args: block (int|str): 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)['transactions'] if not transactions or len(transactions) < index: raise TronError('Transaction not found in block') return transactions[index]
def get_contract(self, contract_address): """Queries a contract's information from the blockchain. Args: contract_address (str): contract address Returns: SmartContract object. """ if not self.is_address(contract_address): raise InvalidTronError('Invalid contract address provided') contract_address = self.address.to_hex(contract_address) return self.full_node.request('/wallet/getcontract', {'value': contract_address}, 'post')
def get_tokens_issued_by_address(self, address): """List the tokens issued by an account. Args: address (str): address Returns: The token issued by the account. An account can issue only one token. """ if not self.tron.isAddress(address): raise InvalidTronError('Invalid address provided') address = self.tron.address.to_hex(address) return self.tron.manager.request('/wallet/getassetissuebyaccount', {'address': address})
def broadcast(self, signed_transaction): """Broadcast the signed transaction Args: signed_transaction (object): signed transaction contract data """ if not is_object(signed_transaction): raise InvalidTronError('Invalid transaction provided') if 'signature' not in signed_transaction: raise TronError('Transaction is not signed') response = self.tron.manager.request('/wallet/broadcasttransaction', signed_transaction) if 'result' in response: response.update({'transaction': signed_transaction}) return response
def get_account_resource(self, address=None): """Query the resource information of the account Args: address (str): Address Results: Resource information of the account """ if address is None: address = self.tron.default_address.hex if not self.tron.isAddress(address): raise InvalidTronError('Invalid address provided') return self.tron.manager.request( '/wallet/getaccountresource', {'address': self.tron.address.to_hex(address)})
def get_event_result(self, contract_address=None, since=0, event_name=None, block_number=None): """Will return all events matching the filters. Args: contract_address (str): Address to query for events. since (int): Filter for events since certain timestamp. event_name (str): Name of the event to filter by. block_number (str): Specific block number to query """ 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') 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}".format( route, since), method='get')
def broadcast(self, signed_transaction): """Broadcast the signed transaction Args: signed_transaction (object): signed transaction contract data Returns: broadcast success or failure """ if not is_object(signed_transaction): raise InvalidTronError('Invalid transaction provided') if 'signature' not in signed_transaction: raise TronError('Transaction is not signed') result = self.tron.manager.request('/wallet/broadcasttransaction', signed_transaction) result.update(signed_transaction) return result
def default_address(self, address: str) -> None: """Sets the address used with all Tron API. Will not sign any transactions. Args: address (str) Tron Address """ if not self.isAddress(address): raise InvalidTronError('Invalid address provided') _hex = self.address.to_hex(address) _base58 = self.address.from_hex(address) _private_base58 = self.address.from_private_key(self._private_key).base58 # check the addresses if self._private_key and _private_base58 != _base58: self._private_key = None self._default_address = AddrSt(hex=_hex, base58=_base58)
def get_band_width(self, address=None): """Query bandwidth information. Args: address (str): address Returns: Bandwidth information for the account. If a field doesn't appear, then the corresponding value is 0. { "freeNetUsed": 557, "freeNetLimit": 5000, "NetUsed": 353, "NetLimit": 5239157853, "TotalNetLimit": 43200000000, "TotalNetWeight": 41228 } """ if address is None: address = self.tron.default_address.hex if not self.tron.isAddress(address): raise InvalidTronError('Invalid address provided') response = self.tron.manager.request( '/wallet/getaccountnet', {'address': self.tron.address.to_hex(address)}) free_net_limit = 0 if 'freeNetLimit' not in response else response[ 'freeNetLimit'] free_net_used = 0 if 'freeNetUsed' not in response else response[ 'freeNetUsed'] net_limit = 0 if 'NetLimit' not in response else response['NetLimit'] net_used = 0 if 'NetUsed' not in response else response['NetUsed'] return (free_net_limit - free_net_used) + (net_limit - net_used)
def send_transaction(self, to, amount, message=None, owner_address=None): """Send an asset to another account. Parameters: to (str): Recipient amount (float): Amount to transfer message (str, optional): Message owner_address (str, optional): the source account for the transfer if not ``default_address`` """ if owner_address is None: owner_address = self.default_address.hex if message is not None and not isinstance(message, str): raise InvalidTronError('Invalid Message') tx = self.transaction.send_transaction(to, amount, owner_address) sign = self.sign(tx, message) result = self.broadcast(sign) return result
def set_address(self, address): """Sets the address used with all Tron API's. Will not sign any transactions. Args: address (str) Tron Address Example: >>> tron.set_address('TSkTw9Hd3oaJULL3er1UNfzASkunE9yA8f') """ if not self.is_address(address): raise InvalidTronError('Invalid address provided') _hex = self.address.to_hex(address) _base58 = self.address.from_hex(address) _private_base58 = self.address.from_private_key( self._private_key).base58 # check the addresses if self._private_key and _private_base58 != _base58: self._private_key = None self.default_address = Address(hex=_hex, base58=_base58)
def get_event_result(self, **kwargs): """Will return all events matching the filters. Args: kwargs (any): List parameters """ # Check the most necessary parameters since_timestamp = kwargs.setdefault('since_timestamp', 0) event_name = kwargs.setdefault('event_name', 'Notify') block_number = kwargs.setdefault('block_number', '') size = kwargs.setdefault('size', 20) page = kwargs.setdefault('page', 1) only_confirmed = kwargs.setdefault('only_confirmed', None) only_unconfirmed = kwargs.setdefault('only_unconfirmed', None) previous_last = kwargs.setdefault('previous_last_event_fingerprint', None) contract_address = kwargs.setdefault('contract_address', self.default_address.hex) 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 sign(self, transaction: Any, private_key=None, use_tron: bool = True, multisig: bool = False, is_message_hex=False): """Safe method for signing your transaction Warnings: method: online_sign() - Use only in extreme cases. Args: transaction (Any): transaction details use_tron (bool): is Tron header multisig (bool): multi sign """ if is_string(transaction): if not is_hex(transaction): raise TronError('Expected hex message input') # Determine which header to attach to the message # before encrypting or decrypting header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER header += str(len(transaction)) if is_message_hex: from eth_hash.auto import keccak as keccak_256 message_hash = keccak_256( header.encode('utf-8') + bytes.fromhex(transaction)) else: message_hash = self.tron.keccak(text=header + transaction) signed_message = Account.sign_hash( self.tron.toHex(message_hash), private_key or self.tron.private_key) return signed_message if not multisig and 'signature' in transaction: raise TronError('Transaction is already signed') try: if not multisig: address = self.tron.address.from_private_key( private_key or self.tron.private_key).hex.lower() owner_address = transaction['raw_data']['contract'][0][ 'parameter']['value']['owner_address'] if address != owner_address: raise ValueError( 'Private key does not match address in transaction') # This option deals with signing of transactions, and writing to the array signed_tx = Account.sign_hash(transaction['txID'], private_key or self.tron.private_key) signature = signed_tx['signature'].hex()[2:] # support multi sign if 'signature' in transaction and is_list( transaction['signature']): if not transaction['signature'].index(signature): transaction['signature'].append(signature) else: transaction['signature'] = [signature] return transaction except ValueError as err: raise InvalidTronError(err)