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

Leer saldos y metadatos de monedas de Sui vía RPC

Una guía práctica del modelo de monedas de Sui: consulta de saldos, metadatos y objetos Coin vía JSON-RPC, con ejemplos ejecutables y una tabla de resultados.

TL;DR

Sui distingue entre un Balance —una cantidad escalar de un tipo de moneda que posee una dirección— y los objetos Coin, que son objetos individuales en propiedad cuya suma da ese balance. Los métodos JSON-RPC sui_getBalance y sui_getAllBalances devuelven balances, mientras que sui_getCoins enumera los objetos Coin subyacentes. Los metadatos como decimals y symbol provienen de sui_getCoinMetadata, y decimals es necesario para convertir balances enteros en bruto a cantidades legibles para humanos. Esta guía explica el modelo de monedas, muestra ejemplos ejecutables en Node.js con el SDK de TypeScript de Sui y proporciona una tabla de resultados reproducible para verificar el comportamiento de tu endpoint.

El modelo de monedas de Sui: Balance frente a objetos Coin

En Sui, un Balance es un valor escalar que representa cuánto de un tipo de moneda específico posee una dirección. No es un objeto en sí mismo; es una cantidad derivada que la red calcula a partir del conjunto de objetos Coin en propiedad de esa dirección. El método JSON-RPC sui_getBalance devuelve este escalar para un tipo de moneda dado, y sui_getAllBalances devuelve todos los balances de todos los tipos de moneda que posee una dirección.

Una Coin es un objeto individual en propiedad de un tipo de moneda específico. Cada objeto Coin tiene su propio ID de objeto, versión y un campo balance. La suma de los campos balance de todos los objetos Coin de un tipo de moneda dado que posee una dirección es igual al Balance devuelto por sui_getBalance. El método sui_getCoins enumera estos objetos Coin, paginados por un cursor.

Confundir estos dos conceptos lleva a totales incorrectos. Si sumas los balances de los objetos Coin devueltos por sui_getCoins pero omites algunos debido a la paginación, contarás de menos. Si tratas el Balance como un ID de objeto, no podrás construir transacciones válidas. La documentación de Sui sobre conceptos de monedas explica esta distinción en detalle.

  • Balance: cantidad escalar por tipo de moneda, devuelta por sui_getBalance y sui_getAllBalances.
  • Objeto Coin: objeto individual en propiedad con su propio ID y balance, enumerado por sui_getCoins.
  • La suma de los balances de los objetos Coin es igual al Balance de ese tipo de moneda.
  • coinObjectCount en la respuesta de balance indica cuántos objetos Coin respaldan ese balance.

Identificadores de tipo de moneda y por qué son la clave de consulta

Cada moneda en Sui se identifica mediante una cadena de tipo Move totalmente cualificada, no por un símbolo. Para el token nativo, el tipo de moneda es 0x2::sui::SUI. Para monedas personalizadas, el formato es <packageId>::<module>::<struct>, por ejemplo 0x2::sui::SUI o 0x1234...::my_coin::MY_COIN. Esta cadena es la clave de consulta para todos los métodos RPC relacionados con monedas.

Símbolos como "SUI" o "USDC" son metadatos, no identificadores. Dos tipos de moneda diferentes podrían teóricamente compartir un símbolo, y los símbolos pueden cambiar si se actualizan los metadatos. Usa siempre la cadena de tipo de moneda al llamar a sui_getBalance, sui_getCoinMetadata o sui_getCoins.

Las cadenas de tipo de moneda son específicas de cada red. Un tipo de moneda que existe en Sui Mainnet puede no existir en Testnet o Devnet. Al crear aplicaciones, asegúrate de que el tipo de moneda sea configurable o se derive del contexto de la red. La referencia de la API JSON-RPC de Sui enumera los formatos exactos de los parámetros de cada método.

  • Token nativo: 0x2::sui::SUI.
  • Moneda personalizada: <packageId>::<module>::<struct>.
  • Los símbolos son metadatos; los tipos de moneda son identificadores.
  • Los tipos de moneda difieren entre redes (Mainnet, Testnet, Devnet).

Leer metadatos de monedas: decimales, símbolo y nombre

