Cette page a été traduite automatiquement. La version anglaise fait référence. Lire en anglais
Aller au contenu principal

API WebSocket

Diffusion de données en temps réel pour le trading d'options Hypercall.

Référence interactive

Consultez la référence interactive de l'API WebSocket pour une meilleure expérience de navigation, avec des exemples en direct et des détails de schéma.

Spécification lisible par machine

Téléchargez la spécification AsyncAPI pour un usage programmatique.

Connexion

Connectez-vous à wss://HOST/ws :

Points de terminaison :

  • Production : wss://api.hypercall.xyz/ws
  • Local : ws://localhost:3000/ws
État du testnet

Le testnet est temporairement désactivé jusqu'à ce que Hypercall acquière davantage de HYPE de testnet.

Identification du portefeuille

Pour recevoir des données sur les canaux authentifiés (ordres, exécutions, portefeuille), identifiez votre portefeuille après la connexion en envoyant un message Authenticate :

{"type": "Authenticate", "wallet": "0x1234..."}

Le serveur répond par une confirmation :

{"type": "Authenticated", "wallet": "0x1234..."}

Après avoir reçu Authenticated, vous pouvez vous abonner aux canaux authentifiés. Si l'adresse du portefeuille est invalide, le serveur répond par un message Error et la connexion reste ouverte.

Obsolète : authentification par paramètre de requête

Le paramètre de requête ?wallet= est toujours pris en charge pour des raisons de rétrocompatibilité, mais il est obsolète et sera supprimé dans une prochaine version. Privilégiez l'approche par message décrite ci-dessus.

Vivacité de la connexion

Le serveur applique un heartbeat WebSocket :

  • Envoie une trame de contrôle Ping toutes les 20 secondes
  • Attend un Pong correspondant dans les 60 secondes
  • Ferme la connexion avec le code de fermeture 1008 et le motif pong timeout si le client cesse de répondre

Les implémentations WebSocket des navigateurs gèrent le ping/pong automatiquement. De nombreuses bibliothèques WebSocket Rust, dont tungstenite et tokio-tungstenite, gèrent également le ping/pong des trames de contrôle pour vous. Consultez la documentation de la bibliothèque de votre client avant d'ajouter une gestion manuelle du Pong. Les implémentations personnalisées ou utilisant des sockets bruts doivent répondre aux trames Ping par un Pong.

Récupération des consommateurs lents

Le serveur ferme une connexion /ws qui ne parvient pas à écouler les données sortantes dans les limites de sécurité configurées pour les messages, les octets encodés, l'ancienneté de la file d'attente ou l'écriture sur le socket. Lorsque la connexion peut encore accepter une trame de fermeture, le serveur utilise le code 1008 et un motif JSON compact :

{"error":"slow_consumer","class":"ordered_public","cause":"message_age","recovery":"snapshot_resubscribe"}

Les champs du motif sont les suivants :

ChampSignification
classClasse de livraison dont la trame a franchi la limite de sécurité.
causemessage_limit, byte_limit, message_age ou write_timeout.
recoveryAction requise à effectuer ensuite, telle que resubscribe, snapshot_resubscribe, portfolio_refetch ou rest_reconcile.

Après toute déconnexion, reconnectez-vous, identifiez à nouveau le portefeuille si nécessaire, réabonnez-vous et réconciliez l'état actuel avant de traiter de nouveaux événements. Les canaux publics ordonnés nécessitent un nouveau snapshot. Les canaux d'événements privés nécessitent une réconciliation via la surface REST faisant autorité, car la relecture par curseur n'est pas encore disponible. Une connexion totalement bloquée peut se terminer avant de pouvoir lire le motif de fermeture, si bien que les clients doivent utiliser ce flux de récupération également en cas de fermeture non propre.

Utilisez des connexions distinctes pour les données de marché publiques à haut débit et pour les commandes authentifiées ou les flux privés. Les classes de livraison déterminent les métriques et le comportement de récupération, mais les trames d'une même connexion partagent toujours un unique chemin d'écriture de socket ordonné. Une écriture publique bloquée peut donc retarder des trames privées ultérieures sur cette même connexion jusqu'à ce que le délai d'écriture la ferme.

Abonnement aux canaux

Envoyez un message JSON pour vous abonner :

{"type": "Subscribe", "channel": "orderbook"}

Pour vous désabonner :

{"type": "Unsubscribe", "channel": "orderbook"}

Vous recevrez une confirmation :

{"type": "Subscribed", "channel": "orderbook"}

Filtrage par symbole

Les canaux order_updates et fills prennent en charge un filtre symbols optionnel. Lorsqu'il est fourni, le serveur n'envoie que les messages dont le sous-jacent correspond à l'un des symboles spécifiés.

