DCAv2Earn/main.py

487 lines
20 KiB
Python

import libraries.balance_accounts as balance_accounts
from libraries.wrappers import earn_binance
from libraries.wrappers import earn_kucoin
from libraries.wrappers import earn_okx
from libraries.wrappers import earn_gateio
from libraries.earner import earner
from libraries.colors import colors
from threading import Thread
from flask import Flask, jsonify, request
from waitress import serve
import time
import datetime
import json
import sqlite3
import socket
def load_keys_from_db(file_name: str) -> list:
'''
Load valid API keys
Parameters
----------
file_name : str
Name of the database file
Returns
-------
valid_keys : list
List of valid API keys
'''
database_connection = sqlite3.connect(file_name)
database_cursor = database_connection.cursor()
database_cursor.execute("SELECT * FROM credentials_table")
data = database_cursor.fetchall()
database_connection.close()
valid_keys = [line[1] for line in data]
return valid_keys
def seconds_to_time(total_seconds: float) -> str:
'''
Takes an int or float as an input and it returns a D:HH:MM:SS formatted string.
Parameters:
total_seconds (float): The number of seconds to convert
Returns:
str: The formatted string
'''
time_delta = datetime.timedelta(seconds=total_seconds)
hours = time_delta.seconds//3600
remainder = time_delta.seconds%3600
minutes = remainder//60
seconds = remainder%60
return f"{time_delta.days}:{hours:02d}:{minutes:02d}:{seconds:02d}"
def main():
while True:
threads = []
#Run earners
for item in earners:
threads.append(Thread(target=item.run))
for item in threads:
item.start()
for item in threads:
item.join()
#Print status
subscriptions = []
redemptions = []
for item in earners:
print(item.get_status_string())
subscriptions.append(item.get_last_subscription())
redemptions.append(item.get_last_redemption())
last_subscription = max(subscriptions, key=lambda d: next(iter(d.values())))
last_subscription_key = next(iter(last_subscription.keys()))
last_subscription_value = next(iter(last_subscription.values()))
if last_subscription_value == 0:
last_subscription_key = "Never"
last_subscription_value = ""
else:
last_subscription_value = datetime.datetime.fromtimestamp(last_subscription_value).strftime('@%Y/%m/%d %H:%M:%S')
last_redemption = max(redemptions, key=lambda d: next(iter(d.values())))
last_redemption_key = next(iter(last_redemption.keys()))
last_redemption_value = next(iter(last_redemption.values()))
if last_redemption_value == 0:
last_redemption_key = "Never"
last_redemption_value = ""
else:
last_redemption_value = datetime.datetime.fromtimestamp(last_redemption_value).strftime('@%Y/%m/%d %H:%M:%S')
print("-"*80)
total_on_trading = sum([item.get_trading_balance() for item in earners])
total_on_earning = sum([item.get_earning_balance() for item in earners])
total_funds = total_on_earning+total_on_trading
time_of_day = datetime.datetime.now().strftime('[%Y/%m/%d %H:%M:%S]')
print(f"Last subscription: {last_subscription_key}{last_subscription_value} | Last redemption: {last_redemption_key}{last_redemption_value}")
print(f"Version {version} | Total funds: {total_funds:.2f} USDT | On earn: {total_on_earning:.2f} USDT ({total_on_earning/total_funds*100:.2f}%)")
print(f"{time_of_day} | Uptime: {seconds_to_time(time.time()-start_time)}")
print(colors.blue+"="*80+colors.white)
#Wait for next lap
time.sleep(config["lap_time"])
#########################
######### API ###########
#########################
earn_api = Flask(__name__)
@earn_api.route("/toggle_pause", methods=['POST'])
def toggle_pause():
'''
GET request
Parameters:
broker: str
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
item.toggle_pause()
return jsonify({'Status': item.get_is_paused()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_step_size", methods=["GET"])
def get_step_size():
'''
GET request
Parameters:
broker: str
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'step_size': item.get_step_size()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/set_step_size", methods=["POST"])
def set_step_size():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
new_step_size = request.json["new_step_size"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if new_step_size is None:
return jsonify({'Error': 'new_step_size is None'})
for item in earners:
if str(item.connector)==broker:
item.set_step_size(new_step_size)
return jsonify({'step_size': new_step_size})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_percentage", methods=["GET"])
def get_percentage():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'percentage': item.get_percentage()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/set_percentage", methods=["POST"])
def set_percentage():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
new_percentage = request.json["new_percentage"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if new_percentage is None:
return jsonify({'Error': 'new_step_size is None'})
for item in earners:
if str(item.connector)==broker:
item.set_percentage(new_percentage)
return jsonify({'percentage': new_percentage})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_time_between_subscriptions", methods=["GET"])
def get_time_between_subscriptions():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'time_between_subscriptions': item.get_time_between_subscriptions()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/set_time_between_subscriptions", methods=["POST"])
def set_time_between_subscriptions():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
new_time_between_subscriptions = request.json["new_time_between_subscriptions"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if new_time_between_subscriptions is None:
return jsonify({'Error': 'new_step_size is None'})
for item in earners:
if str(item.connector)==broker:
item.set_time_between_subscriptions(new_time_between_subscriptions)
return jsonify({'percentage': new_time_between_subscriptions})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_time_between_redemptions", methods=["GET"])
def get_time_between_redemptions():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'time_between_redemptions': item.get_time_between_redemptions()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/set_time_between_redemptions", methods=["POST"])
def set_time_between_redemptions():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
new_time_between_redemptions = request.json["new_time_between_redemptions"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if new_time_between_redemptions is None:
return jsonify({'Error': 'new_step_size is None'})
for item in earners:
if str(item.connector)==broker:
item.set_time_between_redemptions(new_time_between_redemptions)
return jsonify({'percentage': new_time_between_redemptions})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_minimum_amount_in_trading_account", methods=["GET"])
def get_minimum_amount_in_trading_account():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'minimum_amount_in_trading_account': item.get_minimum_amount_in_trading_account()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/set_minimum_amount_in_trading_account", methods=["POST"])
def set_minimum_amount_in_trading_account():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.json["broker"]
new_minimum_amount_in_trading_account = request.json["new_minimum_amount_in_trading_account"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if new_minimum_amount_in_trading_account is None:
return jsonify({'Error': 'new_step_size is None'})
for item in earners:
if str(item.connector)==broker:
item.set_minimum_amount_in_trading_account(new_minimum_amount_in_trading_account)
return jsonify({'percentage': new_minimum_amount_in_trading_account})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_last_subscription", methods=["GET"])
def get_last_subscription():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'last_subscription': item.get_last_subscription()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_last_redemption", methods=["GET"])
def get_last_redemption():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'last_redemption': item.get_last_redemption()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/get_total_balance", methods=["GET"])
def get_total_balance():
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
broker = request.args.get("broker")
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
for item in earners:
if str(item.connector)==broker:
return jsonify({'trading_balance': item.get_trading_balance(), 'earning_balance': item.get_earning_balance()})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/subscribe", methods=["POST"])
def subscribe():
'''
args:
broker: broker name
force_pause: True or False
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
amount = request.json["amount"]
force_pause = request.json["force_pause"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if amount is None:
return jsonify({'Error': 'amount is None'})
if force_pause is None:
return jsonify({'Error': 'force_pause is None'})
for item in earners:
if str(item.connector)==broker:
subscription = item.subscribe(amount, force_pause=force_pause)
return jsonify({'Success': str(subscription)})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
@earn_api.route("/redeem", methods=["POST"])
def redeem():
'''
args:
broker: broker name
force_pause: True or False
'''
if "X-API-KEY" in request.headers and request.headers.get("X-API-KEY") in valid_keys:
valid_brokers = [str(item.connector) for item in earners]
if request.json is None:
return jsonify({'Error': 'request.json is None'})
broker = request.json["broker"]
amount = request.json["amount"]
force_pause = request.json["force_pause"]
if broker is None:
return jsonify({'Error': 'broker is None'})
if broker not in valid_brokers:
return jsonify({'Error': 'broker not valid'})
if amount is None:
return jsonify({'Error': 'amount is None'})
if force_pause is None:
return jsonify({'Error': 'force_pause is None'})
for item in earners:
if str(item.connector)==broker:
subscription = item.redeem(amount, force_pause=force_pause)
return jsonify({'Success': str(subscription)})
return jsonify({'Error': 'broker not found'})
return jsonify({'Error': 'API key not valid'}), 401
def run_API(port):
serve(earn_api, host="0.0.0.0", port=port)
#earn_api.run(host="0.0.0.0", port=port)
if __name__=="__main__":
version = "2025.01.09"
start_time = time.time()
with open("config.json") as f:
config = json.load(f)
connectors = {"binance": earn_binance.binance_earn(),
"gateio": earn_gateio.gateio_earn(),
"kucoin": earn_kucoin.kucoin_earn(),
"okx": earn_okx.okx_earn()}
earners = []
for item in config["exchanges"]:
earners.append(earner(connectors[item], config["exchanges"][item]))
#Load valid API keys
valid_keys = load_keys_from_db("keys/api_credentials.db")
#Threads to run: main loop and flask api
main_threads = [Thread(target=main),Thread(target=run_API, args=(config["api_port"],))]
#Iterate indefinitely:
for m in main_threads:
m.start()