def broadcast_tx(self, tx): data = { "jsonrpc": "2.0", "method": "eth_sendRawTransaction", "params": ["0x" + tx], "id": 1 } response = requests.post(self.base_url, json=data) if 'error' in response.json(): logging.error("MyEtherWallet returned an error: %s", response.json()['error']) raise BroadcastError(response.json()['error']) if int(response.status_code) == 200: tx_id = response.json().get('result', None) logging.info("Transaction ID obtained from broadcast through MyEtherWallet: %s", tx_id) return tx_id logging.error('Error broadcasting the transaction through MyEtherWallet. Error msg: %s', response.text) raise BroadcastError(response.text)
def get_balance(self, address): """ returns the balance in wei with some inspiration from PyWallet """ broadcast_url = self.base_url + '?module=account&action=balance' broadcast_url += '&address=%s' % address broadcast_url += '&tag=pending' if self.api_token: broadcast_url += '&apikey=%s' % self.api_token response = requests.get(broadcast_url) if int(response.status_code) == 200: if response.json().get('message', None) == 'NOTOK': raise BroadcastError(response.json().get('result', None)) balance = int(response.json().get('result', None)) logging.info('Balance check succeeded: %s', response.json()) return balance raise BroadcastError(response.text)
def broadcast_tx(self, tx): hextx = to_hex(tx) broadcast_url = self.base_url + '/tx' response = requests.post(broadcast_url, data=hextx) if int(response.status_code) == 200: tx_id = response.text return tx_id logging.error('Error broadcasting the transaction through the Blockstream API. Error msg: %s', response.text) raise BroadcastError(response.text)
def broadcast_tx(self, tx): tx_hex = tx broadcast_url = self.base_url + '?module=proxy&action=eth_sendRawTransaction' if self.api_token: broadcast_url += '&apikey=%s' % self.api_token response = requests.post(broadcast_url, data={'hex': tx_hex}) if 'error' in response.json(): logging.error("Etherscan returned an error: %s", response.json()['error']) raise BroadcastError(response.json()['error']) if int(response.status_code) == 200: if response.json().get('message', None) == 'NOTOK': raise BroadcastError(response.json().get('result', None)) tx_id = response.json().get('result', None) logging.info("Transaction ID obtained from broadcast through Etherscan: %s", tx_id) return tx_id logging.error('Error broadcasting the transaction through the Etherscan API. Error msg: %s', response.text) raise BroadcastError(response.text)
def broadcast_tx(self, tx): hextx = to_hex(tx) url = self.base_url + '/tx/push' response = requests.post(url, json={'hex': hextx}) if int(response.status_code) == 200: tx_id = response.json().get('data', None) return tx_id logging.error( 'Error broadcasting the transaction through the Blockr.IO API. Error msg: %s', response.text) raise BroadcastError(response.text)
def broadcast_tx(self, tx): hextx = to_hex(tx) broadcast_url = self.base_url + '/txs/push?token=' + self.api_token response = requests.post(broadcast_url, json={'tx': hextx}) if int(response.status_code) == 200: tx_id = response.json().get('txid', None) return tx_id logging.error( 'Error broadcasting the transaction through the Blockcypher API. Error msg: %s', response.text) raise BroadcastError(response.text)
def get_address_nonce(self, address): """ Looks up the address nonce of this address Neccesary for the transaction creation """ broadcast_url = self.base_url + '?module=proxy&action=eth_getTransactionCount' broadcast_url += '&address=%s' % address broadcast_url += '&tag=pending' # Valid tags are 'earliest', 'latest', and 'pending', the last of which includes both pending and committed transactions. if self.api_token: broadcast_url += '&apikey=%s' % self.api_token response = requests.get(broadcast_url, ) if int(response.status_code) == 200: if response.json().get('message', None) == 'NOTOK': raise BroadcastError(response.json().get('result', None)) nonce = int(response.json().get('result', None), 0) logging.info('Nonce check went correct: %s', response.json()) return nonce else: logging.info('response error checking nonce') raise BroadcastError('Error checking the nonce through the Etherscan API. Error msg: %s', response.text)
def broadcast_tx(self, tx): hextx = to_hex(tx) broadcast_url = self.base_url + '/tx/send' response = requests.post(broadcast_url, json={'rawtx': hextx}) if int(response.status_code) == 200: tx_id = response.json().get('txid', None) return tx_id logging.error( 'Error broadcasting the transaction through the Bitpay API. Error msg: %s', response.text) raise BroadcastError(response.text)
def get_balance(self, address, api_token): """ returns the balance in wei with some inspiration from PyWallet """ broadcast_url = self.base_url + '?module=account&action=balance' broadcast_url += '&address=%s' % address broadcast_url += '&tag=latest' if api_token: '&apikey=%s' % api_token response = requests.get(broadcast_url) if int(response.status_code) == 200: balance = int(response.json().get('result', None)) logging.info('Balance check went correct: %s', response.json()) return balance raise BroadcastError(response.text)
def broadcast_tx(self, tx): hextx = to_hex(tx) broadcast_url = self.base_url + '/txs/push' if self.api_token: broadcast_url += '?token=' + self.api_token logging.info(broadcast_url) response = requests.post(broadcast_url, json={'tx': hextx}) logging.info(response) if int(response.status_code) == 201: tx_id = response.json().get('tx', None) tx_hash = tx_id.get('hash', None) logging.info(tx_hash) return tx_hash logging.error( 'Error broadcasting the transaction through the Blockcypher API. Error msg: %s', response.text) raise BroadcastError(response.text)
def broadcast_tx_with_chain(tx, bitcoin_chain, bitcoind=False): """ Broadcast the transaction through the configured set of providers :param tx: :param bitcoin_chain: :return: """ last_exception = None final_tx_id = None # Unlike other providers, we want to broadcast to all available apis for attempt_number in range(0, MAX_BROADCAST_ATTEMPTS): for method_provider in service_provider_methods( 'broadcast_tx', get_providers_for_chain(bitcoin_chain, bitcoind)): try: tx_id = method_provider(tx) if tx_id: logging.info( 'Broadcasting succeeded with method_provider=%s, txid=%s', str(method_provider), tx_id) if final_tx_id and final_tx_id != tx_id: logging.error( 'This should never happen; fail and investigate if it does. Got conflicting tx_ids=%s and %s. Hextx=%s', final_tx_id, tx_id, tx.as_hex()) raise Exception('Got conflicting tx_ids.') final_tx_id = tx_id except Exception as e: logging.warning( 'Caught exception trying provider %s. Trying another. Exception=%s', str(method_provider), e) last_exception = e # At least 1 provider succeeded, so return if final_tx_id: return final_tx_id else: logging.warning( 'Broadcasting failed. Waiting before retrying. This is attempt number %d', attempt_number) time.sleep(BROADCAST_RETRY_INTERVAL) logging.error('Failed broadcasting through all providers') logging.error(last_exception, exc_info=True) raise BroadcastError(last_exception)
def get_address_nonce(self, address, api_token): """ Looks up the address nonce of this address Neccesary for the transaction creation """ broadcast_url = self.base_url + '?module=proxy&action=eth_getTransactionCount' broadcast_url += '&address=%s' % address broadcast_url += '&tag=latest' if api_token: '&apikey=%s' % api_token response = requests.get(broadcast_url, ) if int(response.status_code) == 200: # the int(res, 0) transforms the hex nonce to int nonce = int(response.json().get('result', None), 0) logging.info('Nonce check went correct: %s', response.json()) return nonce else: logging.info('response error checking nonce') raise BroadcastError('Error checking the nonce through the Etherscan API. Error msg: %s', response.text)
def get_balance(self, address): """ returns the balance in wei """ data = { "jsonrpc": "2.0", "method": "eth_getBalance", "params": [address, "latest"], "id": 1 } response = requests.post(self.base_url, json=data) if int(response.status_code) == 200: logging.info('Balance check response: %s', response.json()) balance = int(response.json().get('result', None), 0) logging.info('Balance check succeeded: %s', response.json()) return balance logging.error('Error getting balance through MyEtherWallet. Error msg: %s', response.text) raise BroadcastError(response.text)
def broadcast_tx(self, tx): last_exception = None final_tx_id = None # Broadcast to all available api's for attempt_number in range(0, MAX_BROADCAST_ATTEMPTS): for m in get_providers_for_chain(self.ethereum_chain, self.local_node): try: logging.debug('m=%s', m) txid = m.broadcast_tx(tx, self.api_key) if (txid): logging.info( 'Broadcasting succeeded with method_provider=%s, txid=%s', str(m), txid) if final_tx_id and final_tx_id != txid: logging.error( 'This should never happen; fail and investigate if it does. Got conflicting tx_ids=%s and %s. Hextx=%s', final_tx_id, txid, tx.as_hex()) raise Exception('Got conflicting tx_ids.') final_tx_id = txid return txid except Exception as e: logging.warning( 'Caught exception trying provider %s. Trying another. Exception=%s', str(m), e) last_exception = e # At least 1 provider succeeded, so return if final_tx_id: return final_tx_id else: logging.warning( 'Broadcasting failed. Waiting before retrying. This is attempt number %d', attempt_number) time.sleep(BROADCAST_RETRY_INTERVAL) ##in case of failure: logging.error('Failed broadcasting through all providers') logging.error(last_exception, exc_info=True) raise BroadcastError(last_exception)
def issue(self, chain): """ Issue the certificates on the blockchain :return: """ blockchain_bytes = self.certificate_batch_handler.prepare_batch() for attempt_number in range(0, self.max_retry): try: txid = self.transaction_handler.issue_transaction(blockchain_bytes) self.certificate_batch_handler.finish_batch(txid, chain) logging.info('Broadcast transaction with txid: %s', txid) return txid except BroadcastError: logging.warning( 'Failed broadcast reattempts. Trying to recreate transaction. This is attempt number %d', attempt_number) logging.error('All attempts to broadcast failed. Try rerunning issuer.') raise BroadcastError('All attempts to broadcast failed. Try rerunning issuer.')
def get_address_nonce(self, address): """ Looks up the address nonce of this address Neccesary for the transaction creation """ data = { "jsonrpc": "2.0", "method": "eth_getTransactionCount", "params": [address, "pending"], "id": 1 } response = requests.post(self.base_url, json=data) if int(response.status_code) == 200: # the int(res, 0) transforms the hex nonce to int nonce = int(response.json().get('result', None), 0) logging.info('Nonce check went correct: %s', response.json()) return nonce else: logging.info('response error checking nonce') raise BroadcastError('Error checking the nonce through the MyEtherWallet API. Error msg: %s', response.text)
def issue(self, chain, app_config, recipient_address, token_uri="https://bloxberg.org"): """ Issue the certificates on the blockchain :return: """ blockchain_bytes = self.certificate_batch_handler.prepare_batch() recipient_address = Web3.toChecksumAddress(recipient_address) print(is_checksum_address(recipient_address)) #change token_uri address print(token_uri) #token_uri = "https://bloxberg.org" #blockchain_bytes = str(blockchain_bytes, 'latin-1') blockchain_bytes = blockchain_bytes.hex() for attempt_number in range(0, self.max_retry): try: txid = self.transaction_handler.issue_transaction( recipient_address, token_uri, blockchain_bytes, app_config) event_args = self.transaction_handler.get_event_args( txid, 'Transfer') token_id = event_args['tokenId'] self.certificate_batch_handler.finish_batch( txid, chain, app_config) logging.info('Broadcast transaction with txid %s', txid) return (txid, token_id) except BroadcastError: logging.warning( 'Failed broadcast reattempts. Trying to recreate transaction. This is attempt number %d', attempt_number) logging.error( 'All attempts to broadcast failed. Try rerunning issuer.') raise BroadcastError( 'All attempts to broadcast failed. Try rerunning issuer.')
def update_token_uri(self, chain, app_config, token_id, token_uri): """ Update the tokenURI for the issued certificate batch :return: transaction id """ #token_id = token_array[0] #token_uri = token_array[1] for attempt_number in range(0, self.max_retry): try: txid = self.transaction_handler.update_token_uri( token_id, token_uri, app_config) logging.info( 'Updating tokenURI field with ipfs link. Txid: %s', txid) return txid except BroadcastError: logging.warning( 'Failed broadcast reattempts. Trying to recreate transaction. This is attempt number %d', attempt_number) logging.error( 'All attempts to broadcast failed. Try rerunning issuer.') raise BroadcastError( 'All attempts to broadcast failed. Try rerunning issuer.')
def issue_on_blockchain(self): """ Issue the certificates on the Bitcoin blockchain :param revocation_address: :return: """ self.tree.make_tree() op_return_value_bytes = unhexlify(self.tree.get_merkle_root()) op_return_value = hexlify(op_return_value_bytes) for attempt_number in range(0, self.max_retry): try: if self.prepared_inputs: inputs = self.prepared_inputs else: spendables = self.connector.get_unspent_outputs( self.secure_signer.issuing_address) if not spendables: error_message = 'No money to spend at address {}'.format( self.secure_signer.issuing_address) logging.error(error_message) raise InsufficientFundsError(error_message) cost = self.transaction_handler.estimate_cost_for_certificate_batch( ) current_total = 0 inputs = [] random.shuffle(spendables) for s in spendables: inputs.append(s) current_total += s.coin_value if current_total > cost: break tx = self.transaction_handler.create_transaction( inputs, op_return_value_bytes) hex_tx = hexlify(tx.serialize()) logging.info('Unsigned hextx=%s', hex_tx) prepared_tx = tx_utils.prepare_tx_for_signing(hex_tx, inputs) with FinalizableSigner(self.secure_signer) as signer: signed_tx = signer.sign_transaction(prepared_tx) # log the actual byte count tx_byte_count = tx_utils.get_byte_count(signed_tx) logging.info('The actual transaction size is %d bytes', tx_byte_count) signed_hextx = signed_tx.as_hex() logging.info('Signed hextx=%s', signed_hextx) # verify transaction before broadcasting tx_utils.verify_transaction(signed_hextx, op_return_value) # send tx and persist txid tx_id = self.connector.broadcast_tx(signed_tx) logging.info('Broadcast transaction with txid %s', tx_id) return tx_id except BroadcastError: logging.warning( 'Failed broadcast reattempts. Trying to recreate transaction. This is attempt number %d', attempt_number) logging.error( 'All attempts to broadcast failed. Try rerunning issuer.') raise BroadcastError( 'All attempts to broadcast failed. Try rerunning issuer.')