{"type": "Subscribe", "channel": "order_updates", "symbols": ["BTC"]}

Les sous-jacents simples ("BTC") et les noms d'instruments complets ("BTC-20260131-100000-C") sont tous deux acceptés. Pour ajouter d'autres symboles, envoyez un nouveau Subscribe. Pour supprimer des symboles spécifiques :

{"type": "Unsubscribe", "channel": "order_updates", "symbols": ["BTC"]}

Lorsqu'aucun symbols n'est spécifié, toutes les mises à jour de votre portefeuille sont transmises.

Filtrage de la chaîne d'options

Le canal options_chain prend en charge le filtrage par symboles sous-jacents, date d'échéance et type d'option :

{
"type": "Subscribe",
"channel": "options_chain",
"symbols": ["BTC-20260131-100000-C"],
"expiry": "2026-01-31",
"option_type": "call"
}
FiltreValeursPar défaut
symbolsTableau de symboles d'instruments complets (par ex. ["BTC-20260131-100000-C"])Tous les instruments
expiryChaîne de date "YYYY-MM-DD"Toutes les échéances
option_type"call", "put", ou à omettre pour les deuxLes deux

Canaux disponibles

CanalAuthentification requiseDescription
orderbookNonMises à jour du carnet d'ordres L2 pour tous les symboles
tradesNonFlux public des transactions
market_updatesNonChangements de cotation de marché (créé/supprimé/expiré)
options_chainNonMises à jour incrémentales de la chaîne d'options (filtrables par symboles, échéance, type d'option)
index_pricesNonPrix spot/index en temps réel pour tous les sous-jacents
indicative_market_dataNonFlux de fournisseurs de cotations sur liste d'autorisation. Pas encore disponible de manière générale
order_updatesOuiChangements de statut de vos ordres (filtrables par symbole)
fillsOuiExécutions de vos transactions (filtrables par symbole)
portfolioOuiMises à jour de vos positions et de votre solde
liquidationOuiChangements de l'état de liquidation vous concernant
competitionOuiRécapitulatif de votre P&L de compétition, classement et statistiques finales
competition_engagementOuiChangements de classement, écart avec le rang suivant et classements finaux
rfqOuiCotations RFQ, mises à jour de statut et notifications d'exécution

Types de messages

Passer un ordre (authentifié)

Passez un ordre via le chemin de commande WebSocket.

{
"type": "PlaceOrder",
"wallet": "0x1234...",
"symbol": "BTC-20260131-100000-C",
"side": "Buy",
"size": "1",
"price": "100",
"tif": "gtc",
"route": "book_only",
"client_id": "my-order-1",
"nonce": 1000,
"signature": "0x..."
}
ChampTypeDescription
walletstringAdresse du portefeuille propriétaire de l'ordre
symbolstringSymbole de l'option
sidestring"Buy" ou "Sell"
sizestringTaille du contrat, correspondant exactement à la valeur signée
pricestringPrix limite, correspondant exactement à la valeur signée
tifstringDurée de validité optionnelle, "gtc" par défaut
routestringRoute optionnelle. Utilisez "book_only" pour les ordres WebSocket sensibles au routage. Une route omise reste acceptée au moins jusqu'au 4 juillet 2026.
client_idstringID d'ordre client optionnel
nonceintegerNonce de signature unique
signaturestringSignature EIP-712 PlaceOrder

Le PlaceOrder WebSocket est actuellement acheminé directement vers le carnet d'ordres. route="best_execution" et route="rfq_only" sont rejetés sur WebSocket, car ce chemin n'exécute pas encore le routage RPI/RFQ. Utilisez POST /order pour best_execution.

Mise à jour du carnet d'ordres

Snapshot/mise à jour du carnet d'ordres L2 pour un symbole.

{
"type": "OrderbookUpdate",
"symbol": "BTC-20260131-100000-C",
"bids": [["95000.5", "10.5"], ["94999.0", "25.0"]],
"asks": [["95001.0", "8.0"], ["95002.5", "15.0"]],
"timestamp": 1737331200000
}
ChampTypeDescription
symbolstringSymbole de l'option
bidsarrayNiveaux d'offre sous forme de tuples [price, size], la taille étant exprimée en contrats lisibles par un humain
asksarrayNiveaux de demande sous forme de tuples [price, size], la taille étant exprimée en contrats lisibles par un humain
timestampintegerTimestamp Unix (millisecondes)

Transaction

Événement public de transaction.

{
"type": "Trade",
"symbol": "BTC-20260131-100000-C",
"price": "0.0523",
"size": "5.0",
"side": "buy",
"timestamp": 1737331200000
}
ChampTypeDescription
symbolstringSymbole de l'option
pricestringPrix de la transaction en USD
sizestringTaille de la transaction en contrats
sidestringCôté agresseur (buy ou sell)
timestampintegerTimestamp Unix (millisecondes)