El método sui_getCoinMetadata devuelve los metadatos de un tipo de moneda: decimals, name, symbol, description e iconUrl. El campo decimals es crítico porque los balances en bruto son enteros. Para convertir un balance en bruto a una cantidad legible para humanos, divide entre 10 elevado a la potencia de decimals.

Por ejemplo, si decimals es 9, un balance en bruto de 1.000.000.000 representa 1,0 SUI. Si decimals es 6, un balance en bruto de 1.000.000 representa 1,0 USDC. Sin los decimales correctos, las cantidades mostradas se desviarán en órdenes de magnitud.

Los metadatos pueden faltar en algunas monedas, especialmente en aquellas con metadatos mal formados o no registrados. En tales casos, sui_getCoinMetadata puede devolver null o un error. Tu aplicación debe manejar la ausencia de metadatos con elegancia, quizás recurriendo a un valor de decimales predeterminado o mostrando la cantidad en bruto con una advertencia.

  • decimals es necesario para la conversión legible: raw / 10^decimals.
  • symbol y name son solo para mostrar; no los uses como claves de consulta.
  • iconUrl apunta a una imagen; valida la URL antes de renderizarla.
  • Es posible que falten metadatos; maneja las respuestas null.

Consultar balances: sui_getBalance y sui_getAllBalances

sui_getBalance toma una dirección de propietario y un tipo de moneda, y devuelve un objeto con coinType, coinObjectCount, totalBalance y lockedBalance. El totalBalance es la suma de todos los balances de los objetos Coin de ese tipo de moneda. El lockedBalance representa monedas que están bloqueadas, por ejemplo debido a vesting o staking, y que no son gastables de inmediato.

sui_getAllBalances toma solo una dirección de propietario y devuelve un array de tales objetos de balance para todos los tipos de moneda que posee esa dirección. Esto es útil para vistas de portafolio o cuando no sabes qué tipos de moneda posee una dirección.

Ambos métodos reflejan el estado del checkpoint actual del nodo. Si una transacción se acaba de enviar y aún no se ha incluido en un checkpoint, el balance puede no reflejarla. Para lecturas consistentes, puedes especificar un número de secuencia de checkpoint si el método lo admite, o esperar a que la transacción se finalice.

  • sui_getBalance devuelve coinType, coinObjectCount, totalBalance, lockedBalance.
  • lockedBalance debe excluirse al calcular fondos gastables.
  • sui_getAllBalances devuelve un array de objetos de balance para todos los tipos de moneda.
  • Las lecturas reflejan el checkpoint actual del nodo; las transacciones recientes pueden no estar incluidas.

Enumerar objetos Coin con sui_getCoins y paginación

sui_getCoins devuelve una lista paginada de objetos Coin para un propietario y un tipo de moneda dados. Cada página incluye un array data de objetos Coin y un campo nextCursor. Para enumerar todos los objetos Coin, debes llamar repetidamente al método con el cursor hasta que nextCursor sea null o hasNextPage sea false.

El número de objetos Coin devueltos por sui_getCoins puede diferir del coinObjectCount en la respuesta de balance si algunos objetos Coin están bloqueados. Las monedas bloqueadas siguen siendo propiedad de la dirección, pero pueden no ser devueltas por sui_getCoins según la implementación del nodo. Verifica siempre la suma de los balances de los objetos Coin devueltos contra el totalBalance para detectar discrepancias.

La paginación es esencial para direcciones con muchos objetos Coin. Una sola llamada puede devolver solo un número limitado de objetos, y el límite es específico del proveedor. El SDK de TypeScript de Sui proporciona métodos auxiliares que manejan la paginación automáticamente, pero entender el mecanismo del cursor es importante para el uso de JSON-RPC en bruto.

  • sui_getCoins devuelve data y nextCursor; itera hasta que nextCursor sea null.
  • El recuento puede diferir de coinObjectCount si algunas monedas están bloqueadas.
  • Suma los campos balance de los objetos Coin devueltos para verificarlos contra totalBalance.
  • Los límites de tamaño de página varían según el proveedor; no asumas un máximo fijo.

Ejemplo ejecutable: leer el balance y los metadatos de SUI

