Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Guías de red y protocolo13 min de lectura

API GraphQL de Sui: Consulta de datos de Sui más allá de JSON-RPC

Una guía práctica sobre la superficie de consulta GraphQL respaldada por el indexador de Sui, en qué se diferencia de JSON-RPC y cómo introspeccionarla y consultarla desde Node.js.

TL;DR

Sui expone datos a través de varias superficies: JSON-RPC con un vocabulario de métodos fijo, una API gRPC más reciente utilizada por el SDK de TypeScript actual y un esquema GraphQL respaldado por el indexador que presenta una vista relacional de objetos, transacciones, eventos y checkpoints. GraphQL permite al cliente especificar la forma exacta de la respuesta en un único POST, de modo que una transacción, sus efectos y los objetos que tocó se pueden recuperar en un solo viaje de ida y vuelta en lugar de varias llamadas JSON-RPC. Las solicitudes se envían como un único POST que contiene query, variables y operationName, y una consulta de introspección devuelve el esquema para que las herramientas puedan autocompletar y validar campos. Debido a que el endpoint GraphQL generalmente está respaldado por el indexador, puede retrasarse respecto a la punta de la cadena, y los campos del esquema y su disponibilidad varían según el proveedor y la versión de la red, por lo que la introspección antes de confiar en un campo es esencial. GraphQL es de solo lectura: las transacciones aún se envían a través de JSON-RPC o gRPC.

Las superficies de acceso a datos de Sui y dónde encaja GraphQL

Sui expone los datos de la cadena a través de más de una interfaz, y cada una está optimizada para un estilo de consumo diferente. JSON-RPC es la superficie orientada a métodos: el cliente llama a métodos con nombre como sui_getObject o sui_getTransactionBlock, y cada llamada devuelve una carga útil fija definida por el método. La API gRPC más reciente es utilizada por el SDK de TypeScript actual y proporciona una interfaz tipada y apta para streaming para muchas de las mismas operaciones. El esquema GraphQL respaldado por el indexador se sitúa junto a estas como una vista relacional sobre objetos, transacciones, eventos y checkpoints, con paginación y selección anidada integradas en el propio esquema.

La distinción importa porque las superficies no son intercambiables. JSON-RPC y gRPC son procedimentales: pides algo específico y recibes una forma específica. GraphQL es declarativo: describes la forma que deseas y el servidor devuelve exactamente eso, lo cual es útil cuando un panel o indexador necesita varias entidades relacionadas a la vez. Las referencias de la API de Sui documentan estas superficies como opciones distintas de acceso a datos, y la guía de RPC de Sui cubre el vocabulario de métodos JSON-RPC en detalle.

Para los lectores que vienen del mundo JSON-RPC, el cambio de modelo mental es que GraphQL no es un reemplazo para el envío de transacciones. Es una superficie de lectura. Todavía transmites transacciones a través de JSON-RPC o gRPC; GraphQL es donde ensamblas la vista de lectura de lo que sucedió.

  • JSON-RPC: vocabulario de métodos fijo, cargas útiles de respuesta fijas, una preocupación por llamada.
  • gRPC: interfaz tipada utilizada por el SDK de TypeScript actual, adecuada para streaming e integración con SDK.
  • GraphQL: esquema relacional respaldado por el indexador sobre objetos, transacciones, eventos y checkpoints, con selección anidada y paginación por cursor.

Qué es GraphQL y por qué el cliente controla la forma de la respuesta

GraphQL es un lenguaje de consulta tipado y un entorno de ejecución para API, servido a través de un único endpoint. En lugar de exponer muchos endpoints o métodos, expone un esquema de tipos y campos, y el cliente envía una consulta que describe exactamente qué campos quiere. El servidor valida la consulta contra el esquema y devuelve una respuesta JSON cuya forma refleja la consulta. La documentación de aprendizaje de GraphQL describe esto como el contrato central: un endpoint, un esquema tipado y selección especificada por el cliente.

