Exemplo n.º 1
0
def get_assets_supply(assets=[]):

    supplies = {}

    if 'ASP' in assets:
        supplies['ASP'] = (util.call_jsonrpc_api("get_supply",
                                                 {'asset': 'ASP'})['result'],
                           True)
        assets.remove('ASP')

    if 'GASP' in assets:
        supplies['GASP'] = (0, True)
        assets.remove('GASP')

    if len(assets) > 0:
        sql = '''SELECT asset, SUM(quantity) AS supply, divisible FROM issuances
                 WHERE asset IN ({})
                 AND status = ?
                 GROUP BY asset
                 ORDER BY asset'''.format(','.join(
            ['?' for e in range(0, len(assets))]))
        bindings = assets + ['valid']

        issuances = util.call_jsonrpc_api('sql', {
            'query': sql,
            'bindings': bindings
        })['result']
        for issuance in issuances:
            supplies[issuance['asset']] = (issuance['supply'],
                                           issuance['divisible'])

    return supplies
Exemplo n.º 2
0
def gettransaction_batch(txhash_list):
    raw_txes = util.call_jsonrpc_api("getrawtransaction_batch", {
        'txhash_list': txhash_list,
        'verbose': True,
        'skip_missing': True
    },
                                     abort_on_error=True)['result']
    txes = {}

    for tx_hash, tx in raw_txes.items():
        if tx is None:
            txes[tx_hash] = None
            continue

        valueOut = 0
        for vout in tx['vout']:
            valueOut += vout['value']
        txes[tx_hash] = {
            'txid': tx_hash,
            'version': tx['version'],
            'locktime': tx['locktime'],
            'confirmations':
            tx['confirmations'] if 'confirmations' in tx else 0,
            'blocktime': tx['blocktime'] if 'blocktime' in tx else 0,
            'blockhash': tx['blockhash'] if 'blockhash' in tx else 0,
            'time': tx['time'] if 'time' in tx else 0,
            'valueOut': valueOut,
            'vin': tx['vin'],
            'vout': tx['vout']
        }
    return txes
Exemplo n.º 3
0
def get_asset_info(asset, at_dt=None):
    asset_info = config.mongo_db.tracked_assets.find_one({'asset': asset})

    if asset not in (config.XCP, config.BTC) and at_dt and asset_info['_at_block_time'] > at_dt:
        # get the asset info at or before the given at_dt datetime
        for e in reversed(asset_info['_history']):  # newest to oldest
            if e['_at_block_time'] <= at_dt:
                asset_info = e
                break
        else:  # asset was created AFTER at_dt
            asset_info = None
        if asset_info is None:
            return None
        assert asset_info['_at_block_time'] <= at_dt

    # modify some of the properties of the returned asset_info for BTC and XCP
    if asset == config.BTC:
        if at_dt:
            start_block_index, end_block_index = database.get_block_indexes_for_dates(end_dt=at_dt)
            asset_info['total_issued'] = blockchain.get_gasp_supply(normalize=False, at_block_index=end_block_index)
            asset_info['total_issued_normalized'] = blockchain.normalize_quantity(asset_info['total_issued'])
        else:
            asset_info['total_issued'] = blockchain.get_gasp_supply(normalize=False)
            asset_info['total_issued_normalized'] = blockchain.normalize_quantity(asset_info['total_issued'])
    elif asset == config.XCP:
        # BUG: this does not take end_dt (if specified) into account. however, the deviation won't be too big
        # as XCP doesn't deflate quickly at all, and shouldn't matter that much since there weren't any/much trades
        # before the end of the burn period (which is what is involved with how we use at_dt with currently)
        asset_info['total_issued'] = util.call_jsonrpc_api("get_supply", {'asset': 'ASP'}, abort_on_error=True)['result']
        asset_info['total_issued_normalized'] = blockchain.normalize_quantity(asset_info['total_issued'])
    if not asset_info:
        raise Exception("Invalid asset: %s" % asset)
    return asset_info
Exemplo n.º 4
0
def parse_base64_feed(base64_feed):
    decoded_feed = base64.b64decode(base64_feed)
    feed = json.loads(decoded_feed)
    if not isinstance(feed, dict) or 'feed' not in feed:
        return False

    errors = util.is_valid_json(feed['feed'], config.FEED_SCHEMA)
    if len(errors) > 0:
        raise Exception("Invalid json: {}".format(", ".join(errors)))
    # get broadcast infos
    params = {
        'filters': {
            'field': 'source',
            'op': '=',
            'value': feed['feed']['address']
        },
        'order_by': 'tx_index',
        'order_dir': 'DESC',
        'limit': 1
    }
    broadcasts = util.call_jsonrpc_api('get_broadcasts', params)['result']
    if len(broadcasts) == 0:
        raise Exception("invalid feed address")

    complete_feed = {}
    complete_feed['fee_fraction_int'] = broadcasts[0]['fee_fraction_int']
    complete_feed['source'] = broadcasts[0]['source']
    complete_feed['locked'] = broadcasts[0]['locked']
    complete_feed['counters'] = get_feed_counters(broadcasts[0]['source'])
    complete_feed['info_data'] = sanitize_json_data(feed['feed'])

    feed['feed'] = complete_feed
    return feed
Exemplo n.º 5
0
def get_feed_counters(feed_address):
    counters = {}
    sql = 'SELECT COUNT(*) AS bet_count, SUM(wager_quantity) AS wager_quantity, SUM(wager_remaining) AS wager_remaining, status FROM bets '
    sql += 'WHERE feed_address=? GROUP BY status ORDER BY status DESC'
    bindings = [feed_address]
    params = {'query': sql, 'bindings': bindings}
    counters['bets'] = util.call_jsonrpc_api('sql', params)['result']
    return counters
Exemplo n.º 6
0
 def get_messagefeed_messages_by_index(message_indexes):
     msgs = util.call_jsonrpc_api("get_messages_by_index",
                                  {'message_indexes': message_indexes},
                                  abort_on_error=True)['result']
     events = []
     for m in msgs:
         events.append(messages.decorate_message_for_feed(m))
     return events
Exemplo n.º 7
0
def get_assets_info(assetsList):
    assets = assetsList  # TODO: change the parameter name at some point in the future...shouldn't be using camel case here
    if not isinstance(assets, list):
        raise Exception(
            "assets must be a list of asset names, even if it just contains one entry"
        )
    assets_info = []
    for asset in assets:
        # BTC and XCP.
        if asset in [config.BTC, config.XCP]:
            if asset == config.BTC:
                supply = blockchain.get_btc_supply(normalize=False)
                asset_longname = config.BTC_NAME
            else:
                supply = util.call_jsonrpc_api("get_supply",
                                               {'asset': config.XCP},
                                               abort_on_error=True)['result']
                asset_longname = config.XCP_NAME

            assets_info.append({
                'asset': asset,
                'asset_longname': asset_longname,
                'owner': None,
                'divisible': True,
                'locked': False,
                'supply': supply,
                'description': '',
                'issuer': None
            })
            continue

        # User-created asset.
        tracked_asset = config.mongo_db.tracked_assets.find_one(
            {'$or': [{
                'asset': asset
            }, {
                'asset_longname': asset
            }]}, {
                '_id': 0,
                '_history': 0
            })
        if not tracked_asset:
            continue  # asset not found, most likely
        assets_info.append({
            'asset': tracked_asset['asset'],
            'asset_longname': tracked_asset['asset_longname'],
            'owner': tracked_asset['owner'],
            'divisible': tracked_asset['divisible'],
            'locked': tracked_asset['locked'],
            'supply': tracked_asset['total_issued'],
            'description': tracked_asset['description'],
            'issuer': tracked_asset['owner']
        })
    return assets_info
