Autorización de agentes
Soporte de firma con múltiples claves 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 resulta útil para:
- Seguridad: mantenga las claves de la wallet de trading en almacenamiento en frío y use claves en caliente para firmar
- Operación: varios miembros del equipo pueden firmar con claves distintas
- Automatización: los sistemas automatizados pueden firmar con claves dedicadas
Dos modelos de autorización
Hypercall tiene dos sistemas de delegación independientes, según el producto:
| Producto | Tipo de delegación | Almacenamiento | Cómo configurarlo |
|---|---|---|---|
| Opciones (API REST) | Autorización de agentes | Estado del motor de Hypercall | POST /approve-agent |
| Perpetuos | API wallet | On-chain (su contrato Account) | Directiva hc_update_api_wallet |
Son sistemas independientes. Aprobar un agente para operar opciones no lo autoriza para perpetuos, y viceversa.
Opciones: autorización de agentes (off-chain)
Los agentes firman mensajes EIP-712 PlaceOrder y CancelOrder en nombre de una wallet de trading. La API verifica el agente contra el estado de autorización del motor antes de que la orden llegue al motor.
Perpetuos: API wallet (on-chain)
Las API wallets firman órdenes y cancelaciones de perpetuos en el dominio EIP-712 HypercallApiSign. Hypercall verifica el firmante contra su contrato Account (isApiWalletActive()) antes de admitir la orden. En la ruta TEE (la opción predeterminada de la app, y opcional para clientes de la API), un enclave seguro que guarda una clave de trading de Hyperliquid independiente para su Account firma y envía la orden nativa. En la ruta de smart contract, una configuración avanzada de la app, la orden pasa por su contrato Account. Consulte Firma EIP-712 para la referencia de firma y Perpetuos para el flujo.
Para agregar o eliminar una API wallet, envíe una directiva hc_update_api_wallet firmada por la wallet administradora (manager) de la cuenta.
Esto replica 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 nonce nuevo se acepta si:
!stored_set.contains(nonce): no está duplicadononce > min(stored_set)una vez que el conjunto contiene 100 entradas: es mayor que el nonce más pequeño almacenadononceestá dentro de (T - 2 días, T + 1 día) respecto del timestamp del servidor
Se permiten nonces fuera de orden (por ejemplo, el nonce 105 y luego el 102 funcionan si ambos están por encima del mínimo del conjunto). El conjunto está limitado a 100 entradas, por lo que las más antiguas se descartan a medida que se agregan nuevas. Esto evita que una cuenta quede bloqueada por un único nonce muy 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 y la wallet de QP para los handshakes. Los clientes deben usar Date.now() (epoch en milisegundos) como semilla del nonce e incrementarlo de forma monótona.
Autorización de agentes para opciones
Firma directa
Si signer == wallet, la orden siempre está autorizada (autofirma).
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 estar vencida
- 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
agentde la solicitud
Struct EIP-712:
struct ApproveAgent {
address agent;
uint64 nonce;
}
Respuesta: ApproveAgentResponse
{
"success": true,
"error": null
}
Notas:
- La autorización de agentes es estado del motor registrado en el journal y sobrevive a los reinicios
- Las aprobaciones realizadas mediante este endpoint no vencen
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 a las solicitudes de trading. Las publicaciones en el Trollbox pueden almacenar en caché una autorización positiva de agente durante más tiempo, por lo que un agente revocado recientemente aún podría publicar hasta que esa caché expire o la invalidación de mejor esfuerzo llegue a la ubicación edge correspondiente. Esta caché no autoriza mutaciones en la API de trading.
- Tras la revocación, el agente ya no puede firmar en nombre de la wallet
Revocar todos los agentes
Endpoint: DELETE /revoke-all-agents
Solicitud: { "nonce": 3, "signature": "0x..." }, firmada por el propietario de la wallet sobre RevokeAllAgents(uint64 nonce). Elimina todos los agentes de la wallet recuperada.
Obtener agentes autorizados
Endpoint: GET /authorized-agents?wallet=...
Parámetros de consulta:
wallet(obligatorio)
Respuesta:
{
"agents": [
"0x...",
"0x..."
]
}
Notas:
- Devuelve solo agentes activos y no vencidos
Uso de agentes
Firmar órdenes con un agente
Una vez aprobado un agente:
- Firme la orden con la wallet del agente: use la wallet del agente para firmar los mensajes
PlaceOrder/CancelOrder - Configure el campo wallet: asigne al campo
walletla 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. The REST body uses snake_case `client_id`.
const { clientId, ...rest } = message;
const response = await fetch('/order', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
...rest,
client_id: clientId,
signature
})
});
Órdenes masivas con un agente
Los endpoints masivos verifican la autorización de agentes por elemento:
- Cada orden en
POST /bulk_orderpuede estar firmada por un agente distinto - La autorización de agentes se verifica por elemento
- Si algún elemento no supera la autorización de agente, ese elemento devuelve un error en
BulkOrderResult
Verificaciones de autorización
Middleware (órdenes individuales)
Endpoints:
POST /orderDELETE /orderDELETE /order_cloid
Verificación: signature_and_agent_middleware comprueba que:
- La recuperación de la firma se completa correctamente
- El firmante está autorizado (signer == wallet O agente autorizado)
Handler (órdenes masivas)
Endpoints:
POST /bulk_orderDELETE /bulk_orderDELETE /bulk_order_cloid
Verificación: verificación por elemento en el handler:
- Recuperación de la firma por elemento
- Verificación de la autorización de agentes por elemento
Almacenamiento de la autorización
La autorización de agentes es estado propiedad del motor. Los comandos ApproveAgent y RevokeAgent se registran en el journal, se restauran mediante el replay 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 sigue 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 es una fecha futura.
Vencimiento
El motor admite un expires_at en una autorización y trata a un agente vencido
como no autorizado. POST /approve-agent no lo establece, por lo que los agentes
aprobados mediante la API permanecen activos hasta que se revocan.
Consideraciones de seguridad
- Seguridad de la clave del agente: proteja las claves privadas de los agentes (use hardware wallets o una gestión segura de claves)
- Auditorías periódicas: revise con regularidad los agentes autorizados mediante
GET /authorized-agents - Revoque los agentes sin uso: revoque los agentes que ya no necesite
Buenas 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 los agentes: lleve un registro de qué agentes colocan órdenes
- Revoque de inmediato: revoque los agentes en cuanto dejen de ser necesarios
Problemas comunes
"Signer 0x... is not authorized to act for wallet 0x..."
Causa: el agente no está aprobado o la autorización venció o fue revocada.
Solución: apruebe el agente mediante POST /approve-agent o firme directamente con la wallet.
La autorización de agentes 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 está vencida
Solución: verifique el estado del agente mediante GET /authorized-agents?wallet=....