예제 #1
0
def v1_price():
    exchange_address = request.args.get("exchangeAddress")

    if (exchange_address is None):
        return "{error:missing parameter}"  # TODO return actual error

    exchange_info = load_exchange_info(datastore.Client(), exchange_address)

    if (exchange_info == None):
        return "{error: no exchange found for this address}"  # TODO return a proper json error

    result = {
        "symbol":
        exchange_info["symbol"],
        "price":
        calculate_marginal_rate(int(exchange_info["cur_eth_total"]),
                                int(exchange_info["cur_tokens_total"]))
    }

    return json.dumps(result)
예제 #2
0
def v1_price():
    exchange_address = request.args.get("exchangeAddress")

    if (exchange_address is None):
        return jsonify(error='missing parameter: exchangeAddress'), 400

    exchange_info = load_exchange_info(datastore.Client(), exchange_address)

    if (exchange_info == None):
        return jsonify(error='no exchange found for this address'), 404

    result = {
        "symbol":
        exchange_info["symbol"],
        "price":
        calculate_marginal_rate(int(exchange_info["cur_eth_total"]),
                                int(exchange_info["cur_tokens_total"]))
    }

    return jsonify(result)
예제 #3
0
def v1_get_exchange():
    exchange_address = request.args.get("exchangeAddress")

    if (exchange_address is None):
        return jsonify(error='missing parameter: exchangeAddress'), 400

    exchange_info = load_exchange_info(datastore.Client(), exchange_address)

    if (exchange_info == None):
        return jsonify(error='no exchange found for this address'), 404

    result = {
        "symbol":
        exchange_info["symbol"],
        "name":
        exchange_info["name"],
        "price":
        calculate_marginal_rate(int(exchange_info["cur_eth_total"]),
                                int(exchange_info["cur_tokens_total"])),
        "fee":
        exchange_info["fee"],
        "version":
        exchange_info["version"],
        "exchangeAddress":
        exchange_info["address"],
        "ethLiquidity":
        exchange_info["cur_eth_total"],
        "ethDecimals":
        18,
        "tokenAddress":
        exchange_info["token_address"],
        "tokenLiquidity":
        exchange_info["cur_tokens_total"],
        "tokenDecimals":
        exchange_info["token_decimals"],
    }

    return jsonify(result)
예제 #4
0
def v1_chart():
    exchange_address = request.args.get("exchangeAddress")
    start_time = request.args.get("startTime")
    end_time = request.args.get("endTime")
    unit_type = request.args.get("unit")

    if ((exchange_address is None) or (start_time is None)
            or (end_time is None) or (unit_type is None)):
        return "{error:missing parameter}"  # TODO return actual error

    # load the datastore exchange info
    exchange_info = load_exchange_info(datastore.Client(), exchange_address)

    exchange_address = to_checksum_address(exchange_address)
    unit_type = unit_type.lower()

    # query ETH and token balances, taking Purchase and Liquidity events
    bq_client = bigquery.Client()

    exchange_table_id = "exchange_history_" + exchange_address
    exchange_table_name = "`" + PROJECT_ID + "." + EXCHANGES_DATASET_ID + "." + exchange_table_id + "`"

    bq_query_sql = """
    	SELECT cast(sum(cast(eth as numeric)) as string) as eth_amount, cast(sum(cast(tokens as numeric)) as string) as token_amount, """ + unit_type + """ as date
    	FROM """ + exchange_table_name + """
    	where (event = 'TokenPurchase' or event = 'EthPurchase' or event = 'RemoveLiquidity' or event = 'AddLiquidity')
    		and ((timestamp >= """ + start_time + """) and (timestamp <= """ + end_time + """))
    	group by """ + unit_type + """
    	order by """ + unit_type + """ asc """

    print(bq_query_sql)

    # query the balances for each bucket TODO refer to bucket type parameter to determine how to group transactions
    balances_query = bq_client.query(bq_query_sql)

    balances_results = balances_query.result()

    balances_by_bucket = []

    # maintain a running total of eth/tokens so we can determine the rate for each bucket
    running_eth_total = 0
    running_tokens_total = 0

    token_decimals = exchange_info["token_decimals"]

    for row in balances_results:
        eth_amount = int(row.get("eth_amount"))
        token_amount = int(row.get("token_amount"))

        running_eth_total += eth_amount
        running_tokens_total += token_amount

        bucket_rate = running_tokens_total / running_eth_total

        balances_by_bucket.append({
            "ethLiquidity":
            running_eth_total / 1e18,
            "tokenLiquidity":
            running_tokens_total / (10**token_decimals),
            "marginalEthRate":
            bucket_rate,
            "date":
            row.get("date"),
        })

    # now query for trade volume
    bq_query_sql = """
    	SELECT cast(sum(abs(cast(eth as numeric))) as string) as trade_volume, """ + unit_type + """
    	FROM """ + exchange_table_name + """
    	where (event = 'TokenPurchase' or event = 'EthPurchase')
    		and ((timestamp >= """ + start_time + """) and (timestamp <= """ + end_time + """))
    	group by """ + unit_type + """
    	order by """ + unit_type + """ asc """

    print(bq_query_sql)

    volume_query = bq_client.query(bq_query_sql)

    volume_results = volume_query.result()

    volume_by_bucket = []

    index = 0
    for row in volume_results:
        balances_by_bucket[index]["ethVolume"] = int(
            row.get("trade_volume")) / 1e18
        index += 1

    return json.dumps(balances_by_bucket)
