Autorização de Agentes
Suporte a assinatura com múltiplas chaves para market makers.
Visão geral
A autorização de agentes permite que uma chave de assinatura dedicada (agente) envie e cancele ordens em nome de uma carteira de negociação. Isso é útil para:
- Segurança: mantenha as chaves da carteira de negociação em armazenamento a frio e use chaves quentes para assinar
- Operacional: vários membros da equipe podem assinar com chaves diferentes
- Automação: sistemas automatizados podem assinar com chaves dedicadas
Dois modelos de autorização
A Hypercall tem dois sistemas de delegação separados, dependendo do produto:
| Produto | Tipo de delegação | Armazenamento | Como configurar |
|---|---|---|---|
| Opções (REST API) | Autorização de agente | Estado do engine da Hypercall | POST /approve-agent |
| Perpétuos | Carteira de API | On-chain (seu contrato Account) | Diretiva hc_update_api_wallet |
Esses sistemas são independentes. Aprovar um agente para negociar opções não o autoriza para perpétuos, e vice-versa.
Opções: autorização de agente (off-chain)
Os agentes assinam mensagens EIP-712 PlaceOrder e CancelOrder em nome de uma carteira de negociação. A API verifica o agente no estado de autorização do engine antes que a ordem chegue ao engine.
Perpétuos: carteira de API (on-chain)
As carteiras de API assinam ordens e cancelamentos de perpétuos no domínio EIP-712 HypercallApiSign. A Hypercall verifica o signatário no seu contrato Account (isApiWalletActive()) antes de admitir a ordem. Na rota TEE (o padrão do app, e opcional para clientes de API), um enclave seguro que guarda uma chave de negociação separada da Hyperliquid para a sua Account assina e envia a ordem nativa. Na rota de smart contract, uma configuração avançada no app, a ordem passa pelo seu contrato Account. Consulte Assinatura EIP-712 para a referência de assinatura e Perpétuos para o fluxo.
Para adicionar ou remover uma carteira de API, envie uma diretiva hc_update_api_wallet assinada pela carteira gestora da conta.
Isso espelha o modelo de carteiras de API da Hyperliquid. A Hyperliquid documenta essas carteiras como carteiras de API, também chamadas de carteiras de agente, em Nonces and API wallets, e documenta approveAgent no Exchange endpoint.
Proteção contra replay de nonce
O rastreamento de nonces segue o modelo de nonce da Hyperliquid. Todas as ações assinadas (ordens, aprovação/revogação de agentes, handshakes de QP) compartilham um espaço de nonces por signatário. O engine armazena os 100 maiores nonces por endereço signatário. Um novo nonce é aceito se:
!stored_set.contains(nonce): não é duplicadononce > min(stored_set)quando o conjunto tem 100 entradas: é maior que o menor nonce armazenadononceestá dentro de (T - 2 dias, T + 1 dia) em relação ao timestamp do servidor
Nonces fora de ordem são permitidos (por exemplo, o nonce 105 e depois o 102 funcionam se ambos estiverem acima do mínimo do conjunto). O conjunto é limitado a 100 entradas, então as entradas mais antigas são removidas à medida que novas são adicionadas. Isso evita que uma conta fique inutilizável por causa de um único nonce muito alto.
O signatário do nonce é o endereço que assinou a mensagem EIP-712: a carteira de API para ordens, o signatário recuperado para autorização de agentes e a carteira do QP para handshakes. Os clientes devem usar Date.now() (epoch em milissegundos) como semente do nonce e incrementá-lo de forma monotônica.
Autorização de agentes para opções
Assinatura direta
Se signer == wallet, a ordem é sempre autorizada (autoassinatura).
Assinatura por agente
Se signer != wallet, o signatário precisa ser um agente autorizado:
- O agente precisa estar presente no estado de autorização mantido pelo engine
- A autorização não pode estar expirada
- Os snapshots do engine e o journal do engine são as fontes duráveis para reinicialização
Aprovar agente
Endpoint: POST /approve-agent
Requisição: ApproveAgentRequest
{
"agent": "0x...",
"nonce": 1,
"signature": "0x..."
}
Assinatura:
- O dono da carteira assina a mensagem
ApproveAgent - A carteira é derivada da assinatura recuperada
- O agente é o campo
agentna requisição
Struct EIP-712:
struct ApproveAgent {
address agent;
uint64 nonce;
}
Resposta: ApproveAgentResponse
{
"success": true,
"error": null
}
Observações:
- A autorização de agente é estado do engine registrado no journal e sobrevive a reinicializações
- Aprovações feitas por este endpoint não expiram
Revogar agente
Endpoint: DELETE /revoke-agent
Requisição: RevokeAgentRequest
{
"agent": "0x...",
"nonce": 2,
"signature": "0x..."
}
Assinatura:
- O dono da carteira assina a mensagem
RevokeAgent - A carteira é derivada da assinatura recuperada
Struct EIP-712:
struct RevokeAgent {
address agent;
uint64 nonce;
}
Resposta: RevokeAgentResponse
Observações:
- Aplica um comando
RevokeAgentregistrado no journal ao estado de autorização mantido pelo engine - As verificações de autorização da API de negociação leem o estado do backend e aplicam as revogações às requisições de negociação. A publicação no Trollbox pode manter em cache a autorização positiva do agente por mais tempo, então um agente revogado recentemente ainda pode conseguir publicar até que esse cache expire ou que a invalidação best-effort chegue ao edge location relevante. Esse cache não autoriza mutações na API de negociação.
- Após a revogação, o agente não pode mais assinar pela carteira
Revogar todos os agentes
Endpoint: DELETE /revoke-all-agents
Requisição: { "nonce": 3, "signature": "0x..." }, assinada pelo dono da carteira sobre RevokeAllAgents(uint64 nonce). Remove todos os agentes da carteira recuperada.
Consultar agentes autorizados
Endpoint: GET /authorized-agents?wallet=...
Parâmetros de consulta:
wallet(obrigatório)
Resposta:
{
"agents": [
"0x...",
"0x..."
]
}
Observações:
- Retorna apenas agentes ativos e não expirados
Uso de agentes
Assinando ordens com um agente
Depois que um agente é aprovado:
- Assine a ordem com a carteira do agente: use a carteira do agente para assinar mensagens
PlaceOrder/CancelOrder - Defina o campo wallet: defina o campo
walletcom o endereço da carteira de negociação (não o endereço do agente) - Verificação no middleware: o middleware verifica se o agente está autorizado para essa carteira
Exemplo:
// 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
})
});
Ordens em lote com um agente
Os endpoints em lote verificam a autorização de agente item a item:
- Cada ordem em
POST /bulk_orderpode ser assinada por um agente diferente - A autorização de agente é verificada item a item
- Se algum item falhar na autorização de agente, esse item retorna erro em
BulkOrderResult
Verificações de autorização
Middleware (ordens individuais)
Endpoints:
POST /orderDELETE /orderDELETE /order_cloid
Verificação: signature_and_agent_middleware verifica:
- A recuperação da assinatura é bem-sucedida
- O signatário está autorizado (signer == wallet OU agente autorizado)
Handler (ordens em lote)
Endpoints:
POST /bulk_orderDELETE /bulk_orderDELETE /bulk_order_cloid
Verificação: verificação item a item no handler:
- Recuperação da assinatura por item
- Verificação de autorização de agente por item
Armazenamento da autorização
A autorização de agentes é estado mantido pelo engine. Os comandos ApproveAgent e RevokeAgent são registrados no journal, restaurados pelo replay do engine e expostos pelo snapshot de leitura para as verificações da API.
Lógica de autorização
A autorização do signatário é uma lógica OU explícita:
- Assinatura direta:
signer == wallet. - Assinatura por agente: o snapshot do engine contém um registro de autorização para
wallet_address == <wallet>eagent_address == <signer>, eexpires_atestá ausente ou no futuro.
Expiração
O engine aceita um expires_at em uma autorização e trata um agente expirado
como não autorizado. POST /approve-agent não define esse campo, então os agentes
aprovados pela API permanecem ativos até serem revogados.
Considerações de segurança
- Segurança da chave do agente: proteja as chaves privadas dos agentes (use hardware wallets ou um gerenciamento de chaves seguro)
- Auditorias regulares: revise regularmente os agentes autorizados via
GET /authorized-agents - Revogue agentes sem uso: revogue os agentes que não são mais necessários
Boas práticas
- Use agentes para automação: mantenha as chaves da carteira de negociação em armazenamento a frio e use agentes para sistemas automatizados
- Limite o escopo dos agentes: aprove apenas os agentes que precisam de acesso
- Monitore o uso dos agentes: acompanhe quais agentes estão enviando ordens
- Revogue rapidamente: revogue os agentes imediatamente quando não forem mais necessários
Problemas comuns
"Signer 0x... is not authorized to act for wallet 0x..."
Causa: o agente não foi aprovado ou a autorização expirou ou foi revogada.
Solução: aprove o agente via POST /approve-agent ou assine diretamente com a carteira.
A autorização de agente não está funcionando
Causas:
- O agente não está presente no estado de autorização mantido pelo engine
- A autorização foi revogada
- A autorização está expirada
Solução: verifique o status do agente via GET /authorized-agents?wallet=....