En un flujo de trabajo JSON-RPC de Sui, obtener una transacción, sus efectos y los objetos que tocó normalmente implica una llamada para la transacción y luego llamadas adicionales para cada objeto o efecto que necesites. Cada llamada devuelve una carga útil fija, por lo que a menudo recibes más campos de los que usas y aún necesitas más llamadas para armar el panorama completo. GraphQL invierte esto: escribes una consulta que selecciona la transacción, sus efectos y los objetos que tocó como campos anidados, y el servidor devuelve una única respuesta que contiene solo esos campos.

Este es el mecanismo detrás de la reducción de viajes de ida y vuelta. No es que GraphQL sea inherentemente más rápido por byte; es que el cliente puede expresar una lectura de múltiples entidades como una sola operación en lugar de N operaciones. Para los indexadores y paneles que ensamblan repetidamente la misma vista relacional, esa diferencia se acumula.

Por qué GraphQL importa para indexadores y paneles

Los indexadores y paneles comparten un patrón común: necesitan una transacción más sus efectos más los objetos que tocó, a menudo para muchas transacciones en secuencia. En JSON-RPC ese patrón se convierte en una expansión de llamadas, y cada llamada consume unidades de solicitud y agrega un viaje de ida y vuelta. GraphQL colapsa la expansión en una sola consulta con selección anidada, lo que reduce tanto los viajes de ida y vuelta como el consumo de unidades de solicitud para la misma lectura lógica.

La paginación basada en cursor es parte del esquema en lugar de una ocurrencia tardía. En lugar de rastrear desplazamientos manualmente, solicitas una página y recibes un cursor que pasas a la siguiente consulta. Este es el mismo patrón descrito en la guía Lecturas de objetos de Sui y paginación de campos dinámicos para JSON-RPC, pero expresado como campos del esquema. Para un panel que pagina a través de checkpoints o eventos, el cursor se convierte en el token de continuación estable.

La vista relacional también ayuda con uniones que son incómodas en una API orientada a métodos. Si necesitas un evento y la transacción que lo emitió, o un checkpoint y las transacciones que contiene, el esquema puede expresar esa relación directamente. La guía Flujo de checkpoints y servicio de ledger de Sui cubre el lado del checkpoint de ese panorama, y la guía Efectos de transacción y cambios de objetos en Sui cubre cómo se estructuran los efectos cuando realmente necesitas analizarlos.

  • Una consulta puede seleccionar una transacción, sus efectos y los objetos que tocó.
  • La paginación por cursor es un campo del esquema, no un cálculo manual de desplazamiento.
  • La selección anidada reduce el número de llamadas necesarias para ensamblar una vista relacional.
  • Menos llamadas generalmente significa menos unidades de solicitud consumidas para la misma lectura.

En qué se diferencia una solicitud GraphQL de una solicitud JSON-RPC

Una solicitud GraphQL es un único POST HTTP al endpoint GraphQL con un cuerpo JSON que contiene query, variables y opcionalmente operationName. El campo query contiene el documento GraphQL, variables contiene los valores referenciados por ese documento, y operationName desambigua cuando un documento contiene más de una operación. La respuesta es un objeto JSON con un campo data y, cuando algo sale mal, un arreglo errors.

Una solicitud JSON-RPC también es un POST, pero su cuerpo es un sobre JSON-RPC 2.0 con jsonrpc, method, params e id. La especificación JSON-RPC 2.0 define este modelo orientado a métodos: el cliente nombra un método y pasa parámetros posicionales o con nombre, y el servidor devuelve un resultado o un error identificado por el mismo id. No hay negociación de esquema en la solicitud misma; el vocabulario de métodos lo fija el servidor.

La consecuencia práctica es que las solicitudes GraphQL son autodescriptivas de una manera en que las solicitudes JSON-RPC no lo son. Una consulta GraphQL nombra los campos que quiere, por lo que la forma de la respuesta es visible en la solicitud. Una llamada JSON-RPC nombra un método, y la forma de la respuesta se define en otro lugar. Por eso las herramientas GraphQL pueden autocompletar y validar contra el esquema, mientras que las herramientas JSON-RPC dependen de la documentación o de clientes generados.

