Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Integración y Desarrollo11 min de lectura

Consultar el saldo de una billetera en todas las cadenas: un método multicadena reproducible

Un flujo de trabajo práctico y verificable para leer saldos nativos y de tokens en múltiples cadenas mediante llamadas RPC directas, con normalización, almacenamiento en caché y manejo de fallos.

TL;DR

Consultar el saldo de una billetera en todas las cadenas implica consultar el estado propio de cada cadena, ya que ninguna red individual conoce lo que una dirección posee en otras. El enfoque confiable consiste en llamar al método de saldo nativo en el endpoint RPC de cada cadena y luego consultar los contratos de tokens por separado para los activos tipo ERC-20. Este artículo ofrece un procedimiento ejecutable con curl, JavaScript y Python, además de un método de tabla de resultados para que puedas registrar y verificar cada valor por ti mismo. También cubre los modos de fallo que hacen que las comprobaciones de saldo multicadena parezcan incorrectas: IDs de cadena equivocados, cachés obsoletas, decimales y límites de velocidad.

Qué significa realmente consultar un saldo en todas las cadenas

Una dirección de blockchain no es una cuenta global. La misma cadena de caracteres puede existir en Ethereum, BNB Smart Chain, Arbitrum, Optimism, Polygon y docenas de otras redes, pero cada red almacena su propio estado de forma independiente. Cuando consultas el saldo de una billetera en todas las cadenas, estás ejecutando una consulta por cadena y luego agregando las respuestas fuera de la cadena.

Esta distinción es importante porque la mayor parte de la confusión en torno a las herramientas de saldo multicadena proviene de tratar el resultado como un único número. Una vista de portafolio es una agregación del lado del cliente o del servidor de muchas respuestas RPC independientes, cada una denominada en la unidad nativa de esa cadena. La capa de agregación, no la blockchain, decide cómo se combinan y muestran los valores.

Este artículo se centra en un método reproducible que puedes ejecutar tú mismo contra cualquier conjunto de cadenas compatibles con EVM. El mismo modelo mental se aplica a redes no EVM, pero los métodos RPC y los estándares de tokens difieren, por lo que se tratan como una integración separada.

  • Saldo nativo: una llamada RPC por cadena, devuelta en la unidad más pequeña de la cadena.
  • Saldo de token: una llamada por contrato de token por cadena, usando los decimales del token.
  • Agregación: tu código convierte unidades, aplica precios si es necesario y registra la procedencia.

Requisitos previos y supuestos

Necesitas una lista de las cadenas que te interesan, cada una con un ID de cadena y un endpoint RPC que estés autorizado a usar. También necesitas la dirección pública que estás inspeccionando; nunca una clave privada, porque las lecturas de saldo son operaciones públicas. Para los saldos de tokens necesitas las direcciones de los contratos de tokens y sus decimales, que puedes leer del propio contrato.

Los ejemplos usan marcadores de posición como RPC_URL y WALLET_ADDRESS. Reemplázalos con tu propio endpoint y dirección. Si aún no tienes endpoints para cada red, la guía de endpoints RPC multicadena explica cómo funciona la selección de endpoints, y el directorio de redes de OnFinality enumera las redes compatibles que puedes asignar a tu lista de cadenas.

  • Una lista de cadenas con chainId, nombre, RPC_URL y símbolo nativo.
  • Una dirección de billetera pública en formato hexadecimal con checksum o en minúsculas.
  • Opcional: direcciones de contratos de tokens para saldos ERC-20.
  • Un lugar para registrar los resultados, como una hoja de cálculo o un archivo JSON.

El modelo mental: una consulta por cadena, una unidad por respuesta

Cada cadena EVM expone eth_getBalance, que devuelve el saldo nativo en wei como una cadena hexadecimal. Wei es la unidad más pequeña; un ether son 10^18 wei en cadenas similares a Ethereum, pero otras cadenas pueden usar decimales diferentes para su unidad nativa. La respuesta RPC no te indica el símbolo ni los decimales, por lo que tu lista de cadenas debe contener esos metadatos.

Los saldos de tokens son diferentes. Un contrato ERC-20 almacena un mapeo de dirección a cantidad, y lo lees con la función balanceOf. El entero devuelto debe dividirse por 10^decimales, donde decimales se lee de la función decimals() del contrato. Por lo tanto, una consulta de saldo de token son dos llamadas por token: una para decimales (almacenable en caché) y otra para balanceOf.

Esta separación es la razón por la que un verificador de saldo de billetera puede mostrar un total nativo rápidamente pero tardar más para los tokens. Los saldos nativos son una llamada por cadena; los saldos de tokens escalan con el número de contratos que verificas.

Procedimiento ejecutable: saldos nativos con curl

