Made the user_publickeys to be read from file. Black is now used for formating.
This commit is contained in:
parent
cb33802e87
commit
21f0d0c229
@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
'''
|
"""
|
||||||
Fetch BTCUSD OHLC data from few market places and serve it forward with simple json api.
|
Fetch BTCUSD OHLC data from few market places and serve it forward with simple json api.
|
||||||
|
|
||||||
Creates: ./btc_ohlc.db
|
Creates: ./btc_ohlc.db
|
||||||
serves: localhost:5000/[t] and /serverkey
|
serves: localhost:5000/[t] and /serverkey
|
||||||
Authentication via auth header with signatures
|
Authentication via auth header with signatures
|
||||||
'''
|
"""
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import json
|
import json
|
||||||
@ -19,30 +19,43 @@ import requests
|
|||||||
import ecdsa
|
import ecdsa
|
||||||
import krakenex
|
import krakenex
|
||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request
|
||||||
#from Cryptodome.Cipher import AES
|
|
||||||
|
# from Cryptodome.Cipher import AES
|
||||||
|
|
||||||
DATABASE = "btc_ohlc.db"
|
DATABASE = "btc_ohlc.db"
|
||||||
|
KEYSFILE = "userkeys.json"
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
## Add your public key here
|
|
||||||
user_publickeys = {
|
|
||||||
"user1": 'f1debc13fb21fe0eee54525aa4f8aae5733b201c755edaa55f8893c90aa375b261a62eaa3110651ac5d7705d402581256a37508b0a1ca28bd919ea44710d9c88'
|
|
||||||
}
|
|
||||||
|
|
||||||
## Generate the ECDSA keys for this instance
|
## Generate the ECDSA keys for this instance
|
||||||
print("Generating ECDSA keys for this instance... just wait a bit...")
|
print("Generating ECDSA keys for this instance... just wait a bit...")
|
||||||
server_private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
|
server_private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
|
||||||
server_public_key = server_private_key.get_verifying_key()
|
server_public_key = server_private_key.get_verifying_key()
|
||||||
# We need the hexadecimal form for sharing over http/json
|
# We need the hexadecimal form for sharing over http/json
|
||||||
server_public_key_hex = binascii.hexlify(server_public_key.to_string()).decode('utf-8')
|
server_public_key_hex = binascii.hexlify(server_public_key.to_string()).decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
database_lock = threading.Lock()
|
database_lock = threading.Lock()
|
||||||
|
|
||||||
# Empty response json
|
# Empty response json
|
||||||
empty_dict = {"exchange": "", "timestamp": 0, "open": 0, "high": 0, "low": 0, "close": 0, "volume_quote": 0, "volume_base": 0, "trades": 0}
|
empty_dict = {
|
||||||
|
"exchange": "",
|
||||||
|
"timestamp": 0,
|
||||||
|
"open": 0,
|
||||||
|
"high": 0,
|
||||||
|
"low": 0,
|
||||||
|
"close": 0,
|
||||||
|
"volume_quote": 0,
|
||||||
|
"volume_base": 0,
|
||||||
|
"trades": 0,
|
||||||
|
}
|
||||||
empty_json = json.dumps(empty_dict)
|
empty_json = json.dumps(empty_dict)
|
||||||
|
|
||||||
|
|
||||||
|
def read_keys():
|
||||||
|
with open(KEYSFILE, "r") as cfile:
|
||||||
|
user_keys = json.load(cfile)
|
||||||
|
return user_keys["user_publickeys"]
|
||||||
|
|
||||||
|
|
||||||
def check_database():
|
def check_database():
|
||||||
"""
|
"""
|
||||||
Check the database for the 'ohlc' table.
|
Check the database for the 'ohlc' table.
|
||||||
@ -50,7 +63,8 @@ def check_database():
|
|||||||
"""
|
"""
|
||||||
if not os.path.exists(DATABASE):
|
if not os.path.exists(DATABASE):
|
||||||
new_db = sqlite3.connect(DATABASE)
|
new_db = sqlite3.connect(DATABASE)
|
||||||
new_db.execute("""\
|
new_db.execute(
|
||||||
|
"""\
|
||||||
CREATE TABLE ohlc (
|
CREATE TABLE ohlc (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
exchange TEXT NOT NULL,
|
exchange TEXT NOT NULL,
|
||||||
@ -61,7 +75,8 @@ def check_database():
|
|||||||
close REAL NOT NULL,
|
close REAL NOT NULL,
|
||||||
volume_quote REAL NOT NULL,
|
volume_quote REAL NOT NULL,
|
||||||
volume_base REAL NOT NULL,
|
volume_base REAL NOT NULL,
|
||||||
trades INTEGER NOT NULL )""")
|
trades INTEGER NOT NULL )"""
|
||||||
|
)
|
||||||
|
|
||||||
new_db.commit()
|
new_db.commit()
|
||||||
new_db.close()
|
new_db.close()
|
||||||
@ -76,7 +91,8 @@ def check_database():
|
|||||||
|
|
||||||
# Create the table if it doesn't exist
|
# Create the table if it doesn't exist
|
||||||
if not table_exists:
|
if not table_exists:
|
||||||
new_db.execute("""\
|
new_db.execute(
|
||||||
|
"""\
|
||||||
CREATE TABLE ohlc (
|
CREATE TABLE ohlc (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
exchange TEXT NOT NULL,
|
exchange TEXT NOT NULL,
|
||||||
@ -87,9 +103,11 @@ def check_database():
|
|||||||
close REAL NOT NULL,
|
close REAL NOT NULL,
|
||||||
volume_quote REAL NOT NULL,
|
volume_quote REAL NOT NULL,
|
||||||
volume_base REAL NOT NULL,
|
volume_base REAL NOT NULL,
|
||||||
trades INTEGER NOT NULL )""")
|
trades INTEGER NOT NULL )"""
|
||||||
|
)
|
||||||
new_db.commit()
|
new_db.commit()
|
||||||
|
|
||||||
|
|
||||||
def fetch_kraken():
|
def fetch_kraken():
|
||||||
"""
|
"""
|
||||||
Fetch BTCUSD OHLC data from Kraken in json.
|
Fetch BTCUSD OHLC data from Kraken in json.
|
||||||
@ -98,88 +116,89 @@ def fetch_kraken():
|
|||||||
"""
|
"""
|
||||||
kraken = krakenex.API()
|
kraken = krakenex.API()
|
||||||
|
|
||||||
response = kraken.query_public('OHLC', {'pair': 'BTCUSD', 'interval': 240 })
|
response = kraken.query_public("OHLC", {"pair": "BTCUSD", "interval": 240})
|
||||||
ohlc_data = response['result']['XXBTZUSD']
|
ohlc_data = response["result"]["XXBTZUSD"]
|
||||||
|
|
||||||
candle_stick_data = {
|
candle_stick_data = {
|
||||||
'exchange': 'kraken',
|
"exchange": "kraken",
|
||||||
'timestamp': ohlc_data[1][0],
|
"timestamp": ohlc_data[1][0],
|
||||||
'open': ohlc_data[0][1],
|
"open": ohlc_data[0][1],
|
||||||
'high': max(item[2] for item in ohlc_data),
|
"high": max(item[2] for item in ohlc_data),
|
||||||
'low': min(item[3] for item in ohlc_data),
|
"low": min(item[3] for item in ohlc_data),
|
||||||
'close': ohlc_data[-1][4],
|
"close": ohlc_data[-1][4],
|
||||||
'volume_quote': sum(float(item[5]) for item in ohlc_data),
|
"volume_quote": sum(float(item[5]) for item in ohlc_data),
|
||||||
'volume_base': sum(float(item[6]) for item in ohlc_data),
|
"volume_base": sum(float(item[6]) for item in ohlc_data),
|
||||||
'trades': sum(item[7] for item in ohlc_data),
|
"trades": sum(item[7] for item in ohlc_data),
|
||||||
}
|
}
|
||||||
|
|
||||||
kraken_json = json.dumps(candle_stick_data, indent=2)
|
kraken_json = json.dumps(candle_stick_data, indent=2)
|
||||||
#print("Kraken: OK")
|
|
||||||
#print(kraken_json)
|
|
||||||
return kraken_json
|
return kraken_json
|
||||||
|
|
||||||
|
|
||||||
def fetch_bitstamp():
|
def fetch_bitstamp():
|
||||||
"""
|
"""
|
||||||
Fetch Bitstamp data ja serve it as json.
|
Fetch Bitstamp data ja serve it as json.
|
||||||
Returns:
|
Returns:
|
||||||
str: 5min OHLC data in JSON format.
|
str: 5min OHLC data in JSON format.
|
||||||
"""
|
"""
|
||||||
response = requests.get("https://www.bitstamp.net/api/v2/ohlc/btcusd/?step=300&limit=1")
|
response = requests.get(
|
||||||
|
"https://www.bitstamp.net/api/v2/ohlc/btcusd/?step=300&limit=1"
|
||||||
|
)
|
||||||
|
|
||||||
if response.status_code == 200: # check if the request was successful
|
if response.status_code == 200: # check if the request was successful
|
||||||
bitstamp_data = response.json()
|
bitstamp_data = response.json()
|
||||||
ohlc_data = bitstamp_data["data"]["ohlc"]
|
ohlc_data = bitstamp_data["data"]["ohlc"]
|
||||||
|
|
||||||
candle_stick_data = {
|
candle_stick_data = {
|
||||||
'exchange': 'bitstamp',
|
"exchange": "bitstamp",
|
||||||
'timestamp': int(ohlc_data[0]['timestamp']),
|
"timestamp": int(ohlc_data[0]["timestamp"]),
|
||||||
'open': float(ohlc_data[0]['open']),
|
"open": float(ohlc_data[0]["open"]),
|
||||||
'high': float(ohlc_data[0]['high']),
|
"high": float(ohlc_data[0]["high"]),
|
||||||
'low': float(ohlc_data[0]['low']),
|
"low": float(ohlc_data[0]["low"]),
|
||||||
'close': float(ohlc_data[0]['close']),
|
"close": float(ohlc_data[0]["close"]),
|
||||||
'volume_quote': float(ohlc_data[0]['volume']),
|
"volume_quote": float(ohlc_data[0]["volume"]),
|
||||||
'volume_base': 0, # not provided by Bitstamp API
|
"volume_base": 0, # not provided by Bitstamp API
|
||||||
'trades': 0, # not provided by Bitstamp API
|
"trades": 0, # not provided by Bitstamp API
|
||||||
}
|
}
|
||||||
|
|
||||||
bitstamp_json = json.dumps(candle_stick_data, indent=2)
|
bitstamp_json = json.dumps(candle_stick_data, indent=2)
|
||||||
#print("Bitstamp: OK")
|
|
||||||
# print(bitstamp_json)
|
|
||||||
return bitstamp_json
|
return bitstamp_json
|
||||||
else:
|
# if we get any thing else than http/200
|
||||||
print(f"Error fetching data from Bitstamp API: {response.status_code}")
|
print(f"Error fetching data from Bitstamp API: {response.status_code}")
|
||||||
return empty_json
|
return empty_json
|
||||||
|
|
||||||
|
|
||||||
def fetch_bitfinex():
|
def fetch_bitfinex():
|
||||||
"""
|
"""
|
||||||
Bitfinex
|
Bitfinex
|
||||||
Returns:
|
Returns:
|
||||||
str: 5min OHLC data in JSON format.
|
str: 5min OHLC data in JSON format.
|
||||||
"""
|
"""
|
||||||
response = requests.get("https://api-pub.bitfinex.com/v2/candles/trade:5m:tBTCUSD/last")
|
response = requests.get(
|
||||||
|
"https://api-pub.bitfinex.com/v2/candles/trade:5m:tBTCUSD/last"
|
||||||
|
)
|
||||||
|
|
||||||
if response.status_code == 200: # check if the request was successful
|
if response.status_code == 200: # check if the request was successful
|
||||||
ohlc_data = response.json()
|
ohlc_data = response.json()
|
||||||
candle_stick_data = {
|
candle_stick_data = {
|
||||||
'exchange': 'bitfinex',
|
"exchange": "bitfinex",
|
||||||
'timestamp': ohlc_data[0],
|
"timestamp": ohlc_data[0],
|
||||||
'open': ohlc_data[1],
|
"open": ohlc_data[1],
|
||||||
'high': ohlc_data[2],
|
"high": ohlc_data[2],
|
||||||
'low': ohlc_data[3],
|
"low": ohlc_data[3],
|
||||||
'close': ohlc_data[4],
|
"close": ohlc_data[4],
|
||||||
'volume_quote': ohlc_data[5],
|
"volume_quote": ohlc_data[5],
|
||||||
'volume_base': 0, # not provided by Bitfinex API
|
"volume_base": 0, # not provided by Bitfinex API
|
||||||
'trades': 0, # not provided by Bitfinex API
|
"trades": 0, # not provided by Bitfinex API
|
||||||
}
|
}
|
||||||
|
|
||||||
bitfinex_json = json.dumps(candle_stick_data, indent=2)
|
bitfinex_json = json.dumps(candle_stick_data, indent=2)
|
||||||
#print("Bitfinex: OK")
|
|
||||||
#print(bitfinex_json)
|
|
||||||
return bitfinex_json
|
return bitfinex_json
|
||||||
else:
|
# if we get any thing else than http/200
|
||||||
print(f"Error fetching data from Bitfinex API: {response.status_code}")
|
print(f"Error fetching data from Bitfinex API: {response.status_code}")
|
||||||
return empty_json
|
return empty_json
|
||||||
|
|
||||||
|
|
||||||
def fetch_gemini():
|
def fetch_gemini():
|
||||||
"""
|
"""
|
||||||
Fetch BTCUSD OHLC data from Gemini
|
Fetch BTCUSD OHLC data from Gemini
|
||||||
@ -191,56 +210,58 @@ def fetch_gemini():
|
|||||||
if response.status_code == 200: # check if the request was successful
|
if response.status_code == 200: # check if the request was successful
|
||||||
gemini_ohlc = response.json()
|
gemini_ohlc = response.json()
|
||||||
candle_stick_data = {
|
candle_stick_data = {
|
||||||
'exchange': 'gemini',
|
"exchange": "gemini",
|
||||||
'timestamp': gemini_ohlc[0][0],
|
"timestamp": gemini_ohlc[0][0],
|
||||||
'open': gemini_ohlc[0][1],
|
"open": gemini_ohlc[0][1],
|
||||||
'high': gemini_ohlc[0][2],
|
"high": gemini_ohlc[0][2],
|
||||||
'low': gemini_ohlc[0][3],
|
"low": gemini_ohlc[0][3],
|
||||||
'close': gemini_ohlc[0][4],
|
"close": gemini_ohlc[0][4],
|
||||||
'volume_quote': 0, # not provided by Gemini API
|
"volume_quote": 0, # not provided by Gemini API
|
||||||
'volume_base': gemini_ohlc[0][5],
|
"volume_base": gemini_ohlc[0][5],
|
||||||
'trades': 0, # not provided by Gemini API
|
"trades": 0, # not provided by Gemini API
|
||||||
}
|
}
|
||||||
gemini_json = json.dumps(candle_stick_data, indent=2)
|
gemini_json = json.dumps(candle_stick_data, indent=2)
|
||||||
#print("Gemini: OK")
|
|
||||||
#print(gemini_json)
|
|
||||||
return gemini_json
|
return gemini_json
|
||||||
else:
|
# if we get any thing else than http/200
|
||||||
print(f"Error fetching data from Gemini API: {response.status_code}")
|
print(f"Error fetching data from Gemini API: {response.status_code}")
|
||||||
return empty_json
|
return empty_json
|
||||||
|
|
||||||
|
|
||||||
def fetch_bybit():
|
def fetch_bybit():
|
||||||
"""
|
"""
|
||||||
Fetch BTCUSD OHLC data from Bybit
|
Fetch BTCUSD OHLC data from Bybit
|
||||||
Returns:
|
Returns:
|
||||||
str: 5min OHLC data in JSON format.
|
str: 5min OHLC data in JSON format.
|
||||||
"""
|
"""
|
||||||
base_url = 'https://api.bybit.com/v2/public/kline/list?symbol=BTCUSD&interval=5&from='
|
base_url = (
|
||||||
|
"https://api.bybit.com/v2/public/kline/list?symbol=BTCUSD&interval=5&from="
|
||||||
|
)
|
||||||
current_unixtime = int(time.time())
|
current_unixtime = int(time.time())
|
||||||
last_minute = math.floor(current_unixtime / 60)
|
last_minute = math.floor(current_unixtime / 60)
|
||||||
last_minute_unixtime = str(last_minute * 60 - 300)
|
last_minute_unixtime = str(last_minute * 60 - 300)
|
||||||
query_url = ''.join([base_url, last_minute_unixtime])
|
query_url = "".join([base_url, last_minute_unixtime])
|
||||||
response = requests.get(query_url)
|
response = requests.get(query_url)
|
||||||
|
|
||||||
if response.status_code == 200: # check if the request was successful
|
if response.status_code == 200: # check if the request was successful
|
||||||
bybit_ohlc = response.json()
|
bybit_ohlc = response.json()
|
||||||
candle_stick_data = {
|
candle_stick_data = {
|
||||||
'exchange': 'bybit',
|
"exchange": "bybit",
|
||||||
'timestamp': bybit_ohlc['result'][0]['open_time'],
|
"timestamp": bybit_ohlc["result"][0]["open_time"],
|
||||||
'open': bybit_ohlc['result'][0]['open'],
|
"open": bybit_ohlc["result"][0]["open"],
|
||||||
'high': bybit_ohlc['result'][0]['high'],
|
"high": bybit_ohlc["result"][0]["high"],
|
||||||
'low': bybit_ohlc['result'][0]['low'],
|
"low": bybit_ohlc["result"][0]["low"],
|
||||||
'close': bybit_ohlc['result'][0]['close'],
|
"close": bybit_ohlc["result"][0]["close"],
|
||||||
'volume_quote': bybit_ohlc['result'][0]['volume'],
|
"volume_quote": bybit_ohlc["result"][0]["volume"],
|
||||||
'volume_base': bybit_ohlc['result'][0]['turnover'],
|
"volume_base": bybit_ohlc["result"][0]["turnover"],
|
||||||
'trades': 0
|
"trades": 0,
|
||||||
}
|
}
|
||||||
bybit_json = json.dumps(candle_stick_data, indent=2)
|
bybit_json = json.dumps(candle_stick_data, indent=2)
|
||||||
return bybit_json
|
return bybit_json
|
||||||
else:
|
# if we get any thing else than http/200
|
||||||
print(f"Error fetching data from Bybit API: {response.status_code}")
|
print(f"Error fetching data from Bybit API: {response.status_code}")
|
||||||
return empty_json
|
return empty_json
|
||||||
|
|
||||||
|
|
||||||
def write_dict_to_database(in_dict, connection):
|
def write_dict_to_database(in_dict, connection):
|
||||||
"""
|
"""
|
||||||
Writes given dict to given database.
|
Writes given dict to given database.
|
||||||
@ -251,20 +272,23 @@ def write_dict_to_database(in_dict, connection):
|
|||||||
# use placeholders for the values in the insert statement
|
# use placeholders for the values in the insert statement
|
||||||
insert_query = "insert into ohlc (exchange, timestamp, open, high, low, close, volume_quote, volume_base, trades) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
insert_query = "insert into ohlc (exchange, timestamp, open, high, low, close, volume_quote, volume_base, trades) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
|
|
||||||
values = (in_dict['exchange'],
|
values = (
|
||||||
in_dict['timestamp'],
|
in_dict["exchange"],
|
||||||
in_dict['open'],
|
in_dict["timestamp"],
|
||||||
in_dict['high'],
|
in_dict["open"],
|
||||||
in_dict['low'],
|
in_dict["high"],
|
||||||
in_dict['close'],
|
in_dict["low"],
|
||||||
in_dict['volume_quote'],
|
in_dict["close"],
|
||||||
in_dict['volume_base'],
|
in_dict["volume_quote"],
|
||||||
in_dict['trades'])
|
in_dict["volume_base"],
|
||||||
|
in_dict["trades"],
|
||||||
|
)
|
||||||
## apply lock while writing to database
|
## apply lock while writing to database
|
||||||
with database_lock:
|
with database_lock:
|
||||||
cursor.execute(insert_query, values)
|
cursor.execute(insert_query, values)
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
|
|
||||||
def get_the_data():
|
def get_the_data():
|
||||||
"""
|
"""
|
||||||
Creates infinite While True loop to fetch OHLC data and save it to database.
|
Creates infinite While True loop to fetch OHLC data and save it to database.
|
||||||
@ -280,6 +304,7 @@ def get_the_data():
|
|||||||
print("fetches done at", time.time(), "sleeping now for 290")
|
print("fetches done at", time.time(), "sleeping now for 290")
|
||||||
time.sleep(290)
|
time.sleep(290)
|
||||||
|
|
||||||
|
|
||||||
def check_auth(text, signature):
|
def check_auth(text, signature):
|
||||||
"""
|
"""
|
||||||
Check signatures against known public keys
|
Check signatures against known public keys
|
||||||
@ -294,80 +319,90 @@ def check_auth(text, signature):
|
|||||||
## Create bytes-object from the public in 'value' variable
|
## Create bytes-object from the public in 'value' variable
|
||||||
## and use it to create VerifyingKey (vk)
|
## and use it to create VerifyingKey (vk)
|
||||||
public_key_bytes = bytes.fromhex(value)
|
public_key_bytes = bytes.fromhex(value)
|
||||||
verifying_key = ecdsa.VerifyingKey.from_string(public_key_bytes, curve=ecdsa.SECP256k1)
|
verifying_key = ecdsa.VerifyingKey.from_string(
|
||||||
|
public_key_bytes, curve=ecdsa.SECP256k1
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
verifying_key.verify(sig_bytes, bytes(text, 'utf-8'))
|
verifying_key.verify(sig_bytes, bytes(text, "utf-8"))
|
||||||
print('user is', key)
|
print("user is", key)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except ecdsa.BadSignatureError:
|
except ecdsa.BadSignatureError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
|
@app.route("/")
|
||||||
def get_data():
|
def get_data():
|
||||||
"""
|
"""
|
||||||
Serve the data from the database. Limit the responses by given timestamp.
|
Serve the data from the database. Limit the responses by given timestamp.
|
||||||
The pretty thing is under consideration...
|
The pretty thing is under consideration...
|
||||||
"""
|
"""
|
||||||
# Get the time (t) argument from the url"
|
# Get the time (t) argument from the url"
|
||||||
query_timestamp = request.args.get('t')
|
query_timestamp = request.args.get("t")
|
||||||
# Should we make output pretty for curl users?
|
# Should we make output pretty for curl users?
|
||||||
query_pretty = request.args.get('pretty')
|
query_pretty = request.args.get("pretty")
|
||||||
|
|
||||||
# Authentication header, signatured the query with private key of a user
|
# Authentication header, signatured the query with private key of a user
|
||||||
signature = request.headers.get('auth')
|
signature = request.headers.get("auth")
|
||||||
get_url = request.url
|
get_url = request.url
|
||||||
if not check_auth(get_url, signature):
|
if not check_auth(get_url, signature):
|
||||||
return 'Access denied! Check your keys, maybe.', 403
|
return "Access denied! Check your keys, maybe.", 403
|
||||||
|
|
||||||
with database_lock:
|
with database_lock:
|
||||||
btc_db = sqlite3.connect(DATABASE)
|
btc_db = sqlite3.connect(DATABASE)
|
||||||
if query_timestamp:
|
if query_timestamp:
|
||||||
rows = btc_db.execute("SELECT exchange, timestamp, open, high, low, close FROM ohlc WHERE timestamp > ? ORDER BY timestamp", (query_timestamp,)).fetchall()
|
rows = btc_db.execute(
|
||||||
|
"SELECT exchange, timestamp, open, high, low, close FROM ohlc WHERE timestamp > ? ORDER BY timestamp",
|
||||||
|
(query_timestamp,),
|
||||||
|
).fetchall()
|
||||||
else:
|
else:
|
||||||
rows = btc_db.execute('SELECT exchange, timestamp, open, high, low, close FROM ohlc ORDER BY timestamp').fetchall()
|
rows = btc_db.execute(
|
||||||
|
"SELECT exchange, timestamp, open, high, low, close FROM ohlc ORDER BY timestamp"
|
||||||
|
).fetchall()
|
||||||
query_timestamp = 0
|
query_timestamp = 0
|
||||||
|
|
||||||
data = {
|
data = {"timestamp": time.time(), "rows": rows}
|
||||||
"timestamp": time.time(),
|
|
||||||
"rows": rows
|
|
||||||
}
|
|
||||||
|
|
||||||
# make sha256 checksum and append it to the data object
|
# make sha256 checksum and append it to the data object
|
||||||
data_shasum = sha256(json.dumps(data).encode('utf-8')).hexdigest()
|
data_shasum = sha256(json.dumps(data).encode("utf-8")).hexdigest()
|
||||||
updated_data = {"shasum": data_shasum}
|
updated_data = {"shasum": data_shasum}
|
||||||
updated_data.update(data)
|
updated_data.update(data)
|
||||||
data = updated_data
|
data = updated_data
|
||||||
|
|
||||||
# sign the response
|
# sign the response
|
||||||
signature = server_private_key.sign(json.dumps(data).encode('utf-8'))
|
signature = server_private_key.sign(json.dumps(data).encode("utf-8"))
|
||||||
signature_hex = binascii.hexlify(signature).decode('utf-8')
|
signature_hex = binascii.hexlify(signature).decode("utf-8")
|
||||||
data['signature'] = signature_hex
|
data["signature"] = signature_hex
|
||||||
|
|
||||||
if query_pretty:
|
if query_pretty:
|
||||||
response = json.dumps(data, indent=2, separators=(';\n', ' :'))
|
response = json.dumps(data, indent=2, separators=(";\n", " :"))
|
||||||
else:
|
else:
|
||||||
response = json.dumps(data)
|
response = json.dumps(data)
|
||||||
return response, 200, {'Content-Type': 'application/json'}
|
return response, 200, {"Content-Type": "application/json"}
|
||||||
|
|
||||||
@app.route('/serverkey')
|
|
||||||
|
@app.route("/serverkey")
|
||||||
def give_serverkey():
|
def give_serverkey():
|
||||||
"""
|
"""
|
||||||
Serve the public keys of this instace to the world.
|
Serve the public keys of this instace to the world.
|
||||||
"""
|
"""
|
||||||
## This endpoint also under Authentication?
|
## This endpoint also under Authentication?
|
||||||
signature = request.headers.get('auth')
|
signature = request.headers.get("auth")
|
||||||
get_url = request.url
|
get_url = request.url
|
||||||
if not check_auth(get_url, signature):
|
if not check_auth(get_url, signature):
|
||||||
return 'Access denied! Check your keys, maybe.', 403
|
return "Access denied! Check your keys, maybe.", 403
|
||||||
|
|
||||||
return jsonify({'public_key': server_public_key_hex})
|
return jsonify({"public_key": server_public_key_hex})
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
if __name__ == "__main__":
|
||||||
# Make sanity checks for the database
|
# Make sanity checks for the database
|
||||||
check_database()
|
check_database()
|
||||||
|
|
||||||
# Start the data fetching backend process
|
# Get the users public keys
|
||||||
|
user_publickeys = read_keys()
|
||||||
|
|
||||||
|
# Start the data fetching backend process§
|
||||||
fetch_thread = threading.Thread(target=get_the_data)
|
fetch_thread = threading.Thread(target=get_the_data)
|
||||||
fetch_thread.daemon = True
|
fetch_thread.daemon = True
|
||||||
fetch_thread.start()
|
fetch_thread.start()
|
||||||
|
5
btc_tracker/userkeys.json
Normal file
5
btc_tracker/userkeys.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"user_publickeys": {
|
||||||
|
"user1": "f1debc13fb21fe0eee54525aa4f8aae5733b201c755edaa55f8893c90aa375b261a62eaa3110651ac5d7705d402581256a37508b0a1ca28bd919ea44710d9c88"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user