Подпись API-запросов ECDSA для dYdX V4 на Python: Руководство

Подпись API-запросов ECDSA для dYdX V4 на Python: Руководство Python & API
Пошаговое руководство по реализации криптографической подписи ECDSA (Secp256k1) для API децентрализованной биржи dYdX V4 на Python.
Суть: В dYdX V4 аутентификация запросов к Indexer API выполняется с помощью криптографической подписи ECDSA на эллиптической кривой Secp256k1. Для этого формируется строка из таймстампа, метода, пути запроса и тела (body), которая хэшируется через SHA-256 и подписывается приватным ключом. Полученная подпись кодируется в Base64 и передается в HTTP-заголовках.

Исходный код

Для реализации подписи мы будем использовать стандартную библиотеку hashlib, модуль base64 и популярную библиотеку ecdsa для работы с кривой SECP256k1. Этот подход гарантирует высокую производительность, что критически важно при построении высокочастотных торговых систем.

Перед тем как перейти к коду подписи, отметим, что при проектировании торговых роботов важно учитывать не только безопасность запросов, но и транзакционные издержки. Подробнее об этом вы можете прочитать в нашей статье Расчет комиссий мейкера/тейкера (Fee Tiers) в CCXT Python.

import base64
import hashlib
import json
from datetime import datetime, timezone
import ecdsa

class DydxV4Signer:
    def __init__(self, private_key_hex: str):
        """
        Инициализация подписанта dYdX V4.
        :param private_key_hex: Приватный ключ в шестнадцатеричном формате (hex)
        """
        self.private_key_bytes = bytes.fromhex(private_key_hex)
        self.signing_key = ecdsa.SigningKey.from_string(
            self.private_key_bytes,
            curve=ecdsa.SECP256k1,
            hashfunc=hashlib.sha256
        )

    def generate_headers(self, method: str, request_path: str, body: str = "") -> dict:
        """
        Генерация заголовков аутентификации для Indexer API dYdX V4.
        """
        # dYdX V4 требует ISO 8601 таймстамп с миллисекундами и суффиксом Z
        timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z"
        
        # Формируем сообщение для подписи: timestamp + method + request_path + body
        message = f"{timestamp}{method.upper()}{request_path}{body}"
        message_bytes = message.encode("utf-8")
        
        # Подписываем SHA-256 хэш сообщения с использованием детерминированного ECDSA (RFC 6979)
        signature_bytes = self.signing_key.sign(
            message_bytes,
            hashfunc=hashlib.sha256,
            sigencode=ecdsa.util.sigencode_string_canonize
        )
        
        # Кодируем подпись в Base64
        signature_b64 = base64.b64encode(signature_bytes).decode("utf-8")
        
        return {
            "dydx-signature": signature_b64,
            "dydx-timestamp": timestamp,
            "Content-Type": "application/json"
        }

Разбор параметров

  • private_key_hex: Приватный ключ пользователя dYdX Chain в формате hex. Он используется для генерации объекта ecdsa.SigningKey на эллиптической кривой SECP256k1.
  • method: HTTP-метод запроса (например, GET, POST, DELETE). Метод обязательно приводится к верхнему регистру перед конкатенацией.
  • request_path: Относительный путь API-эндпоинта, включая параметры запроса (например, /v4/orders?limit=100).
  • body: Строковое представление тела запроса (JSON). Для GET-запросов или запросов без тела передается пустая строка.
  • sigencode_string_canonize: Функция сериализации подписи, которая гарантирует соответствие стандарту BIP-62 (низкое значение S), предотвращая пластичность подписи (signature malleability).

Как запустить

Для запуска скрипта вам потребуется установить библиотеку ecdsa и библиотеку requests для отправки HTTP-запросов. Выполните команду в терминале:

pip install ecdsa requests

После установки зависимостей вы можете использовать следующий пример для отправки авторизованного запроса к приватному эндпоинту dYdX V4 (например, получение информации о балансе аккаунта):

import requests

# Инициализируем подписант вашим приватным ключом (64 символа hex)
private_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
signer = DydxV4Signer(private_key)

# Параметры запроса
endpoint = "/v4/accounts/dydx1..."  # Укажите ваш dYdX адрес
base_url = "https://indexer.dydx.trade"

# Генерация заголовков
headers = signer.generate_headers(method="GET", request_path=endpoint)

# Отправка запроса
response = requests.get(f"{base_url}{endpoint}", headers=headers)
print(response.json())

Подобная архитектура безопасности является стандартом для децентрализованных бирж. Если вы планируете масштабировать свои торговые алгоритмы на другие площадки, рекомендуем ознакомиться с нашей статьей про Треугольный арбитраж на OKX: Python скрипт для Triangular Arbitrage, где также активно применяются механизмы быстрой подписи запросов.

Для работы с высокочастотными потоками данных (например, ликвидациями в реальном времени), стандартных HTTP-запросов может быть недостаточно. В таких случаях разработчики создают кастомные WebSocket-решения. Пример реализации такого подхода описан в статье Создание кастомного адаптера CCXT.Pro для парсинга ликвидаций Bitget.

Оцените статью
FinFluct