예제 #1
0
class BitcoinCandyQuery(object):
    def __init__(self, vdb, settings):
        self.vdb = vdb
        self.coin = self.vdb.get_coin_info('bitcoin-candy')

        self.addrs = [{'addr':        a,
                       'p2sh_p2wpkh': a[:1] == "3",
                       'bech32':      a[:3] == "bc1"}
                      for a in settings.addresses]

        self.tails = not settings.not_tails
        self.cache = settings.cache_requests

        self.wd = WebData(tails=self.tails, cache=self.cache)
        self.explorer = self.coin['explorer'].strip('/')

        self._add_nuggets()

    def _add_nuggets(self):
        for a in self.addrs:
            converted_addr = str(ConvertedAddress(a['addr'], "bitcoin-candy"))
            aapi = "%s/insight-api/addr/%s" % (self.explorer, converted_addr)
            addr_info = self.wd.fetch_web_url_json_info(aapi)
            for t in addr_info['transactions']:
                tapi = "%s/insight-api/tx/%s" % (self.explorer, t)
                tx_info = self.wd.fetch_web_url_json_info(tapi)
                for o in tx_info['vout']:
                    if o['scriptPubKey']['addresses'][0] != converted_addr:
                        continue
                    n = o['n']
                    satoshis = int(float(o['value']) * 100000)
                    self.vdb['nuggets'].append_direct_query(a, self.coin,
                                                            t, o['n'],
                                                            satoshis)
예제 #2
0
 def __init__(self, settings, addr):
     super().__init__(settings, addr)
     self.wd = WebData(tails=self.tails, cache=self.cache)
     self.addr_info = self.wd.fetch_addr_info(self.addr)
     ins = list(self._get_addr_ins())
     outs = list(self._get_addr_outs())
     self._validate_outs(ins, outs)
     tx_block_map = self._get_tx_block_map(ins, outs)
     for i in ins:
         i['block'] = tx_block_map[i['hash']]
     for o in outs:
         o['block'] = tx_block_map[o['hash']]
     self['spans'] = self._calc_spans(ins, outs)
     print(self['spans'])
예제 #3
0
    def __init__(self, vdb, settings):
        self.vdb = vdb
        self.coin = self.vdb.get_coin_info('bitcore')

        self.addrs = [{
            'addr': a,
            'p2sh_p2wpkh': a[:1] == "3",
            'bech32': a[:3] == "bc1"
        } for a in settings.addresses]

        self.tails = not settings.not_tails
        self.cache = settings.cache_requests

        self.wd = WebData(tails=self.tails, cache=self.cache)
        self._add_nuggets()
예제 #4
0
    def __init__(self, settings):
        super().__init__()
        addrs = settings.addresses
        addrs.sort()
        self.forkdrop_info = ForkdropInfo()
        self.tails = not settings.not_tails
        self.cache = settings.cache_requests
        self.bfc_force = settings.bfc_force
        self.claim_save_file = settings.claim_save_file
        self.wd = WebData(tails=self.tails, cache=self.cache)

        self['addrs'] = [AddressInfo(self.wd, addr) for addr in addrs]
        self['basic_coins'] = [c for c in self.forkdrop_info['bitcoin'] if
                               self._classify(c) == "basic"]
        self['basic_coins'].sort(key=lambda x: self._coin_sort(x))
        self['tbd_coins'] = [c for c in self.forkdrop_info['bitcoin'] if
                             self._classify(c) == "tbd"]
        self['tbd_coins'].sort(key=lambda x: self._coin_sort(x))
        self['special_coins'] = [c for c in self.forkdrop_info['bitcoin'] if
                                 self._classify(c) == "special"]
        self['special_coins'].sort(key=lambda x: self._coin_sort(x))
        self['registered_coins'] = [c for c in self.forkdrop_info['bitcoin'] if
                                    self._classify(c) == "registered"]
        self['registered_coins'].sort(key=lambda x: self._coin_sort(x))
        self['exchanges'] = self.forkdrop_info['exchanges']
        self['nuggets'] = NuggetList(self, tails=self.tails,
                                     bfc_force=self.bfc_force)
예제 #5
0
class BitcoreQuery(object):
    def __init__(self, vdb, settings):
        self.vdb = vdb
        self.coin = self.vdb.get_coin_info('bitcore')

        self.addrs = [{
            'addr': a,
            'p2sh_p2wpkh': a[:1] == "3",
            'bech32': a[:3] == "bc1"
        } for a in settings.addresses]

        self.tails = not settings.not_tails
        self.cache = settings.cache_requests

        self.wd = WebData(tails=self.tails, cache=self.cache)
        self._add_nuggets()

    def _add_nuggets(self):
        for a in self.addrs:
            addr = a['addr']
            url = UNSPENT_URL % addr
            unspent_info = self.wd.fetch_web_url_json_info(url)
            for u in unspent_info['unspent_outputs']:
                self.vdb['nuggets'].append_direct_query(
                    a, self.coin, u['tx_hash'], u['tx_ouput_n'],
                    int(u['value']))
