diff --git a/app/src/core/config.py b/app/src/core/config.py index ecba6c7..d0a9964 100644 --- a/app/src/core/config.py +++ b/app/src/core/config.py @@ -40,7 +40,7 @@ def load_settings() -> Settings: bot_parse_mode=os.getenv("BOT_PARSE_MODE", "HTML").strip() or "HTML", app_env=os.getenv("APP_ENV", "dev").strip() or "dev", log_level=os.getenv("LOG_LEVEL", "INFO").strip().upper() or "INFO", - tz=os.getenv("TZ", "Europe/Madrid").strip() or "Europe/Madrid", + tz=os.getenv("TZ", "Europe/Minsk").strip() or "Europe/Minsk", exchange_enabled=_parse_bool(os.getenv("EXCHANGE_ENABLED", "false")), exchange_name=os.getenv("EXCHANGE_NAME", "dzengi").strip() or "dzengi", exchange_base_url=os.getenv("EXCHANGE_BASE_URL", "").strip(), diff --git a/app/src/integrations/exchange/auth.py b/app/src/integrations/exchange/auth.py new file mode 100644 index 0000000..a0a8efa --- /dev/null +++ b/app/src/integrations/exchange/auth.py @@ -0,0 +1,25 @@ + +import hmac +import hashlib +import time + + +class ExchangeAuth: + def __init__(self, api_key: str, api_secret: str): + self.api_key = api_key + self.api_secret = api_secret.encode() + + def sign(self, query: str) -> str: + return hmac.new(self.api_secret, query.encode(), hashlib.sha256).hexdigest() + + def build_headers(self): + return { + "X-MBX-APIKEY": self.api_key, + } + + def build_signed_params(self, params: dict): + params["timestamp"] = int(time.time() * 1000) + query = "&".join(f"{k}={v}" for k, v in params.items()) + signature = self.sign(query) + params["signature"] = signature + return params diff --git a/app/src/integrations/exchange/private_client.py b/app/src/integrations/exchange/private_client.py new file mode 100644 index 0000000..adc7982 --- /dev/null +++ b/app/src/integrations/exchange/private_client.py @@ -0,0 +1,24 @@ + +from src.core.config import load_settings +from src.integrations.exchange.rest_client import ExchangeRestClient +from src.integrations.exchange.auth import ExchangeAuth + + +class ExchangePrivateClient: + def __init__(self): + settings = load_settings() + self.client = ExchangeRestClient() + self.auth = ExchangeAuth( + api_key=settings.exchange_api_key, + api_secret=settings.exchange_api_secret, + ) + + def get_account_info(self): + params = {} + signed = self.auth.build_signed_params(params) + + return self.client.get_json( + "/api/v2/account", + params=signed, + headers=self.auth.build_headers(), + ) diff --git a/docs/stages/stage-03-4-auth.md b/docs/stages/stage-03-4-auth.md new file mode 100644 index 0000000..a109547 --- /dev/null +++ b/docs/stages/stage-03-4-auth.md @@ -0,0 +1,10 @@ + +# Stage 03.4 — Auth + +## Что реализовано +- HMAC подпись +- headers +- private client + +## Дальше +Stage 03.5 — account + balances