Exemplo n.º 1
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
Exemplo n.º 2
0
 def gettransactions(self, address, after_txid='', max_txs=MAX_TRANSACTIONS):
     txs = []
     res1 = self.compose_request('get_tx_received', address, after_txid)
     if res1['status'] != 'success':
         raise ClientError("Chainso get_tx_received request unsuccessful, status: %s" % res1['status'])
     res2 = self.compose_request('get_tx_spent', address, after_txid)
     if res2['status'] != 'success':
         raise ClientError("Chainso get_tx_spent request unsuccessful, status: %s" % res2['status'])
     res = res1['data']['txs'] + res2['data']['txs']
     tx_conf = [(t['txid'], t['confirmations']) for t in res]
     tx_conf_sorted = sorted(tx_conf, key=lambda x: x[1], reverse=True)
     for tx in tx_conf_sorted[:max_txs]:
         t = self.gettransaction(tx[0])
         txs.append(t)
     return txs
Exemplo n.º 3
0
 def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
     if not self.api_key:
         raise ClientError("Method getutxos() is not available for CryptoID without API key")
     utxos = []
     address = self._address_convert(address)
     variables = {'active': address.address}
     res = self.compose_request('unspent', variables=variables)
     if len(res['unspent_outputs']) > 50:
         _logger.info("CryptoID: Large number of outputs for address %s, "
                      "UTXO list may be incomplete" % address.address)
     for utxo in res['unspent_outputs'][::-1]:
         if utxo['txid'] == after_txid:
             break
         utxos.append({
             'address': address.address_orig,
             'txid': utxo['txid'],
             'confirmations': utxo['confirmations'],
             'output_n': utxo['tx_output_n'] if 'tx_output_n' in utxo else utxo['tx_ouput_n'],
             'input_n': 0,
             'block_height': None,
             'fee': None,
             'size': 0,
             'value': int(utxo['value']),
             'script': utxo['script'],
             'date': None
         })
     return utxos[::-1][:limit]
Exemplo n.º 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']
Exemplo n.º 5
0
    def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
        txs = []

        res = self.proxy.getaddressinfo(address)
        if not (res['ismine'] or res['iswatchonly']):
            raise ClientError(
                "Address %s not found in bitcoind wallet, use 'importpubkey' or 'importaddress' to add "
                "address to wallet." % address)

        txs_list = self.proxy.listunspent(0, 99999999, [address])
        for t in sorted(txs_list,
                        key=lambda x: x['confirmations'],
                        reverse=True):
            txs.append({
                'address': t['address'],
                'tx_hash': t['txid'],
                'confirmations': t['confirmations'],
                'output_n': t['vout'],
                'input_n': -1,
                'block_height': None,
                'fee': None,
                'size': 0,
                'value': int(t['amount'] * self.units),
                'script': t['scriptPubKey'],
                'date': None,
            })
            if t['txid'] == after_txid:
                txs = []

        return txs
