예제 #1
0
    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
예제 #2
0
 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
예제 #3
0
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)
예제 #4
0
 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']
예제 #5
0
 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
예제 #7
0
 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
예제 #8
0
 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
예제 #9
0
 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
예제 #10
0
 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
예제 #11
0
 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
예제 #12
0
 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
예제 #13
0
 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
예제 #14
0
    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
예제 #15
0
파일: bitaps.py 프로젝트: jimtje/bitcoinlib
 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
예제 #16
0
 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
예제 #17
0
 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
예제 #18
0
 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
예제 #19
0
 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
예제 #20
0
 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
예제 #21
0
    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)
예제 #22
0
 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
예제 #23
0
 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}
예제 #24
0
    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
예제 #25
0
 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}
예제 #26
0
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)
예제 #27
0
    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
예제 #28
0
 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
예제 #29
0
파일: bitaps.py 프로젝트: d42/bitcoinlib
    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
예제 #30
0
 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
예제 #31
0
    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)