Comienza con una sola cadena para confirmar tu endpoint y el formato de dirección. La solicitud JSON-RPC a continuación pide el saldo nativo en el último bloque. El array params contiene la dirección y la etiqueta de bloque; usa "latest" para el saldo actual o un número de bloque para una consulta histórica.

  • Una respuesta exitosa contiene un campo result con una cadena hexadecimal como 0x0 o 0xde0b6b3a7640000.
  • Un campo error generalmente indica una dirección mal formada, un método no soportado o un problema con el endpoint.
  • Convierte la cadena hexadecimal a un entero y luego divide por 10^nativeDecimals para obtener la cantidad legible.
curl -s -X POST "$RPC_URL" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBalance",
    "params": ["WALLET_ADDRESS", "latest"]
  }'

Procedimiento ejecutable: todas las cadenas en JavaScript

El script a continuación itera sobre una lista de cadenas, llama a eth_getBalance en cada endpoint, convierte el resultado e imprime una tabla. Utiliza fetch, que está disponible en Node.js moderno y en navegadores. Mantén la lista de cadenas en un solo lugar para que los mismos metadatos impulsen tanto la consulta como la visualización.

Este patrón es el núcleo de cualquier verificación de saldo multicadena. Las decisiones de ingeniería importantes son cómo manejas una cadena fallida, cómo evitas los límites de velocidad y cómo registras qué endpoint produjo cada valor.

const chains = [
  { name: "Ethereum", chainId: 1, rpc: "RPC_URL_ETH", symbol: "ETH", decimals: 18 },
  { name: "BNB Smart Chain", chainId: 56, rpc: "RPC_URL_BSC", symbol: "BNB", decimals: 18 },
  { name: "Arbitrum One", chainId: 42161, rpc: "RPC_URL_ARB", symbol: "ETH", decimals: 18 }
];

const address = "WALLET_ADDRESS";

async function getNativeBalance(chain) {
  const res = await fetch(chain.rpc, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: chain.chainId,
      method: "eth_getBalance",
      params: [address, "latest"]
    })
  });
  const json = await res.json();
  if (json.error) throw new Error(`${chain.name}: ${json.error.message}`);
  const wei = BigInt(json.result);
  const divisor = 10n ** BigInt(chain.decimals);
  return Number(wei) / Number(divisor);
}

for (const chain of chains) {
  try {
    const balance = await getNativeBalance(chain);
    console.log(`${chain.name}\t${balance}\t${chain.symbol}`);
  } catch (err) {
    console.log(`${chain.name}\tERROR\t${err.message}`);
  }
}

Procedimiento ejecutable: saldos de tokens en Python

Los saldos nativos son solo una parte del panorama. Para verificar saldos de tokens, llama a la función balanceOf del contrato usando eth_call. El selector de función para balanceOf(address) es 0x70a08231, seguido de la dirección rellenada a 32 bytes. El selector de decimals() es 0x313ce567.

El ejemplo de Python a continuación construye los datos de llamada, llama al contrato y convierte el resultado. Almacena en caché los decimales por contrato porque los decimales rara vez cambian. Ejecútalo contra una cadena primero y luego extiéndelo a tu lista de cadenas.

import json, urllib.request

RPC_URL = "RPC_URL"
TOKEN = "TOKEN_CONTRACT_ADDRESS"
WALLET = "WALLET_ADDRESS"

def rpc(method, params):
    payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method, "params": params}).encode()
    req = urllib.request.Request(RPC_URL, data=payload, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req) as resp:
        body = json.loads(resp.read())
    if "error" in body:
        raise RuntimeError(body["error"]["message"])
    return body["result"]

def pad_address(addr):
    return addr.lower().replace("0x", "").rjust(64, "0")

decimals_hex = rpc("eth_call", [{"to": TOKEN, "data": "0x313ce567"}, "latest"])
decimals = int(decimals_hex, 16)

balance_hex = rpc("eth_call", [{"to": TOKEN, "data": "0x70a08231" + pad_address(WALLET)}, "latest"])
balance = int(balance_hex, 16) / (10 ** decimals)
print(f"Token balance: {balance}")

Registrar resultados en una tabla de verificación

Una verificación de saldo multicadena solo es confiable si puedes reproducirla. Registra una fila por cadena con el nombre de la cadena, el ID de cadena, la etiqueta del endpoint, el número de bloque, el resultado hexadecimal sin procesar, la cantidad convertida y la marca de tiempo. El número de bloque es importante porque los saldos cambian; sin él, dos ejecuciones en momentos diferentes no son comparables.

La tabla a continuación es una plantilla, no datos medidos. Complétala con tus propias ejecuciones. Si un valor parece incorrecto, el hexadecimal sin procesar y el número de bloque te permiten volver a consultar el mismo estado y confirmar si el problema está en los datos de la cadena o en tu lógica de conversión.

  • | Cadena | ID de cadena | Etiqueta del endpoint | Bloque | Hex sin procesar | Convertido | Marca de tiempo |
  • | Ethereum | 1 | primary | (tu bloque) | (tu hex) | (tu valor) | (tu hora) |
  • | BNB Smart Chain | 56 | primary | (tu bloque) | (tu hex) | (tu valor) | (tu hora) |
  • | Arbitrum One | 42161 | primary | (tu bloque) | (tu hex) | (tu valor) | (tu hora) |

