Hyperliquid expone dos canales WebSocket distintos para datos de trades y fills: el canal público trades, que está limitado a una moneda y entrega cada trade de un mercado, y el canal userFills, que está limitado a un usuario y entrega solo los fills de la cuenta autenticada. Suscribirse al ámbito incorrecto es el error de integración más común. El protocolo de suscripción usa un mensaje JSON con un type y un objeto subscription que contiene el nombre del canal y su parámetro (coin o user). Debido a que los mensajes WebSocket solo se entregan mientras la conexión está activa, una conexión caída crea un vacío que debe rellenarse desde la API Info y reconciliarse mediante una identidad de fill estable, no solo por marca de tiempo. Esta guía cubre la mecánica de los canales, las formas de los payloads, un ejemplo ejecutable en Node.js, una tabla de resultados para autoevaluación y la resolución de problemas de modos de fallo comunes.
Dos ámbitos para datos de trades y fills
La API WebSocket de Hyperliquid separa los datos de trades en dos canales con ámbitos fundamentalmente diferentes. El canal público trades se suscribe por moneda y entrega cada trade que ocurre en ese mercado, sin importar quién lo inició. El canal userFills está limitado al usuario y entrega solo los fills que pertenecen a la cuenta autenticada. Elegir el canal incorrecto para tu caso de uso es el error de integración más común: un consumidor de datos de mercado que se suscribe a userFills no verá nada a menos que se autentique como usuario, mientras que un rastreador de cuentas que se suscribe a trades recibirá un torrente de actividad de mercado no relacionada.
La distinción importa porque los dos canales tienen diferentes requisitos de autenticación, diferentes formas de payload y diferentes rutas de reconciliación. El canal trades es público y no requiere autenticación; el canal userFills requiere un contexto de usuario autenticado. Para una visión completa del ciclo de vida de la conexión y las suscripciones genéricas, consulta Suscripciones WebSocket de Hyperliquid y ciclo de vida de la conexión. Para el equivalente basado en pull de los fills de usuario, consulta Leer fills de usuario y estado de órdenes de Hyperliquid a través de la API Info.
La lista de canales y el formato del mensaje de suscripción están definidos por la documentación de suscripciones WebSocket de Hyperliquid, las formas de payload por canal por la documentación de formatos de datos WebSocket, y la superficie de pull contra la que debe reconciliar una reconexión por la documentación del endpoint Info. Trata esas fuentes como la verdad absoluta para los nombres de campos y canales.
- trades: limitado a moneda, público, cada trade del mercado.
- userFills: limitado a usuario, autenticado, solo los fills de tu cuenta.
- El ámbito incorrecto es el error de integración más común.
Protocolo de suscripción y formato de mensaje
El protocolo de suscripción WebSocket de Hyperliquid sigue un formato de mensaje JSON documentado en Hyperliquid Docs, WebSocket subscriptions. Para suscribirse, el cliente envía un mensaje con un campo type establecido en "subscribe" y un objeto subscription que contiene el nombre del canal y su parámetro. Para el canal trades, el parámetro es el símbolo de la moneda; para userFills, el parámetro es la dirección del usuario. El servidor responde con un acuse de suscripción que replica los detalles de la suscripción. Para cancelar la suscripción, el cliente envía un mensaje con type "unsubscribe" y el mismo objeto subscription.
El acuse es importante para confirmar que la suscripción fue aceptada y para detectar errores como un nombre de moneda inválido o autenticación faltante. Hyperliquid Docs, WebSocket post requests and data formats especifica las formas exactas de payload para cada canal. Un mensaje de suscripción típico se ve como {"type":"subscribe","subscription":{"type":"trades","coin":"ETH"}} para trades, o {"type":"subscribe","subscription":{"type":"userFills","user":"0x..."}} para userFills. El acuse incluirá el mismo objeto subscription, lo que permite al cliente correlacionar la respuesta con la solicitud.
const WebSocket = require('ws');
const ws = new WebSocket('wss://api.hyperliquid.xyz/ws');
ws.on('open', () => {
// Subscribe to trades for ETH
ws.send(JSON.stringify({
type: 'subscribe',
subscription: { type: 'trades', coin: 'ETH' }
}));
// Subscribe to userFills for the authenticated account
ws.send(JSON.stringify({
type: 'subscribe',
subscription: { type: 'userFills', user: '0xYourAddress' }
}));
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.channel === 'subscriptionResponse') {
console.log('Subscription acknowledged:', msg.data);
} else if (msg.channel === 'trades') {
console.log('Trade:', msg.data);
} else if (msg.channel === 'userFills') {
console.log('Fill:', msg.data);
}
});Formas de payload y campos de identidad de fill
El payload del canal trades incluye campos como coin, price, size, side, time y un id de trade. El payload del canal userFills incluye campos similares más fee y closed PnL cuando corresponda. Según Hyperliquid Docs, WebSocket post requests and data formats, los nombres y tipos exactos de los campos están documentados por canal. Para la deduplicación, la identidad estable suele ser la combinación del id de trade (o id de fill) y la dirección del usuario para userFills, o solo el id de trade para trades. Las marcas de tiempo por sí solas no son una identidad estable porque múltiples trades pueden compartir el mismo milisegundo, y la API Info puede reportar registros en un orden ligeramente diferente.
Al reconciliar fills en vivo del WebSocket con la respuesta userFills de la API Info, haz coincidir los campos de identidad compartidos —como el id de fill o el id de trade— en lugar de la marca de tiempo. El endpoint userFills de la API Info devuelve registros con una forma similar pero puede incluir campos adicionales o un orden diferente. Un conjunto de deduplicación indexado por la identidad del fill asegura que los registros límite no se dupliquen. Para una mirada más profunda a la superficie de la API Info, consulta Leer fills de usuario y estado de órdenes de Hyperliquid a través de la API Info.
- trades: coin, price, size, side, time, id de trade.
- userFills: agrega fee, closed PnL y campos específicos del usuario.
- Identidad estable: id de trade o id de fill, no la marca de tiempo.
Vacío de reconexión y estrategia de relleno
Una conexión WebSocket entrega mensajes solo mientras está abierta. Si la conexión se cae —por problemas de red, reinicios del servidor o errores del lado del cliente— cualquier trade o fill que haya ocurrido durante el vacío se pierde porque el canal no reproduce mensajes perdidos. Esta es una limitación fundamental del modelo de streaming. Para recuperarse, el cliente debe detectar la desconexión, registrar la marca de tiempo del último mensaje recibido y luego rellenar desde la API Info. Para userFills, el endpoint userFills de la API Info se puede consultar con un rango de tiempo o recuperando fills recientes. Para trades, se puede usar la vista de trades por moneda en la API Info.
El relleno debe reconciliarse con el flujo en vivo para evitar duplicados. Debido a que la API Info y el WebSocket pueden reportar el mismo fill con un orden o marcas de tiempo ligeramente diferentes, la deduplicación debe basarse en la identidad del fill. Un conjunto de deduplicación acotado (por ejemplo, un Set con un tamaño máximo) puede rastrear ids de fill recientes y suprimir duplicados en el límite. Hyperliquid Docs, Info endpoint (userFills) es la fuente autorizada para el equivalente de pull. Para consideraciones de límite de tasa durante el relleno, consulta Límites de tasa de la API de Hyperliquid: Info versus Exchange.
const WebSocket = require('ws');
const fetch = require('node-fetch');
const WS_URL = 'wss://api.hyperliquid.xyz/ws';
const INFO_URL = 'https://api.hyperliquid.xyz/info';
const USER = '0xYourAddress';
const COIN = 'ETH';
const seenFills = new Set();
const MAX_SEEN = 10000;
let lastDisconnectTime = null;
function addSeen(id) {
if (seenFills.size >= MAX_SEEN) {
const first = seenFills.values().next().value;
seenFills.delete(first);
}
seenFills.add(id);
}
async function backfillUserFills(startTime) {
const res = await fetch(INFO_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: 'userFills',
user: USER,
startTime: startTime
})
});
const fills = await res.json();
for (const fill of fills) {
const id = fill.tid || fill.hash;
if (!seenFills.has(id)) {
addSeen(id);
console.log('Backfilled fill:', fill);
}
}
}
function connect() {
const ws = new WebSocket(WS_URL);
ws.on('open', () => {
console.log('Connected');
ws.send(JSON.stringify({
type: 'subscribe',
subscription: { type: 'trades', coin: COIN }
}));
ws.send(JSON.stringify({
type: 'subscribe',
subscription: { type: 'userFills', user: USER }
}));
if (lastDisconnectTime) {
backfillUserFills(lastDisconnectTime);
}
});
ws.on('message', (data) => {
const msg = JSON.parse(data);
if (msg.channel === 'userFills') {
for (const fill of msg.data) {
const id = fill.tid || fill.hash;
if (!seenFills.has(id)) {
addSeen(id);
console.log('Live fill:', fill);
}
}
} else if (msg.channel === 'trades') {
console.log('Trade:', msg.data);
}
});
ws.on('close', () => {
console.log('Disconnected');
lastDisconnectTime = Date.now();
setTimeout(connect, 1000);
});
ws.on('error', (err) => {
console.error('WebSocket error:', err);
});
}
connect();Reconciliación entre superficies en vivo y de pull
La reconciliación es el proceso de hacer coincidir los fills en vivo del WebSocket con sus contrapartes de la API Info. Las dos superficies pueden reportar el mismo fill con un orden o marcas de tiempo ligeramente diferentes porque son generadas por rutas internas distintas. Una estrategia de deduplicación basada solo en marcas de tiempo eliminará fills legítimos que comparten una marca de tiempo o duplicará fills que tienen marcas de tiempo ligeramente diferentes. El enfoque correcto es deduplicar por la identidad del fill —típicamente el id de trade (tid) o un hash de transacción— que es estable en ambas superficies.
Al rellenar después de una desconexión, obtén los userFills de la API Info para el período del vacío e inserta cualquier fill cuya identidad no esté ya en el conjunto de deduplicación. Debido a que la API Info puede devolver fills en un orden diferente, el cliente no debe asumir que el primer registro es el más antiguo. En su lugar, procesa todos los registros y confía en el conjunto de identidades. Para trades, se aplica el mismo principio: usa el id de trade para deduplicar entre el canal trades en vivo y la vista de trades por moneda de la API Info. Para un mecanismo relacionado, consulta Mecánica de las tasas de financiación de Hyperliquid.
- Coincidir por identidad de fill (tid/hash), no por marca de tiempo.
- Procesar todos los registros de relleno; no asumir el orden.
- Usar un conjunto acotado para limitar la memoria.
Ejemplo ejecutable en Node.js con deduplicación y relleno
El siguiente ejemplo en Node.js usa la librería ws para suscribirse a trades de una moneda y userFills de una cuenta. Mantiene un conjunto de deduplicación acotado, detecta desconexiones, rellena mediante la API Info y se vuelve a suscribir. El código es autocontenido y se puede ejecutar con node después de instalar ws y node-fetch. Reemplaza las constantes USER y COIN con tus propios valores.
El ejemplo demuestra la mecánica central: al abrir, envía mensajes de suscripción; al recibir un mensaje, analiza el canal y procesa fills; al cerrar, registra el tiempo de desconexión y programa una reconexión; al reconectar, rellena desde la API Info usando el tiempo registrado. El conjunto de deduplicación evita fills duplicados en el límite. Este patrón es esencial para cualquier integración en producción que requiera procesamiento exactly-once de fills.
// Full example is provided in the previous section. This section repeats the key logic for clarity.
// See the code block above for the complete runnable script.Tabla de resultados para autoevaluación
Para validar tu integración contra tu propio endpoint, mide las siguientes métricas. Completa la tabla con tus valores observados. Este es un método verificado por el lector; no se proporcionan números de referencia aquí porque dependen de tu red, proveedor y actividad de mercado. Usa una ventana de medición consistente (por ejemplo, 5 minutos) y registra los resultados.
La tabla debe incluir: rendimiento de mensajes (mensajes por segundo), campos observados por registro (enumera los campos que ves en los payloads de trades y userFills), duración del vacío en una reconexión forzada (tiempo entre la desconexión y la re-suscripción exitosa), registros rellenados (número de fills obtenidos de la API Info durante el relleno) y duplicados suprimidos (número de fills omitidos por el conjunto de deduplicación). Estos datos te ayudan a ajustar el tamaño de tu conjunto de deduplicación y tu estrategia de relleno.
- Rendimiento de mensajes: ___ mensajes/seg.
- Campos observados por registro: ___.
- Duración del vacío en reconexión forzada: ___ ms.
- Registros rellenados: ___.
- Duplicados suprimidos: ___.
Modos de fallo y resolución de problemas
Varios modos de fallo son comunes al integrarse con los canales WebSocket de Hyperliquid. Suscribirse a userFills sin autenticación dará como resultado que no haya datos o un error; asegúrate de que el parámetro user sea una dirección válida y de que la conexión esté autenticada si es necesario. Una discrepancia en el nombre de la moneda o en mayúsculas/minúsculas (por ejemplo, "eth" vs "ETH") no producirá trades; usa siempre el símbolo exacto como está documentado. Una conexión silenciosa que deja de entregar mensajes puede indicar un problema de red o un tiempo de espera inactivo del lado del servidor; implementa un ping/heartbeat y una verificación de actividad que espere un mensaje dentro de una ventana de tiempo de espera.
Los fills duplicados después de una reconexión ocurren cuando el límite no está deduplicado. Si rellenas desde la API Info y también recibes el mismo fill en el flujo en vivo, el conjunto de deduplicación debe detectarlo. Si ves duplicados, verifica que tu clave de identidad sea consistente en ambas superficies. Para problemas de límite de tasa durante re-suscripciones en ráfaga, consulta Límites de tasa de la API de Hyperliquid: Info versus Exchange. Para la disponibilidad de endpoints, consulta Endpoints RPC de Hyperliquid (RPC Assistant).
- userFills sin autenticación: sin datos.
- Discrepancia en el nombre de la moneda: sin trades.
- Conexión silenciosa: agregar heartbeat.
- Duplicados: verificar la clave de deduplicación.
Limitaciones y compensaciones
La profundidad histórica de la API Info es limitada; puede que no proporcione fills anteriores a una ventana determinada. Una interrupción prolongada puede requerir un relleno amplio que consuma una cantidad significativa de presupuesto de límite de tasa. El costo de un relleno amplio aumenta con el número de monedas y usuarios que rastreas. Además, la re-suscripción en ráfaga puede exceder los límites de conexión o de solicitudes, que varían según el proveedor. Consulta siempre la guía de Límites de tasa y diseña tu lógica de reconexión con retroceso exponencial.
Los canales WebSocket no reproducen mensajes perdidos, por lo que el cliente es responsable de la recuperación de vacíos. Esto significa que tu aplicación debe persistir la última identidad de fill vista y la marca de tiempo en disco o en una base de datos para sobrevivir a reinicios del proceso. La dependencia de la API Info para el relleno introduce una segunda superficie que debe reconciliarse, lo que agrega complejidad. Para el historial OHLCV, un enfoque diferente usando candleSnapshot puede ser más apropiado; consulta Construir el historial OHLCV de Hyperliquid desde candleSnapshot.
- La profundidad histórica de la API Info es limitada.
- Un relleno amplio consume límites de tasa.
- Sin reproducción: el cliente debe persistir el estado.
- Los límites del proveedor varían.
Próximos pasos y lecturas adicionales
Para profundizar tu comprensión, revisa la documentación autorizada de Hyperliquid para suscripciones WebSocket y formatos de datos, y el endpoint Info para userFills. Para una visión más amplia de la red Hyperliquid, consulta Página de la red Hyperliquid. Para detalles de precios y servicios, consulta Precios de RPC y Servicio de API. El centro de aprendizaje de OnFinality contiene guías adicionales sobre el uso de la API de Hyperliquid.
Al construir sistemas en producción, considera usar un proveedor de RPC gestionado para manejar la confiabilidad de la conexión y los límites de tasa. La página Endpoints RPC de Hyperliquid (RPC Assistant) puede ayudarte a encontrar endpoints adecuados. Prueba siempre tu integración contra tu propio endpoint y mide las métricas de la tabla de resultados para asegurar la corrección y el rendimiento.
- Revisar Hyperliquid Docs para suscripciones y formatos de datos.
- Usar la API Info para relleno y reconciliación.
- Medir tu propio rendimiento y recuperación de vacíos.
- Considerar RPC gestionado para confiabilidad.