예제 #5
0
def v1_ticker():
    exchange_address = request.args.get("exchangeAddress")

    if (exchange_address is None):
        return "{error:missing parameter}"  # TODO return actual error

    # use current time as end time
    end_time = int(time.time())

    ds_client = datastore.Client()

    # load the datastore cache
    exchange_cache = load_exchange_cache(ds_client, exchange_address)

    use_cache = False

    # check how old the cache is
    if ((exchange_cache is None) == False):
        elapsed = end_time - exchange_cache["last_updated"]

        # use the cache
        if (elapsed <= CACHE_DURATION_SECONDS):
            print("using cache for " + exchange_address)
            use_cache = True

    # load the datastore exchange info
    exchange_info = load_exchange_info(ds_client, exchange_address)

    if (exchange_info == None):
        return "{error: no exchange found for this address}"  # TODO return a proper json error

    eth_liquidity = int(exchange_info["cur_eth_total"])
    erc20_liquidity = int(exchange_info["cur_tokens_total"])

    # grab these values from the cache if we should
    if (use_cache):
        end_time = exchange_cache["end_time"]

        start_time = exchange_cache["start_time"]

        end_exchange_rate = exchange_cache["end_exchange_rate"]

        start_exchange_rate = exchange_cache["start_exchange_rate"]

        eth_trade_volume = exchange_cache["eth_trade_volume"]

        weighted_avg_price_total = exchange_cache["weighted_avg_price_total"]

        highest_price = exchange_cache["highest_price"]
        lowest_price = exchange_cache["lowest_price"]

        last_trade_price = exchange_cache["last_trade_price"]

        last_trade_eth_qty = exchange_cache["last_trade_eth_qty"]
        last_trade_erc20_qty = exchange_cache["last_trade_erc20_qty"]

        num_transactions = exchange_cache["num_transactions"]
    else:
        # floor to last 15 minute mark. this ensures that all SQL queries in 15 minute windows are the same and use cached BigQuery results
        # end_time = math.floor(end_time / 900) * 900;

        # pull logs from TICKER_NUM_HOURS hours ago
        start_time = end_time - (60 * 60 * TICKER_NUM_HOURS)

        # pull the transactions from this exchange
        bq_client = bigquery.Client()

        exchange_table_id = "exchange_history_" + to_checksum_address(
            exchange_address)

        exchange_table_name = "`" + PROJECT_ID + "." + EXCHANGES_DATASET_ID + "." + exchange_table_id + "`"

        bq_query_sql = """
	         SELECT 
	         		tx_hash,
	        		CAST(event as STRING) as event, CAST(timestamp as INT64) as timestamp,
	        		CAST(eth as STRING) as eth, CAST(tokens as STRING) as tokens,
	        		CAST(cur_eth_total as STRING) as eth_liquidity, CAST(cur_tokens_total as STRING) as tokens_liquidity
	         FROM """ + exchange_table_name + """
	          WHERE (timestamp >= """ + str(
            start_time
        ) + """ and timestamp <= """ + str(
            end_time
        ) + """)""" + """ group by event, timestamp, eth, tokens, cur_eth_total, cur_tokens_total, tx_hash """ + """ order by timestamp desc, tx_hash asc"""

        print(bq_query_sql)

        # query all the blocks and their associated timestamps
        exchange_query = bq_client.query(bq_query_sql)

        exchange_results = exchange_query.result()

        start_exchange_rate = -1
        end_exchange_rate = -1

        highest_price = -1
        lowest_price = sys.maxsize

        num_transactions = 0

        eth_trade_volume = 0

        last_trade_price = 0
        last_trade_eth_qty = 0
        last_trade_erc20_qty = 0

        weighted_avg_price_total = 0

        # iterate through the results from oldest to newest (timestamp asc)
        for row in exchange_results:
            row_event = row.get("event")
            row_eth = int(row.get("eth"))
            row_eth_liquidity = int(row.get("eth_liquidity"))

            row_tokens = int(row.get("tokens"))
            row_tokens_liquidity = int(row.get("tokens_liquidity"))

            # the exchange rate after this transaction was executed
            exchange_rate_after_transaction = calculate_marginal_rate(
                row_eth_liquidity, row_tokens_liquidity)
            # the exchange rate before this transaction was executed
            exchange_rate_before_transaction = calculate_marginal_rate(
                row_eth_liquidity - row_eth, row_tokens_liquidity - row_tokens)

            # track highest price
            if (exchange_rate_after_transaction > highest_price):
                highest_price = exchange_rate_after_transaction

            # track lowest price
            if (exchange_rate_after_transaction < lowest_price):
                lowest_price = exchange_rate_after_transaction

            # if we haven't set a start price yet, take the exchange rate before this transaction
            if (start_exchange_rate < 0):
                start_exchange_rate = exchange_rate_before_transaction

            # override the end_price with each transaction to get the latest
            end_exchange_rate = exchange_rate_after_transaction

            num_transactions += 1

            if (row_event == "EthPurchase" or row_event == "TokenPurchase"):
                eth_trade_volume += abs(row_eth)

                last_trade_price = exchange_rate_before_transaction

                last_trade_eth_qty = row_eth
                last_trade_erc20_qty = row_tokens

                # for calculating average weighted price, take the amount of eth times the rate that they traded at
                weighted_avg_price_total += (abs(row_eth) *
                                             exchange_rate_before_transaction)

        # calculate average weighted price
        if (eth_trade_volume != 0):
            weighted_avg_price_total = weighted_avg_price_total / eth_trade_volume

        # update the cache
        exchange_cache["end_time"] = end_time
        exchange_cache["start_time"] = start_time

        exchange_cache["end_exchange_rate"] = end_exchange_rate
        exchange_cache["start_exchange_rate"] = start_exchange_rate

        exchange_cache["eth_trade_volume"] = str(eth_trade_volume)
        exchange_cache["weighted_avg_price_total"] = weighted_avg_price_total

        exchange_cache["highest_price"] = highest_price
        exchange_cache["lowest_price"] = lowest_price

        exchange_cache["last_trade_price"] = last_trade_price

        exchange_cache["last_updated"] = end_time

        exchange_cache["last_trade_eth_qty"] = str(last_trade_eth_qty)
        exchange_cache["last_trade_erc20_qty"] = str(last_trade_erc20_qty)

        exchange_cache["num_transactions"] = num_transactions

        ds_client.put(exchange_cache)

    price_change = end_exchange_rate - start_exchange_rate
    price_change_percent = price_change / start_exchange_rate

    marginal_rate = calculate_marginal_rate(eth_liquidity, erc20_liquidity)

    inv_marginal_rate = 1 / marginal_rate

    result = {
        "symbol": exchange_info["symbol"],
        "startTime": start_time,
        "endTime": end_time,
        "price": marginal_rate,
        "invPrice": inv_marginal_rate,
        "highPrice": highest_price,
        "lowPrice": lowest_price,
        "weightedAvgPrice": weighted_avg_price_total,
        "priceChange": price_change,
        "priceChangePercent": price_change_percent,
        "ethLiquidity": str(eth_liquidity),
        "erc20Liquidity": str(erc20_liquidity),
        "lastTradePrice": last_trade_price,
        "lastTradeEthQty": str(last_trade_eth_qty),
        "lastTradeErc20Qty": str(last_trade_erc20_qty),
        "tradeVolume": str(eth_trade_volume),
        "count": num_transactions
    }

    if ("theme" in exchange_info):
        result["theme"] = exchange_info["theme"]

    return json.dumps(result)