def gettransaction(self, tx_id): tx = self.compose_request('transaction', tx_id) rawtx = tx['raw'] t = Transaction.import_raw(rawtx, network=self.network) if tx['confirmations']: t.status = 'confirmed' else: t.status = 'unconfirmed' if t.coinbase: t.input_total = t.output_total else: t.input_total = tx['total_input_value'] t.output_total = tx['total_output_value'] t.fee = tx['total_fee'] t.hash = tx['hash'] t.block_hash = tx['block_hash'] t.block_height = tx['block_height'] t.confirmations = tx['confirmations'] t.date = datetime.strptime(tx['block_time'], "%Y-%m-%dT%H:%M:%S+%f") t.size = tx['size'] for n, i in enumerate(t.inputs): i.value = tx['inputs'][n]['value'] for n, o in enumerate(t.outputs): if tx['outputs'][n]['address']: o.spent = True if 'spent_hash' in tx['outputs'][n] else False return t
def gettransaction(self, tx_id): res = self.compose_request('get_tx', tx_id) tx = res['data'] raw_tx = tx['tx_hex'] t = Transaction.import_raw(raw_tx, network=self.network) input_total = 0 output_total = 0 for n, i in enumerate(t.inputs): i.value = int( round(float(tx['inputs'][n]['value']) * self.units, 0)) input_total += i.value for o in t.outputs: # TODO: Check if output is spent o.spent = None output_total += o.value t.hash = tx_id t.block_hash = tx['blockhash'] t.date = datetime.fromtimestamp(tx['time']) t.rawtx = raw_tx t.size = tx['size'] t.network_name = self.network t.locktime = tx['locktime'] t.input_total = input_total t.output_total = output_total t.fee = t.input_total - t.output_total t.confirmations = tx['confirmations'] if tx['confirmations']: t.status = 'confirmed' else: t.status = 'unconfirmed' return t
def transaction_decompose(network): rawtx = request.args.get('rawtx', type=str) form = TransactionDecomposeForm() srv = SmurferService(network) if form.validate_on_submit(): try: t = Transaction.import_raw(form.rawtx.data, network=srv.network) except Exception as e: flash(_('Invalid raw transaction hex, could not parse: %s' % e), category='error') else: # TODO: Retreiving prev_tx input values should be included in bitcoinlib try: for n, i in enumerate(t.inputs): ti = srv.gettransaction(i.prev_txid.hex()) t.inputs[n].value = ti.outputs[i.output_n_int].value t.verify() except TransactionError as e: flash(_('Could not verify transaction: %s' % e), category='warning') t_json = t.as_json() return render_template( 'explorer/transaction_elements.html', title=_('Decomposed Transaction'), subtitle=_('Transaction elements as dictionary'), transaction_dict=t_json, rawtx=form.rawtx.data, network=network) form.rawtx.data = rawtx return render_template('explorer/transaction_decompose.html', title=_('Decompose Transaction'), subtitle=_('Decompose your raw transaction hex'), form=form, network=network)
def getrawtransaction(self, tx_id): tx = self.compose_request('rawtx', tx_id) t = Transaction.import_raw(tx['rawtx'], network=self.network) for i in t.inputs: if not i.address: raise ClientError("Address missing in input. Provider might not support segwit transactions") return tx['rawtx']
def gettransaction(self, txid, block_height=None): res = self.compose_request('get_tx', txid) tx = res['data'] rawtx = tx['tx_hex'] t = Transaction.parse_hex(rawtx, strict=False, network=self.network) input_total = 0 output_total = 0 if not t.coinbase: for n, i in enumerate(t.inputs): i.value = int(round(float(tx['inputs'][n]['value']) * self.units, 0)) input_total += i.value for o in t.outputs: o.spent = None output_total += o.value if not t.block_height and tx['confirmations']: t.block_height = self.getblock(tx['blockhash'], False, 1, 1)['height'] t.block_hash = tx['blockhash'] t.rawtx = bytes.fromhex(rawtx) t.size = tx['size'] t.network = self.network t.locktime = tx['locktime'] t.input_total = input_total t.output_total = output_total t.fee = 0 if t.input_total: t.fee = t.input_total - t.output_total t.confirmations = tx['confirmations'] if tx['confirmations']: t.status = 'confirmed' t.date = datetime.utcfromtimestamp(tx['time']) else: t.status = 'unconfirmed' t.date = None return t
def transaction_broadcast(network): rawtx = request.data srv = SmurferService(network) errors = [] txid = '' res = {} try: t = Transaction.import_raw(rawtx) except Exception as e: errors.append(_('Invalid raw transaction hex, could not parse: %s' % e)) else: known_tx = srv.gettransaction(t.txid) if known_tx: errors.append(_('This transaction %s is already included in the blockchain' % t.txid)) else: res = srv.sendrawtransaction(rawtx) if not res or 'txid' not in res: # TODO: Get decent error message, without private details errors.append(_('Could not send raw transaction. %s' % srv.errors.get('bcoin', ''))) data = { 'success': True if txid else False, 'txid': txid, 'errors': ','.join(errors), 'raw_response': res } return jsonify(data), 200 if txid else 400
def gettransaction(self, tx_id, latest_block=None): tx = self.compose_request('rawtx', tx_id) raw_tx = self.getrawtransaction(tx_id) t = Transaction.import_raw(raw_tx, self.network) input_total = 0 for n, i in enumerate(t.inputs): if 'prev_out' in tx['inputs'][n]: i.value = tx['inputs'][n]['prev_out']['value'] input_total += i.value for n, o in enumerate(t.outputs): o.spent = tx['out'][n]['spent'] if 'block_height' in tx and tx['block_height']: if not latest_block: latest_block = self.blockcount() t.status = 'confirmed' t.date = datetime.utcfromtimestamp(tx['time']) t.block_height = tx['block_height'] t.confirmations = 1 if latest_block > t.block_height: t.confirmations = latest_block - t.block_height else: t.status = 'unconfirmed' t.confirmations = 0 t.date = None t.hash = tx_id t.rawtx = raw_tx t.size = tx['size'] t.network_name = self.network t.locktime = tx['lock_time'] t.version = struct.pack('>L', tx['ver']) t.input_total = input_total if t.coinbase: t.input_total = t.output_total t.fee = t.input_total - t.output_total return t
def gettransaction(self, tx_id): tx = self.compose_request('txs', tx_id, variables={'includeHex': 'true'}) t = Transaction.import_raw(tx['hex'], network=self.network) t.hash = tx_id if tx['confirmations']: t.status = 'confirmed' else: t.status = 'unconfirmed' t.date = datetime.strptime(tx['confirmed'][:19], "%Y-%m-%dT%H:%M:%S") t.confirmations = tx['confirmations'] t.block_height = tx['block_height'] t.block_hash = tx['block_hash'] t.fee = tx['fees'] t.rawtx = tx['hex'] t.size = tx['size'] t.network_name = self.network t.input_total = 0 if t.coinbase: t.input_total = t.output_total for n, i in enumerate(t.inputs): if 'output_value' in tx['inputs'][n]: i.value = tx['inputs'][n]['output_value'] t.input_total += i.value for n, o in enumerate(t.outputs): if 'spent_by' in tx['outputs'][n]: o.spent = True return t
def gettransaction(self, tx_id): tx = self.compose_request('rawtx', tx_id) raw_tx = self.getrawtransaction(tx_id) t = Transaction.import_raw(raw_tx) input_total = None for n, i in enumerate(t.inputs): if 'prev_out' in tx['inputs'][n]: i.value = tx['inputs'][n]['prev_out']['value'] input_total = input_total + i.value if input_total is not None else i.value for n, o in enumerate(t.outputs): o.spent = tx['out'][n]['spent'] # if tx['relayed_by'] == '0.0.0.0': if tx['block_height']: t.status = 'confirmed' else: t.status = 'unconfirmed' t.hash = tx_id t.date = datetime.fromtimestamp(tx['time']) t.block_height = tx['block_height'] t.rawtx = raw_tx t.size = tx['size'] t.network_name = self.network t.locktime = tx['lock_time'] t.version = struct.pack('>L', tx['ver']) t.input_total = input_total t.fee = t.input_total - t.output_total return t
def gettransaction(self, txid): variables = {'id': txid, 'hex': None} tx = self.compose_request(path_type='explorer', variables=variables) t = Transaction.parse_hex(tx['hex'], strict=False, network=self.network) variables = {'t': txid} tx_api = self.compose_request('txinfo', path_type='api', variables=variables) for n, i in enumerate(t.inputs): if i.script_type != 'coinbase': i.value = int(round(tx_api['inputs'][n]['amount'] * self.units, 0)) else: i.value = 0 t.coinbase = True for n, o in enumerate(t.outputs): o.spent = None if tx['confirmations']: t.status = 'confirmed' else: t.status = 'unconfirmed' t.date = datetime.utcfromtimestamp(tx['time']) t.block_height = tx_api['block'] t.block_hash = tx['blockhash'] t.confirmations = tx['confirmations'] t.rawtx = bytes.fromhex(tx['hex']) t.size = tx['size'] t.network = self.network t.locktime = tx['locktime'] t.version = tx['version'].to_bytes(4, 'big') t.output_total = int(round(tx_api['total_output'] * self.units, 0)) t.input_total = t.output_total t.fee = 0 if t.input_total: t.fee = t.input_total - t.output_total return t
def gettransaction(self, txid, block_height=None, get_input_values=True): tx = self.proxy.getrawtransaction(txid, 1) t = Transaction.import_raw(tx['hex'], network=self.network) t.confirmations = tx['confirmations'] if t.confirmations: t.status = 'confirmed' t.verified = True for i in t.inputs: if i.prev_txid == b'\x00' * 32: i.value = t.output_total i.script_type = 'coinbase' continue if get_input_values: txi = self.proxy.getrawtransaction(i.prev_txid.hex(), 1) i.value = int( round( float(txi['vout'][i.output_n_int]['value']) / self.network.denominator)) for o in t.outputs: o.spent = None t.version = tx['version'].to_bytes(4, 'big') t.date = datetime.fromtimestamp(tx['blocktime']) t.block_height = block_height t.update_totals() return t
def gettransaction(self, txid): tx = self.proxy.getrawtransaction(txid, 1) t = Transaction.import_raw(tx['hex'], network=self.network) t.confirmations = tx['confirmations'] if t.confirmations: t.status = 'confirmed' t.verified = True for i in t.inputs: if i.prev_hash == b'\x00' * 32: i.value = t.output_total i.script_type = 'coinbase' continue txi = self.proxy.getrawtransaction(to_hexstring(i.prev_hash), 1) i.value = int( round( float(txi['vout'][i.output_n_int]['value']) / self.network.denominator)) for o in t.outputs: o.spent = None t.block_hash = tx['blockhash'] t.version = struct.pack('>L', tx['version']) t.date = datetime.fromtimestamp(tx['blocktime']) t.hash = txid t.update_totals() return t
def gettransaction(self, txid): tx = self.compose_request('txs', txid, variables={'includeHex': 'true'}) t = Transaction.import_raw(tx['hex'], network=self.network) if tx['confirmations']: t.status = 'confirmed' t.date = datetime.strptime(tx['confirmed'][:19], "%Y-%m-%dT%H:%M:%S") else: t.status = 'unconfirmed' t.confirmations = tx['confirmations'] t.block_height = tx['block_height'] if tx['block_height'] > 0 else None t.fee = tx['fees'] t.rawtx = bytes.fromhex(tx['hex']) t.size = int(len(tx['hex']) / 2) t.network = self.network t.input_total = 0 if len(t.inputs) != len(tx['inputs']): raise ClientError("Invalid number of inputs provided. Raw tx: %d, blockcypher: %d" % (len(t.inputs), len(tx['inputs']))) for n, i in enumerate(t.inputs): if not t.coinbase and not (tx['inputs'][n]['output_index'] == i.output_n_int and tx['inputs'][n]['prev_hash'] == i.prev_txid.hex()): raise ClientError("Transaction inputs do not match raw transaction") if 'output_value' in tx['inputs'][n]: if not t.coinbase: i.value = tx['inputs'][n]['output_value'] t.input_total += i.value if len(t.outputs) != len(tx['outputs']): raise ClientError("Invalid number of outputs provided. Raw tx: %d, blockcypher: %d" % (len(t.outputs), len(tx['outputs']))) for n, o in enumerate(t.outputs): if 'spent_by' in tx['outputs'][n]: o.spent = True o.spending_txid = tx['outputs'][n]['spent_by'] return t
def _parse_transaction(self, tx, block_height=None, get_input_values=True): t = Transaction.import_raw(tx['hex'], network=self.network) t.confirmations = tx.get('confirmations') t.block_hash = tx.get('blockhash') t.status = 'unconfirmed' for i in t.inputs: if i.prev_txid == b'\x00' * 32: i.script_type = 'coinbase' continue if get_input_values: txi = self.proxy.getrawtransaction(i.prev_txid.hex(), 1) i.value = int( round( float(txi['vout'][i.output_n_int]['value']) / self.network.denominator)) for o in t.outputs: o.spent = None if not block_height and t.block_hash: block_height = self.proxy.getblock(t.block_hash, 1)['height'] t.block_height = block_height if not t.confirmations and block_height is not None: if not self.latest_block: self.latest_block = self.blockcount() t.confirmations = (self.latest_block - block_height) + 1 if t.confirmations or block_height: t.status = 'confirmed' t.verified = True t.version = tx['version'].to_bytes(4, 'big') t.version_int = tx['version'] t.date = None if 'time' not in tx else datetime.utcfromtimestamp( tx['time']) t.update_totals() return t
def _parse_transaction(self, tx): t = Transaction.import_raw(tx['rawTx'], network=self.network) t.status = 'unconfirmed' if tx['confirmations']: t.status = 'confirmed' t.hash = tx['txId'] if 'timestamp' in tx and tx['timestamp']: t.date = datetime.fromtimestamp(tx['timestamp']) elif 'blockTime' in tx and tx['blockTime']: t.date = datetime.fromtimestamp(tx['blockTime']) t.confirmations = tx['confirmations'] if 'blockHeight' in tx: t.block_height = tx['blockHeight'] t.block_hash = tx['blockHash'] t.fee = tx['fee'] t.rawtx = tx['rawTx'] t.size = tx['size'] t.network = self.network if not t.coinbase: for i in t.inputs: i.value = tx['vIn'][str(i.index_n)]['amount'] for o in t.outputs: if tx['vOut'][str(o.output_n)]['spent']: o.spent = True if t.coinbase: t.input_total = tx['outputsAmount'] - t.fee else: t.input_total = tx['inputsAmount'] t.output_total = tx['outputsAmount'] return t
def _parse_transaction(self, tx, strict=True): status = 'unconfirmed' if tx['confirmations']: status = 'confirmed' t = Transaction.parse_hex(tx['hex'], strict=False, network=self.network) if not t.txid == tx['hash']: if strict: raise ClientError('Received transaction has different txid') else: t.txid = tx['hash'] _logger.warning('Received transaction has different txid') t.locktime = tx['locktime'] t.network = self.network t.fee = tx['fee'] t.date = datetime.utcfromtimestamp(tx['time']) if tx['time'] else None t.confirmations = tx['confirmations'] t.block_height = tx['height'] if tx['height'] > 0 else None t.block_hash = tx['block'] t.status = status if not t.coinbase: for i in t.inputs: i.value = tx['inputs'][t.inputs.index(i)]['coin']['value'] for o in t.outputs: o.spent = None t.update_totals() return t
def _parse_db_transaction(db_tx): if not db_tx.raw: return False t = Transaction.import_raw(db_tx.raw, db_tx.network_name) # locktime, version, coinbase?, witness_type # t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network, # fee=tx['fee'], size=tx['size'], hash=tx['txid'], # date=tdate, input_total=tx['input_total'], output_total=tx['output_total'], # confirmations=confirmations, block_height=block_height, status=tx['status'], # coinbase=tx['coinbase'], rawtx=tx['raw_hex'], witness_type=tx['witness_type']) for n in db_tx.nodes: if n.is_input: t.inputs[n.output_n].value = n.value t.inputs[n.output_n].address = n.address else: t.outputs[n.output_n].spent = n.spent t.outputs[n.output_n].spending_txid = n.spending_txid t.outputs[n.output_n].spending_index_n = n.spending_index_n t.hash = to_bytes(db_tx.txid) t._txid = db_tx.txid t.date = db_tx.date t.block_hash = db_tx.block_hash t.block_height = db_tx.block_height t.confirmations = db_tx.confirmations t.status = 'confirmed' t.fee = db_tx.fee t.update_totals() if t.coinbase: t.input_total = t.output_total _logger.info("Retrieved transaction %s from cache" % t.txid) return t
def gettransaction(self, tx_id): variables = {'id': tx_id, 'hex': None} tx = self.compose_request(path_type='explorer', variables=variables) t = Transaction.import_raw(tx['hex'], self.network) variables = {'t': tx_id} tx_api = self.compose_request('txinfo', path_type='api', variables=variables) for n, i in enumerate(t.inputs): i.value = int(round(tx_api['inputs'][n]['amount'] * self.units, 0)) for n, o in enumerate(t.outputs): o.spent = None if tx['confirmations']: t.status = 'confirmed' else: t.status = 'unconfirmed' t.hash = tx_id t.date = datetime.fromtimestamp(tx['time']) t.block_height = tx_api['block'] t.block_hash = tx['blockhash'] t.confirmations = tx['confirmations'] t.rawtx = tx['hex'] t.size = tx['size'] t.network = self.network t.locktime = tx['locktime'] t.version = struct.pack('>L', tx['version']) t.input_total = int(round(tx_api['total_input'] * self.units, 0)) t.output_total = int(round(tx_api['total_output'] * self.units, 0)) t.fee = t.input_total - t.output_total return t
def _parse_transaction(self, tx, block_count=None): block_height = None if not tx['block_height'] else tx['block_height'] confirmations = tx['confirmations'] if block_height and not confirmations and tx['status'] == 'confirmed': if not block_count: block_count = self.blockcount() confirmations = block_count - block_height tx_date = None if not tx.get('date') else datetime.strptime( tx['date'], "%Y-%m-%dT%H:%M:%S") # FIXME: Blocksmurfer returns 'date' or 'time', should be consistent if not tx_date and 'time' in tx: tx_date = datetime.utcfromtimestamp(tx['time']) t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network, fee=tx['fee'], size=tx['size'], txid=tx['txid'], date=tx_date, input_total=tx['input_total'], output_total=tx['output_total'], confirmations=confirmations, block_height=block_height, status=tx['status'], coinbase=tx['coinbase'], rawtx=bytes.fromhex(tx['raw_hex']), witness_type=tx['witness_type']) for ti in tx['inputs']: t.add_input(prev_txid=ti['prev_txid'], output_n=ti['output_n'], keys=ti.get('keys', []), index_n=ti['index_n'], unlocking_script=ti['script'], value=ti['value'], public_hash=bytes.fromhex(ti['public_hash']), address=ti['address'], witness_type=ti['witness_type'], locktime_cltv=ti['locktime_cltv'], locktime_csv=ti['locktime_csv'], signatures=ti['signatures'], compressed=ti['compressed'], encoding=ti['encoding'], unlocking_script_unsigned=ti['script_code'], sigs_required=ti['sigs_required'], sequence=ti['sequence'], witnesses=[bytes.fromhex(w) for w in ti['witnesses']], script_type=ti['script_type'], strict=False) for to in tx['outputs']: t.add_output(value=to['value'], address=to['address'], public_hash=to['public_hash'], lock_script=to['script'], spent=to['spent'], strict=False) t.update_totals() return t
def _convert_to_transaction(self, tx): if tx['confirmations']: status = 'confirmed' else: status = 'unconfirmed' fees = None if 'fees' not in tx else int( round(float(tx['fees']) * self.units, 0)) value_in = 0 if 'valueIn' not in tx else tx['valueIn'] isCoinbase = False if 'isCoinBase' in tx and tx['isCoinBase']: value_in = tx['valueOut'] isCoinbase = True t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network, fee=fees, size=tx['size'], hash=tx['txid'], date=datetime.utcfromtimestamp(tx['blocktime']), confirmations=tx['confirmations'], block_height=tx['blockheight'], block_hash=tx['blockhash'], status=status, input_total=int(round(float(value_in) * self.units, 0)), coinbase=isCoinbase, output_total=int( round(float(tx['valueOut']) * self.units, 0))) for ti in tx['vin']: if isCoinbase: t.add_input(prev_hash=32 * b'\0', output_n=4 * b'\xff', unlocking_script=ti['coinbase'], index_n=ti['n'], script_type='coinbase', sequence=ti['sequence']) else: value = int(round(float(ti['value']) * self.units, 0)) t.add_input(prev_hash=ti['txid'], output_n=ti['vout'], unlocking_script=ti['scriptSig']['hex'], index_n=ti['n'], value=value, sequence=ti['sequence'], double_spend=False if ti['doubleSpentTxID'] is None else ti['doubleSpentTxID']) for to in tx['vout']: value = int(round(float(to['value']) * self.units, 0)) t.add_output( value=value, lock_script=to['scriptPubKey']['hex'], spent=True if to['spentTxId'] else False, output_n=to['n'], spending_txid=None if not to['spentTxId'] else to['spentTxId'], spending_index_n=None if not to['spentIndex'] else to['spentIndex']) return t
def get_transactions(self): if not self.created: return succeed([]) # Update all transactions self.wallet.transactions_update(network=self.network) # TODO: 'Access to a protected member _session of a class' txs = self.wallet._session.query(DbTransaction.raw, DbTransaction.confirmations, DbTransaction.date, DbTransaction.fee) \ .filter(DbTransaction.wallet_id == self.wallet.wallet_id) \ .all() transactions = [] for db_result in txs: transaction = Transaction.import_raw(db_result[0], network=self.network) transaction.confirmations = db_result[1] transaction.date = db_result[2] transaction.fee = db_result[3] transactions.append(transaction) # Sort them based on locktime transactions.sort(key=lambda tx: tx.locktime, reverse=True) my_keys = [key.address for key in self.wallet.keys(network=self.network, is_active=False)] transactions_list = [] for transaction in transactions: value = 0 input_addresses = [] output_addresses = [] for tx_input in transaction.inputs: input_addresses.append(tx_input.address) if tx_input.address in my_keys: # At this point, we do not have the value of the input so we should do a database query for it db_res = self.wallet._session.query(DbTransactionInput.value).filter( hexlify(tx_input.prev_hash) == DbTransactionInput.prev_hash, tx_input.output_n_int == DbTransactionInput.output_n).all() if db_res: value -= db_res[0][0] # TODO: db_res[0][0] not an int, but hash string (value/fee expected?) for tx_output in transaction.outputs: output_addresses.append(tx_output.address) if tx_output.address in my_keys: value += tx_output.value transactions_list.append({ 'id': transaction.hash, 'outgoing': value < 0, 'from': ','.join(input_addresses), 'to': ','.join(output_addresses), 'amount': abs(value), 'fee_amount': transaction.fee, 'currency': self.currency, 'timestamp': time.mktime(transaction.date.timetuple()), 'description': f'Confirmations: {transaction.confirmations}' }) return succeed(transactions_list)
def _parse_transaction(self, tx, block_count=None): block_height = None if not tx['block_height'] else tx['block_height'] confirmations = tx['confirmations'] if block_height and not confirmations and tx['status'] == 'confirmed': if not block_count: block_count = self.blockcount() confirmations = block_count - block_height tdate = None try: # FIXME: On blocksmurfer side: always return timestamp tdate = datetime.strptime(tx['date'], "%Y-%m-%dT%H:%M:%S") except (KeyError, TypeError): if 'time' in tx: tdate = datetime.utcfromtimestamp(tx['time']) t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network, fee=tx['fee'], size=tx['size'], txid=tx['txid'], date=tdate, input_total=tx['input_total'], output_total=tx['output_total'], confirmations=confirmations, block_height=block_height, status=tx['status'], coinbase=tx['coinbase'], rawtx=bytes.fromhex(tx['raw_hex']), witness_type=tx['witness_type']) for ti in tx['inputs']: # TODO: BS should return public key t.add_input(prev_txid=ti['prev_txid'], output_n=ti['output_n'], index_n=ti['index_n'], unlocking_script=ti['script'], value=ti['value'], public_hash=bytes.fromhex(ti['public_hash']), address=ti['address'], witness_type=ti['witness_type'], locktime_cltv=ti['locktime_cltv'], locktime_csv=ti['locktime_csv'], signatures=ti['signatures'], compressed=ti['compressed'], encoding=ti['encoding'], unlocking_script_unsigned=ti['script_code'], sigs_required=ti['sigs_required'], sequence=ti['sequence'], witnesses=ti['witnesses']) for to in tx['outputs']: t.add_output(value=to['value'], address=to['address'], public_hash=to['public_hash'], lock_script=to['script'], spent=to['spent']) t.update_totals() return t
def sendrawtransaction(self, rawtx): res = self.compose_request('broadcast', variables={'tx': rawtx}, method='post') txid = '' if 'success' in res and res['success']: t = Transaction.import_raw(rawtx) txid = t.txid return {'txid': txid, 'response_dict': res}
def gettransaction(self, tx_id): res = self.compose_request('dashboards/transaction/', data=tx_id) tx = res['data'][tx_id]['transaction'] confirmations = res['context']['state'] - tx['block_id'] status = 'unconfirmed' if confirmations: status = 'confirmed' witness_type = 'legacy' if tx['has_witness']: witness_type = 'segwit' input_total = tx['input_total'] if tx['is_coinbase']: input_total = tx['output_total'] t = Transaction(locktime=tx['lock_time'], version=tx['version'], network=self.network, fee=tx['fee'], size=tx['size'], hash=tx['hash'], date=datetime.strptime(tx['time'], "%Y-%m-%d %H:%M:%S"), confirmations=confirmations, block_height=tx['block_id'], status=status, input_total=input_total, coinbase=tx['is_coinbase'], output_total=tx['output_total'], witness_type=witness_type) index_n = 0 if not res['data'][tx_id]['inputs']: # This is a coinbase transaction, add input t.add_input(prev_hash=b'\00' * 32, output_n=0, value=input_total) for ti in res['data'][tx_id]['inputs']: if ti['spending_witness']: witnesses = b"".join([varstr(to_bytes(x)) for x in ti['spending_witness'].split(",")]) t.add_input(prev_hash=ti['transaction_hash'], output_n=ti['index'], unlocking_script=witnesses, index_n=index_n, value=ti['value'], address=ti['recipient'], witness_type='segwit') else: t.add_input(prev_hash=ti['transaction_hash'], output_n=ti['index'], unlocking_script_unsigned=ti['script_hex'], index_n=index_n, value=ti['value'], address=ti['recipient'], unlocking_script=ti['spending_signature_hex']) index_n += 1 for to in res['data'][tx_id]['outputs']: try: deserialize_address(to['recipient'], network=self.network.name) addr = to['recipient'] except EncodingError: addr = '' t.add_output(value=to['value'], address=addr, lock_script=to['script_hex'], spent=to['is_spent'], output_n=to['index']) return t
def sendrawtransaction(self, rawtx): res = self.compose_request('broadcast', variables={'tx': rawtx}, method='post') txid = '' if 'success' in res and res['success']: t = Transaction.parse_hex(rawtx, strict=False, network=self.network) txid = t.txid return {'txid': txid, 'response_dict': res}
def transaction_broadcast(network): rawtx = request.args.get('rawtx', type=str) form = TransactionSendForm() if form.validate_on_submit(): srv = SmurferService(network) try: t = Transaction.import_raw(form.rawtx.data, network=srv.network) except Exception as e: flash(_('Invalid raw transaction hex, could not parse: %s' % e), category='error') else: # TODO: Retreiving prev_tx input values should be included in bitcoinlib try: for n, i in enumerate(t.inputs): ti = srv.gettransaction(i.prev_hash) t.inputs[n].value = ti.outputs[i.output_n_int].value t.verify() except TransactionError as e: flash(_('Could not verify transaction: %s' % e), category='warning') known_tx = srv.gettransaction(t.txid) if known_tx: flash(_( 'This transaction %s is already included in the blockchain' % t.txid), category='error') elif not t.verified: flash( _('Invalid transaction, could not verify transaction %s' % t.txid), category='error') else: res = srv.sendrawtransaction(form.rawtx.data) if not res or 'txid' not in res: # TODO: Get decent error message, without private details flash(_('Could not send raw transaction. %s' % srv.errors.get('bcoin', '')), category='error') return render_template( 'explorer/transaction_send.html', title=_('Transaction Send'), subtitle=_( 'Your Transaction was broadcasted successfully!'), txid=res['txid'], network=network) form.rawtx.data = rawtx return render_template( 'explorer/transaction_broadcast.html', title=_('Send Transaction'), rawtx=rawtx, subtitle=_('Broadcast your transaction on the network'), form=form, network=network)
def _parse_transaction(self, tx): status = 'unconfirmed' if tx['confirmations']: status = 'confirmed' witness_type = 'legacy' if 'inputs' in tx and [ti['witness'] for ti in tx['inputs'] if ti['witness'] and ti['witness'] != ['NULL']]: witness_type = 'segwit' input_total = tx['input_amount_int'] t_time = None if tx['time']: t_time = datetime.utcfromtimestamp(tx['time']) if tx['coinbase']: input_total = tx['output_amount_int'] t = Transaction(locktime=tx['locktime'], version=int(tx['version']), network=self.network, fee=tx['fee_int'], size=tx['size'], hash=tx['txid'], date=t_time, confirmations=tx['confirmations'], block_height=tx['block'], status=status, input_total=input_total, coinbase=tx['coinbase'], output_total=tx['output_amount_int'], witness_type=witness_type) index_n = 0 if tx['coinbase']: t.add_input(prev_hash=b'\00' * 32, output_n=0, value=input_total) else: for ti in tx['inputs']: unlocking_script = ti['script_sig']['hex'] witness_type = 'legacy' if ti['witness'] and ti['witness'] != ['NULL']: address = Address.import_address(ti['addresses'][0]) if address.script_type == 'p2sh': witness_type = 'p2sh-segwit' else: witness_type = 'segwit' unlocking_script = b"".join([varstr(to_bytes(x)) for x in ti['witness']]) t.add_input(prev_hash=ti['txid'], output_n=ti['vout'], unlocking_script=unlocking_script, index_n=index_n, value=ti['value_int'], address=ti['addresses'][0], sequence=ti['sequence'], witness_type=witness_type) index_n += 1 for to in tx['outputs']: spent = False spending_txid = None if 'spend_txid' in to and to['spend_txid']: spent = True spending_txid = to['spend_txid'] address = '' if to['addresses']: address = to['addresses'][0] t.add_output(value=to['value_int'], address=address, lock_script=to['script_pub_key']['hex'], spent=spent, output_n=to['n'], spending_txid=spending_txid) return t
def gettransaction(self, txid): tx = self.proxy.getrawtransaction(txid, 1) t = Transaction.import_raw(tx['hex'], network=self.network) t.confirmations = tx['confirmations'] if t.confirmations: t.status = 'confirmed' t.verified = True for i in t.inputs: txi = self.proxy.getrawtransaction(to_hexstring(i.prev_hash), 1) value = int(float(txi['vout'][i.output_n_int]['value']) / self.network.denominator) i.value = value t.block_hash = tx['blockhash'] t.version = tx['version'] t.date = datetime.fromtimestamp(tx['blocktime']) t.update_totals() return t
def _parse_transaction(self, tx): # t = Transaction.import_raw(tx['rawTx'], network=self.network) status = 'unconfirmed' if tx['confirmations']: status = 'confirmed' date = None if 'timestamp' in tx and tx['timestamp']: date = datetime.utcfromtimestamp(tx['timestamp']) elif 'blockTime' in tx and tx['blockTime']: date = datetime.utcfromtimestamp(tx['blockTime']) block_height = None block_hash = None if 'blockHeight' in tx: block_height = tx['blockHeight'] if 'blockHash' in tx: block_hash = tx['blockHash'] witness_type = 'legacy' if tx['segwit']: witness_type = 'segwit' t = Transaction( locktime=tx['lockTime'], version=tx['version'], network=self.network, fee=tx['fee'], fee_per_kb=None if 'feeRate' not in tx else int(tx['feeRate']), size=tx['size'], hash=tx['txId'], date=date, confirmations=tx['confirmations'], block_height=block_height, block_hash=block_hash, input_total=tx['inputsAmount'], output_total=tx['outputsAmount'], status=status, coinbase=tx['coinbase'], verified=None if 'valid' not in tx else tx['valid'], witness_type=witness_type) for n, ti in tx['vIn'].items(): if t.coinbase: t.add_input(prev_hash=ti['txId'], output_n=ti['vOut'], unlocking_script=ti['scriptSig'], sequence=ti['sequence'], index_n=int(n), value=0) else: t.add_input(prev_hash=ti['txId'], output_n=ti['vOut'], unlocking_script=ti['scriptSig'], unlocking_script_unsigned=ti['scriptPubKey'], address='' if 'address' not in ti else ti['address'], sequence=ti['sequence'], index_n=int(n), value=ti['amount']) for _, to in tx['vOut'].items(): spending_txid = None if not to['spent'] else to['spent'][0]['txId'] spending_index_n = None if not to['spent'] else to['spent'][0]['vIn'] t.add_output(to['value'], '' if 'address' not in to else to['address'], '' if 'addressHash' not in to else to['addressHash'], lock_script=to['scriptPubKey'], spent=bool(to['spent']), spending_txid=spending_txid, spending_index_n=spending_index_n) return t
def _parse_transaction(self, tx): witness_type = 'legacy' if len([ti['witness'] for ti in tx['inputs'] if ti['witness'] != '00']): witness_type = 'segwit' coinbase = False if tx['inputs'][0]['prevout']['hash'] == '00' * 32: coinbase = True status = 'unconfirmed' if tx['confirmations']: status = 'confirmed' t = Transaction(locktime=tx['locktime'], version=tx['version'], network=self.network, fee=tx['fee'], size=int(len(tx['hex'])/2), hash=tx['hash'], date=datetime.fromtimestamp(tx['time']), confirmations=tx['confirmations'], block_height=tx['height'], block_hash=tx['block'], rawtx=tx['hex'], status=status, coinbase=coinbase, witness_type=witness_type) for ti in tx['inputs']: witness_type = 'legacy' script = ti['script'] if ti['witness'] != '00': witness_type = 'segwit' script = ti['witness'][2:] address = '' value = 0 if 'coin' in ti: address = ti['coin']['address'] value = ti['coin']['value'] t.add_input(prev_hash=ti['prevout']['hash'], output_n=ti['prevout']['index'], unlocking_script=script, address=address, value=value, witness_type=witness_type, sequence=ti['sequence']) output_n = 0 for to in tx['outputs']: address = '' if to['address']: address = to['address'] t.add_output(value=to['value'], address=address, lock_script=to['script'], output_n=output_n, spent=None) output_n += 1 t.update_totals() if t.coinbase: t.input_total = t.output_total return t
def get_transactions(self): if not self.created: return succeed([]) from bitcoinlib.transactions import Transaction from bitcoinlib.wallets import DbTransaction, DbTransactionInput # Update all transactions self.wallet.transactions_update(network=self.network) txs = self.wallet._session.query(DbTransaction.raw, DbTransaction.confirmations, DbTransaction.date, DbTransaction.fee)\ .filter(DbTransaction.wallet_id == self.wallet.wallet_id)\ .all() transactions = [] for db_result in txs: transaction = Transaction.import_raw(db_result[0], network=self.network) transaction.confirmations = db_result[1] transaction.date = db_result[2] transaction.fee = db_result[3] transactions.append(transaction) # Sort them based on locktime transactions.sort(key=lambda tx: tx.locktime, reverse=True) my_keys = [key.address for key in self.wallet.keys(network=self.network, is_active=False)] transactions_list = [] for transaction in transactions: value = 0 input_addresses = [] output_addresses = [] for tx_input in transaction.inputs: input_addresses.append(tx_input.address) if tx_input.address in my_keys: # At this point, we do not have the value of the input so we should do a database query for it db_res = self.wallet._session.query(DbTransactionInput.value).filter( hexlify(tx_input.prev_hash) == DbTransactionInput.prev_hash, tx_input.output_n_int == DbTransactionInput.output_n).all() if db_res: value -= db_res[0][0] for tx_output in transaction.outputs: output_addresses.append(tx_output.address) if tx_output.address in my_keys: value += tx_output.value transactions_list.append({ 'id': transaction.hash, 'outgoing': value < 0, 'from': ','.join(input_addresses), 'to': ','.join(output_addresses), 'amount': abs(value), 'fee_amount': transaction.fee, 'currency': 'BTC', 'timestamp': time.mktime(transaction.date.timetuple()), 'description': 'Confirmations: %d' % transaction.confirmations }) return succeed(transactions_list)