El siguiente ejemplo en Node.js usa el SDK de TypeScript de Sui para leer el balance de SUI de una dirección, obtener los metadatos de la moneda SUI y convertir el balance en bruto a una cantidad legible para humanos. Asume que has instalado @mysten/sui y que tienes una URL de endpoint RPC de Sui.

Reemplaza YOUR_RPC_URL por el endpoint de tu proveedor, como un endpoint de Sui de OnFinality. El ejemplo usa getBalance, getCoinMetadata y getCoins del cliente del SDK. Los métodos del SDK se corresponden directamente con los métodos JSON-RPC descritos anteriormente.

import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';

const client = new SuiClient({ url: 'YOUR_RPC_URL' });
const address = '0xYOUR_ADDRESS';
const coinType = '0x2::sui::SUI';

async function main() {
  // 1. Get balance for SUI
  const balance = await client.getBalance({ owner: address, coinType });
  console.log('Raw totalBalance:', balance.totalBalance);
  console.log('coinObjectCount:', balance.coinObjectCount);
  console.log('lockedBalance:', balance.lockedBalance);

  // 2. Get coin metadata
  const metadata = await client.getCoinMetadata({ coinType });
  if (!metadata) {
    console.error('Metadata not found for', coinType);
    return;
  }
  console.log('Decimals:', metadata.decimals);
  console.log('Symbol:', metadata.symbol);

  // 3. Convert raw balance to human-readable
  const humanReadable = Number(balance.totalBalance) / Math.pow(10, metadata.decimals);
  console.log('Human-readable balance:', humanReadable, metadata.symbol);

  // 4. Page through coin objects and sum
  let cursor = null;
  let sum = 0n;
  let count = 0;
  do {
    const page = await client.getCoins({ owner: address, coinType, cursor });
    for (const coin of page.data) {
      sum += BigInt(coin.balance);
      count++;
    }
    cursor = page.nextCursor;
  } while (cursor);

  console.log('Sum of coin objects:', sum.toString());
  console.log('Number of coin objects:', count);
  console.log('Matches totalBalance:', sum.toString() === balance.totalBalance);
}

main().catch(console.error);

Ejemplo ejecutable: llamadas JSON-RPC en bruto con curl

Si prefieres JSON-RPC en bruto, puedes usar curl para llamar a los mismos métodos. El siguiente ejemplo llama a sui_getBalance y sui_getCoinMetadata para SUI en una dirección dada. Reemplaza YOUR_RPC_URL y 0xYOUR_ADDRESS por tu endpoint y dirección.

La especificación JSON-RPC 2.0 define el formato de la solicitud: una versión jsonrpc, un method, params y un id. La API JSON-RPC de Sui sigue esta especificación. Las respuestas incluyen un objeto result o un objeto error.

curl -X POST YOUR_RPC_URL \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "sui_getBalance",
    "params": ["0xYOUR_ADDRESS", "0x2::sui::SUI"]
  }'

curl -X POST YOUR_RPC_URL \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "sui_getCoinMetadata",
    "params": ["0x2::sui::SUI"]
  }'

Tabla de resultados reproducible para tu endpoint

Para verificar el comportamiento de tu endpoint y documentar tus propias mediciones, completa la siguiente tabla con datos de tu proveedor RPC. Usa una dirección y un tipo de moneda conocidos, y ejecuta los métodos descritos anteriormente. Esta tabla es para tus propios registros; no es un benchmark proporcionado por OnFinality.

Registra el totalBalance en bruto, los decimals de los metadatos, la cantidad legible para humanos, el coinObjectCount y si la suma de los objetos Coin coincide con el totalBalance. Si no coinciden, investiga balances bloqueados o problemas de paginación.

  • Tipo de moneda: p. ej., 0x2::sui::SUI
  • totalBalance en bruto: entero de sui_getBalance
  • Decimales: de sui_getCoinMetadata
  • Cantidad legible para humanos: raw / 10^decimals
  • Recuento de objetos Coin: de coinObjectCount o del recuento de resultados de sui_getCoins
  • Suma de objetos Coin: suma de los campos balance de sui_getCoins
  • Coincidencia: sí/no

Limitaciones y compensaciones en las lecturas de monedas