// JSON-RPC 2.0 request envelope (method-oriented)
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "sui_getObject",
  "params": ["0xOBJECT_ID", { "showType": true }]
}

// GraphQL request body (client-specified selection)
{
  "query": "query GetObject($id: SuiAddress!) { object(address: $id) { address version digest } }",
  "variables": { "id": "0xOBJECT_ID" },
  "operationName": "GetObject"
}

Introspección: confirmar el esquema antes de confiar en los campos

La introspección es el mecanismo de GraphQL que devuelve el propio esquema como datos. Un cliente puede preguntar qué tipos existen, qué campos tiene cada tipo y qué argumentos aceptan esos campos. La documentación de aprendizaje de GraphQL describe la introspección como la base para herramientas como autocompletado, validación y exploradores de esquemas. Para Sui, la introspección es la forma confiable de confirmar que un campo que pretendes usar realmente existe en el endpoint que estás consultando.

Esto importa porque el esquema GraphQL de Sui y su disponibilidad varían según el proveedor y la versión de la red. Un campo que existe en un endpoint puede estar ausente o renombrado en otro, y una consulta que funciona contra un endpoint de testnet puede fallar contra mainnet. Introspeccionar primero convierte un fallo en tiempo de ejecución en una restricción conocida. También te dice si la introspección está habilitada: deshabilitarla en producción es común, y cuando está deshabilitada debes confiar en una consulta fija en lugar de herramientas generadas.

El ejemplo a continuación envía una consulta de introspección para confirmar que el esquema es accesible. Es deliberadamente pequeño: pide el nombre del tipo de consulta y algunos de sus campos, lo cual es suficiente para probar que el endpoint responde con un esquema. Una consulta de introspección completa devuelve todo el sistema de tipos y es mucho más grande.

// introspection.mjs — confirm the GraphQL schema is reachable
const ENDPOINT = process.env.SUI_GRAPHQL_ENDPOINT;

const introspectionQuery = `
  query IntrospectQueryType {
    __schema {
      queryType {
        name
        fields {
          name
          description
        }
      }
    }
  }
`;

const res = await fetch(ENDPOINT, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({ query: introspectionQuery, operationName: "IntrospectQueryType" })
});

const json = await res.json();
if (json.errors) {
  console.error("Introspection failed:", json.errors);
  process.exit(1);
}

const queryType = json.data.__schema.queryType;
console.log("Query type:", queryType.name);
console.log("Fields:", queryType.fields.map((f) => f.name).join(", "));

Una consulta ejecutable en Node.js para una transacción y sus efectos

Una vez confirmado el esquema, se puede seleccionar una transacción concreta y sus efectos usando variables. El ejemplo a continuación usa fetch, que está disponible en las versiones actuales de Node.js, y pasa el digest de la transacción como una variable en lugar de interpolarlo en la cadena de consulta. Usar variables es el patrón recomendado porque mantiene estable el documento de consulta y permite que el servidor valide el valor contra el tipo del esquema.

La consulta selecciona una transacción por digest y pide sus efectos y los objetos que tocó. Los nombres exactos de los campos dependen de la versión del esquema expuesta por tu endpoint, por lo que el paso de introspección va primero. Si un nombre de campo difiere, el servidor devuelve un error nombrando el campo desconocido, y ajustas la consulta contra el esquema introspeccionado en lugar de adivinar.

La respuesta es un objeto JSON cuya forma de data refleja la consulta. Debido a que el cliente especificó la selección, no hay necesidad de filtrar campos no utilizados después. Esta es la reducción de viajes de ida y vuelta en la práctica: un solo POST devuelve la transacción, sus efectos y los objetos relacionados juntos.