Exemplo n.º 8
0
 def get_last_n_messages(count=100):
     if count > 1000:
         raise Exception("The count is too damn high")
     message_indexes = list(
         range(
             max(config.state['last_message_index'] - count, 0) + 1,
             config.state['last_message_index'] + 1))
     msgs = util.call_jsonrpc_api("get_messages_by_index",
                                  {'message_indexes': message_indexes},
                                  abort_on_error=True)['result']
     for i in range(len(msgs)):
         msgs[i] = messages.decorate_message_for_feed(msgs[i])
     return msgs
Exemplo n.º 9
0
def get_block_info(block_index, prefetch=0, min_message_index=None):
    global block_info_cache
    if block_index in block_info_cache:
        return block_info_cache[block_index]

    block_info_cache.clear()
    blocks = util.call_jsonrpc_api(
        'get_blocks',
        {'block_indexes': list(range(block_index, block_index + prefetch)),
         'min_message_index': min_message_index},
        abort_on_error=True, use_cache=False)['result']
    for block in blocks:
        block_info_cache[block['block_index']] = block
    return block_info_cache[block_index]
Exemplo n.º 10
0
 def proxy_to_aspired(method='', params=[]):
     if method == 'sql':
         raise Exception("Invalid method")
     result = util.call_jsonrpc_api(method, params)
     if 'error' in result:
         if result['error'].get('data', None):
             errorMsg = result['error']['data'].get(
                 'message', result['error']['message'])
             if isinstance(errorMsg, bytes):
                 errorMsg = str(errorMsg, 'utf-8')
         else:
             errorMsg = json.dumps(result['error'])
         raise Exception(errorMsg if errorMsg is not None else "UNKNOWN")
     return result['result']
Exemplo n.º 11
0
def get_unspent_txouts(source, return_confirmed=False):
    """returns a list of unspent outputs for a specific address
    @return: A list of dicts, with each entry in the dict having the following keys:
    """
    txouts = util.call_jsonrpc_api('get_unspent_txouts', {
        'address': source,
        'unconfirmed': True
    },
                                   abort_on_error=True)['result']
    if return_confirmed:
        return txouts, [
            output for output in txouts if output['confirmations'] > 0
        ]
    else:
        return txouts
Exemplo n.º 12
0
def get_bets(bet_type,
             feed_address,
             deadline,
             target_value=None,
             leverage=5040):
    limit = 50
    bindings = []
    sql = 'SELECT * FROM bets WHERE counterwager_remaining>0 AND '
    sql += 'bet_type=? AND feed_address=? AND leverage=? AND deadline=? '
    bindings += [bet_type, feed_address, leverage, deadline]
    if target_value:
        sql += 'AND target_value=? '
        bindings.append(target_value)
    sql += 'ORDER BY ((counterwager_quantity+0.0)/(wager_quantity+0.0)) ASC LIMIT ?'
    bindings.append(limit)
    params = {'query': sql, 'bindings': bindings}
    return util.call_jsonrpc_api('sql', params)['result']
Exemplo n.º 13
0
def get_feed(address_or_url=''):
    conditions = {
        '$or': [{
            'source': address_or_url
        }, {
            'info_url': address_or_url
        }],
        'info_status': 'valid'
    }
    result = {}
    feeds = config.mongo_db.feeds.find(conditions,
                                       projection={'_id': False},
                                       limit=1)
    for feed in feeds:
        if 'targets' not in feed['info_data'] or ('type' in feed['info_data']
                                                  and feed['info_data']['type']
                                                  in ['all', 'cfd']):
            feed['info_data']['next_broadcast'] = util.next_interval_date(
                feed['info_data']['broadcast_date'])
            feed['info_data']['next_deadline'] = util.next_interval_date(
                feed['info_data']['deadline'])
        result = feed
        result['counters'] = get_feed_counters(feed['source'])

    if 'counters' not in result:
        params = {
            'filters': {
                'field': 'source',
                'op': '=',
                'value': address_or_url
            },
            'order_by': 'tx_index',
            'order_dir': 'DESC',
            'limit': 10
        }
        broadcasts = util.call_jsonrpc_api('get_broadcasts', params)['result']
        if broadcasts:
            return {
                'broadcasts': broadcasts,
                'counters': get_feed_counters(address_or_url)
            }
    return result
Exemplo n.º 14
0
def get_user_bets(addresses=[], status="open"):
    params = {
        'filters': {
            'field': 'source',
            'op': 'IN',
            'value': addresses
        },
        'status': status,
        'order_by': 'tx_index',
        'order_dir': 'DESC',
        'limit': 100
    }
    bets = util.call_jsonrpc_api('get_bets', params)['result']

    sources = {}
    for bet in bets:
        sources[bet['feed_address']] = True

    return {
        'bets': bets,
        'feeds': get_feeds_by_source_addresses(list(sources.keys()))
    }
Exemplo n.º 15
0
def get_pairs_with_orders(addresses=[], max_pairs=12):

    pairs_with_orders = []

    sources = '''AND source IN ({})'''.format(','.join(
        ['?' for e in range(0, len(addresses))]))

    sql = '''SELECT (MIN(give_asset, get_asset) || '/' || MAX(give_asset, get_asset)) AS pair,
                    COUNT(*) AS order_count
             FROM orders
             WHERE give_asset != get_asset AND status = ? {}
             GROUP BY pair
             ORDER BY order_count DESC
             LIMIT ?'''.format(sources)

    bindings = ['open'] + addresses + [max_pairs]

    my_pairs = util.call_jsonrpc_api('sql', {
        'query': sql,
        'bindings': bindings
    })['result']

    for my_pair in my_pairs:
        base_asset, quote_asset = util.assets_to_asset_pair(
            *tuple(my_pair['pair'].split("/")))
        top_pair = {
            'base_asset': base_asset,
            'quote_asset': quote_asset,
            'my_order_count': my_pair['order_count']
        }
        if my_pair['pair'] == 'GASP/ASP':  # ASP/GASP always in first
            pairs_with_orders.insert(0, top_pair)
        else:
            pairs_with_orders.append(top_pair)

    return pairs_with_orders
Exemplo n.º 16
0
def search_raw_transactions(address, unconfirmed=True):
    return util.call_jsonrpc_api('search_raw_transactions', {
        'address': address,
        'unconfirmed': unconfirmed
    },
                                 abort_on_error=True)['result']
Exemplo n.º 17
0
def get_normalized_balances(addresses):
    """
    This call augments aspire's get_balances with a normalized_quantity field. It also will include any owned
    assets for an address, even if their balance is zero.
    NOTE: Does not retrieve GASP balance. Use get_address_info for that.
    """
    if not isinstance(addresses, list):
        raise Exception(
            "addresses must be a list of addresses, even if it just contains one address"
        )
    if not len(addresses):
        raise Exception("Invalid address list supplied")

    filters = []
    for address in addresses:
        filters.append({'field': 'address', 'op': '==', 'value': address})

    mappings = {}
    result = util.call_jsonrpc_api("get_balances", {
        'filters': filters,
        'filterop': 'or'
    },
                                   abort_on_error=True)['result']

    isowner = {}
    owned_assets = config.mongo_db.tracked_assets.find(
        {'$or': [{
            'owner': a
        } for a in addresses]}, {
            '_history': 0,
            '_id': 0
        })
    for o in owned_assets:
        isowner[o['owner'] + o['asset']] = o

    data = []
    for d in result:
        if not d['quantity'] and ((d['address'] + d['asset']) not in isowner):
            continue  # don't include balances with a zero asset value
        asset_info = config.mongo_db.tracked_assets.find_one(
            {'asset': d['asset']})
        divisible = True  # ASP and GASP
        if asset_info and 'divisible' in asset_info:
            divisible = asset_info['divisible']
        d['normalized_quantity'] = blockchain.normalize_quantity(
            d['quantity'], divisible)
        d['owner'] = (d['address'] + d['asset']) in isowner
        d['asset_longname'] = asset_info['asset_longname']
        mappings[d['address'] + d['asset']] = d
        data.append(d)

    # include any owned assets for each address, even if their balance is zero
    for key in isowner:
        if key not in mappings:
            o = isowner[key]
            data.append({
                'address': o['owner'],
                'asset': o['asset'],
                'quantity': 0,
                'normalized_quantity': 0,
                'owner': True,
            })

    return data