Exécution (authentifié)

Notification d'exécution de votre transaction.

{
"type": "Fill",
"order_id": 12345,
"fill_id": 67890,
"symbol": "BTC-20260131-100000-C",
"side": "buy",
"price": "0.0523",
"size": "5.0",
"timestamp": 1737331200000,
"wallet_address": "0x1234...abcd",
"fee": "0",
"trade_id": 99999,
"is_taker": true
}
ChampTypeDescription
order_idintegerID de votre ordre
fill_idintegerID de l'exécution
symbolstringSymbole de l'option
sidestringSens de la transaction (buy ou sell)
pricestringPrix d'exécution en USD
sizestringTaille de l'exécution en contrats
timestampintegerHorodatage Unix (millisecondes)
wallet_addressstringAdresse de votre portefeuille
feestringFrais de transaction prélevés. Renvoie 0 tant que les frais de la venue de lancement sont désactivés
trade_idintegerID unique de la transaction
is_takerbooleanIndique si vous étiez le taker
builder_code_addressstring?Portefeuille du builder code (le cas échéant)
builder_code_feestring?Frais du builder code. Renvoie null tant que les frais de la venue de lancement sont désactivés

Mise à jour du portefeuille (authentifié)

Mise à jour du flux de portefeuille pour les positions, les soldes, la marge et les Greeks.

Exemple de mise à jour des Greeks :

