Autorización de Agentes
Soporte de firma multi-clave para market makers.
Descripción General
La autorización de agentes permite que una clave de firma dedicada (agente) coloque y cancele órdenes en nombre de una wallet de trading. Esto es útil para:
- Seguridad: Mantenga las claves de la wallet de trading en almacenamiento en frío y use claves calientes para firmar
- Operaciones: Varios miembros del equipo pueden firmar con claves diferentes
- Automatización: Los sistemas automatizados pueden firmar con claves dedicadas
Dos Modelos de Autorización
Hypercall tiene dos sistemas de delegación separados según el producto:
| Producto | Tipo de Delegación | Almacenamiento | Cómo Configurarlo |
|---|---|---|---|
| Opciones (API REST) | Autorización de agente | Off-chain (base de datos) | POST /approve-agent |
| Perpetuos (directivas on-chain) | API wallet | On-chain (contrato Exchange) | Directiva hc_update_api_wallet |
Estos son sistemas independientes. Aprobar un agente para el trading de opciones no lo autoriza para perpetuos, y viceversa.
Opciones: Autorización de Agente (Off-Chain)
Los agentes firman mensajes EIP-712 de PlaceOrder y CancelOrder en nombre de una wallet de trading. El servidor de la API verifica la autorización contra su base de datos antes de reenviarla al motor.
Perpetuos: API Wallet (On-Chain)
Las API wallets firman directivas de perpetuos usando el dominio EIP-712 HypercallAgentSign. El contrato Exchange verifica la autorización on-chain mediante isApiWalletActive(). Consulte Firma EIP-712 para la referencia completa de firma de directivas.
Para agregar o eliminar una API wallet, envíe una directiva hc_update_api_wallet firmada por la wallet administradora de la cuenta.
Esto refleja el modelo de API wallets de Hyperliquid. Hyperliquid las documenta como API wallets, también llamadas agent wallets, en Nonces and API wallets, y documenta approveAgent en el Exchange endpoint.
Protección contra Repetición de Nonces
El seguimiento de nonces sigue el modelo de nonces de Hyperliquid. Todas las acciones firmadas (órdenes, aprobación/revocación de agentes, handshakes de QP) comparten un espacio de nonces por firmante. El motor almacena los 100 nonces más altos por dirección de firmante. Un nuevo nonce se acepta si:
nonce > min(stored_set)-- debe ser mayor que el nonce almacenado más pequeño!stored_set.contains(nonce)-- no debe ser un duplicadononceestá dentro de (T - 2 días, T + 1 día) respecto al timestamp del servidor
Se permiten nonces fuera de orden (p. ej., nonce 105 y luego 102 funcionan ambos si ambos están por encima del mínimo del conjunto). El conjunto está limitado a 100 entradas, por lo que las entradas más antiguas se eliminan a medida que se agregan nuevas. Esto evita que la cuenta quede inutilizada por un único nonce grande.
El firmante del nonce es la dirección que firmó el mensaje EIP-712: la API wallet para órdenes, el firmante recuperado para la autorización de agentes, la wallet QP para handshakes. Los clientes deben usar Date.now() (época en milisegundos) como semilla del nonce e incrementarla de forma monotónica.
Autorización de Agentes para Opciones
Firma Directa
Si signer == wallet, la orden siempre está autorizada (auto-firma).
Firma por Agente
Si signer != wallet, el firmante debe ser un agente autorizado:
- El agente debe estar presente en el estado de autorización propiedad del motor
- La autorización no debe haber expirado
- Los snapshots del motor y el journal del motor son las fuentes duraderas para el reinicio
Aprobar Agente
Endpoint: POST /approve-agent
Solicitud: ApproveAgentRequest
{
"agent": "0x...",
"nonce": 1,
"signature": "0x..."
}
Firma:
- El propietario de la wallet firma el mensaje
ApproveAgent - La wallet se deriva de la firma recuperada
- El agente es el campo
agenten la solicitud
Struct EIP-712:
struct ApproveAgent {
address agent;
uint64 nonce;
}
Respuesta: ApproveAgentResponse
{
"success": true,
"error": null
}
Notas:
- La autorización de agentes es persistente (almacenada en la base de datos)
- La autorización no expira a menos que se establezca
expires_at(aún no implementado)
Revocar Agente
Endpoint: DELETE /revoke-agent
Solicitud: RevokeAgentRequest
{
"agent": "0x...",
"nonce": 2,
"signature": "0x..."
}
Firma:
- El propietario de la wallet firma el mensaje
RevokeAgent - La wallet se deriva de la firma recuperada
Struct EIP-712:
struct RevokeAgent {
address agent;
uint64 nonce;
}
Respuesta: RevokeAgentResponse
Notas:
- Aplica un comando
RevokeAgentregistrado en el journal al estado de autorización propiedad del motor - Las verificaciones de autorización de la API de trading leen el estado del backend y aplican las revocaciones para las solicitudes de trading. La publicación en el Trollbox puede almacenar en caché la autorización positiva de un agente durante más tiempo, por lo que un agente recientemente revocado aún podría publicar hasta que esa caché expire o la invalidación de mejor esfuerzo alcance la ubicación de borde correspondiente. Esta caché no autoriza mutaciones de la API de trading.
- El agente ya no puede firmar por la wallet después de la revocación
Obtener Agentes Autorizados
Endpoint: GET /authorized-agents?wallet=...
Parámetros de consulta:
wallet(requerido)
Respuesta:
{
"agents": [
"0x...",
"0x..."
]
}
Notas:
- Devuelve solo agentes activos y no expirados
- Ordenados por
created_at DESC
Uso de Agentes
Firmar Órdenes con un Agente
Una vez que un agente está aprobado:
- Firme la orden con la wallet del agente: Use la wallet del agente para firmar los mensajes
PlaceOrder/CancelOrder - Configure el campo wallet: Establezca el campo
walletcon la dirección de la wallet de trading (no la dirección del agente) - Verificación del middleware: El middleware verifica que el agente esté autorizado para esa wallet
Ejemplo:
// 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
})
});
Órdenes en Bloque con un Agente
Los endpoints en bloque verifican la autorización del agente por cada ítem:
- Cada orden en
POST /bulk_orderpuede estar firmada por un agente diferente - La autorización del agente se verifica por ítem
- Si algún ítem falla la autorización del agente, ese ítem devuelve un error en
BulkOrderResult
Verificaciones de Autorización
Middleware (Órdenes Individuales)
Endpoints:
POST /orderDELETE /orderDELETE /order_cloid
Verificación: signature_and_agent_middleware verifica que:
- La recuperación de la firma sea exitosa
- El firmante esté autorizado (signer == wallet O agente autorizado)
Handler (Órdenes en Bloque)
Endpoints:
POST /bulk_orderDELETE /bulk_orderDELETE /bulk_order_cloid
Verificación: Verificación por ítem en el handler:
- Recuperación de la firma por ítem
- Verificación de autorización del agente por ítem
Almacenamiento de la Autorización
La autorización de agentes es un estado propiedad del motor. Los comandos ApproveAgent y RevokeAgent se registran en el journal, se restauran mediante la reproducción del motor y se exponen a través del snapshot de lectura para las verificaciones de la API.
Lógica de Autorización
La autorización del firmante es una lógica OR explícita:
- Firma directa:
signer == wallet. - Firma por agente: el snapshot del motor contiene un registro de autorización para
wallet_address == <wallet>yagent_address == <signer>, yexpires_atestá ausente o en el futuro.
Expiración
expires_at se aplica mediante las verificaciones de autorización del snapshot del motor. Los agentes con
expires_at < NOW() se consideran no autorizados.
Consideraciones de Seguridad
- Seguridad de las claves del agente: Proteja las claves privadas del agente (use hardware wallets o gestión segura de claves)
- Auditorías regulares: Revise regularmente los agentes autorizados mediante
GET /authorized-agents - Revoque agentes sin uso: Revoque los agentes que ya no sean necesarios
- Expiración: Use
expires_atpara autorizaciones temporales de agentes cuando la ruta de aprobación exponga un vencimiento no predeterminado
Mejores Prácticas
- Use agentes para la automatización: Mantenga las claves de la wallet de trading en almacenamiento en frío y use agentes para los sistemas automatizados
- Limite el alcance de los agentes: Apruebe solo los agentes que necesiten acceso
- Monitoree el uso de agentes: Haga seguimiento de qué agentes están colocando órdenes
- Revoque con prontitud: Revoque los agentes inmediatamente cuando ya no sean necesarios
Problemas Comunes
"Unauthorized: signer not authorized for wallet"
Causa: El agente no está aprobado o la autorización expiró o fue revocada.
Solución: Apruebe el agente mediante POST /approve-agent o firme directamente con la wallet.
La Autorización del Agente No Funciona
Causas:
- El agente no está presente en el estado de autorización propiedad del motor
- La autorización fue revocada
- La autorización ha expirado
Solución: Verifique el estado del agente mediante GET /authorized-agents?wallet=....