def list_entity_tags(currency, entity_id): # from entity id to list of tags session = get_session(currency, 'transformed') entity_group = get_id_group(entity_id) query = "SELECT * FROM cluster_tags WHERE cluster_group = %s and cluster" \ " = %s" concurrent_query = "SELECT * FROM address_by_id_group WHERE " \ "address_id_group = %s and address_id = %s" results = session.execute(query, [entity_group, entity_id]) # concurrent queries statements_and_params = [] for row in results.current_rows: address_id_group = get_id_group(row.address_id) params = (address_id_group, row.address_id) statements_and_params.append((concurrent_query, params)) addresses = execute_concurrent(session, statements_and_params, raise_on_first_error=False) id_address = dict() # to temporary store the id-address mapping for (success, address) in addresses: if not success: pass else: id_address[address.one().address_id] = address.one().address entity_tags = [] for row in results.current_rows: entity_tags.append(Tag.from_entity_row(row, id_address[row.address_id], currency).to_dict()) return entity_tags
def list_address_incoming_relations(currency, address, paging_state=None, page_size=None): session = get_session(currency, 'transformed') address_id, address_id_group = get_address_id_id_group(currency, address) if address_id: query = "SELECT * FROM address_incoming_relations WHERE " \ "dst_address_id_group = %s AND dst_address_id = %s" fetch_size = ADDRESS_PAGE_SIZE if page_size: fetch_size = page_size statement = SimpleStatement(query, fetch_size=fetch_size) results = session.execute(statement, [address_id_group, address_id], paging_state=paging_state) paging_state = results.paging_state rates = get_rates(currency)['rates'] relations = [] for row in results.current_rows: src_address_id_group = get_id_group(row.src_address_id) src_address = get_address_by_id_group(currency, src_address_id_group, row.src_address_id) relations.append( AddressIncomingRelations.from_row(row, src_address, rates).to_dict()) return paging_state, relations return None, None
def get_statistics(currency): session = get_session(currency, 'transformed') query = "SELECT * FROM summary_statistics LIMIT 1" result = session.execute(query) if result: return Statistics.from_row(result[0], currency).to_dict() return None
def get_address_id(currency, address): session = get_session(currency, 'transformed') query = "SELECT address_id FROM address WHERE address_prefix = %s " \ "AND address = %s" result = session.execute(query, [address[:ADDRESS_PREFIX_LENGTH], address]) if result: return result[0].address_id return None
def get_block(currency, height): session = get_session(currency, 'raw') query = "SELECT * FROM block WHERE height = %s" result = session.execute(query, [height]) if result: return Block.from_row(result[0]).to_dict() return None
def get_address(currency, address): session = get_session(currency, 'transformed') query = "SELECT * FROM address WHERE address_prefix = %s AND address = %s" result = session.execute(query, [address[:ADDRESS_PREFIX_LENGTH], address]) if result: return Address.from_row(result[0], get_rates(currency)['rates']).to_dict() return None
def list_matching_addresses(currency, expression): # TODO: rather slow with bech32 address (loop through pages instead) session = get_session(currency, 'transformed') query = "SELECT address FROM address WHERE address_prefix = %s" statement = SimpleStatement(query, fetch_size=ADDRESS_PAGE_SIZE) result = session.execute(statement, [expression[:ADDRESS_PREFIX_LENGTH]]) return [ row.address for row in result if row.address.startswith(expression) ]
def list_address_tags(currency, address): session = get_session(currency, 'transformed') query = "SELECT * FROM address_tags WHERE address = %s" results = session.execute(query, [address]) address_tags = [Tag.from_address_row(row, currency, True).to_dict() for row in results.current_rows] return address_tags
def get_entity(currency, entity_id): # from entity id to complete entity stats session = get_session(currency, 'transformed') entity_id_group = get_id_group(entity_id) query = "SELECT * FROM cluster WHERE cluster_group = %s AND cluster = %s " result = session.execute(query, [entity_id_group, entity_id]) rates = get_rates(currency)['rates'] if result: return Entity.from_row(result[0], rates).to_dict() return None
def list_matching_txs(currency, expression, leading_zeros): session = get_session(currency, 'raw') query = 'SELECT tx_hash from transaction where tx_prefix = %s' results = session.execute(query, [expression[:TX_PREFIX_LENGTH]]) txs = [ "0" * leading_zeros + str(hex(int.from_bytes(row.tx_hash, byteorder="big")))[2:] for row in results ] return [tx for tx in txs if tx.startswith(expression)]
def get_address_entity_id(currency, address): # from address to entity id only session = get_session(currency, 'transformed') address_id, address_id_group = get_address_id_id_group(currency, address) if isinstance(address_id, int): query = "SELECT cluster FROM address_cluster WHERE " \ "address_id_group = %s AND address_id = %s " result = session.execute(query, [address_id_group, address_id]) if result: return result[0].cluster return None
def list_entity_relations(currency, entity_id, is_outgoing, targets=None, paging_state=None, page_size=None, from_search=False): if is_outgoing: table, this, that = ('outgoing', 'src', 'dst') cls = EntityOutgoingRelations else: table, this, that = ('incoming', 'dst', 'src') cls = EntityIncomingRelations session = get_session(currency, 'transformed') entity_id_group = get_id_group(entity_id) has_targets = isinstance(targets, list) parameters = [entity_id_group, entity_id] basequery = "SELECT * FROM cluster_{}_relations WHERE " \ "{}_cluster_group = %s AND " \ "{}_cluster = %s".format(table, this, this) if has_targets: if len(targets) == 0: return None query = basequery.replace('*', '{}_cluster'.format(that)) query += " AND {}_cluster in ({})".format(that, ','.join(targets)) else: query = basequery fetch_size = ENTITY_PAGE_SIZE if page_size: fetch_size = page_size statement = SimpleStatement(query, fetch_size=fetch_size) results = session.execute(statement, parameters, paging_state=paging_state) paging_state = results.paging_state current_rows = results.current_rows if has_targets: statements_and_params = [] query = basequery + " AND {}_cluster = %s".format(that) for row in results.current_rows: params = parameters.copy() params.append(getattr(row, "{}_cluster".format(that))) statements_and_params.append((query, params)) results = execute_concurrent(session, statements_and_params, raise_on_first_error=False) current_rows = [] for (success, row) in results: if not success: pass else: current_rows.append(row.one()) rates = get_rates(currency)['rates'] relations = [] for row in current_rows: relations.append(cls.from_row(row, rates, from_search).to_dict()) return paging_state, relations
def list_blocks(currency, paging_state=None): session = get_session(currency, 'raw') query = "SELECT * FROM block" statement = SimpleStatement(query, fetch_size=BLOCKS_PAGE_SIZE) results = session.execute(statement, paging_state=paging_state) paging_state = results.paging_state block_list = [Block.from_row(row).to_dict() for row in results.current_rows] return paging_state, block_list
def get_tx(currency, tx_hash): session = get_session(currency, 'raw') query = "SELECT * FROM transaction WHERE tx_prefix = %s AND tx_hash = %s" result = session.execute( query, [tx_hash[:TX_PREFIX_LENGTH], bytearray.fromhex(tx_hash)]) if result: return Tx.from_row(result[0], get_rates(currency, result[0].height)['rates']).to_dict() return None
def list_tags(label, currency=None): label_norm = alphanumeric_lower(label) label_norm_prefix = label_norm[:LABEL_PREFIX_LENGTH] session = get_session(currency=currency, keyspace_type='transformed') query = "SELECT * FROM tag_by_label WHERE label_norm_prefix = %s and " \ "label_norm = %s" rows = session.execute(query, [label_norm_prefix, label_norm]) if rows: return [ Tag.from_address_row(row, row.currency).to_dict() for row in rows ] return None
def list_block_txs(currency, height): session = get_session(currency, 'raw') query = "SELECT * FROM block_transactions WHERE height = %s" results = session.execute(query, [height]) if results: rates = get_rates(currency, height) block_txs = BlockTxs.from_row(results[0], rates['rates']).to_dict() return block_txs return None
def get_rates(currency, height=-1): """ Returns the exchange rate for a given block height """ if height == -1: height = get_statistics(currency)['no_blocks'] - 1 session = get_session(currency, 'transformed') session.row_factory = dict_factory query = "SELECT * FROM exchange_rates WHERE height = %s" result = session.execute(query, [height]) if result.current_rows: r = result.current_rows[0] return ExchangeRate(r['height'], {k: v for k, v in r.items() if k != 'height'}).to_dict() raise ValueError("Cannot find height {} in currency {}" .format(height, currency))
def list_txs(currency, paging_state=None): session = get_session(currency, 'raw') query = "SELECT * FROM transaction" statement = SimpleStatement(query, fetch_size=TXS_PAGE_SIZE) results = session.execute(statement, paging_state=paging_state) paging_state = results.paging_state heights = [row.height for row in results.current_rows] rates = list_rates(currency, heights) tx_list = [ Tx.from_row(row, rates[row.height]).to_dict() for row in results.current_rows ] return paging_state, tx_list
def list_addresses_links(currency, address, neighbor): session = get_session(currency, 'transformed') address_id, address_id_group = get_address_id_id_group(currency, address) neighbor_id, neighbor_id_group = get_address_id_id_group( currency, neighbor) if address_id and neighbor_id: query = "SELECT tx_list FROM address_outgoing_relations WHERE " \ "src_address_id_group = %s AND src_address_id = %s AND " \ "dst_address_id = %s" results = session.execute(query, [address_id_group, address_id, neighbor_id]) if results.current_rows: txs = [tx_hash for tx_hash in results.current_rows[0].tx_list] query = "SELECT * FROM address_transactions WHERE " \ "address_id_group = %s AND address_id = %s AND " \ "tx_hash IN %s" results1 = session.execute( query, [address_id_group, address_id, ValueSequence(txs)]) results2 = session.execute( query, [neighbor_id_group, neighbor_id, ValueSequence(txs)]) if results1.current_rows and results2.current_rows: links = dict() for row in results1.current_rows: hsh = row.tx_hash.hex() links[hsh] = dict() links[hsh]['tx_hash'] = hsh links[hsh]['height'] = row.height links[hsh]['timestamp'] = row.timestamp links[hsh]['input_value'] = row.value for row in results2.current_rows: hsh = row.tx_hash.hex() links[hsh]['output_value'] = row.value heights = [e['height'] for e in links.values()] rates = list_rates(currency, heights) return [ Link.from_dict(e, rates[e['height']]).to_dict() for e in links.values() ] return []
def list_labels(currency, expression): # Normalize label expression_norm = alphanumeric_lower(expression) expression_norm_prefix = expression_norm[:LABEL_PREFIX_LENGTH] session = get_session(currency=currency, keyspace_type='transformed') query = "SELECT label, label_norm, currency FROM tag_by_label WHERE " \ "label_norm_prefix = %s GROUP BY label_norm_prefix, label_norm" result = session.execute(query, [expression_norm_prefix]) if currency: return list( dict.fromkeys([ row.label for row in result if row.label_norm.startswith(expression_norm) and row.currency.lower() == currency ])) return list( dict.fromkeys([ row.label for row in result if row.label_norm.startswith(expression_norm) ]))
def list_rates(currency, heights=-1): """ Returns the exchange rates for a list of block heights """ session = get_session(currency, 'transformed') session.row_factory = dict_factory if heights == -1: heights = [get_statistics(currency)['no_blocks'] - 1] concurrent_query = "SELECT * FROM exchange_rates WHERE height = %s" statements_and_params = [] for h in heights: statements_and_params.append((concurrent_query, [h])) rates = execute_concurrent(session, statements_and_params, raise_on_first_error=False) height_rates = dict() # key: height, value: {'eur': 0, 'usd':0} for (success, rate) in rates: if not success: pass else: d = rate.one() height_rates[d['height']] = {k: v for k, v in d.items() if k != 'height'} return height_rates
def list_address_txs(currency, address, paging_state=None, pagesize=None): session = get_session(currency, 'transformed') address_id, address_id_group = get_address_id_id_group(currency, address) if address_id: query = "SELECT * FROM address_transactions WHERE address_id = %s " \ "AND address_id_group = %s" fetch_size = ADDRESS_PAGE_SIZE if pagesize: fetch_size = pagesize statement = SimpleStatement(query, fetch_size=fetch_size) results = session.execute(statement, [address_id, address_id_group], paging_state=paging_state) paging_state = results.paging_state if results: heights = [row.height for row in results.current_rows] rates = list_rates(currency, heights) address_txs = [ AddressTx.from_row(row, address, rates[row.height]).to_dict() for row in results.current_rows ] return paging_state, address_txs return None, None
def list_entity_addresses(currency, entity_id, paging_state, page_size): session = get_session(currency, 'transformed') entity_id_group = get_id_group(entity_id) query = "SELECT * FROM cluster_addresses WHERE cluster_group = %s AND " \ "cluster = %s" fetch_size = ENTITY_ADDRESSES_PAGE_SIZE if page_size: fetch_size = page_size statement = SimpleStatement(query, fetch_size=fetch_size) results = session.execute(statement, [entity_id_group, entity_id], paging_state=paging_state) if results: paging_state = results.paging_state rates = get_rates(currency)['rates'] addresses = [] for row in results.current_rows: address_id_group = get_id_group(row.address_id) address = get_address_by_id_group(currency, address_id_group, row.address_id) addresses.append(EntityAddress.from_entity_row(row, address, rates) .to_dict()) return paging_state, addresses return paging_state, None
def list_taxonomies(): session = get_session(currency=None, keyspace_type='tagpacks') query = "SELECT * FROM taxonomy_by_key LIMIT 100" rows = session.execute(query) return [Taxonomy.from_row(row).to_dict() for row in rows]
def list_concepts(taxonomy): session = get_session(currency=None, keyspace_type='tagpacks') query = "SELECT * FROM concept_by_taxonomy_id WHERE taxonomy = %s" rows = session.execute(query, [taxonomy]) return [Concept.from_row(row).to_dict() for row in rows]
def get_address_by_id_group(currency, address_id_group, address_id): session = get_session(currency, 'transformed') query = "SELECT address FROM address_by_id_group WHERE " \ "address_id_group = %s and address_id = %s" result = session.execute(query, [address_id_group, address_id]) return result[0].address if result else None