Autorisation d'agent
Prise en charge de la signature multi-clés pour les teneurs de marché.
Vue d'ensemble
L'autorisation d'agent permet à une clé de signature dédiée (agent) de placer et d'annuler des ordres au nom d'un portefeuille de trading. Cela est utile pour :
- Sécurité : conservez les clés du portefeuille de trading en stockage à froid et utilisez des clés « chaudes » pour la signature
- Opérationnel : plusieurs membres d'une équipe peuvent signer avec des clés différentes
- Automatisation : les systèmes automatisés peuvent signer avec des clés dédiées
Deux modèles d'autorisation
Hypercall dispose de deux systèmes de délégation distincts selon le produit :
| Produit | Type de délégation | Stockage | Mise en place |
|---|---|---|---|
| Options (API REST) | Autorisation d'agent | Hors chaîne (base de données) | POST /approve-agent |
| Perpétuels (directives on-chain) | Portefeuille API | Sur la chaîne (contrat Exchange) | Directive hc_update_api_wallet |
Ce sont des systèmes indépendants. Approuver un agent pour le trading d'options ne l'autorise pas pour les perpétuels, et inversement.
Options : autorisation d'agent (hors chaîne)
Les agents signent les messages EIP-712 PlaceOrder et CancelOrder au nom d'un portefeuille de trading. Le serveur API vérifie l'autorisation dans sa base de données avant de transmettre au moteur.
Perpétuels : portefeuille API (on-chain)
Les portefeuilles API signent les directives des perpétuels en utilisant le domaine EIP-712 HypercallAgentSign. Le contrat Exchange vérifie l'autorisation sur la chaîne via isApiWalletActive(). Consultez Signature EIP-712 pour la référence complète de la signature des directives.
Pour ajouter ou supprimer un portefeuille API, soumettez une directive hc_update_api_wallet signée par le portefeuille gestionnaire du compte.
Cela reflète le modèle de portefeuille API de Hyperliquid. Hyperliquid documente ces portefeuilles API, aussi appelés portefeuilles d'agent, dans Nonces and API wallets, et documente approveAgent dans Exchange endpoint.
Protection contre le rejeu de nonce
Le suivi des nonces suit le modèle de nonce de Hyperliquid. Toutes les actions signées (ordres, approbation/révocation d'agent, handshakes QP) partagent un espace de nonces par signataire. Le moteur stocke les 100 nonces les plus élevés par adresse de signataire. Un nouveau nonce est accepté si :
nonce > min(stored_set)-- il doit être supérieur au plus petit nonce stocké!stored_set.contains(nonce)-- il ne doit pas être un doublonnoncese situe dans l'intervalle (T - 2 jours, T + 1 jour) par rapport à l'horodatage du serveur
Les nonces hors séquence sont autorisés (par exemple, nonce 105 puis 102 fonctionnent tous deux si les deux sont supérieurs au minimum de l'ensemble). L'ensemble est limité à 100 entrées, donc les entrées les plus anciennes sont évincées à mesure que de nouvelles sont ajoutées. Cela empêche le blocage d'un compte à cause d'un seul nonce trop grand.
Le signataire du nonce est l'adresse qui a signé le message EIP-712 : le portefeuille API pour les ordres, le signataire récupéré pour l'autorisation d'agent, le portefeuille QP pour les handshakes. Les clients doivent utiliser Date.now() (epoch en millisecondes) comme graine de nonce et incrémenter de manière monotone.
Autorisation d'agent pour les options
Signature directe
Si signer == wallet, l'ordre est toujours autorisé (auto-signature).
Signature par agent
Si signer != wallet, le signataire doit être un agent autorisé :
- L'agent doit être présent dans l'état d'autorisation détenu par le moteur
- L'autorisation ne doit pas être expirée
- Les snapshots du moteur et le journal du moteur sont les sources durables de restauration au redémarrage
Approuver un agent
Endpoint : POST /approve-agent
Requête : ApproveAgentRequest
{
"agent": "0x...",
"nonce": 1,
"signature": "0x..."
}
Signature :
- Le propriétaire du portefeuille signe le message
ApproveAgent - Le portefeuille est dérivé de la signature récupérée
- L'agent est le champ
agentde la requête
Struct EIP-712 :
struct ApproveAgent {
address agent;
uint64 nonce;
}
Réponse : ApproveAgentResponse
{
"success": true,
"error": null
}
Remarques :
- L'autorisation d'agent est persistante (stockée en base de données)
- L'autorisation n'expire pas sauf si
expires_atest défini (pas encore implémenté)
Révoquer un agent
Endpoint : DELETE /revoke-agent
Requête : RevokeAgentRequest
{
"agent": "0x...",
"nonce": 2,
"signature": "0x..."
}
Signature :
- Le propriétaire du portefeuille signe le message
RevokeAgent - Le portefeuille est dérivé de la signature récupérée
Struct EIP-712 :
struct RevokeAgent {
address agent;
uint64 nonce;
}
Réponse : RevokeAgentResponse
Remarques :
- Applique une commande journalisée
RevokeAgentà l'état d'autorisation détenu par le moteur - Les vérifications d'autorisation de l'API de trading lisent l'état du backend et appliquent les révocations pour les requêtes de trading. La publication dans la trollbox peut mettre en cache une autorisation d'agent positive plus longtemps, de sorte qu'un agent récemment révoqué pourrait encore pouvoir publier jusqu'à l'expiration de ce cache ou jusqu'à ce que l'invalidation au mieux atteigne la localisation périphérique concernée. Ce cache n'autorise pas les mutations de l'API de trading.
- L'agent ne peut plus signer pour le portefeuille après révocation
Obtenir les agents autorisés
Endpoint : GET /authorized-agents?wallet=...
Paramètres de requête :
wallet(obligatoire)
Réponse :
{
"agents": [
"0x...",
"0x..."
]
}
Remarques :
- Ne renvoie que les agents actifs et non expirés
- Trié par
created_at DESC
Utilisation des agents
Signer des ordres avec un agent
Une fois qu'un agent est approuvé :
- Signez l'ordre avec le portefeuille de l'agent : utilisez le portefeuille de l'agent pour signer les messages
PlaceOrder/CancelOrder - Définissez le champ wallet : définissez le champ
walletsur l'adresse du portefeuille de trading (et non l'adresse de l'agent) - Vérification par le middleware : le middleware vérifie que l'agent est autorisé pour ce portefeuille
Exemple :
// 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
})
});
Ordres groupés avec un agent
Les endpoints groupés vérifient l'autorisation de l'agent élément par élément :
- Chaque ordre dans
POST /bulk_orderpeut être signé par un agent différent - L'autorisation de l'agent est vérifiée élément par élément
- Si un élément échoue à l'autorisation d'agent, cet élément renvoie une erreur dans
BulkOrderResult
Vérifications d'autorisation
Middleware (ordres individuels)
Endpoints :
POST /orderDELETE /orderDELETE /order_cloid
Vérification : signature_and_agent_middleware vérifie :
- La récupération de la signature réussit
- Le signataire est autorisé (signer == wallet OU agent autorisé)
Handler (ordres groupés)
Endpoints :
POST /bulk_orderDELETE /bulk_orderDELETE /bulk_order_cloid
Vérification : vérification par élément dans le handler :
- Récupération de la signature par élément
- Vérification de l'autorisation de l'agent par élément
Stockage des autorisations
L'autorisation d'agent est un état détenu par le moteur. Les commandes ApproveAgent et RevokeAgent sont journalisées, restaurées via le rejeu du moteur, et exposées via le snapshot de lecture pour les vérifications de l'API.
Logique d'autorisation
L'autorisation du signataire est une logique OU explicite :
- Signature directe :
signer == wallet. - Signature par agent : le snapshot du moteur contient un enregistrement d'autorisation pour
wallet_address == <wallet>etagent_address == <signer>, etexpires_atest absent ou dans le futur.
Expiration
expires_at est appliqué par les vérifications d'autorisation du snapshot du moteur. Les agents avec
expires_at < NOW() sont traités comme non autorisés.
Considérations de sécurité
- Sécurité des clés d'agent : protégez les clés privées des agents (utilisez des portefeuilles matériels ou une gestion sécurisée des clés)
- Audits réguliers : examinez régulièrement les agents autorisés via
GET /authorized-agents - Révoquez les agents inutilisés : révoquez les agents qui ne sont plus nécessaires
- Expiration : utilisez
expires_atpour les autorisations d'agent temporaires lorsque le chemin d'approbation expose une expiration non définie par défaut
Bonnes pratiques
- Utilisez des agents pour l'automatisation : conservez les clés du portefeuille de trading en stockage à froid, utilisez des agents pour les systèmes automatisés
- Limitez la portée des agents : n'approuvez que les agents qui ont besoin d'un accès
- Surveillez l'utilisation des agents : suivez quels agents placent des ordres
- Révoquez rapidement : révoquez immédiatement les agents qui ne sont plus nécessaires
Problèmes courants
« Unauthorized: signer not authorized for wallet »
Cause : l'agent n'est pas approuvé ou l'autorisation a expiré/a été révoquée.
Solution : approuvez l'agent via POST /approve-agent ou signez directement avec le portefeuille.
L'autorisation d'agent ne fonctionne pas
Causes :
- L'agent n'est pas présent dans l'état d'autorisation détenu par le moteur
- L'autorisation a été révoquée
- L'autorisation a expiré
Solution : vérifiez le statut de l'agent via GET /authorized-agents?wallet=....