Exemplo n.º 18
0
    def handle_get():
        if flask.request.headers.get("Content-Type",
                                     None) == 'application/csp-report':
            try:
                data_json = flask.request.get_data().decode('utf-8')
                data = json.loads(data_json)
                assert 'csp-report' in data
            except Exception as e:
                obj_error = jsonrpc.exceptions.JSONRPCInvalidRequest(
                    data="Invalid JSON-RPC 2.0 request format")
                return flask.Response(obj_error.json.encode(),
                                      200,
                                      mimetype='application/json')

            tx_logger.info("***CSP SECURITY --- %s" % data_json)
            return flask.Response('', 200)

        # "ping" aspired to test
        cp_s = time.time()
        cp_result_valid = True
        try:
            cp_status = util.call_jsonrpc_api("get_running_info",
                                              abort_on_error=True,
                                              use_cache=False)['result']
        except:
            cp_result_valid = False
        cp_e = time.time()

        # "ping" aspireblockd to test, as well
        cb_s = time.time()
        cb_result_valid = True
        cb_result_error_code = None
        payload = {
            "id": 0,
            "jsonrpc": "2.0",
            "method": "is_ready",
            "params": [],
        }
        headers = {'content-type': 'application/json', 'Connection': 'close'}
        try:
            url = "http://127.0.0.1:%s/api/" % config.RPC_PORT
            r = grequests.map((grequests.post(url,
                                              data=json.dumps(payload),
                                              headers=headers), ))[0]
            if r is None:
                raise Exception("result is None")
        except Exception as e:
            cb_result_valid = False
            cb_result_error_code = "GOT EXCEPTION: %s" % e
        else:
            if r.status_code != 200:
                cb_result_valid = False
                cb_result_error_code = "GOT STATUS %s" % r.status_code if r else 'COULD NOT CONTACT'
            cb_result = r.json()
            if 'error' in cb_result:
                cb_result_valid = False
                cb_result_error_code = "GOT ERROR: %s" % cb_result['error']
        cb_e = time.time()

        result = {
            'aspire-server':
            'OK' if cp_result_valid else 'NOT OK',
            'aspire-server_ver':
            '%s.%s.%s' %
            (cp_status['version_major'], cp_status['version_minor'],
             cp_status['version_revision']) if cp_result_valid else '?',
            'aspire-server_last_block':
            cp_status['last_block'] if cp_result_valid else '?',
            'aspire-server_last_message_index':
            cp_status['last_message_index'] if cp_result_valid else '?',
            'aspire-server_caught_up':
            config.state['cp_caught_up'],
            'aspire-server_check_elapsed':
            cp_e - cp_s,
            'aspireblock':
            'OK' if cb_result_valid else 'NOT OK',
            'aspireblock_ver':
            config.VERSION,
            'aspireblock_check_elapsed':
            cb_e - cb_s,
            'aspireblock_error':
            cb_result_error_code,
            'aspireblock_last_message_index':
            config.state['last_message_index'],
            'aspireblock_caught_up':
            blockfeed.fuzzy_is_caught_up(),
            'aspireblock_cur_block': {
                'block_hash':
                config.state['cur_block'].get('block_hash', '??'),
                'block_index':
                config.state['cur_block'].get('block_index', '??')
            },
            'aspireblock_last_processed_block': {
                'block_hash':
                config.state['my_latest_block'].get('block_hash', '??'),
                'block_index':
                config.state['my_latest_block'].get('block_index', '??')
            },
        }

        response_code = 200
        # error if we couldn't make a successful call to aspire-server or aspireblock's API (500)
        if not cp_result_valid or not cb_result_valid:
            response_code = 500
            result['ERROR'] = "aspire-server_api_contact_error"
        # error 510 if the aspire-server last block is more than 1 block behind backend
        elif not result['aspire-server_caught_up']:
            response_code = 510
            result['ERROR'] = "aspire-server_not_caught_up"
        # error 511 if the aspireblock last block is more than 1 block behind aspire-server
        elif not result['aspireblock_caught_up']:
            response_code = 511
            result['ERROR'] = "aspireblock_not_caught_up"
        else:
            result['ERROR'] = None

        response = flask.Response(json.dumps(result),
                                  response_code,
                                  mimetype='application/json')
        _set_cors_headers(response)
        return response
Exemplo n.º 19
0
def get_escrowed_balances(addresses):
    addresses_holder = ','.join(['?' for e in range(0, len(addresses))])

    sql = '''SELECT (source || '_' || give_asset) AS source_asset, source AS address, give_asset AS asset, SUM(give_remaining) AS quantity
            FROM orders
            WHERE source IN ({}) AND status = ? AND give_asset != ?
            GROUP BY source_asset'''.format(addresses_holder)
    bindings = addresses + ['open', config.BTC]
    results = util.call_jsonrpc_api("sql", {
        'query': sql,
        'bindings': bindings
    },
                                    abort_on_error=True)['result']

    sql = '''SELECT (tx0_address || '_' || forward_asset) AS source_asset, tx0_address AS address, forward_asset AS asset, SUM(forward_quantity) AS quantity
             FROM order_matches
             WHERE tx0_address IN ({}) AND forward_asset != ? AND status = ?
             GROUP BY source_asset'''.format(addresses_holder)
    bindings = addresses + [config.BTC, 'pending']
    results += util.call_jsonrpc_api("sql", {
        'query': sql,
        'bindings': bindings
    },
                                     abort_on_error=True)['result']

    sql = '''SELECT (tx1_address || '_' || backward_asset) AS source_asset, tx1_address AS address, backward_asset AS asset, SUM(backward_quantity) AS quantity
             FROM order_matches
             WHERE tx1_address IN ({}) AND backward_asset != ? AND status = ?
             GROUP BY source_asset'''.format(addresses_holder)
    bindings = addresses + [config.BTC, 'pending']
    results += util.call_jsonrpc_api("sql", {
        'query': sql,
        'bindings': bindings
    },
                                     abort_on_error=True)['result']

    sql = '''SELECT source AS address, '{}' AS asset, SUM(wager_remaining) AS quantity
             FROM bets
             WHERE source IN ({}) AND status = ?
             GROUP BY address'''.format(config.XCP, addresses_holder)
    bindings = addresses + ['open']
    results += util.call_jsonrpc_api("sql", {
        'query': sql,
        'bindings': bindings
    },
                                     abort_on_error=True)['result']

    sql = '''SELECT tx0_address AS address, '{}' AS asset, SUM(forward_quantity) AS quantity
             FROM bet_matches
             WHERE tx0_address IN ({}) AND status = ?
             GROUP BY address'''.format(config.XCP, addresses_holder)
    bindings = addresses + ['pending']
    results += util.call_jsonrpc_api("sql", {
        'query': sql,
        'bindings': bindings
    },
                                     abort_on_error=True)['result']

    sql = '''SELECT tx1_address AS address, '{}' AS asset, SUM(backward_quantity) AS quantity
             FROM bet_matches
             WHERE tx1_address IN ({}) AND status = ?
             GROUP BY address'''.format(config.XCP, addresses_holder)
    bindings = addresses + ['pending']
    results += util.call_jsonrpc_api("sql", {
        'query': sql,
        'bindings': bindings
    },
                                     abort_on_error=True)['result']

    escrowed_balances = {}
    for order in results:
        if order['address'] not in escrowed_balances:
            escrowed_balances[order['address']] = {}
        if order['asset'] not in escrowed_balances[order['address']]:
            escrowed_balances[order['address']][order['asset']] = 0
        escrowed_balances[order['address']][
            order['asset']] += order['quantity']

    return escrowed_balances
