Las puertas de enlace de Sui RPC miden las solicitudes mediante unidades de cómputo estimadas por método, con ventanas móviles y encabezados de costo. Las consultas pesadas como queryTransactionBlocks y multiGetCoins dominan el costo. Este artículo explica el mecanismo, proporciona ejemplos ejecutables del SDK de TypeScript para paginación y optimización de costos, y discute el manejo de errores 429 con retirada, además de la transición en curso hacia GraphQL.
Respuesta directa: Lo que necesitas saber sobre los límites de tasa de Sui RPC
Los límites de tasa de Sui RPC no son simplemente un número fijo de solicitudes por segundo. La puerta de enlace de Sui estima un costo de unidad de cómputo para cada método, y tu uso se mide contra una ventana móvil. Métodos pesados como queryTransactionBlocks y multiGetCoins consumen muchas más unidades que llamadas ligeras como getObject. Cuando excedes las unidades asignadas, recibes respuestas HTTP 429. Para gestionar costos y evitar errores 429 en producción, debes dar forma a tus consultas: usa paginación, evita la paginación vertical profunda y prefiere GraphQL a medida que se convierte en la interfaz recomendada.
Este artículo explica el mecanismo de contabilidad de unidades de cómputo, muestra cómo escribir consultas eficientes en costos con el SDK de TypeScript de Sui y proporciona una estrategia de retirada para manejar errores 429. También cubrimos los cambios documentados en los límites de tasa de RPC públicos anunciados por la Fundación Sui y la transición en curso de JSON-RPC heredado a GraphQL.
Cómo funcionan las unidades de cómputo en Sui RPC
La puerta de enlace de Sui asigna un costo estimado de unidad de cómputo a cada método RPC. Esta estimación refleja el trabajo del lado del servidor requerido para cumplir la solicitud. Por ejemplo, queryTransactionBlocks con un tamaño de página grande puede escanear muchas transacciones, mientras que multiGetCoins obtiene múltiples objetos de moneda en una sola llamada. Los valores exactos de las unidades no están documentados públicamente en una tabla fija, pero la documentación de Sui sobre mejores prácticas de RPC señala que ciertos métodos son más costosos y recomienda la paginación para limitar la carga.
La puerta de enlace aplica límites de tasa usando una ventana móvil. En lugar de un simple contador por segundo, se te asigna un presupuesto de unidades de cómputo sobre una ventana de tiempo deslizante (por ejemplo, por minuto o por hora). Cada solicitud deduce su costo estimado de tu presupuesto actual. Cuando el presupuesto se agota, la puerta de enlace devuelve un 429 con un encabezado Retry-After o una indicación similar. Los encabezados de respuesta incluyen x-sui-rpc-units (o similar) para mostrar el costo de la solicitud, lo que te permite monitorear tu consumo.
Es importante tener en cuenta que estos valores de unidad son estimaciones, no mediciones exactas. La carga real puede variar según el estado de la red y el tamaño de los datos devueltos. Por lo tanto, trata los valores de unidad como una guía para dar forma a tus consultas, no como un medidor de facturación preciso.
- Métodos pesados:
queryTransactionBlocks,queryEvents,multiGetTransactionBlocks,multiGetCoins - Métodos ligeros:
getObject,getBalance,getChainIdentifier - Ventana móvil: presupuesto de unidades de cómputo sobre un período de tiempo deslizante
- Encabezados:
x-sui-rpc-units(o similar) indican el costo por solicitud
Paginación: vertical vs horizontal
La paginación es la herramienta principal para controlar el consumo de unidades de cómputo. Los métodos RPC de Sui como queryTransactionBlocks y queryEvents devuelven un nextCursor que puedes usar para obtener la siguiente página. Hay dos estrategias de paginación: vertical y horizontal.
La paginación vertical significa obtener una gran cantidad de elementos en una sola solicitud estableciendo un limit alto (por ejemplo, 1000). Esto es eficiente en términos de viajes de ida y vuelta, pero puede ser costoso en unidades de cómputo porque la puerta de enlace debe procesar y serializar una carga útil grande. La paginación horizontal significa usar un limit más pequeño (por ejemplo, 50) y hacer múltiples solicitudes para recorrer los datos. Esto distribuye la carga en múltiples solicitudes, cada una con un costo de unidad más bajo, y generalmente es recomendado por la documentación de Sui para evitar tiempos de espera y límites de tasa.
La documentación de Sui sobre mejores prácticas de RPC aconseja explícitamente usar paginación y evitar tamaños de página grandes. Por ejemplo, al consultar bloques de transacciones, usa un limit de 50 o menos, y sigue siempre el nextCursor hasta que devuelva null. Este enfoque reduce el consumo máximo de unidades de cómputo por solicitud y hace que tu uso sea más predecible.
Ejemplo ejecutable: Consultas que optimizan costos con el SDK de TypeScript de Sui
A continuación se muestra un ejemplo autónomo que utiliza el SDK de TypeScript de Sui. Demuestra cómo consultar bloques de transacciones con paginación horizontal, cómo obtener múltiples monedas con multiGetCoins y cómo manejar errores 429 con retirada exponencial. El ejemplo usa el endpoint público de Testnet de Sui, pero puedes reemplazarlo con tu propia URL de RPC desde la página de red de Sui de OnFinality.
El código primero crea un SuiClient con un envoltorio de fetch personalizado que intercepta respuestas 429 y reintenta con retirada. Luego define una función para consultar bloques de transacciones en páginas de 50, imprimiendo el digest y el encabezado de unidades de cómputo si está disponible. Finalmente, demuestra multiGetCoins con una lista de IDs de objetos de moneda.
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
// Custom fetch wrapper to handle 429 with exponential backoff
async function fetchWithRetry(url: string, options: any, retries = 3): Promise<Response> {
let attempt = 0;
while (attempt <= retries) {
const response = await fetch(url, options);
if (response.status === 429 && attempt < retries) {
const retryAfter = response.headers.get('retry-after');
const delayMs = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, attempt) * 1000;
console.log(`429 received, retrying in ${delayMs}ms`);
await new Promise(resolve => setTimeout(resolve, delayMs));
attempt++;
continue;
}
return response;
}
throw new Error('Exhausted retries due to 429');
}
// Create a SuiClient with the custom fetch
const client = new SuiClient({
url: getFullnodeUrl('testnet'), // Replace with your own RPC URL
fetch: fetchWithRetry as any,
});
// Horizontal pagination for queryTransactionBlocks
async function queryAllTransactionBlocks() {
let cursor: string | null = null;
let hasNextPage = true;
while (hasNextPage) {
const page = await client.queryTransactionBlocks({
cursor,
limit: 50, // small page size to control compute units
order: 'descending',
});
console.log(`Fetched ${page.data.length} blocks, nextCursor: ${page.hasNextPage ? page.nextCursor : 'null'}`);
// Process each block digest
for (const block of page.data) {
console.log(block.digest);
}
// Check for next page
if (page.hasNextPage && page.nextCursor) {
cursor = page.nextCursor;
} else {
hasNextPage = false;
}
}
}
// Example of multiGetCoins (heavy method)
async function getMultipleCoins(coinIds: string[]) {
const coins = await client.multiGetCoins({ ids: coinIds });
console.log(`Fetched ${coins.data.length} coins`);
for (const coin of coins.data) {
console.log(coin.coinObjectId, coin.balance);
}
}
// Run the example
async function main() {
await queryAllTransactionBlocks();
// Replace with actual coin IDs
await getMultipleCoins(['0x...', '0x...']);
}
main().catch(console.error);Resultados esperados y cómo verificar
Cuando ejecutes el ejemplo, deberías ver una serie de líneas de registro que muestran cada página de bloques de transacciones. La llamada queryTransactionBlocks devolverá un nextCursor hasta que todas las páginas estén agotadas. La llamada multiGetCoins devolverá los objetos de moneda para los IDs proporcionados.
Para verificar que tus consultas son eficientes en costos, inspecciona los encabezados de respuesta. La puerta de enlace de Sui incluye un encabezado como x-sui-rpc-units que indica las unidades de cómputo consumidas por la solicitud. Puedes registrar este encabezado en tu envoltorio de fetch para monitorear tu uso. Por ejemplo, modifica la función fetchWithRetry para imprimir response.headers.get('x-sui-rpc-units') para cada respuesta exitosa.
También, verifica el encabezado Retry-After en las respuestas 429. La puerta de enlace puede proporcionar un tiempo de espera sugerido. Nuestra lógica de retirada usa ese encabezado si está presente, de lo contrario, recurre a la retirada exponencial (1s, 2s, 4s). Este es un patrón documentado para manejar límites de tasa en APIs HTTP.
Fallos comunes y soluciones
Un fallo común es recibir errores 429 porque estás usando un limit grande (por ejemplo, 1000) en queryTransactionBlocks. La solución es reducir el límite a 50 o menos y usar paginación horizontal. Otro fallo es no seguir el nextCursor correctamente, lo que lleva a bucles infinitos o pérdida de datos. Siempre verifica hasNextPage y actualiza el cursor solo cuando no sea nulo.
Otro problema es usar multiGetCoins con una matriz muy grande de IDs de monedas. Este método es pesado porque obtiene múltiples objetos en una sola llamada. Si tienes muchas monedas, considera agrupar los IDs en grupos más pequeños (por ejemplo, 50 por llamada) para reducir el costo de unidad de cómputo por solicitud.
Finalmente, si estás usando la interfaz JSON-RPC heredada, puedes encontrar límites de tasa más estrictos que la interfaz GraphQL. La Fundación Sui ha anunciado cambios en los límites de tasa de RPC públicos, y la recomendación es migrar a GraphQL para una mejor eficiencia y menores costos. Consulta el anuncio del foro de Sui para más detalles (nota: es un registro de anuncio, no un punto de referencia).
Compensaciones y limitaciones
La paginación horizontal reduce el consumo de unidades de cómputo por solicitud, pero aumenta el número de solicitudes, lo que puede sumar un consumo total de unidades más alto si estás recorriendo un conjunto de datos grande. Hay una compensación entre el número de solicitudes y el costo por solicitud. Debes probar diferentes tamaños de página para encontrar el punto óptimo para tu carga de trabajo.
Los valores de unidad de cómputo son estimaciones y pueden cambiar a medida que evoluciona la red de Sui. La documentación de Sui es la fuente autorizada para las mejores prácticas actuales, pero no publica una tabla fija de costos de unidad. Por lo tanto, debes monitorear tu uso real a través del encabezado x-sui-rpc-units y ajustar tus consultas en consecuencia.
La transición de JSON-RPC a GraphQL está en curso. Aunque GraphQL es más flexible y a menudo más eficiente, tiene una sintaxis de consulta diferente y requiere una curva de aprendizaje. La documentación de Sui proporciona una guía de migración, pero debes probar tus consultas a fondo antes de cambiar en producción.
Próximos pasos y lecturas adicionales
Para aprovechar al máximo Sui RPC, comienza revisando la documentación oficial de Mejores prácticas de RPC de Sui. Luego, explora la guía de RPC de Sui de OnFinality para consejos específicos del proveedor. Si gestionas múltiples endpoints, considera usar el monitoreo y conmutación por error de RPC de OnFinality para garantizar alta disponibilidad.
Para cargas de trabajo de producción, es posible que desees usar un servicio de RPC dedicado como el servicio de API de OnFinality para obtener límites de tasa más altos y recursos dedicados. Consulta la página de precios para opciones. Además, mantente actualizado sobre los últimos cambios de RPC de Sui siguiendo el Foro de desarrolladores de Sui.
Finalmente, a medida que el ecosistema se mueve hacia GraphQL, comienza a experimentar con la interfaz GraphQL de Sui. La documentación de GraphQL de Sui proporciona ejemplos y guías de migración. Al adoptar estas prácticas, puedes gestionar costos y evitar errores 429 de manera efectiva.