Exemplo n.º 6
0
    def getblock(self, blockid, parse_transactions, page, limit):
        block = self.compose_request('block', str(blockid))
        # FIXME: This doesnt work if page or limit is used, also see pages calc below
        block['tx_count'] = len(block['txs'])
        txs = block['txs']
        parsed_txs = []
        if parse_transactions:
            txs = txs[(page-1)*limit:page*limit]
        for tx in txs:
            tx['confirmations'] = block['depth']
            tx['time'] = block['time']
            tx['height'] = block['height']
            tx['block'] = block['hash']
            if parse_transactions:
                t = self._parse_transaction(tx)
                if t.txid != tx['hash']:
                    raise ClientError("Could not parse tx %s. Different txid's" % (tx['hash']))
                parsed_txs.append(t)
            else:
                parsed_txs.append(tx['hash'])

        block['time'] = block['time']
        block['txs'] = parsed_txs
        block['page'] = page
        block['pages'] = int(block['tx_count'] // limit) + (block['tx_count'] % limit > 0)
        block['limit'] = limit
        block['prev_block'] = block.pop('prevBlock')
        block['merkle_root'] = block.pop('merkleRoot')
        block['block_hash'] = block.pop('hash')
        return block
Exemplo n.º 7
0
 def gettransactions(self,
                     address,
                     after_txid='',
                     max_txs=MAX_TRANSACTIONS):
     txs = []
     address = self._address_convert(address)
     if address.witness_type != 'legacy':
         raise ClientError("Provider does not support segwit addresses")
     res = self.compose_request('addrs',
                                address.address,
                                variables={
                                    'unspentOnly': 0,
                                    'limit': 2000
                                })
     if not isinstance(res, list):
         res = [res]
     for a in res:
         if 'txrefs' not in a:
             continue
         txids = []
         for t in a['txrefs'][::-1]:
             if t['tx_hash'] not in txids:
                 txids.append(t['tx_hash'])
             if t['tx_hash'] == after_txid:
                 txids = []
         if len(txids) > 500:
             _logger.warning(
                 "BlockCypher: Large number of transactions for address %s, "
                 "Transaction list may be incomplete" %
                 address.address_orig)
         for txid in txids[:max_txs]:
             t = self.gettransaction(txid)
             txs.append(t)
     return txs
Exemplo n.º 8
0
    def getutxos(self, addresslist):
        txs = []

        for addr in addresslist:
            res = self.proxy.validateaddress(addr)
            if not (res['ismine'] or res['iswatchonly']):
                raise ClientError(
                    "Address %s not found in Litecoind wallet, use 'importaddress' to add address to "
                    "wallet." % addr)

        for t in self.proxy.listunspent(0, 99999999, addresslist):
            txs.append({
                'address': t['address'],
                'tx_hash': t['txid'],
                'confirmations': t['confirmations'],
                'output_n': t['vout'],
                'input_n': -1,
                'block_height': None,
                'fee': None,
                'size': 0,
                'value': int(t['amount'] * self.units),
                'script': t['scriptPubKey'],
                'date': None,
            })

        return txs
Exemplo n.º 9
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
Exemplo n.º 10
0
    def getutxos(self, address, after_txid='', max_txs=MAX_TRANSACTIONS):
        txs = []

        res = self.proxy.getaddressinfo(address)
        if not (res['ismine'] or res['iswatchonly']):
            raise ClientError(
                "Address %s not found in litecoind wallet, use 'importaddress' to add address to "
                "wallet." % address)

        for t in self.proxy.listunspent(0, 99999999, [address]):
            txs.append({
                'address': t['address'],
                'tx_hash': t['txid'],
                'confirmations': t['confirmations'],
                'output_n': t['vout'],
                'input_n': -1,
                'block_height': None,
                'fee': None,
                'size': 0,
                'value': int(t['amount'] * self.units),
                'script': t['scriptPubKey'],
                'date': None,
            })

        return txs
Exemplo n.º 11
0
 def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
     utxos = []
     offset = 0
     while True:
         res = self.compose_request('outputs', {'recipient': address, 'is_spent': 'false'}, offset=offset)
         if len(res['data']) == REQUEST_LIMIT:
             raise ClientError("Blockchair returned more then maximum of %d data rows" % REQUEST_LIMIT)
         current_block = res['context']['state']
         for utxo in res['data'][::-1]:
             if utxo['is_spent']:
                 continue
             if utxo['transaction_hash'] == after_txid:
                 utxos = []
                 continue
             utxos.append({
                 'address': address,
                 'txid': utxo['transaction_hash'],
                 'confirmations': current_block - utxo['block_id'],
                 'output_n': utxo['index'],
                 'input_n': 0,
                 'block_height': utxo['block_id'],
                 'fee': None,
                 'size': 0,
                 'value': utxo['value'],
                 'script': utxo['script_hex'],
                 'date': datetime.strptime(utxo['time'], "%Y-%m-%d %H:%M:%S")
             })
         if not len(res['data']) or len(res['data']) < REQUEST_LIMIT:
             break
         offset += REQUEST_LIMIT
     return utxos[:limit]
Exemplo n.º 12
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):
            if not tx['inputs'][n]['address']:
                raise ClientError(
                    "Address missing in input. Provider might not support segwit transactions"
                )
            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
Exemplo n.º 13
0
 def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
     utxos = []
     page = 1
     while True:
         variables = {
             'mode': 'verbose',
             'limit': 50,
             'page': page,
             'order': 'asc'
         }
         try:
             res = self.compose_request('address', 'transactions', address,
                                        variables)
             res2 = self.compose_request('address',
                                         'unconfirmed/transactions',
                                         address, variables)
         except ClientError as e:
             if "address not found" in self.resp.text:
                 return []
             else:
                 raise ClientError(e.msg)
         txs = res['data']['list']
         txs += res2['data']['list']
         for tx in txs:
             for outp in tx['vOut']:
                 utxo = tx['vOut'][outp]
                 if 'address' not in utxo or utxo[
                         'address'] != address or utxo['spent']:
                     continue
                 utxos.append({
                     'address':
                     utxo['address'],
                     'txid':
                     tx['txId'],
                     'confirmations':
                     0
                     if 'confirmations' not in tx else tx['confirmations'],
                     'output_n':
                     int(outp),
                     'input_n':
                     0,
                     'block_height':
                     None if 'blockHeight' not in tx else tx['blockHeight'],
                     'fee':
                     None,
                     'size':
                     0,
                     'value':
                     utxo['value'],
                     'script':
                     utxo['scriptPubKey'],
                     'date':
                     datetime.utcfromtimestamp(tx['timestamp'])
                 })
             if tx['txId'] == after_txid:
                 utxos = []
         page += 1
         if page > res['data']['pages']:
             break
     return utxos[:limit]
Exemplo n.º 14
0
    def getutxos(self, address, after_txid='', limit=MAX_TRANSACTIONS):
        # First get all transactions for this address from the blockchain
        from bitcoinlib.services.services import Service
        srv = Service(network=self.network.name, providers=['bcoin'])
        txs = srv.gettransactions(address, limit=25)

        # Fail if large number of transactions are found
        if not srv.complete:
            raise ClientError("If not all transactions known, we cannot determine utxo's. "
                              "Increase limit or use other provider")

        utxos = []
        for tx in txs:
            for unspent in tx.outputs:
                if unspent.address != address:
                    continue
                if not srv.isspent(tx.txid, unspent.output_n):
                    utxos.append(
                        {
                            'address': unspent.address,
                            'txid': tx.txid,
                            'confirmations': tx.confirmations,
                            'output_n': unspent.output_n,
                            'input_n': 0,
                            'block_height': tx.block_height,
                            'fee': tx.fee,
                            'size': tx.size,
                            'value': unspent.value,
                            'script': unspent.lock_script.hex(),
                            'date': tx.date,
                         }
                    )
                    if tx.txid == after_txid:
                        utxos = []
        return utxos[:limit]
Exemplo n.º 15
0
 def gettransaction(self, tx_id):
     tx = self.compose_request('tx', tx_id)
     t = Transaction.import_raw(tx['hex'], network=self.network)
     if tx['confirmations']:
         t.status = 'confirmed'
     t.hash = tx_id
     t.date = datetime.strptime(tx['date'], "%Y-%m-%dT%H:%M:%S.%fZ")
     t.confirmations = tx['confirmations']
     if 'height' in tx:
         t.block_height = tx['height']
         t.block_hash = tx['blockhash']
     t.fee = tx['fee']
     t.rawtx = tx['hex']
     t.size = len(tx['hex']) // 2
     t.network = self.network
     if t.coinbase:
         input_values = []
         t.input_total = t.output_total
     else:
         input_values = [(inp['account'], -inp['value'])
                         for inp in tx['entries'] if inp['value'] < 0]
         if len(input_values) >= 49:
             raise ClientError(
                 "More then 49 transaction inputs not supported by bitgo")
         t.input_total = sum([x[1] for x in input_values])
     for i in t.inputs:
         if not i.address:
             raise ClientError(
                 "Address missing in input. Provider might not support segwit transactions"
             )
         if len(t.inputs) != len(input_values):
             i.value = None
             continue
         value = [x[1] for x in input_values if x[0] == i.address]
         if len(value) != 1:
             _logger.warning(
                 "BitGoClient: Address %s input value should be found exactly 1 times in value list"
                 % i.address)
             i.value = None
         else:
             i.value = value[0]
     for o in t.outputs:
         o.spent = None
     if t.input_total != t.output_total + t.fee:
         t.input_total = t.output_total + t.fee
     return t