Exemplo n.º 20
0
def compile_asset_pair_market_info():
    """Compiles the pair-level statistics that show on the View Prices page of aspirewallet, for instance"""
    # loop through all open orders, and compile a listing of pairs, with a count of open orders for each pair
    end_dt = datetime.datetime.utcnow()
    start_dt = end_dt - datetime.timedelta(days=1)
    start_block_index, end_block_index = database.get_block_indexes_for_dates(start_dt=start_dt, end_dt=end_dt)
    open_orders = util.call_jsonrpc_api(
        "get_orders",
        {'filters': [
            {'field': 'give_remaining', 'op': '>', 'value': 0},
            {'field': 'get_remaining', 'op': '>', 'value': 0},
            {'field': 'fee_required_remaining', 'op': '>=', 'value': 0},
            {'field': 'fee_provided_remaining', 'op': '>=', 'value': 0},
        ],
            'status': 'open',
            'show_expired': False,
        }, abort_on_error=True)['result']
    pair_data = {}
    asset_info = {}

    def get_price(base_quantity_normalized, quote_quantity_normalized):
        return float(D(quote_quantity_normalized / base_quantity_normalized))

    # COMPOSE order depth, lowest ask, and highest bid column data
    for o in open_orders:
        (base_asset, quote_asset) = util.assets_to_asset_pair(o['give_asset'], o['get_asset'])
        pair = '%s/%s' % (base_asset, quote_asset)
        base_asset_info = asset_info.get(base_asset, config.mongo_db.tracked_assets.find_one({'asset': base_asset}))
        if base_asset not in asset_info:
            asset_info[base_asset] = base_asset_info
        quote_asset_info = asset_info.get(quote_asset, config.mongo_db.tracked_assets.find_one({'asset': quote_asset}))
        if quote_asset not in asset_info:
            asset_info[quote_asset] = quote_asset_info

        pair_data.setdefault(
            pair,
            {'open_orders_count': 0, 'lowest_ask': None, 'highest_bid': None,
             'completed_trades_count': 0, 'vol_base': 0, 'vol_quote': 0})
        #^ highest ask = open order selling base, highest bid = open order buying base
        #^ we also initialize completed_trades_count, vol_base, vol_quote because every pair inited here may
        # not have cooresponding data out of the trades_data_by_pair aggregation below
        pair_data[pair]['open_orders_count'] += 1
        base_quantity_normalized = blockchain.normalize_quantity(o['give_quantity'] if base_asset == o['give_asset'] else o['get_quantity'], base_asset_info['divisible'])
        quote_quantity_normalized = blockchain.normalize_quantity(o['give_quantity'] if quote_asset == o['give_asset'] else o['get_quantity'], quote_asset_info['divisible'])
        order_price = get_price(base_quantity_normalized, quote_quantity_normalized)
        if base_asset == o['give_asset']:  # selling base
            if pair_data[pair]['lowest_ask'] is None or order_price < pair_data[pair]['lowest_ask']:
                pair_data[pair]['lowest_ask'] = order_price
        elif base_asset == o['get_asset']:  # buying base
            if pair_data[pair]['highest_bid'] is None or order_price > pair_data[pair]['highest_bid']:
                pair_data[pair]['highest_bid'] = order_price

    # COMPOSE volume data (in XCP and BTC), and % change data
    # loop through all trade volume over the past 24h, and match that to the open orders
    trades_data_by_pair = config.mongo_db.trades.aggregate([
        {"$match": {
            "block_time": {"$gte": start_dt, "$lte": end_dt}}
         },
        {"$project": {
            "base_asset": 1,
            "quote_asset": 1,
            "base_quantity_normalized": 1,  # to derive base volume
            "quote_quantity_normalized": 1  # to derive quote volume
        }},
        {"$group": {
            "_id":   {"base_asset": "$base_asset", "quote_asset": "$quote_asset"},
            "vol_base":   {"$sum": "$base_quantity_normalized"},
            "vol_quote":   {"$sum": "$quote_quantity_normalized"},
            "count": {"$sum": 1},
        }}
    ])
    for e in trades_data_by_pair:
        pair = '%s/%s' % (e['_id']['base_asset'], e['_id']['quote_asset'])
        pair_data.setdefault(pair, {'open_orders_count': 0, 'lowest_ask': None, 'highest_bid': None})
        #^ initialize an empty pair in the event there are no open orders for that pair, but there ARE completed trades for it
        pair_data[pair]['completed_trades_count'] = e['count']
        pair_data[pair]['vol_base'] = e['vol_base']
        pair_data[pair]['vol_quote'] = e['vol_quote']

    # compose price data, relative to BTC and XCP
    mps_xcp_btc, xcp_btc_price, btc_xcp_price = get_price_primatives()
    for pair, e in pair_data.items():
        base_asset, quote_asset = pair.split('/')
        _24h_vol_in_btc = None
        _24h_vol_in_xcp = None
        # derive asset price data, expressed in BTC and XCP, for the given volumes
        if base_asset == config.XCP:
            _24h_vol_in_xcp = e['vol_base']
            _24h_vol_in_btc = blockchain.round_out(e['vol_base'] * xcp_btc_price) if xcp_btc_price else 0
        elif base_asset == config.BTC:
            _24h_vol_in_xcp = blockchain.round_out(e['vol_base'] * btc_xcp_price) if btc_xcp_price else 0
            _24h_vol_in_btc = e['vol_base']
        else:  # base is not XCP or BTC
            price_summary_in_xcp, price_summary_in_btc, price_in_xcp, price_in_btc, aggregated_price_in_xcp, aggregated_price_in_btc = \
                get_xcp_btc_price_info(base_asset, mps_xcp_btc, xcp_btc_price, btc_xcp_price, with_last_trades=0, start_dt=start_dt, end_dt=end_dt)
            if price_in_xcp:
                _24h_vol_in_xcp = blockchain.round_out(e['vol_base'] * price_in_xcp)
            if price_in_btc:
                _24h_vol_in_btc = blockchain.round_out(e['vol_base'] * price_in_btc)

            if _24h_vol_in_xcp is None or _24h_vol_in_btc is None:
                # the base asset didn't have price data against BTC or XCP, or both...try against the quote asset instead
                price_summary_in_xcp, price_summary_in_btc, price_in_xcp, price_in_btc, aggregated_price_in_xcp, aggregated_price_in_btc = \
                    get_xcp_btc_price_info(quote_asset, mps_xcp_btc, xcp_btc_price, btc_xcp_price, with_last_trades=0, start_dt=start_dt, end_dt=end_dt)
                if _24h_vol_in_xcp is None and price_in_xcp:
                    _24h_vol_in_xcp = blockchain.round_out(e['vol_quote'] * price_in_xcp)
                if _24h_vol_in_btc is None and price_in_btc:
                    _24h_vol_in_btc = blockchain.round_out(e['vol_quote'] * price_in_btc)
            pair_data[pair]['24h_vol_in_{}'.format(config.XCP.lower())] = _24h_vol_in_xcp  # might still be None
            pair_data[pair]['24h_vol_in_{}'.format(config.BTC.lower())] = _24h_vol_in_btc  # might still be None

        # get % change stats -- start by getting the first trade directly before the 24h period starts
        prev_trade = config.mongo_db.trades.find({
            "base_asset": base_asset,
            "quote_asset": quote_asset,
            "block_time": {'$lt': start_dt}}).sort('block_time', pymongo.DESCENDING).limit(1)
        latest_trade = config.mongo_db.trades.find({
            "base_asset": base_asset,
            "quote_asset": quote_asset}).sort('block_time', pymongo.DESCENDING).limit(1)
        if not prev_trade.count():  # no previous trade before this 24hr period
            pair_data[pair]['24h_pct_change'] = None
        else:
            prev_trade = prev_trade[0]
            latest_trade = latest_trade[0]
            prev_trade_price = get_price(prev_trade['base_quantity_normalized'], prev_trade['quote_quantity_normalized'])
            latest_trade_price = get_price(latest_trade['base_quantity_normalized'], latest_trade['quote_quantity_normalized'])
            pair_data[pair]['24h_pct_change'] = ((latest_trade_price - prev_trade_price) / prev_trade_price) * 100
        pair_data[pair]['last_updated'] = end_dt
        # print "PRODUCED", pair, pair_data[pair]
        config.mongo_db.asset_pair_market_info.update({'base_asset': base_asset, 'quote_asset': quote_asset}, {"$set": pair_data[pair]}, upsert=True)

    # remove any old pairs that were not just updated
    config.mongo_db.asset_pair_market_info.remove({'last_updated': {'$lt': end_dt}})
    logger.info("Recomposed 24h trade statistics for %i asset pairs: %s" % (len(pair_data), ', '.join(list(pair_data.keys()))))
