Эта страница переведена автоматически. Оригинал на английском языке является каноническим. Читать на английском
Перейти к основному содержимому

Авторизация агентов

Поддержка подписи несколькими ключами для маркетмейкеров.

Обзор

Авторизация агента позволяет выделенному ключу подписи (агенту) размещать и отменять ордера от имени торгового кошелька. Это полезно для:

  • Безопасности: храните ключи торгового кошелька в холодном хранилище, а для подписи используйте горячие ключи
  • Операционной работы: несколько участников команды могут подписывать разными ключами
  • Автоматизации: автоматизированные системы могут подписывать выделенными ключами

Две модели авторизации

В Hypercall есть две отдельные системы делегирования в зависимости от продукта:

ПродуктТип делегированияХранениеКак настроить
Опционы (REST API)Авторизация агентаОфчейн (база данных)POST /approve-agent
Перпы (ончейн-директивы)API-кошелёкОнчейн (контракт Exchange)Директива hc_update_api_wallet

Это независимые системы. Одобрение агента для торговли опционами не даёт ему прав на перпы, и наоборот.

Опционы: авторизация агента (офчейн)

Агенты подписывают EIP-712-сообщения PlaceOrder и CancelOrder от имени торгового кошелька. API-сервер проверяет авторизацию по своей базе данных перед передачей в движок.

Перпы: API-кошелёк (ончейн)

API-кошельки подписывают директивы для перпов, используя EIP-712-домен HypercallAgentSign. Контракт Exchange проверяет авторизацию ончейн через isApiWalletActive(). Полный справочник по подписи директив см. в разделе Подпись EIP-712.

Чтобы добавить или удалить API-кошелёк, отправьте директиву hc_update_api_wallet, подписанную управляющим кошельком аккаунта.

Это повторяет модель API-кошельков Hyperliquid. Hyperliquid описывает их как API-кошельки, также называемые агентскими кошельками, в разделе Nonces and API wallets, а approveAgent документирован в разделе Exchange endpoint.

Защита от повторного использования nonce

Отслеживание nonce следует модели nonce Hyperliquid. Все подписанные действия (ордера, одобрение/отзыв агента, QP-хендшейки) используют общее пространство nonce на каждого подписанта. Движок хранит 100 наибольших nonce для каждого адреса подписанта. Новый nonce принимается, если:

  1. nonce > min(stored_set) — должен быть больше наименьшего хранимого nonce
  2. !stored_set.contains(nonce) — не должен быть дубликатом
  3. nonce находится в пределах (T - 2 дня, T + 1 день) от временной метки сервера

Nonce вне порядка допустимы (например, nonce 105, затем 102 — оба сработают, если оба выше минимума набора). Набор ограничен 100 записями, поэтому по мере добавления новых старейшие записи вытесняются. Это исключает блокировку аккаунта из-за одного слишком большого nonce.

Подписант nonce — это адрес, подписавший EIP-712-сообщение: API-кошелёк для ордеров, восстановленный подписант для авторизации агента, QP-кошелёк для хендшейков. Клиентам следует использовать Date.now() (миллисекунды эпохи) в качестве начального значения nonce и монотонно его увеличивать.

Авторизация агентов для опционов

Прямая подпись

Если signer == wallet, ордер всегда авторизован (самоподпись).

Подпись агентом

Если signer != wallet, подписант должен быть авторизованным агентом:

  • Агент должен присутствовать в состоянии авторизации, принадлежащем движку
  • Авторизация не должна быть просроченной
  • Снепшоты движка и журнал движка — надёжные источники при перезапуске

Одобрение агента

Эндпоинт: POST /approve-agent

Запрос: ApproveAgentRequest

{
"agent": "0x...",
"nonce": 1,
"signature": "0x..."
}

Подпись:

  • Владелец кошелька подписывает сообщение ApproveAgent
  • Кошелёк определяется из восстановленной подписи
  • Агент — это поле agent в запросе

Структура EIP-712:

struct ApproveAgent {
address agent;
uint64 nonce;
}

Ответ: ApproveAgentResponse

{
"success": true,
"error": null
}

Примечания:

  • Авторизация агента постоянна (хранится в БД)
  • Авторизация не истекает, если не задано expires_at (пока не реализовано)

Отзыв агента

Эндпоинт: DELETE /revoke-agent

Запрос: RevokeAgentRequest

{
"agent": "0x...",
"nonce": 2,
"signature": "0x..."
}

Подпись:

  • Владелец кошелька подписывает сообщение RevokeAgent
  • Кошелёк определяется из восстановленной подписи

Структура EIP-712:

struct RevokeAgent {
address agent;
uint64 nonce;
}

Ответ: RevokeAgentResponse