예제 #6
0
class BlockchainAddressInfo(AddressInfo):
    """ Info queried for a single address from blockchain.com block explorerer.         Spans of blocks that that address held coins are calculeted
    """
    def __init__(self, settings, addr):
        super().__init__(settings, addr)
        self.wd = WebData(tails=self.tails, cache=self.cache)
        self.addr_info = self.wd.fetch_addr_info(self.addr)
        ins = list(self._get_addr_ins())
        outs = list(self._get_addr_outs())
        self._validate_outs(ins, outs)
        tx_block_map = self._get_tx_block_map(ins, outs)
        for i in ins:
            i['block'] = tx_block_map[i['hash']]
        for o in outs:
            o['block'] = tx_block_map[o['hash']]
        self['spans'] = self._calc_spans(ins, outs)
        print(self['spans'])

    def _calc_spans(self, ins, outs):
        spans = {}
        out_lookup = {o['span_id']: o for o in outs}
        for i in ins:
            span_id = i['span_id']
            o = out_lookup[span_id] if span_id in out_lookup.keys() else None
            spans[span_id] = {'funded': i, 'defunded': o}
        return spans

    def _span_id(self, tx_index, n, value):
        return "%s %s %s" % (tx_index, n, value)

    def _validate_outs(self, ins, outs):
        # make sure data is consistent by having every out correspond to
        # a previous in.
        i_set = set(t['span_id'] for t in ins)
        o_set = set(t['span_id'] for t in outs)
        #print(i_set)
        #print(o_set)
        for o in o_set:
            assert o in i_set

    def _iter_tx_blocks(self, txes):
        hashes = [t['hash'] for t in txes]
        for h in list(set(hashes)):
            d = self.wd.fetch_tx_info(h)
            yield h, d['block_height']

    def _get_tx_block_map(self, ins, outs):
        return {h: height for h, height in self._iter_tx_blocks(ins + outs)}

    def _get_addr_ins(self):
        for tx in self.addr_info['txs']:
            outs = [o for o in tx['out'] if o['addr'] == self.addr]
            for o in outs:
                yield {
                    'n': o['n'],
                    'hash': tx['hash'],
                    'value': o['value'],
                    'tx_index': o['tx_index'],
                    'span_id': self._span_id(o['tx_index'], o['n'], o['value'])
                }

    def _get_addr_outs(self):
        for tx in self.addr_info['txs']:
            ins = [
                i for i in tx['inputs'] if i['prev_out']['addr'] == self.addr
            ]
            for i in ins:
                n = i['prev_out']['n']
                value = i['prev_out']['value']
                tx_index = i['prev_out']["tx_index"]

                yield {
                    'tx_index': tx_index,
                    'n': n,
                    'value': value,
                    'hash': tx['hash'],
                    'span_id': self._span_id(tx_index, n, value)
                }
예제 #7
0
class BitcoinCbcQuery(object):
    def __init__(self, vdb, settings):
        self.vdb = vdb
        self.coin = self.vdb.get_coin_info('bitcoin-cbc')

        self.addrs = [{
            'addr': a,
            'p2sh_p2wpkh': a[:1] == "3",
            'bech32': a[:3] == "bc1"
        } for a in settings.addresses]

        self.tails = not settings.not_tails
        self.cache = settings.cache_requests
        self.bfc_force = settings.bfc_force

        self.wd = WebData(tails=self.tails, cache=self.cache)
        self._add_nuggets()

    def _slice_table(self, content):
        # kinda hacky - slices out the last html table in the content
        start = content.rfind("<table")
        end = content.rfind("</table>")
        return content[start:end] + "</table>"

    def _strip(self, td):
        # kinda hacky - gets at the internal text of a html <a> element if
        # there is one instead of just text
        if len(td.getchildren()) > 0:
            return td.getchildren()[0].text
        return td.text

    def _iter_txes(self, addr_html):
        table = self._slice_table(addr_html)
        t = ET.XML(table)
        rows = iter(t)
        headers = [col.text for col in next(rows)]
        for row in rows:
            values = [col for col in row]
            yield values[0].getchildren()[0].attrib['href']

    def _iter_tx_outputs(self, tx_html):
        table = self._slice_table(tx_html)
        t = ET.XML(table)
        rows = iter(t)
        headers = [col.text for col in next(rows)]
        for row in rows:
            values = [col for col in row]
            index = int(values[0].getchildren()[0].text)
            amount = int(float(values[2].text) * SATOSHIS_PER_BTC)
            addr = values[3].getchildren()[0].text
            yield index, amount, addr

    def _add_nuggets(self):
        for a in self.addrs:
            addr = a['addr']
            addr_url = ADDR_URL % addr
            addr_html = self.wd.fetch_web_url_text_info(addr_url)
            for tx_path in self._iter_txes(addr_html):
                txid = tx_path.split('/')[-1].split("#")[0]
                tx_url = ADDR_URL % tx_path
                tx_html = self.wd.fetch_web_url_text_info(tx_url)
                for index, satoshis, to_addr in self._iter_tx_outputs(tx_html):
                    if to_addr != addr:
                        continue
                    self.vdb['nuggets'].append_direct_query(
                        a, self.coin, txid, index, satoshis)