// query-transaction.mjs — fetch a transaction and its effects in one round-trip
const ENDPOINT = process.env.SUI_GRAPHQL_ENDPOINT;
const DIGEST = process.env.SUI_TX_DIGEST;

const query = `
  query TransactionWithEffects($digest: String!) {
    transaction(digest: $digest) {
      digest
      effects {
        status
        timestamp
        objectChanges {
          address
          inputState
          outputState
        }
      }
    }
  }
`;

const res = await fetch(ENDPOINT, {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    query,
    variables: { digest: DIGEST },
    operationName: "TransactionWithEffects"
  })
});

const json = await res.json();
if (json.errors) {
  console.error("Query errors:", json.errors);
  process.exit(1);
}

console.log(JSON.stringify(json.data.transaction, null, 2));

Medir viajes de ida y vuelta y bytes contra tu propio endpoint

El valor de GraphQL para una carga de trabajo dada es una cuestión empírica, y la forma honesta de responderla es medir contra el endpoint que realmente usas. La tabla a continuación es una plantilla: complétala con tus propias observaciones en lugar de confiar en números de otro entorno. Ejecuta la misma tarea lógica dos veces, una como una secuencia de llamadas JSON-RPC y otra como una sola consulta GraphQL, y registra las llamadas, los bytes y los viajes de ida y vuelta de cada una.

Registra el cursor de paginación utilizado para cada página para que la comparación sea reproducible. Si una tarea abarca varias páginas, anota el valor del cursor para que otro lector pueda reproducir la misma secuencia. Los bytes se pueden medir a partir de la longitud del cuerpo de la respuesta, y los viajes de ida y vuelta se pueden contar como el número de solicitudes HTTP emitidas. Mantén la definición de la tarea idéntica en ambas columnas para que la comparación sea significativa.

Debido a que el comportamiento del proveedor varía, trata cualquier medición individual como específica de ese endpoint, red y momento. El método es lo que se transfiere: define la tarea, ejecuta ambas superficies y registra los números.

  • Tarea: describe la lectura lógica en una frase, por ejemplo, 'obtener la transacción X con sus efectos y los objetos tocados'.
  • Llamadas JSON-RPC: cuenta el número de llamadas a métodos emitidas.
  • Llamadas GraphQL: cuenta el número de solicitudes POST emitidas.
  • Bytes totales: suma los tamaños de los cuerpos de respuesta de cada superficie.
  • Viajes de ida y vuelta: cuenta las solicitudes HTTP, incluidos los reintentos.
  • Cursor de paginación utilizado: registra el valor del cursor para cada página para que la ejecución sea reproducible.

Limitaciones y compensaciones de la superficie GraphQL

El endpoint GraphQL generalmente está respaldado por el indexador, lo que significa que puede retrasarse respecto a la punta de la cadena. Una transacción que acaba de finalizar puede no aparecer aún en el índice, por lo que un panel que lee inmediatamente después del envío puede observar un vacío. Esta es una propiedad del pipeline de indexación, no un defecto de GraphQL, pero cambia cómo diseñas los flujos de lectura después de escritura. Si necesitas la vista más fresca posible, JSON-RPC o gRPC pueden ser la mejor superficie para esa lectura específica.

Los campos del esquema y su disponibilidad varían según el proveedor y la versión de la red. Un campo presente en un endpoint puede estar ausente en otro, y una consulta que funciona en testnet puede necesitar ajustes en mainnet. Introspeccionar antes de confiar en un campo es la mitigación práctica, pero no elimina la variación. Cuando la introspección está deshabilitada en producción, lo cual es común, las herramientas generadas no pueden descubrir el esquema, y se debe mantener una consulta fija a mano.