Exemplo n.º 21
0
def get_pairs(quote_asset='ASP',
              exclude_pairs=[],
              max_pairs=12,
              from_time=None):

    bindings = []

    sql = '''SELECT (CASE
                        WHEN forward_asset = ? THEN backward_asset
                        ELSE forward_asset
                    END) AS base_asset,
                    (CASE
                        WHEN backward_asset = ? THEN backward_asset
                        ELSE forward_asset
                    END) AS quote_asset,
                    (CASE
                        WHEN backward_asset = ? THEN (forward_asset || '/' || backward_asset)
                        ELSE (backward_asset || '/' || forward_asset)
                    END) AS pair,
                    (CASE
                        WHEN forward_asset = ? THEN backward_quantity
                        ELSE forward_quantity
                    END) AS bq,
                    (CASE
                        WHEN backward_asset = ? THEN backward_quantity
                        ELSE forward_quantity
                    END) AS qq '''
    if from_time:
        sql += ''', block_time '''

    sql += '''FROM order_matches '''
    bindings += [
        quote_asset, quote_asset, quote_asset, quote_asset, quote_asset
    ]

    if from_time:
        sql += '''INNER JOIN blocks ON order_matches.block_index = blocks.block_index '''

    priority_quote_assets = []
    for priority_quote_asset in config.QUOTE_ASSETS:
        if priority_quote_asset != quote_asset:
            priority_quote_assets.append(priority_quote_asset)
        else:
            break

    if len(priority_quote_assets) > 0:
        asset_bindings = ','.join(
            ['?' for e in range(0, len(priority_quote_assets))])
        sql += '''WHERE ((forward_asset = ? AND backward_asset NOT IN ({}))
                         OR (forward_asset NOT IN ({}) AND backward_asset = ?)) '''.format(
            asset_bindings, asset_bindings)
        bindings += [
            quote_asset
        ] + priority_quote_assets + priority_quote_assets + [quote_asset]
    else:
        sql += '''WHERE ((forward_asset = ?) OR (backward_asset = ?)) '''
        bindings += [quote_asset, quote_asset]

    if len(exclude_pairs) > 0:
        sql += '''AND pair NOT IN ({}) '''.format(','.join(
            ['?' for e in range(0, len(exclude_pairs))]))
        bindings += exclude_pairs

    if from_time:
        sql += '''AND block_time > ? '''
        bindings += [from_time]

    sql += '''AND forward_asset != backward_asset
              AND status = ?'''

    bindings += ['completed', max_pairs]

    sql = '''SELECT base_asset, quote_asset, pair, SUM(bq) AS base_quantity, SUM(qq) AS quote_quantity
             FROM ({})
             GROUP BY pair
             ORDER BY quote_quantity DESC
             LIMIT ?'''.format(sql)

    return util.call_jsonrpc_api('sql', {
        'query': sql,
        'bindings': bindings
    })['result']
Exemplo n.º 22
0
def get_pair_price(base_asset,
                   quote_asset,
                   max_block_time=None,
                   supplies=None):

    if not supplies:
        supplies = get_assets_supply([base_asset, quote_asset])

    sql = '''SELECT *, MAX(tx0_index, tx1_index) AS tx_index, blocks.block_time
             FROM order_matches INNER JOIN blocks ON order_matches.block_index = blocks.block_index
             WHERE
                forward_asset IN (?, ?) AND
                backward_asset IN (?, ?) '''
    bindings = [base_asset, quote_asset, base_asset, quote_asset]

    if max_block_time:
        sql += '''AND block_time <= ? '''
        bindings += [max_block_time]

    sql += '''ORDER BY tx_index DESC
             LIMIT 2'''

    order_matches = util.call_jsonrpc_api('sql', {
        'query': sql,
        'bindings': bindings
    })['result']

    if len(order_matches) == 0:
        last_price = D(0.0)
    elif order_matches[0]['forward_asset'] == base_asset:
        last_price = calculate_price(
            order_matches[0]['forward_quantity'],
            order_matches[0]['backward_quantity'],
            supplies[order_matches[0]['forward_asset']][1],
            supplies[order_matches[0]['backward_asset']][1])
    else:
        last_price = calculate_price(
            order_matches[0]['backward_quantity'],
            order_matches[0]['forward_quantity'],
            supplies[order_matches[0]['backward_asset']][1],
            supplies[order_matches[0]['forward_asset']][1])

    trend = 0
    if len(order_matches) == 2:
        if order_matches[1]['forward_asset'] == base_asset:
            before_last_price = calculate_price(
                order_matches[0]['forward_quantity'],
                order_matches[0]['backward_quantity'],
                supplies[order_matches[0]['forward_asset']][1],
                supplies[order_matches[0]['backward_asset']][1])
        else:
            before_last_price = calculate_price(
                order_matches[0]['backward_quantity'],
                order_matches[0]['forward_quantity'],
                supplies[order_matches[0]['backward_asset']][1],
                supplies[order_matches[0]['forward_asset']][1])
        if last_price < before_last_price:
            trend = -1
        elif last_price > before_last_price:
            trend = 1

    return D(last_price), trend
Exemplo n.º 23
0
def gaspd_rpc(command, params):
    return util.call_jsonrpc_api(command,
                                 params=params,
                                 endpoint=config.BACKEND_URL_NOAUTH,
                                 auth=config.BACKEND_AUTH,
                                 abort_on_error=True)['result']
