Авторизація агентів
Підтримка підпису кількома ключами для маркетмейкерів.
Огляд
Авторизація агентів дозволяє виділеному ключу підпису (агенту) розміщувати та скасовувати заявки від імені торгового гаманця. Це корисно для:
- Безпеки: тримайте ключі торгового гаманця в холодному сховищі, використовуйте гарячі ключі для підпису
- Операційної діяльності: кілька членів команди можуть підписувати різними ключами
- Автоматизації: автоматизовані системи можуть підписувати виділеними ключами
Дві моделі авторизації
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 приймається, якщо:
nonce > min(stored_set)-- має бути більшим за найменший збережений nonce!stored_set.contains(nonce)-- не повинен бути дублікатом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 читають стан бекенду та застосовують відкликання для торгових запитів. Публікація в trollbox може кешувати позитивну авторизацію агента довше, тому нещодавно відкликаний агент усе ще може публікувати повідомлення, поки цей кеш не закінчиться або best-effort інвалідація не досягне відповідної edge-локації. Цей кеш не авторизує мутації торгового API.
- Агент більше не може підписувати для гаманця після відкликання
Отримання авторизованих агентів
Ендпоінт: GET /authorized-agents?wallet=...
Параметри запиту:
wallet(обов'язковий)
Відповідь:
{
"agents": [
"0x...",
"0x..."
]
}
Примітки:
- Повертає лише активних, непрострочених агентів
- Впорядковано за
created_at DESC
Використання агента
Підписання заявок агентом
Після схвалення агента:
- Підпишіть заявку гаманцем агента: використовуйте гаманець агента для підписання повідомлень
PlaceOrder/CancelOrder - Встановіть поле wallet: встановіть поле
walletна адресу торгового гаманця (не адресу агента) - Перевірка 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 /orderDELETE /orderDELETE /order_cloid
Перевірка: signature_and_agent_middleware перевіряє:
- Відновлення підпису успішне
- Підписант авторизований (signer == wallet АБО агент авторизований)
Обробник (пакетні заявки)
Ендпоінти:
POST /bulk_orderDELETE /bulk_orderDELETE /bulk_order_cloid
Перевірка: поелементна перевірка в обробнику:
- Відновлення підпису для кожного елемента
- Перевірка авторизації агента для кожного елемента
Зберігання авторизації
Авторизація агентів — це стан, що належить рушію. Команди ApproveAgent та RevokeAgent журналюються, відновлюються через реплей рушія та надаються через знімок для читання для перевірок API.
Логіка авторизації
Авторизація підписанта — це явна логіка АБО:
- Пряме підписання:
signer == wallet. - Підписання агентом: знімок рушія містить запис авторизації для
wallet_address == <wallet>таagent_address == <signer>, аexpires_atвідсутній або в майбутньому.
Закінчення терміну дії
expires_at застосовується перевірками авторизації знімка рушія. Агенти з
expires_at < NOW() вважаються неавторизованими.
Міркування безпеки
- Безпека ключів агентів: захищайте приватні ключі агентів (використовуйте апаратні гаманці або безпечне управління ключами)
- Регулярні аудити: регулярно переглядайте авторизованих агентів через
GET /authorized-agents - Відкликайте невикористовуваних агентів: відкликайте агентів, які більше не потрібні
- Термін дії: використовуйте
expires_atдля тимчасових авторизацій агентів, коли шлях схвалення надає нестандартний термін дії
Найкращі практики
- Використовуйте агентів для автоматизації: тримайте ключі торгового гаманця в холодному сховищі, використовуйте агентів для автоматизованих систем
- Обмежуйте область дії агентів: схвалюйте лише тих агентів, яким потрібен доступ
- Відстежуйте використання агентів: відстежуйте, які агенти розміщують заявки
- Відкликайте оперативно: відкликайте агентів негайно, коли вони більше не потрібні
Поширені проблеми
«Unauthorized: signer not authorized for wallet»
Причина: агент не схвалений або авторизація прострочена/відкликана.
Рішення: схваліть агента через POST /approve-agent або підпишіть безпосередньо гаманцем.
Авторизація агента не працює
Причини:
- Агент відсутній у стані авторизації, що належить рушію
- Авторизацію було відкликано
- Авторизація прострочена
Рішення: перевірте статус агента через GET /authorized-agents?wallet=....