From 012fa0b301804cdf662541b3cead2ae9ec985cfa Mon Sep 17 00:00:00 2001 From: Carlos Wu Fei Date: Mon, 16 Oct 2023 05:11:16 +0100 Subject: [PATCH] Add websocket subscription symbols list --- api/research/controller.py | 49 +++++++++++++++++++++++- api/research/routes.py | 16 +++++++- api/research/schemas.py | 25 ++++++++++++ web/.env | 1 + web/src/pages/research/ControllerTab.jsx | 24 ++++++++++++ web/src/pages/research/Research.jsx | 9 ++++- web/src/pages/research/actions.js | 9 +++++ web/src/pages/research/saga.js | 1 + 8 files changed, 130 insertions(+), 4 deletions(-) diff --git a/api/research/controller.py b/api/research/controller.py index e03520c37..a85982940 100644 --- a/api/research/controller.py +++ b/api/research/controller.py @@ -1,11 +1,12 @@ from db import setup_db from datetime import datetime from time import sleep -from tools.handle_error import json_response, json_response_error +from tools.handle_error import json_response, json_response_error, json_response_message from pymongo.errors import DuplicateKeyError from apis import ThreeCommasApi from tools.round_numbers import round_numbers from pymongo import ASCENDING +from fastapi.encoders import jsonable_encoder class Controller: """ @@ -134,4 +135,50 @@ def get_3commas_signals(self): return json_response({"message": "Successfully retrieved profitable 3commas signals", "data": signals}) + """ + Get pairs that binbot-research signals are subscribed to + receive cryptodata + + To merge with blacklist + """ + def get_subscribed_symbols(self): + query_result = self.db.subscribed_symbols.find({}).sort("pair", ASCENDING) + all_symbols = list(query_result) + return json_response( + {"message": "Successfully retrieved blacklist", "data": all_symbols} + ) + + def delete_all_subscribed_symbols(self): + query_result = self.db.subscribed_symbols.delete_many({}) + + return json_response( + {"message": "Successfully deleted all symbols", "data": { + "total": 0 + }} + ) + def bulk_upsert_all(self, data): + symbols = jsonable_encoder(data) + self.db.subscribed_symbols.delete_many({}) + try: + query_result = self.db.subscribed_symbols.insert_many( + symbols, + ) + return json_response( + {"message": "Successfully created new susbcribed list", "data": { + "total": len(query_result.inserted_ids) + 1 + }} + ) + except Exception as error: + return json_response_error(f"Failed to update symbol in the subscribed list {error}") + + def edit_subscribed_symbol(self, symbol): + symbol = jsonable_encoder(symbol) + try: + self.db.subscribed_symbols.update_one( + symbol, + upsert=True, + ) + return json_response_message("Successfully update symbol in the subscribed list") + except Exception as error: + return json_response_error(f"Failed to update symbol in the subscribed list {error}") \ No newline at end of file diff --git a/api/research/routes.py b/api/research/routes.py index 2bf8269db..ec1b11948 100644 --- a/api/research/routes.py +++ b/api/research/routes.py @@ -2,7 +2,7 @@ from apis import ThreeCommasApi from research.controller import Controller -from research.schemas import BlacklistSchema, BlacklistResponse +from research.schemas import BlacklistSchema, BlacklistResponse, SubscribedSymbolsSchema research_blueprint = APIRouter() @@ -42,3 +42,17 @@ def get_blacklisted(): @research_blueprint.get("/3commas-presets", tags=["blacklist and research"]) def three_commas_presets(): return ThreeCommasApi().get_marketplace_presets() + + +@research_blueprint.get("/subscribed", tags=["blacklist and research"]) +def get_subscribed_symbols(): + return Controller().get_subscribed_symbols() + + +@research_blueprint.post("/subscribed", tags=["blacklist and research"]) +def create_subscribed_symbols(data: list[SubscribedSymbolsSchema]): + return Controller().bulk_upsert_all(data) + +@research_blueprint.put("/subscribed/{symbol}", tags=["blacklist and research"]) +def edit_subscribed_symbol(symbol: str): + return Controller().edit_subscribed_symbol(symbol) diff --git a/api/research/schemas.py b/api/research/schemas.py index bb603dc22..bc1428392 100644 --- a/api/research/schemas.py +++ b/api/research/schemas.py @@ -16,3 +16,28 @@ class Config: class BlacklistResponse(StandardResponse): data: list[BlacklistSchema] + + +""" +Database control for symbols that are used +in signals. +""" +class SubscribedSymbolsSchema(BaseModel): + _id: str + pair: str + blacklisted: bool = False + blacklisted_reason: str = "" + + class Config: + schema_extra = { + "example": { + "_id": "BNBBTC", + "pair": "BNBBTC", + "blacklisted": False, + "blacklisted_reason": "Overtraded" + } + } + + +class SubscribedSymbolsResponse(StandardResponse): + data: list[SubscribedSymbolsSchema] diff --git a/web/.env b/web/.env index d3ceaa627..190bda841 100644 --- a/web/.env +++ b/web/.env @@ -30,6 +30,7 @@ REACT_APP_TICKER=/account/ticker REACT_APP_TICKER_24="https://api.binance.com/api/v3/ticker/24hr" REACT_APP_RESEARCH_BLACKLIST=/research/blacklist REACT_APP_RESEARCH_CONTROLLER=/autotrade-settings/bots +REACT_APP_SUBSCRIBED="/research/subscribed" REACT_APP_NO_CANNIBALISM_SYMBOLS=/account/symbols/no-cannibal REACT_APP_BINANCE_INFO="https://api.binance.com/api/v3/exchangeInfo" REACT_APP_HEDGE_GBP=/account/hedge-gbp diff --git a/web/src/pages/research/ControllerTab.jsx b/web/src/pages/research/ControllerTab.jsx index 4663a418d..5da737534 100644 --- a/web/src/pages/research/ControllerTab.jsx +++ b/web/src/pages/research/ControllerTab.jsx @@ -21,6 +21,7 @@ export const ControllerTab = ({ addToBlacklist, removeFromBlacklist, triggerGbpHedge, + subscribedSymbols, }) => { const [addBlacklist, setAddBlacklist] = useImmer({ reason: "", pair: "" }); const [removeBlacklist, setRemoveBlacklist] = useState(""); @@ -124,6 +125,29 @@ export const ControllerTab = ({ {" "} +
+

Subscribed

+ + {subscribedSymbols && subscribedSymbols.length > 0 && ( + + + + + + {subscribedSymbols.map((x, i) => ( + + ))} + + + + )} + diff --git a/web/src/pages/research/Research.jsx b/web/src/pages/research/Research.jsx index 80505cdd8..855bf8d43 100644 --- a/web/src/pages/research/Research.jsx +++ b/web/src/pages/research/Research.jsx @@ -5,6 +5,7 @@ import { Nav, NavItem, NavLink, TabContent, TabPane } from "reactstrap"; import { addNotification, checkValue } from "../../validations"; import { loadCandlestick, getSymbols } from "../bots/actions"; import { getBalanceRaw } from "../../state/balances/actions"; +import { getSubscribedListApi } from "./actions"; import { getBlacklist, addBlackList, @@ -31,10 +32,12 @@ class Research extends React.Component { }; } - componentDidMount = () => { + componentDidMount = async () => { this.props.getBlacklist(); this.props.getSymbols(); this.props.getBalanceRaw(); + const subscribedList = await getSubscribedListApi(); + this.setState({ subscribedList: subscribedList.data }) }; componentDidUpdate = (p, s) => { @@ -105,6 +108,7 @@ class Research extends React.Component { { this.props.addBlackList(data); @@ -136,6 +140,7 @@ const mapStateToProps = (state) => { symbols: symbols, blacklistData: blacklistData, balance_raw: balanceRaw, + }; }; @@ -145,5 +150,5 @@ export default connect(mapStateToProps, { getBlacklist, addBlackList, deleteBlackList, - getBalanceRaw + getBalanceRaw, })(Research); diff --git a/web/src/pages/research/actions.js b/web/src/pages/research/actions.js index 08a19d648..3212ff08d 100644 --- a/web/src/pages/research/actions.js +++ b/web/src/pages/research/actions.js @@ -1,3 +1,4 @@ +import request from "../../request"; import { addNotification } from "../../validations"; export const GET_RESEARCH = "GET_RESEARCH"; @@ -129,3 +130,11 @@ export function deleteBlackListFailed() { type: DELETE_BLACKLIST_ERROR } } + +/** + * Websocket subscribed list of cryptos + */ +export async function getSubscribedListApi() { + const symbols = request(process.env.REACT_APP_SUBSCRIBED) + return symbols; +} diff --git a/web/src/pages/research/saga.js b/web/src/pages/research/saga.js index 733d0410c..e98d1ad4c 100644 --- a/web/src/pages/research/saga.js +++ b/web/src/pages/research/saga.js @@ -101,3 +101,4 @@ export function* deleteBlacklistApi({ pair }) { export function* watchDeleteBlackListApi() { yield takeLatest(DELETE_BLACKLIST, deleteBlacklistApi); } +