Wallet Balance
Wallet Balance responde a una pregunta distinta de la del Ledger. El Ledger es la contabilidad económica propia de Ishtaran — Available, Pending, Reserved, Payable, Delivered — poblada exclusivamente por flujos reales de Payment/Settlement/Payout. Wallet Balance es una observación del estado de la chain: cuántos tokens realmente están, ahora mismo, en la dirección self-custody registrada de una Account. Simulado en Sandbox, real on-chain en Production.
Nunca sume los dos, nunca sustituya uno por el otro. Una Account puede tener un Payable
grande en el Ledger y un Wallet Balance de 0 al mismo tiempo — nada se ha pagado on-chain
todavía. O una wallet puede tener fondos sobre los que el Ledger no tiene ninguna opinión — su
dueño movió dinero hacia allí desde fuera de cualquier flujo mediado por Ishtaran.
Un ejemplo concreto
Suponga que la wallet de una Account tiene 100 USDT on-chain ahora mismo (Wallet Balance), mientras que su Ledger muestra Payable: 30, Reserved: 10, Delivered: 25 por actividad de Settlement no relacionada. Son cinco números distintos que responden cinco preguntas distintas — nunca los sume, y nunca reporte uno como si fuera el otro:
| Campo | Fuente | Pregunta que responde |
|---|---|---|
| Wallet Balance: 100 USDT | Estado de chain observado | "¿Cuántos tokens hay en esta dirección ahora mismo?" |
| Ledger Payable: 30 | Settlement (aún no pagado) | "¿Cuánto liquidó Ishtaran a esta Account pero todavía no movió on-chain?" |
| Ledger Reserved: 10 | Reserva de Transaction (en curso) | "¿Cuánto está bloqueado contra una Transaction todavía en progreso?" |
| Ledger Delivered: 25 | Payout (ya movido on-chain) | "¿Cuánto ha pagado Ishtaran ya a esta Account históricamente?" |
Un Wallet Balance de 100 no significa que 30 de eso sea "el Payable"; la wallet puede tener esos 100 de un depósito completamente no relacionado, un Payout anterior, o fondos movidos desde fuera de Ishtaran por completo. Al revés, un Payable de 30 no garantiza que la wallet muestre +30 una vez pagado — el timing on-chain, las comisiones de red, y los payouts parciales hacen que ambos números se muevan de forma independiente. Muestre ambos, etiquetados por separado, nunca fusionados en un solo saldo mostrado.
Por qué existe esto
Toda Account con una ExecutionDestination registrada ya tiene una wallet real, direccionable —
Self-Custody exige una antes de que cualquier leg de Settlement pueda ejecutar.
Wallet Balance responde a la pregunta que esa misma dirección siempre plantea implícitamente:
"¿cuánto hay realmente ahí?" — sin requerir que un Settlement, un Withdrawal, o cualquier otro
evento que afecte al Ledger haya ocurrido antes.
Consultar un saldo
- Lectura en snapshot —
GET /v1/accounts/{accountId}/wallet-balancesdevuelve la última observación conocida de la plataforma: la dirección, el saldo, cuándo se observó por última vez, y si esa observación está desactualizada. Esta llamada nunca consulta la blockchain directamente — segura de llamar en cada carga de página. - Actualización autoritativa —
POST /v1/accounts/{accountId}/wallet-balances/refreshle pide a la plataforma que verifique el estado real de la chain ahora mismo. La plataforma aplica su propia guarda corta (~30 segundos) de frescura/single-flight del lado del servidor — llamar esto con más frecuencia de la necesaria siempre es seguro, nunca un error, nunca costo extra de proveedor. Revise los camposstale/refreshSuppressedde la respuesta para saber si realmente ocurrió una verificación real. - Agregado multi-asset —
GET /v1/accounts/{accountId}/wallet-balances/aggregatesuma el saldo entre varios AssetNetworks que el llamador ya conoce (por ejemplo, USDT en múltiples networks), agrupado por Asset, con un desglose por network en el resultado. Nunca suma entre Assets distintos.
Mantenido actualizado automáticamente
La plataforma mantiene el saldo de una wallet actualizado por su cuenta — un Settlement, Payout, o Withdrawal que confirma bajo Self-Custody dispara una actualización orientada a eventos para la dirección afectada, además de un barrido periódico de reconciliación en segundo plano. Un cliente no necesita hacer polling agresivo para tener corrección.
Un cliente PUEDE observar de forma independiente una chain real por su cuenta (solo en Production — no hay chain independiente que consultar en Sandbox) como una señal barata y opcional para decidir cuándo llamar antes al endpoint de refresh. Esa observación siempre es solo una pista: la plataforma siempre reverifica por su cuenta y nunca acepta un saldo reportado por el cliente como autoritativo.
Send vs Pay
Ambos mueven fondos fuera de una wallet, pero significan cosas estructuralmente distintas para la plataforma:
- Send es una transferencia directa wallet-a-wallet, iniciada por el remitente. Nunca crea una Transaction, PaymentIntent, ni Settlement — es un peer pagándole a otro peer, punto final.
- Pay es el cumplimiento de un Payment Request existente (una PaymentIntent vinculada a una Transaction específica). Conduce el pipeline real Transaction → PaymentIntent → Settlement descrito en Transaction, Settlement, Split y Refund — Split, Fee, y la contabilidad del Ledger se aplican igual que en cualquier otro Settlement.
Una solicitud para previsualizar cuánto costará un pago (comisiones, monto recibido) nunca debe, por sí sola, crear nada real — ninguna Transaction, ninguna PaymentIntent. Solo una confirmación explícita debe avanzar al pipeline real de Pay.
Receive
Recibir no es tanto una capacidad distinta como dos cosas diferentes que una Account puede hacer:
- Aceptar un Send directo — nada que configurar de antemano; cualquier dirección self-custody registrada puede recibir una transferencia.
- Emitir un Payment Request — crear una PaymentIntent de antemano (un monto, una descripción opcional, una expiración) para que un pagador pueda cumplirla vía Pay. El pagador nunca necesita una relación de cuenta con quien la solicitó, más allá de la propia Transaction compartida que representa el pedido.
Rutas
- Consultar saldo (barato, en caché):
GET /v1/accounts/{accountId}/wallet-balances - Actualizar saldo (autoritativo, con guarda):
POST /v1/accounts/{accountId}/wallet-balances/refresh - Agregado entre AssetNetworks:
GET /v1/accounts/{accountId}/wallet-balances/aggregate