Las cadenas de tipo de moneda son específicas de cada red. Un tipo de moneda que existe en Mainnet puede no existir en Testnet. Codificar los tipos de moneda de forma fija puede romperse al cambiar de red. Haz siempre que los tipos de moneda sean configurables o derívalos del contexto de la red.

Los decimales provienen de los metadatos, que pueden faltar o ser incorrectos en monedas mal formadas. Si sui_getCoinMetadata devuelve null, no puedes convertir de forma fiable el balance en bruto a una cantidad legible para humanos. En tales casos, muestra la cantidad en bruto o usa un valor de decimales de reserva con una advertencia clara.

lockedBalance debe excluirse al calcular fondos gastables. El totalBalance incluye monedas bloqueadas, pero solo la diferencia entre totalBalance y lockedBalance es gastable de inmediato. No tener esto en cuenta puede provocar transacciones fallidas.

El estado RPC refleja el checkpoint actual del nodo. Una lectura inmediatamente después de enviar una transacción puede no incluir esa transacción si aún no se ha incluido en un checkpoint. Para operaciones sensibles al tiempo, sondea hasta que la transacción se finalice o usa una lectura específica de checkpoint si se admite.

  • Los tipos de moneda son específicos de cada red; no los codifiques de forma fija entre redes.
  • La ausencia de metadatos impide una conversión precisa de decimales.
  • Excluye lockedBalance para los fondos gastables.
  • Las lecturas reflejan el checkpoint actual del nodo; las transacciones recientes pueden retrasarse.

Solución de problemas comunes en la lectura de monedas

Si sui_getBalance devuelve un totalBalance de cero para una dirección en la que esperas fondos, verifica la cadena de tipo de moneda. Un error tipográfico en el ID del paquete o en el nombre del módulo dará como resultado un balance cero. Confirma también que la dirección es correcta y que estás consultando la red adecuada.

Si sui_getCoinMetadata devuelve null, es posible que la moneda no tenga metadatos registrados. Comprueba la cadena de tipo de moneda y prueba con otra moneda. Si los metadatos existen pero decimals parece incorrecto, verifica el tipo de moneda contra la fuente oficial.

Si la suma de los objetos Coin de sui_getCoins no coincide con totalBalance, comprueba si hay monedas bloqueadas. Algunos objetos Coin pueden estar bloqueados y no ser devueltos por sui_getCoins. Asegúrate también de paginar por todas las páginas; una página omitida dará un recuento inferior.

Si recibes un nextCursor que nunca se convierte en null, puedes estar en un bucle infinito debido a un error del proveedor o a un manejo incorrecto del cursor. Incluye siempre un límite máximo de iteraciones y registra los valores del cursor para depuración.

  • Balance cero: comprueba el tipo de moneda, la dirección y la red.
  • Metadatos nulos: la moneda puede carecer de metadatos; manéjalo con elegancia.
  • Discrepancia en la suma: comprueba monedas bloqueadas y completa la paginación.
  • Paginación infinita: añade un límite máximo de iteraciones y registra los cursores.

Próximos pasos: integrar las lecturas de monedas en tu aplicación

Ahora que puedes leer balances y metadatos, puedes crear funciones como rastreadores de portafolio, flujos de pago y token gates. Para una visión más amplia de los métodos RPC de Sui, consulta la guía RPC de Sui (RPC Assistant). Para entender cómo encajan los objetos Coin en el modelo de objetos, lee Leer objetos, campos dinámicos y paginación de Sui.

Al consultar el historial de transacciones, usa paginación por cursor de Sui queryTransactionBlocks para manejar grandes conjuntos de resultados. Para entender las versiones de objetos y la concurrencia, consulta Versiones de objetos de Sui y ordenación Lamport. Para analizar los efectos de transacciones y los cambios de objetos, consulta Efectos de transacciones y cambios de objetos en Sui.

Para despliegues en producción, considera usar un proveedor RPC fiable. OnFinality ofrece acceso a la red Sui con precios de RPC y un servicio de API. Explora más guías en el centro de aprendizaje de OnFinality.

  • Usa las lecturas de monedas para rastreadores de portafolio, pagos y token gates.
  • Maneja correctamente la paginación y los balances bloqueados.
  • Elige un proveedor RPC fiable para producción.
  • Explora más guías de Sui en OnFinality Learn.

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