Resultado de verificación esperado y cómo interpretarlo

Una ejecución correcta produce una fila por cadena, cada una con un número de bloque y una cantidad convertida. Las cadenas donde la dirección nunca ha recibido fondos deberían devolver 0x0, que se convierte en cero. Una cadena que devuelve un error no es lo mismo que un saldo cero; regístralo como error e investígalo por separado.

Si comparas tu salida con un rastreador de billeteras de terceros, espera pequeñas diferencias. Los rastreadores pueden usar etiquetas de bloque diferentes, almacenar valores en caché o incluir posiciones de tokens y DeFi que tu consulta solo nativa no cubre. La forma de conciliar es comparar el mismo número de bloque y la misma clase de activo, no el total del portafolio principal.

  • Saldo cero: respuesta válida, resultado 0x0.
  • Saldo distinto de cero: confirma decimales y símbolo de tu lista de cadenas.
  • Error: verifica el formato de la dirección, la salud del endpoint y el soporte del método.
  • Discrepancia con un rastreador: alinea el número de bloque y el alcance de los activos antes de concluir cualquier cosa.

Solución de problemas de los modos de fallo comunes

La mayoría de los resultados incorrectos de saldo multicadena provienen de un pequeño conjunto de causas. La primera es usar el ID de cadena o el endpoint equivocado, lo que devuelve un saldo válido para una red diferente. La segunda es la confusión de decimales, especialmente en cadenas cuya unidad nativa no tiene 18 decimales. La tercera es el límite de velocidad: consultar muchas cadenas y tokens en paralelo puede provocar respuestas 429, que algunos scripts tratan silenciosamente como cero.

Una cuarta causa es el almacenamiento en caché obsoleto. Si tu servicio almacena saldos en caché, asegúrate de que la clave de caché incluya el ID de cadena, la dirección y la etiqueta de bloque. Una caché indexada solo por dirección devolverá el saldo de una cadena para todas las cadenas. Por último, confirma que tu endpoint realmente soporta los métodos que llamas; algunos endpoints restringidos permiten eth_getBalance pero no eth_call.

  • Valida el ID de cadena devuelto con eth_chainId antes de confiar en un saldo.
  • Nunca trates un error RPC como un saldo cero.
  • Añade reintentos con retroceso exponencial para respuestas 429 y 5xx.
  • Incluye el ID de cadena y la etiqueta de bloque en cada clave de caché.
  • Registra la etiqueta del endpoint con cada resultado para fines de auditoría.

Limitaciones y compensaciones de las verificaciones de saldo RPC directas

Las consultas RPC directas te dan el mayor control y la procedencia más clara, pero no están exentas de compensaciones. Consultar muchas cadenas implica muchos endpoints, cada uno con su propio perfil de confiabilidad, límites de velocidad y latencia. Los saldos de tokens multiplican el número de llamadas, y los saldos históricos requieren nodos con capacidad de archivo, que son una clase de servicio diferente.

Los endpoints públicos son convenientes para verificaciones ocasionales pero a menudo tienen límites de velocidad y pueden no soportar consultas de archivo. Para uso repetido o en producción, un nodo dedicado o un servicio RPC gestionado proporciona un rendimiento más predecible. La guía de alojamiento de nodos blockchain explica las diferencias operativas, y la página de precios de RPC describe cómo el volumen de solicitudes se asigna a los planes.

  • Latencia: la cadena más lenta determina el tiempo total de respuesta a menos que paralelices.
  • Costo: las consultas de tokens escalan con los contratos, no solo con las cadenas.
  • Datos de archivo: los saldos históricos necesitan nodos de archivo.
  • Consistencia: las diferentes cadenas avanzan a ritmos diferentes, por lo que una instantánea es aproximada.

Próximos pasos: del script a un servicio de saldo multicadena confiable

Una vez que el script básico funcione, el siguiente paso es hacerlo resistente. Paraleliza las consultas de cadena con un límite de concurrencia, reintenta errores transitorios y persiste los resultados con números de bloque. Si necesitas posiciones de tokens y DeFi, añade una lista de tokens por cadena y almacena en caché los decimales. Si necesitas saldos históricos, dirige esas consultas a endpoints con capacidad de archivo.

Para la selección de endpoints en muchas redes, la guía de endpoints RPC multicadena de RPC Assistant cubre los criterios de decisión, y la página del servicio API describe el acceso gestionado. Si estás eligiendo un proveedor para una cadena específica, comienza con RPC Assistant en lugar de codificar un endpoint público en producción.

  • Añade un límite de concurrencia y una política de reintentos.
  • Persiste el hex sin procesar, el número de bloque y la etiqueta del endpoint.
  • Separa las rutas de consulta nativa, de tokens e histórica.
  • Revisa la guía de endpoints RPC multicadena antes de escalar.

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