{
"type": "PortfolioUpdate",
"timestamp": 1737331200000,
"per_leg": [
{
"symbol": "BTC-20260131-100000-C",
"quantity": "2.0",
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
],
"aggregate": {
"delta": 0.91,
"gamma": 0.003,
"theta": -0.12,
"vega": 0.44,
"iv": 0.63
}
}

Pour les portefeuilles vides, les mises à jour des Greeks utilisent :

  • per_leg: []
  • aggregate: null

Récapitulatif du PnL de compétition (authentifié)

Mise à jour du flux de compétition pour l'affichage du PnL en en-tête/pied de page.

{
"type": "CompetitionPnlSummary",
"wallet_address": "0x1234...abcd",
"lifetime_realized_pnl": "1250.50",
"active_competition": {
"competition_id": 7,
"competition_name": "Spring Sprint",
"competition_state": "active",
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null
},
"timestamp": 1737331200000
}

Lorsqu'il n'y a aucune compétition active, active_competition vaut null.

Mise à jour d'ordre (authentifié)

Notification de changement de statut d'un ordre.

{
"type": "OrderUpdate",
"order_id": 12345,
"client_order_id": "my-order-1",
"status": "filled",
"filled_size": "10.0",
"remaining_size": "0",
"avg_fill_price": "0.0523"
}

Mise à jour du marché

Changements dans les listings de marchés.

Marché créé :

{
"type": "MarketUpdate",
"action": "Created",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1737331200000
}

Marché arrivé à échéance :

{
"type": "MarketUpdate",
"action": "Expired",
"symbol": "BTC-20260131-100000-C",
"strike": "100000",
"is_call": true,
"underlying": "BTC",
"expiry": 1738281600,
"timestamp": 1738281600000
}

Position arrivée à échéance (authentifié)

Notification lorsque votre position est réglée à l'échéance.

{
"type": "PositionExpired",
"wallet_address": "0x1234...abcd",
"symbol": "BTC-20260131-100000-C",
"position_size": "10.0",
"settlement_price": "105000",
"settlement_value": "500.0",
"timestamp": 1738281600000
}

Changement d'état de liquidation (authentifié)

Changement de l'état de liquidation de votre compte.

{
"type": "LiquidationStateChange",
"wallet_address": "0x1234...abcd",
"previous_state": "Normal",
"new_state": "Warning",
"equity": "10000.0",
"mm_required": "9500.0",
"shortfall": "0",
"auction_id": null,
"timestamp": 1737331200000
}
ÉtatDescription
NormalLe compte est sain
WarningApproche d'un appel de marge
LiquidatingEnchère de liquidation active

Mise à jour du prix de l'indice

Prix spot/indice regroupés pour tous les sous-jacents.

{
"type": "IndexPriceUpdate",
"prices": [
{"underlying": "BTC", "price": "97250.50"},
{"underlying": "ETH", "price": "3200.00"},
{"underlying": "HYPE", "price": "28.50"}
],
"timestamp": 1737331200000
}
ChampTypeDescription
pricesarrayTableau d'entrées {underlying, price} pour chaque sous-jacent suivi
prices[].underlyingstringSymbole du sous-jacent (par exemple, "BTC", "ETH")
prices[].pricestringPrix spot/indice actuel en USD
timestampintegerHorodatage Unix (millisecondes)

Données de marché indicatives

Flux de fournisseurs de cotations sur liste blanche avec les meilleures offre/demande agrégées des fournisseurs de cotations enregistrés. Ce canal n'est pas encore disponible de manière générale. Utilisez les données de marché REST et les canaux authentifiés ordre/exécution/portefeuille, sauf si Hypercall a activé le streaming de fournisseurs de cotations pour votre intégration.

{
"type": "IndicativeMarketData",
"instrument": "BTC-20260131-100000-C",
"best_bid": "0.0520",
"best_ask": "0.0530",
"indicative_bid_size": "50.0",
"indicative_ask_size": "25.0",
"num_providers": 3,
"timestamp": 1737331200000
}
ChampTypeDescription
instrumentstringSymbole de l'option
best_bidstringMeilleur prix bid agrégé (facultatif)
best_askstringMeilleur prix ask agrégé (facultatif)
bid_ivnumberVolatilité implicite du meilleur bid (facultatif)
ask_ivnumberVolatilité implicite du meilleur ask (facultatif)
indicative_bid_sizestringTaille bid totale sur l'ensemble des fournisseurs (facultatif)
indicative_ask_sizestringTaille ask totale sur l'ensemble des fournisseurs (facultatif)
num_providersintegerNombre de fournisseurs de cotations actifs
timestampintegerHorodatage Unix (millisecondes)

Changement de rang en compétition (authentifié)

Notification lorsque votre rang change dans une compétition active.

{
"type": "CompetitionRankChange",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"from_rank": 15,
"to_rank": 12,
"delta_places": 3,
"pnl": "420.25",
"timestamp": 1737331200000
}

Mise à jour de l'écart en compétition (authentifié)

Distance jusqu'au rang situé juste au-dessus de vous.

{
"type": "CompetitionGapUpdate",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"next_rank": 11,
"gap_metric_value": "50.00",
"timestamp": 1737331200000
}

Classement final de compétition (authentifié)

Envoyé lorsqu'une compétition se termine, avec vos résultats finaux.

{
"type": "CompetitionFinalStanding",
"wallet_address": "0x1234...abcd",
"competition_id": 7,
"rank": 12,
"pnl": "420.25",
"volume": "25000",
"efficiency": "0.01681",
"medal": null,
"timestamp": 1737331200000
}

Cotations RFQ (authentifié)

Cotations reçues en réponse à la soumission de votre RFQ.

{
"type": "RfqQuotes",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"quotes": [
{
"quote_id": "660e8400-e29b-41d4-a716-446655440001",
"net_premium": "52.30",
"expires_at": 1737331225000
}
],
"status": "quoted",
"taker_wallet": "0x1234...abcd"
}

Mise à jour du statut RFQ (authentifié)

Changement de statut d'un RFQ que vous avez soumis.

{
"type": "RfqStatusUpdate",
"rfq_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "executed",
"taker_wallet": "0x1234...abcd"
}

Erreur

Message d'erreur du serveur.

{
"type": "Error",
"message": "Invalid channel: foobar"
}

Authentification

Les canaux authentifiés nécessitent un message d'identification du portefeuille après la connexion :

{"type": "Authenticate", "wallet": "0x1234567890abcdef..."}

Les messages sur les canaux authentifiés sont filtrés pour n'afficher que les données de votre portefeuille. Aucune signature n'est requise pour les connexions WebSocket.

Exemple : client Python

import asyncio
import websockets
import json

async def main():
uri = "wss://api.hypercall.xyz/ws"

async with websockets.connect(uri) as ws:
# Identify the wallet before subscribing to authenticated channels.
await ws.send(json.dumps({
"type": "Authenticate",
"wallet": "0xYourWallet"
}))

# Subscribe to orderbook
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "orderbook"
}))

# Subscribe to fills for BTC only
await ws.send(json.dumps({
"type": "Subscribe",
"channel": "fills",
"symbols": ["BTC"]
}))

# Listen for messages
async for message in ws:
data = json.loads(message)
print(f"Received: {data['type']}")

asyncio.run(main())

Exemple : client TypeScript

const ws = new WebSocket("wss://api.hypercall.xyz/ws");

ws.onopen = () => {
ws.send(JSON.stringify({ type: "Authenticate", wallet: "0xYourWallet" }));

// Subscribe to channels
ws.send(JSON.stringify({ type: "Subscribe", channel: "orderbook" }));

// Subscribe to order updates filtered to BTC
ws.send(JSON.stringify({
type: "Subscribe",
channel: "order_updates",
symbols: ["BTC"],
}));
};

ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
console.log(`Received: ${msg.type}`);

if (msg.type === "OrderbookUpdate") {
console.log(`${msg.symbol}: ${msg.bids.length} bids, ${msg.asks.length} asks`);
}
};