Exemplo n.º 24
0
        def get_address_history(address, start_block=None, end_block=None):
            address_dict = {}

            address_dict['balances'] = util.call_jsonrpc_api(
                "get_balances", {
                    'filters': [
                        {
                            'field': 'address',
                            'op': '==',
                            'value': address
                        },
                    ],
                },
                abort_on_error=True)['result']

            address_dict['debits'] = util.call_jsonrpc_api(
                "get_debits", {
                    'filters': [{
                        'field': 'address',
                        'op': '==',
                        'value': address
                    }, {
                        'field': 'quantity',
                        'op': '>',
                        'value': 0
                    }],
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['credits'] = util.call_jsonrpc_api(
                "get_credits", {
                    'filters': [{
                        'field': 'address',
                        'op': '==',
                        'value': address
                    }, {
                        'field': 'quantity',
                        'op': '>',
                        'value': 0
                    }],
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['proofofwork'] = util.call_jsonrpc_api(
                "get_proofofwork", {
                    'filters': [{
                        'field': 'address',
                        'op': '==',
                        'value': address
                    }, {
                        'field': 'mined',
                        'op': '>',
                        'value': 0
                    }],
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['sends'] = util.call_jsonrpc_api(
                "get_sends", {
                    'filters': [{
                        'field': 'source',
                        'op': '==',
                        'value': address
                    }, {
                        'field': 'destination',
                        'op': '==',
                        'value': address
                    }],
                    'filterop':
                    'or',
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']
            #^ with filterop == 'or', we get all sends where this address was the source OR destination

            address_dict['orders'] = util.call_jsonrpc_api(
                "get_orders", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['order_matches'] = util.call_jsonrpc_api(
                "get_order_matches", {
                    'filters': [
                        {
                            'field': 'tx0_address',
                            'op': '==',
                            'value': address
                        },
                        {
                            'field': 'tx1_address',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'filterop':
                    'or',
                    'order_by':
                    'tx0_block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['btcpays'] = util.call_jsonrpc_api(
                "get_btcpays", {
                    'filters': [{
                        'field': 'source',
                        'op': '==',
                        'value': address
                    }, {
                        'field': 'destination',
                        'op': '==',
                        'value': address
                    }],
                    'filterop':
                    'or',
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['issuances'] = util.call_jsonrpc_api(
                "get_issuances", {
                    'filters': [{
                        'field': 'issuer',
                        'op': '==',
                        'value': address
                    }, {
                        'field': 'source',
                        'op': '==',
                        'value': address
                    }],
                    'filterop':
                    'or',
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['broadcasts'] = util.call_jsonrpc_api(
                "get_broadcasts", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['bets'] = util.call_jsonrpc_api(
                "get_bets", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['bet_matches'] = util.call_jsonrpc_api(
                "get_bet_matches", {
                    'filters': [
                        {
                            'field': 'tx0_address',
                            'op': '==',
                            'value': address
                        },
                        {
                            'field': 'tx1_address',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'filterop':
                    'or',
                    'order_by':
                    'tx0_block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['dividends'] = util.call_jsonrpc_api(
                "get_dividends", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['cancels'] = util.call_jsonrpc_api(
                "get_cancels", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['bet_expirations'] = util.call_jsonrpc_api(
                "get_bet_expirations", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['order_expirations'] = util.call_jsonrpc_api(
                "get_order_expirations", {
                    'filters': [
                        {
                            'field': 'source',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'order_by': 'block_index',
                    'order_dir': 'asc',
                    'start_block': start_block,
                    'end_block': end_block,
                },
                abort_on_error=True)['result']

            address_dict['bet_match_expirations'] = util.call_jsonrpc_api(
                "get_bet_match_expirations", {
                    'filters': [
                        {
                            'field': 'tx0_address',
                            'op': '==',
                            'value': address
                        },
                        {
                            'field': 'tx1_address',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'filterop':
                    'or',
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']

            address_dict['order_match_expirations'] = util.call_jsonrpc_api(
                "get_order_match_expirations", {
                    'filters': [
                        {
                            'field': 'tx0_address',
                            'op': '==',
                            'value': address
                        },
                        {
                            'field': 'tx1_address',
                            'op': '==',
                            'value': address
                        },
                    ],
                    'filterop':
                    'or',
                    'order_by':
                    'block_index',
                    'order_dir':
                    'asc',
                    'start_block':
                    start_block,
                    'end_block':
                    end_block,
                },
                abort_on_error=True)['result']
            return address_dict
Exemplo n.º 25
0
def convert_armory_signedtx_to_raw_hex(signed_tx_ascii):
    endpoint = "http://%s:%s/" % (module_config['ARMORY_UTXSVR_HOST'], ARMORY_UTXSVR_PORT_MAINNET if not config.TESTNET else ARMORY_UTXSVR_PORT_TESTNET)
    params = {'signed_tx_ascii': signed_tx_ascii}
    raw_tx_hex = util.call_jsonrpc_api("convert_signed_tx_to_raw_hex", params=params, endpoint=endpoint, abort_on_error=True)['result']
    return raw_tx_hex
Exemplo n.º 26
0
def create_armory_utx(unsigned_tx_hex, public_key_hex):
    endpoint = "http://%s:%s/" % (module_config['ARMORY_UTXSVR_HOST'], ARMORY_UTXSVR_PORT_MAINNET if not config.TESTNET else ARMORY_UTXSVR_PORT_TESTNET)
    params = {'unsigned_tx_hex': unsigned_tx_hex, 'public_key_hex': public_key_hex}
    utx_ascii = util.call_jsonrpc_api("serialize_unsigned_tx", params=params, endpoint=endpoint, abort_on_error=True)['result']
    return utx_ascii
Exemplo n.º 27
0
def get_market_orders(asset1,
                      asset2,
                      addresses=[],
                      supplies=None,
                      min_fee_provided=0.95,
                      max_fee_required=0.95):

    base_asset, quote_asset = util.assets_to_asset_pair(asset1, asset2)
    if not supplies:
        supplies = get_assets_supply([asset1, asset2])

    market_orders = []
    buy_orders = []
    sell_orders = []

    sql = '''SELECT orders.*, blocks.block_time FROM orders INNER JOIN blocks ON orders.block_index=blocks.block_index
             WHERE  status = ? '''
    bindings = ['open']

    if len(addresses) > 0:
        sql += '''AND source IN ({}) '''.format(','.join(
            ['?' for e in range(0, len(addresses))]))
        bindings += addresses

    sql += '''AND give_remaining > 0
              AND give_asset IN (?, ?)
              AND get_asset IN (?, ?)
              ORDER BY tx_index DESC'''

    bindings += [asset1, asset2, asset1, asset2]

    orders = util.call_jsonrpc_api('sql', {
        'query': sql,
        'bindings': bindings
    })['result']

    for order in orders:
        market_order = {}

        exclude = False
        if order['give_asset'] == 'GASP':
            try:
                fee_provided = order['fee_provided'] / (
                    order['give_quantity'] / 100)
                market_order['fee_provided'] = format(
                    D(order['fee_provided']) /
                    (D(order['give_quantity']) / D(100)), '.2f')
            except Exception as e:
                fee_provided = min_fee_provided - 1  # exclude

            exclude = fee_provided < min_fee_provided

        elif order['get_asset'] == 'GASP':
            try:
                fee_required = order['fee_required'] / (order['get_quantity'] /
                                                        100)
                market_order['fee_required'] = format(
                    D(order['fee_required']) /
                    (D(order['get_quantity']) / D(100)), '.2f')
            except Exception as e:
                fee_required = max_fee_required + 1  # exclude

            exclude = fee_required > max_fee_required

        if not exclude:
            if order['give_asset'] == base_asset:
                try:
                    price = calculate_price(order['give_quantity'],
                                            order['get_quantity'],
                                            supplies[order['give_asset']][1],
                                            supplies[order['get_asset']][1],
                                            'SELL')
                except:
                    continue
                market_order['type'] = 'SELL'
                market_order['amount'] = order['give_remaining']
                market_order['total'] = D(order['give_remaining']) * D(price)
                if not supplies[order['give_asset']][1] and supplies[
                        order['get_asset']][1]:
                    market_order['total'] = int(market_order['total'] *
                                                config.UNIT)
                elif supplies[order['give_asset']][1] and not supplies[
                        order['get_asset']][1]:
                    market_order['total'] = int(market_order['total'] /
                                                config.UNIT)
                else:
                    market_order['total'] = int(market_order['total'])
            else:
                try:
                    price = calculate_price(order['get_quantity'],
                                            order['give_quantity'],
                                            supplies[order['get_asset']][1],
                                            supplies[order['give_asset']][1],
                                            'BUY')
                except:
                    continue
                market_order['type'] = 'BUY'
                market_order['total'] = order['give_remaining']
                market_order['amount'] = D(order['give_remaining']) / D(price)
                if supplies[order['give_asset']][1] and not supplies[
                        order['get_asset']][1]:
                    market_order['amount'] = int(market_order['amount'] /
                                                 config.UNIT)
                elif not supplies[order['give_asset']][1] and supplies[
                        order['get_asset']][1]:
                    market_order['amount'] = int(market_order['amount'] *
                                                 config.UNIT)
                else:
                    market_order['amount'] = int(market_order['amount'])

            market_order['price'] = price

            if len(addresses) > 0:
                completed = format(
                    ((D(order['give_quantity']) - D(order['give_remaining'])) /
                     D(order['give_quantity'])) * D(100), '.2f')
                market_order['completion'] = "{}%".format(completed)
                market_order['tx_index'] = order['tx_index']
                market_order['tx_hash'] = order['tx_hash']
                market_order['source'] = order['source']
                market_order['block_index'] = order['block_index']
                market_order['block_time'] = order['block_time']
                market_orders.append(market_order)
            else:
                if market_order['type'] == 'SELL':
                    sell_orders.append(market_order)
                else:
                    buy_orders.append(market_order)

    if len(addresses) == 0:
        market_orders = merge_same_price_orders(
            sell_orders) + merge_same_price_orders(buy_orders)

    return market_orders
Exemplo n.º 28
0
def _get_order_book(base_asset,
                    quote_asset,
                    bid_book_min_pct_fee_provided=None,
                    bid_book_min_pct_fee_required=None,
                    bid_book_max_pct_fee_required=None,
                    ask_book_min_pct_fee_provided=None,
                    ask_book_min_pct_fee_required=None,
                    ask_book_max_pct_fee_required=None):
    """Gets the current order book for a specified asset pair

    @param: normalized_fee_required: Only specify if buying BTC. If specified, the order book will be pruned down to only
     show orders at and above this fee_required
    @param: normalized_fee_provided: Only specify if selling BTC. If specified, the order book will be pruned down to only
     show orders at and above this fee_provided
    """
    base_asset_info = config.mongo_db.tracked_assets.find_one(
        {'asset': base_asset})
    quote_asset_info = config.mongo_db.tracked_assets.find_one(
        {'asset': quote_asset})

    if not base_asset_info or not quote_asset_info:
        raise Exception("Invalid asset(s)")

    # TODO: limit # results to 8 or so for each book (we have to sort as well to limit)
    base_bid_filters = [
        {
            "field": "get_asset",
            "op": "==",
            "value": base_asset
        },
        {
            "field": "give_asset",
            "op": "==",
            "value": quote_asset
        },
    ]
    base_ask_filters = [
        {
            "field": "get_asset",
            "op": "==",
            "value": quote_asset
        },
        {
            "field": "give_asset",
            "op": "==",
            "value": base_asset
        },
    ]
    if base_asset == config.BTC or quote_asset == config.BTC:
        extra_filters = [
            {
                'field': 'give_remaining',
                'op': '>',
                'value': 0
            },  # don't show empty BTC orders
            {
                'field': 'get_remaining',
                'op': '>',
                'value': 0
            },  # don't show empty BTC orders
            {
                'field': 'fee_required_remaining',
                'op': '>=',
                'value': 0
            },
            {
                'field': 'fee_provided_remaining',
                'op': '>=',
                'value': 0
            },
        ]
        base_bid_filters += extra_filters
        base_ask_filters += extra_filters

    base_bid_orders = util.call_jsonrpc_api("get_orders", {
        'filters': base_bid_filters,
        'show_expired': False,
        'status': 'open',
        'order_by': 'block_index',
        'order_dir': 'asc',
    },
                                            abort_on_error=True)['result']

    base_ask_orders = util.call_jsonrpc_api("get_orders", {
        'filters': base_ask_filters,
        'show_expired': False,
        'status': 'open',
        'order_by': 'block_index',
        'order_dir': 'asc',
    },
                                            abort_on_error=True)['result']

    def get_o_pct(o):
        if o['give_asset'] == config.BTC:  # NB: fee_provided could be zero here
            pct_fee_provided = float(
                (D(o['fee_provided_remaining']) / D(o['give_quantity'])))
        else:
            pct_fee_provided = None
        if o['get_asset'] == config.BTC:  # NB: fee_required could be zero here
            pct_fee_required = float(
                (D(o['fee_required_remaining']) / D(o['get_quantity'])))
        else:
            pct_fee_required = None
        return pct_fee_provided, pct_fee_required

    # filter results by pct_fee_provided and pct_fee_required for BTC pairs as appropriate
    filtered_base_bid_orders = []
    filtered_base_ask_orders = []
    if base_asset == config.BTC or quote_asset == config.BTC:
        for o in base_bid_orders:
            pct_fee_provided, pct_fee_required = get_o_pct(o)
            addToBook = True
            if bid_book_min_pct_fee_provided is not None and pct_fee_provided is not None and pct_fee_provided < bid_book_min_pct_fee_provided:
                addToBook = False
            if bid_book_min_pct_fee_required is not None and pct_fee_required is not None and pct_fee_required < bid_book_min_pct_fee_required:
                addToBook = False
            if bid_book_max_pct_fee_required is not None and pct_fee_required is not None and pct_fee_required > bid_book_max_pct_fee_required:
                addToBook = False
            if addToBook:
                filtered_base_bid_orders.append(o)
        for o in base_ask_orders:
            pct_fee_provided, pct_fee_required = get_o_pct(o)
            addToBook = True
            if ask_book_min_pct_fee_provided is not None and pct_fee_provided is not None and pct_fee_provided < ask_book_min_pct_fee_provided:
                addToBook = False
            if ask_book_min_pct_fee_required is not None and pct_fee_required is not None and pct_fee_required < ask_book_min_pct_fee_required:
                addToBook = False
            if ask_book_max_pct_fee_required is not None and pct_fee_required is not None and pct_fee_required > ask_book_max_pct_fee_required:
                addToBook = False
            if addToBook:
                filtered_base_ask_orders.append(o)
    else:
        filtered_base_bid_orders += base_bid_orders
        filtered_base_ask_orders += base_ask_orders

    def make_book(orders, isBidBook):
        book = {}
        for o in orders:
            if o['give_asset'] == base_asset:
                if base_asset == config.BTC and o[
                        'give_quantity'] <= config.ORDER_BTC_DUST_LIMIT_CUTOFF:
                    continue  # filter dust orders, if necessary

                give_quantity = blockchain.normalize_quantity(
                    o['give_quantity'], base_asset_info['divisible'])
                get_quantity = blockchain.normalize_quantity(
                    o['get_quantity'], quote_asset_info['divisible'])
                unit_price = float((D(get_quantity) / D(give_quantity)))
                remaining = blockchain.normalize_quantity(
                    o['give_remaining'], base_asset_info['divisible'])
            else:
                if quote_asset == config.BTC and o[
                        'give_quantity'] <= config.ORDER_BTC_DUST_LIMIT_CUTOFF:
                    continue  # filter dust orders, if necessary

                give_quantity = blockchain.normalize_quantity(
                    o['give_quantity'], quote_asset_info['divisible'])
                get_quantity = blockchain.normalize_quantity(
                    o['get_quantity'], base_asset_info['divisible'])
                unit_price = float((D(give_quantity) / D(get_quantity)))
                remaining = blockchain.normalize_quantity(
                    o['get_remaining'], base_asset_info['divisible'])
            id = "%s_%s_%s" % (base_asset, quote_asset, unit_price)
            #^ key = {base}_{bid}_{unit_price}, values ref entries in book
            book.setdefault(id, {
                'unit_price': unit_price,
                'quantity': 0,
                'count': 0
            })
            book[id]['quantity'] += remaining  # base quantity outstanding
            book[id]['count'] += 1  # num orders at this price level
        book = sorted(iter(book.values()),
                      key=operator.itemgetter('unit_price'),
                      reverse=isBidBook)
        #^ convert to list and sort -- bid book = descending, ask book = ascending
        return book

    # compile into a single book, at volume tiers
    base_bid_book = make_book(filtered_base_bid_orders, True)
    base_ask_book = make_book(filtered_base_ask_orders, False)

    # get stats like the spread and median
    if base_bid_book and base_ask_book:
        # don't do abs(), as this is "the amount by which the ask price exceeds the bid", so I guess it could be negative
        # if there is overlap in the book (right?)
        bid_ask_spread = float((D(base_ask_book[0]['unit_price']) -
                                D(base_bid_book[0]['unit_price'])))
        bid_ask_median = float((D(
            max(base_ask_book[0]['unit_price'],
                base_bid_book[0]['unit_price'])) -
                                (D(abs(bid_ask_spread)) / 2)))
    else:
        bid_ask_spread = 0
        bid_ask_median = 0

    # compose depth and round out quantities
    bid_depth = D(0)
    for o in base_bid_book:
        o['quantity'] = float(D(o['quantity']))
        bid_depth += D(o['quantity'])
        o['depth'] = float(D(bid_depth))
    bid_depth = float(D(bid_depth))
    ask_depth = D(0)
    for o in base_ask_book:
        o['quantity'] = float(D(o['quantity']))
        ask_depth += D(o['quantity'])
        o['depth'] = float(D(ask_depth))
    ask_depth = float(D(ask_depth))

    # compose raw orders
    orders = filtered_base_bid_orders + filtered_base_ask_orders
    for o in orders:
        # add in the blocktime to help makes interfaces more user-friendly (i.e. avoid displaying block
        # indexes and display datetimes instead)
        o['block_time'] = calendar.timegm(
            util.get_block_time(o['block_index']).timetuple()) * 1000

    result = {
        'base_bid_book': base_bid_book,
        'base_ask_book': base_ask_book,
        'bid_depth': bid_depth,
        'ask_depth': ask_depth,
        'bid_ask_spread': bid_ask_spread,
        'bid_ask_median': bid_ask_median,
        'raw_orders': orders,
        'base_asset': base_asset,
        'quote_asset': quote_asset
    }
    return result
Exemplo n.º 29
0
def get_market_trades(asset1, asset2, addresses=[], limit=50, supplies=None):
    limit = min(limit, 100)
    base_asset, quote_asset = util.assets_to_asset_pair(asset1, asset2)
    if not supplies:
        supplies = get_assets_supply([asset1, asset2])
    market_trades = []

    sources = ''
    bindings = ['expired']
    if len(addresses) > 0:
        placeholder = ','.join(['?' for e in range(0, len(addresses))])
        sources = '''AND (tx0_address IN ({}) OR tx1_address IN ({}))'''.format(
            placeholder, placeholder)
        bindings += addresses + addresses

    sql = '''SELECT order_matches.*, blocks.block_time FROM order_matches INNER JOIN blocks ON order_matches.block_index=blocks.block_index
             WHERE status != ? {}
                AND forward_asset IN (?, ?)
                AND backward_asset IN (?, ?)
             ORDER BY block_index DESC
             LIMIT ?'''.format(sources)

    bindings += [asset1, asset2, asset1, asset2, limit]

    order_matches = util.call_jsonrpc_api('sql', {
        'query': sql,
        'bindings': bindings
    })['result']

    for order_match in order_matches:

        if order_match['tx0_address'] in addresses:
            trade = {}
            trade['match_id'] = order_match['id']
            trade['source'] = order_match['tx0_address']
            trade['countersource'] = order_match['tx1_address']
            trade['block_index'] = order_match['block_index']
            trade['block_time'] = order_match['block_time']
            trade['status'] = order_match['status']
            if order_match['forward_asset'] == base_asset:
                trade['type'] = 'SELL'
                trade['price'] = calculate_price(
                    order_match['forward_quantity'],
                    order_match['backward_quantity'],
                    supplies[order_match['forward_asset']][1],
                    supplies[order_match['backward_asset']][1], 'SELL')
                trade['amount'] = order_match['forward_quantity']
                trade['total'] = order_match['backward_quantity']
            else:
                trade['type'] = 'BUY'
                trade['price'] = calculate_price(
                    order_match['backward_quantity'],
                    order_match['forward_quantity'],
                    supplies[order_match['backward_asset']][1],
                    supplies[order_match['forward_asset']][1], 'BUY')
                trade['amount'] = order_match['backward_quantity']
                trade['total'] = order_match['forward_quantity']
            market_trades.append(trade)

        if len(addresses) == 0 or order_match['tx1_address'] in addresses:
            trade = {}
            trade['match_id'] = order_match['id']
            trade['source'] = order_match['tx1_address']
            trade['countersource'] = order_match['tx0_address']
            trade['block_index'] = order_match['block_index']
            trade['block_time'] = order_match['block_time']
            trade['status'] = order_match['status']
            if order_match['backward_asset'] == base_asset:
                trade['type'] = 'SELL'
                trade['price'] = calculate_price(
                    order_match['backward_quantity'],
                    order_match['forward_quantity'],
                    supplies[order_match['backward_asset']][1],
                    supplies[order_match['forward_asset']][1], 'SELL')
                trade['amount'] = order_match['backward_quantity']
                trade['total'] = order_match['forward_quantity']
            else:
                trade['type'] = 'BUY'
                trade['price'] = calculate_price(
                    order_match['forward_quantity'],
                    order_match['backward_quantity'],
                    supplies[order_match['forward_asset']][1],
                    supplies[order_match['backward_asset']][1], 'BUY')
                trade['amount'] = order_match['forward_quantity']
                trade['total'] = order_match['backward_quantity']
            market_trades.append(trade)

    return market_trades