Exemplo n.º 16
0
    def getblock(self, blockid, parse_transactions, page, limit):
        variables = {
            'parse_transactions': parse_transactions,
            'page': page,
            'limit': limit
        }
        bd = self.compose_request('block', str(blockid), variables=variables)

        txs = []
        if parse_transactions and bd['transactions'] and isinstance(
                bd['transactions'][0], dict):
            block_count = self.blockcount()
            for tx in bd['transactions']:
                tx['confirmations'] = bd['depth']
                tx['time'] = bd['time']
                tx['block_height'] = bd['height']
                tx['block_hash'] = bd['block_hash']
                t = self._parse_transaction(tx, block_count)
                if t.txid != tx['txid']:
                    raise ClientError(
                        "Could not parse tx %s. Different txid's" %
                        (tx['txid']))
                txs.append(t)
        else:
            txs = bd['transactions']

        block = {
            'bits':
            bd['bits'],
            'depth':
            bd['depth'],
            'block_hash':
            bd['block_hash'],
            'height':
            bd['height'],
            'merkle_root':
            bd['merkle_root'],
            'nonce':
            bd['nonce'],
            'prev_block':
            bd['prev_block'],
            'time':
            bd['time'],
            'tx_count':
            bd['tx_count'],
            'txs':
            txs,
            'version':
            bd['version'],
            'page':
            page,
            'pages':
            None if not limit else int(bd['tx_count'] // limit) +
            (bd['tx_count'] % limit > 0),
            'limit':
            limit
        }
        return block
Exemplo n.º 17
0
 def gettransactions(self, address, after_txid='', limit=MAX_TRANSACTIONS):
     txs = []
     res1 = self.compose_request('get_tx_received', address, after_txid)
     if res1['status'] != 'success':
         raise ClientError("Chainso get_tx_received request unsuccessful, status: %s" % res1['status'])
     res2 = self.compose_request('get_tx_spent', address, after_txid)
     if res2['status'] != 'success':
         raise ClientError("Chainso get_tx_spent request unsuccessful, status: %s" % res2['status'])
     res = res1['data']['txs'] + res2['data']['txs']
     res = sorted(res, key=lambda x: x['time'])
     tx_conf = []
     for t in res:
         tt = (t['confirmations'], t['txid'])
         if tt not in tx_conf:
             tx_conf.append(tt)
     for tx in tx_conf[:limit]:
         t = self.gettransaction(tx[1])
         txs.append(t)
     return txs
Exemplo n.º 18
0
 def getutxos(self, address, after_txid='', max_txs=MAX_TRANSACTIONS):
     address = self._address_convert(address)
     if address.witness_type != 'legacy':
         raise ClientError("Provider does not support segwit addresses")
     res = self.compose_request('addrs',
                                address.address,
                                variables={
                                    'unspentOnly': 1,
                                    'limit': 2000
                                })
     transactions = []
     if not isinstance(res, list):
         res = [res]
     for a in res:
         if 'txrefs' not in a:
             continue
         if len(a['txrefs']) > 500:
             _logger.warning(
                 "BlockCypher: Large number of transactions for address %s, "
                 "Transaction list may be incomplete" % address)
         for tx in a['txrefs']:
             if tx['tx_hash'] == after_txid:
                 break
             try:
                 tdate = datetime.strptime(tx['confirmed'],
                                           "%Y-%m-%dT%H:%M:%SZ")
             except ValueError:
                 tdate = datetime.strptime(tx['confirmed'],
                                           "%Y-%m-%dT%H:%M:%S.%fZ")
             transactions.append({
                 'address':
                 address.address_orig,
                 'tx_hash':
                 tx['tx_hash'],
                 'confirmations':
                 tx['confirmations'],
                 'output_n':
                 tx['tx_output_n'],
                 'index':
                 0,
                 'value':
                 int(round(tx['value'] * self.units, 0)),
                 'script':
                 '',
                 'block_height':
                 None,
                 'date':
                 tdate
             })
     return transactions[::-1][:max_txs]
Exemplo n.º 19
0
 def compose_request(self, func=None, path_type='api', variables=None, method='get'):
     # API path: http://chainz.cryptoid.info/ltc/api.dws
     # Explorer path for raw tx: https://chainz.cryptoid.info/explorer/tx.raw.dws
     if variables is None:
         variables = {}
     if path_type == 'api':
         url_path = '%s/api.dws' % self.provider_coin_id
         variables.update({'q': func})
     else:
         url_path = 'explorer/tx.raw.dws'
         variables.update({'coin': self.provider_coin_id})
     if not self.api_key:
         raise ClientError("Request a CryptoID API key before using this provider")
     variables.update({'key': self.api_key})
     return self.request(url_path, variables, method)
Exemplo n.º 20
0
 def compose_request(self,
                     func,
                     variables,
                     service_id='fallback',
                     include_raw=False,
                     method='get'):
     url_path = func + '/' + service_id
     if not isinstance(variables, dict):
         raise ClientError(
             "Cannot compose request without variables. Variables must be of type dictionary."
         )
     if method == 'get':
         variables.update({'currency': self.provider_coin_id})
     else:
         url_path += '?currency=%s' % self.provider_coin_id
     if include_raw:
         variables.update({'include_raw': None})
     return self.request(url_path, variables, method=method)
Exemplo n.º 21
0
    def gettransactions(self,
                        address,
                        after_txid='',
                        max_txs=MAX_TRANSACTIONS):
        txs = []
        while True:
            variables = {'limit': LIMIT_TX, 'after': after_txid}
            retries = 0
            while retries < 3:
                try:
                    res = self.compose_request('tx', 'address', address,
                                               variables)
                except ReadTimeout as e:
                    sleep(3)
                    _logger.info("Bcoin client error: %s" % e)
                    retries += 1
                else:
                    break
                finally:
                    if retries == 3:
                        raise ClientError(
                            "Max retries exceeded with bcoin Client")
            for tx in res:
                txs.append(self._parse_transaction(tx))
            if len(txs) >= max_txs:
                break
            if len(res) == LIMIT_TX:
                after_txid = res[LIMIT_TX - 1]['hash']
            else:
                break

        # Check which outputs are spent/unspent for this address
        if not after_txid:
            address_inputs = [(to_hexstring(inp.prev_hash), inp.output_n_int)
                              for ti in [t.inputs for t in txs] for inp in ti
                              if inp.address == address]
            for tx in txs:
                for to in tx.outputs:
                    if to.address != address:
                        continue
                    spent = True if (tx.hash,
                                     to.output_n) in address_inputs else False
                    txs[txs.index(tx)].outputs[to.output_n].spent = spent
        return txs
Exemplo n.º 22
0
    def getbalance(self, addresslist):
        balance = 0.0
        from bitcoinlib.services.services import Service
        for address in addresslist:
            # First get all transactions for this address from the blockchain
            srv = Service(network=self.network.name, providers=['bcoin'])
            txs = srv.gettransactions(address, limit=25)

            # Fail if large number of transactions are found
            if not srv.complete:
                raise ClientError("If not all transactions known, we cannot determine utxo's. "
                                  "Increase limit or use other provider")

            for a in [output for outputs in [t.outputs for t in txs] for output in outputs]:
                if a.address == address:
                    balance += a.value
            for a in [i for inputs in [t.inputs for t in txs] for i in inputs]:
                if a.address == address:
                    balance -= a.value
        return int(balance)
Exemplo n.º 23
0
 def getutxos(self, addresslist):
     if not self.api_key:
         raise ClientError(
             "Method getutxos() is not available for CryptoID without API key"
         )
     utxos = []
     addresslist = self._addresslist_convert(addresslist)
     for a in addresslist:
         variables = {'active': a.address}
         res = self.compose_request('unspent', variables=variables)
         if len(res['unspent_outputs']) > 29:
             _logger.warning(
                 "CryptoID: Large number of outputs for address %s, "
                 "UTXO list may be incomplete" % a.address)
         for utxo in res['unspent_outputs']:
             utxos.append({
                 'address':
                 a.address_orig,
                 'tx_hash':
                 utxo['tx_hash'],
                 'confirmations':
                 utxo['confirmations'],
                 'output_n':
                 utxo['tx_output_n']
                 if 'tx_output_n' in utxo else utxo['tx_ouput_n'],
                 'input_n':
                 0,
                 'block_height':
                 None,
                 'fee':
                 None,
                 'size':
                 0,
                 'value':
                 int(utxo['value']),
                 'script':
                 utxo['script'],
                 'date':
                 None
             })
     return utxos
Exemplo n.º 24
0
 def _parse_transaction(self, tx):
     t = Transaction.import_raw(tx['raw_hex'], network=self.network)
     if t.hash != tx['txid']:
         raise ClientError(
             "Different hash from Blocksmurfer when parsing transaction")
     t.block_height = None if not tx['block_height'] else tx['block_height']
     t.confirmations = tx['confirmations']
     t.date = None if not tx['date'] else datetime.strptime(
         tx['date'][:19], "%Y-%m-%dT%H:%M:%S")
     if t.block_height and not t.confirmations and tx[
             'status'] == 'confirmed':
         block_count = self.blockcount()
         t.confirmations = block_count - t.block_height
     t.status = tx['status']
     t.fee = tx['fee']
     for ti in t.inputs:
         t.inputs[ti.index_n].value = tx['inputs'][ti.index_n]['value']
     for to in t.outputs:
         t.outputs[to.output_n].spent = tx['outputs'][to.output_n]['spent']
     t.update_totals()
     return t
Exemplo n.º 25
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.fromtimestamp(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']:
         # sequence = struct.pack('<L', ti['sequence'])
         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))
             if not ti['scriptSig']['hex']:
                 raise ClientError("Missing unlocking script in BlockExplorer Input. Possible reason: Segwit is not "
                                   "supported")
             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))
         address = ''
         try:
             address = to['scriptPubKey']['addresses'][0]
         except (ValueError, KeyError):
             pass
         t.add_output(value=value, address=address, lock_script=to['scriptPubKey']['hex'],
                      spent=True if to['spentTxId'] else False, output_n=to['n'])
     return t
Exemplo n.º 26
0
 def gettransactions(self,
                     address,
                     after_txid='',
                     max_txs=MAX_TRANSACTIONS):
     txs = []
     txids = []
     skip = 0
     total = 1
     while total > skip:
         variables = {'limit': LIMIT_TX, 'skip': skip}
         res = self.compose_request('address', address, 'tx', variables)
         for tx in res['transactions']:
             if tx['id'] not in txids:
                 txids.insert(0, tx['id'])
         total = res['total']
         if total > 2000:
             raise ClientError(
                 "BitGoClient: Transactions list limit exceeded > 2000")
         skip = res['start'] + res['count']
     if after_txid:
         txids = txids[txids.index(after_txid) + 1:]
     for txid in txids[:max_txs]:
         txs.append(self.gettransaction(txid))
     return txs