GraphQL es de solo lectura. No envía transacciones; eso sigue siendo tarea de JSON-RPC o gRPC. Por lo tanto, una aplicación completa usa más de una superficie: GraphQL para lecturas relacionales, y JSON-RPC o gRPC para el envío y para lecturas que no deben retrasarse. La guía Suscripciones WebSocket de RPC de Sui cubre el lado de streaming para lectores que necesitan actualizaciones de tipo push en lugar de sondeo.

  • Los endpoints respaldados por el indexador pueden retrasarse respecto a la punta de la cadena.
  • Los campos del esquema y su disponibilidad varían según el proveedor y la versión de la red.
  • La introspección a menudo está deshabilitada en producción, lo que requiere consultas fijas.
  • GraphQL es de solo lectura; el envío de transacciones permanece en JSON-RPC o gRPC.
  • Una aplicación completa normalmente usa más de una superficie de acceso a datos.

Solución de problemas comunes de fallos en consultas GraphQL

La mayoría de los fallos de GraphQL caen en un pequeño número de categorías, y la respuesta de error generalmente nombra la causa. Un error de validación significa que la consulta hace referencia a un campo o argumento que no existe en el esquema; la solución es introspeccionar y corregir el nombre del campo o el tipo del argumento. Un error de ejecución significa que la consulta era válida pero el resolver falló, a menudo porque la entidad solicitada no existe o el indexador aún no la ha visto.

Un campo data ausente con un arreglo errors es la forma estándar de error de GraphQL. Lee primero las entradas de errors: incluyen un mensaje y a menudo una ruta que apunta al campo que falló. Si el error menciona un campo desconocido, el esquema en ese endpoint difiere de lo que asumiste. Si el error menciona una discrepancia de tipos, verifica que tus variables coincidan con los tipos de argumento declarados.

Si la introspección misma falla, el endpoint puede tener la introspección deshabilitada, o el endpoint puede no ser un endpoint GraphQL en absoluto. Confirma la URL y el método HTTP: GraphQL es un POST a un único endpoint, no una llamada a método. Si la respuesta es HTML en lugar de JSON, la solicitud probablemente llegó a un servidor web en lugar del manejador de GraphQL.

  • Error de validación: campo o argumento no está en el esquema — introspecciona y corrige.
  • Error de ejecución: el resolver falló — verifica la existencia de la entidad y la frescura del indexador.
  • Campo desconocido en errors: el esquema difiere de tu suposición.
  • Discrepancia de tipos: las variables no coinciden con los tipos de argumento declarados.
  • Fallo de introspección: introspección deshabilitada o endpoint incorrecto.
  • Respuesta HTML: la solicitud llegó a un servidor web, no al manejador de GraphQL.

Próximos pasos para construir sobre la superficie GraphQL de Sui

El camino práctico es introspeccionar primero, luego escribir consultas contra el esquema confirmado, y después medir la carga de trabajo contra tu propio endpoint. Comienza con una consulta pequeña que seleccione una sola entidad, confirma la forma de la respuesta y amplía a selección anidada una vez que lo básico funcione. Mantén el documento de consulta estable y pasa los valores como variables para que el servidor pueda validarlos contra el esquema.

Para equipos que ejecutan indexadores o paneles, el centro de aprendizaje de OnFinality recopila guías relacionadas sobre acceso a datos de Sui, y la página de la red Sui cubre el contexto de la red. Si estás evaluando endpoints para una carga de trabajo en producción, la página de precios de RPC y la página de servicio de API describen el lado comercial, mientras que la guía de RPC de Sui sigue siendo la referencia para el vocabulario de métodos JSON-RPC que aún necesitarás para el envío.

Un próximo experimento razonable es tomar un panel de dashboard que actualmente se expande en varias llamadas JSON-RPC y reescribirlo como una sola consulta GraphQL, luego completar la tabla de resultados de la sección de medición. Eso te da una comparación concreta y reproducible para tu propio entorno en lugar de un número prestado.

  • Introspecciona el endpoint antes de escribir consultas.
  • Comienza con una consulta de una sola entidad, luego amplía a selección anidada.
  • Pasa los valores como variables para que el servidor los valide.
  • Mide un panel de dashboard real contra ambas superficies.
  • Mantén JSON-RPC o gRPC para el envío de transacciones y las lecturas más frescas.

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar