11from __future__ import annotations
2- from typing import List, Optional
2+ from typing import List, Optional, Union, Dict
33
44import os
55from pathlib import Path
66import json
77from enum import Enum
8- from typing import Union
98
109from pydantic import BaseModel, HttpUrl, ValidationError, validator, DirectoryPath
1110
1716class Exchanges(Enum):
1817 BYBIT = "bybit"
1918
20-
2119class Messengers(Enum):
2220 DISCORD = "discord"
2321 TELEGRAM = "telegram"
2422
25-
2623class API(BaseModel):
2724 filename: str = "quantdatav2.json"
2825 mode: str = "remote"
@@ -36,7 +33,6 @@ class Hotkeys(BaseModel):
3633 enter_short: str = "3"
3734 take_profit_short: str = "4"
3835
39-
4036class Bot(BaseModel):
4137 bot_name: str
4238 volume_check: bool = True
@@ -75,10 +71,8 @@ class Bot(BaseModel):
7571 whitelist: List[str] = []
7672 dashboard_enabled: bool = False
7773 shared_data_path: Optional[str] = None
78- #risk_management: Optional[dict] = None
7974 linear_grid: Optional[dict] = None
8075 hotkeys: Hotkeys
81- # shared_data_path: Optional[DirectoryPath] = None
8276
8377 @validator('hotkeys')
8478 def validate_hotkeys(cls, value):
@@ -211,13 +205,13 @@ def check_volume_check_is_bool(cls, v):
211205 if not isinstance(v, bool):
212206 raise ValueError("volume_check must be a boolean")
213207 return v
214-
208+
215209class Exchange(BaseModel):
216210 name: str
217211 account_name: str
218212 api_key: str
219213 api_secret: str
220- passphrase: str = None
214+ passphrase: Optional[ str] = None
221215 symbols_allowed: int = 12
222216
223217class Logger(BaseModel):
@@ -251,13 +245,12 @@ class Telegram(BaseModel):
251245 bot_token: str
252246 chat_id: str
253247
254-
255248class Config(BaseModel):
256249 api: API
257250 bot: Bot
258- exchanges: List[Exchange] # <-- Changed from List[Exchange]
251+ exchanges: List[Exchange]
259252 logger: Logger
260- messengers: dict [str, Union[Discord, Telegram]]
253+ messengers: Dict [str, Union[Discord, Telegram]]
261254
262255def resolve_shared_data_path(relative_path: str) -> Path:
263256 # Get the directory of the config file
@@ -271,47 +264,26 @@ def resolve_shared_data_path(relative_path: str) -> Path:
271264
272265 return absolute_path
273266
274- def load_config(path):
275- if not path.is_file():
276- raise ValueError(f"{path} does not exist")
277- else:
278- with open(path) as f:
279- try:
280- data = json.load(f)
281- except json.JSONDecodeError as exc:
282- raise ValueError(
283- f"ERROR: Invalid JSON: {exc.msg}, line {exc.lineno}, column {exc.colno}"
284- )
285- try:
286- config_data = Config(**data)
287-
288- # Resolve shared_data_path if it's provided
289- if config_data.bot.shared_data_path:
290- config_data.bot.shared_data_path = str(resolve_shared_data_path(config_data.bot.shared_data_path))
291-
292- return config_data
293- except ValidationError as e:
294- # Enhanced error output
295- error_details = "\n".join([f"{err['loc']} - {err['msg']}" for err in e.errors()])
296- raise ValueError(f"Configuration Error(s):\n{error_details}")
297-
298- # def load_config(path):
299- # if not path.is_file():
300- # raise ValueError(f"{path} does not exist")
301- # else:
302- # f = open(path)
303- # try:
304- # data = json.load(f)
305- # except json.JSONDecodeError as exc:
306- # raise ValueError(
307- # f"ERROR: Invalid JSON: {exc.msg}, line {exc.lineno}, column {exc.colno}"
308- # )
309- # try:
310- # return Config(**data)
311- # except ValidationError as e:
312- # # Enhancing the error output for better clarity
313- # error_details = "\n".join([f"{err['loc']} - {err['msg']}" for err in e.errors()])
314- # raise ValueError(f"Configuration Error(s):\n{error_details}")
267+ def load_json(file_path: Path) -> dict:
268+ with open(file_path, 'r') as file:
269+ return json.load(file)
270+
271+ def load_config(config_path: Path, account_path: Path) -> Config:
272+ config_data = load_json(config_path)
273+ account_data = load_json(account_path)
274+
275+ # Merge account data into config data
276+ for exchange in config_data['exchanges']:
277+ for account in account_data['exchanges']:
278+ if exchange['name'] == account['name'] and exchange['account_name'] == account['account_name']:
279+ exchange.update({
280+ 'api_key': account['api_key'],
281+ 'api_secret': account['api_secret'],
282+ 'passphrase': account.get('passphrase', None)
283+ })
284+ break
285+
286+ return Config(**config_data)
315287
316288def get_exchange_name(cli_exchange_name):
317289 if cli_exchange_name:
@@ -344,70 +316,3 @@ def get_exchange_credentials(exchange_name, account_name):
344316 return api_key, secret_key, passphrase, symbols_allowed
345317 else:
346318 raise ValueError(f"Account {account_name} for exchange {exchange_name} not found in the config file.")
347-
348- # def get_exchange_credentials(exchange_name, account_name):
349- # with open('config.json') as file:
350- # data = json.load(file)
351- # exchange_data = None
352- # for exchange in data['exchanges']:
353- # if exchange['name'] == exchange_name and exchange['account_name'] == account_name:
354- # exchange_data = exchange
355- # break
356- # if exchange_data:
357- # api_key = exchange_data['api_key']
358- # secret_key = exchange_data['api_secret']
359- # passphrase = exchange_data.get('passphrase')
360- # symbols_allowed = exchange_data.get('symbols_allowed', 12) # Default to 12 if not specified
361- # return api_key, secret_key, passphrase, symbols_allowed
362- # else:
363- # raise ValueError(f"Account {account_name} for exchange {exchange_name} not found in the config file.")
364-
365- # def get_exchange_credentials(exchange_name, account_name):
366- # with open('config.json') as file:
367- # data = json.load(file)
368- # exchange_data = None
369- # for exchange in data['exchanges']:
370- # if exchange['name'] == exchange_name and exchange['account_name'] == account_name:
371- # exchange_data = exchange
372- # break
373- # if exchange_data:
374- # api_key = exchange_data['api_key']
375- # secret_key = exchange_data['api_secret']
376- # passphrase = exchange_data.get('passphrase') # Not all exchanges require a passphrase
377- # return api_key, secret_key, passphrase
378- # else:
379- # raise ValueError(f"Account {account_name} for exchange {exchange_name} not found in the config file.")
380-
381- # def get_exchange_credentials(exchange_name):
382- # with open('config.json') as file:
383- # data = json.load(file)
384- # exchange_data = None
385- # for exchange in data['exchanges']:
386- # if exchange['name'] == exchange_name:
387- # exchange_data = exchange
388- # break
389- # if exchange_data:
390- # api_key = exchange_data['api_key']
391- # secret_key = exchange_data['api_secret']
392- # passphrase = exchange_data.get('passphrase') # Not all exchanges require a passphrase
393- # return api_key, secret_key, passphrase
394- # else:
395- # raise ValueError(f"Exchange {exchange_name} not found in the config file.")
396-
397-
398- # def get_exchange_name(cli_exchange_name):
399- # if cli_exchange_name:
400- # return cli_exchange_name
401- # else:
402- # with open('config.json') as file:
403- # data = json.load(file)
404- # return data['exchange']
405-
406- # def get_exchange_credentials(exchange_name):
407- # with open('config.json') as file:
408- # data = json.load(file)
409- # exchange_data = data['exchanges'][exchange_name]
410- # api_key = exchange_data['api_key']
411- # secret_key = exchange_data['secret_key']
412- # passphrase = exchange_data.get('passphrase') # Not all exchanges require a passphrase
413- # return api_key, secret_key, passphrase
0 commit comments