Files
siloqy/prod/bingx/signing.py

49 lines
1.3 KiB
Python
Raw Normal View History

from __future__ import annotations
import hashlib
import hmac
import time
from collections.abc import Mapping
from urllib.parse import urlencode
def utc_timestamp_ms() -> int:
return int(time.time() * 1000)
def canonical_query(params: Mapping[str, object]) -> str:
filtered = {
key: value
for key, value in params.items()
if value is not None and value != ""
}
ordered = sorted(filtered.items(), key=lambda item: item[0])
return urlencode(ordered, doseq=True)
def sign_query(secret_key: str, query: str) -> str:
return hmac.new(
secret_key.encode("utf-8"),
query.encode("utf-8"),
hashlib.sha256,
).hexdigest()
def build_signed_params(
params: Mapping[str, object],
secret_key: str,
*,
timestamp_ms: int | None = None,
recv_window_ms: int | None = 5_000,
) -> dict[str, object]:
signed = dict(params)
signed["timestamp"] = utc_timestamp_ms() if timestamp_ms is None else int(timestamp_ms)
try:
parsed_recv_window = int(recv_window_ms) if recv_window_ms is not None else 5_000
except Exception:
parsed_recv_window = 5_000
signed["recvWindow"] = parsed_recv_window if parsed_recv_window > 0 else 5_000
query = canonical_query(signed)
signed["signature"] = sign_query(secret_key, query)
return signed