Примечания:

  • Применяет журналируемую команду RevokeAgent к состоянию авторизации, принадлежащему движку
  • Проверки авторизации торгового API читают состояние бэкенда и применяют отзывы для торговых запросов. Публикация в троллбоксе может кэшировать положительную авторизацию агента дольше, поэтому недавно отозванный агент может по-прежнему публиковать сообщения, пока кэш не истечёт или инвалидация по мере возможности не дойдёт до соответствующей edge-локации. Этот кэш не даёт прав на мутации торгового API.
  • После отзыва агент больше не может подписывать за кошелёк

Получение списка авторизованных агентов

Эндпоинт: GET /authorized-agents?wallet=...

Параметры запроса:

  • wallet (обязательный)

Ответ:

{
"agents": [
"0x...",
"0x..."
]
}

Примечания:

  • Возвращает только активных агентов с непросроченной авторизацией
  • Сортировка по created_at DESC

Использование агентов

Подпись ордеров агентом

После одобрения агента:

  1. Подпишите ордер кошельком агента: используйте кошелёк агента для подписи сообщений PlaceOrder / CancelOrder
  2. Заполните поле wallet: укажите в поле wallet адрес торгового кошелька (не адрес агента)
  3. Проверка в middleware: middleware проверяет, что агент авторизован для этого кошелька

Пример:

// Agent wallet signs the order
const agentSigner = new ethers.Wallet(agentPrivateKey);

const message = {
wallet: "0x...", // Trading wallet (not agent)
symbol: "BTC-20250131-100000-C",
side: "Buy",
size: "0.1",
price: "100.0",
tif: "gtc",
clientId: "mm-1",
nonce: 1
};

// Sign with agent wallet
const signature = await agentSigner._signTypedData(domain, types, message);

// Send request
const response = await fetch('/order', {
method: 'POST',
body: JSON.stringify({
...message,
signature
})
});

Пакетные ордера с агентом

Пакетные эндпоинты проверяют авторизацию агента для каждого элемента:

  • Каждый ордер в POST /bulk_order может быть подписан разным агентом
  • Авторизация агента проверяется для каждого элемента
  • Если у какого-либо элемента проверка авторизации агента не проходит, этот элемент возвращает ошибку в BulkOrderResult

Проверки авторизации

Middleware (одиночные ордера)

Эндпоинты:

  • POST /order
  • DELETE /order
  • DELETE /order_cloid

Проверка: signature_and_agent_middleware проверяет:

  1. Восстановление подписи успешно
  2. Подписант авторизован (signer == wallet ИЛИ агент авторизован)

Обработчик (пакетные ордера)

Эндпоинты:

  • POST /bulk_order
  • DELETE /bulk_order
  • DELETE /bulk_order_cloid

Проверка: поэлементная проверка в обработчике:

  1. Восстановление подписи для каждого элемента
  2. Проверка авторизации агента для каждого элемента

Хранение авторизации

Авторизация агентов — это состояние, принадлежащее движку. Команды ApproveAgent и RevokeAgent журналируются, восстанавливаются через воспроизведение журнала движка и доступны через снепшот чтения для проверок API.

Логика авторизации

Авторизация подписанта — это явная логика ИЛИ:

  • Прямая подпись: signer == wallet.
  • Подпись агентом: снепшот движка содержит запись авторизации для wallet_address == <wallet> и agent_address == <signer>, а expires_at отсутствует или находится в будущем.

Истечение срока

expires_at контролируется проверками авторизации по снепшоту движка. Агенты с expires_at < NOW() считаются неавторизованными.

Вопросы безопасности

  1. Безопасность ключей агента: защищайте приватные ключи агентов (используйте аппаратные кошельки или безопасное управление ключами)
  2. Регулярные аудиты: регулярно проверяйте список авторизованных агентов через GET /authorized-agents
  3. Отзывайте неиспользуемых агентов: отзывайте агентов, которые больше не нужны
  4. Истечение срока: используйте expires_at для временной авторизации агентов, когда путь одобрения позволяет задать нестандартный срок истечения

Рекомендации

  1. Используйте агентов для автоматизации: храните ключи торгового кошелька в холодном хранилище, для автоматизированных систем используйте агентов
  2. Ограничивайте область действия агентов: одобряйте только тех агентов, которым нужен доступ
  3. Отслеживайте использование агентов: следите за тем, какие агенты размещают ордера
  4. Отзывайте своевременно: отзывайте агентов сразу, как только они перестают быть нужны

Типичные проблемы

"Unauthorized: signer not authorized for wallet"

Причина: агент не одобрен, либо авторизация истекла или отозвана.

Решение: одобрите агента через POST /approve-agent или подписывайте кошельком напрямую.

Авторизация агента не работает

Причины:

  • Агент отсутствует в состоянии авторизации, принадлежащем движку
  • Авторизация была отозвана
  • Авторизация истекла

Решение: проверьте статус агента через GET /authorized-agents?wallet=....