Fintech
Formance

Formance – Martillo de Oro

Martín Paoletta

Martín Paoletta

22 mayo 2025
Formance – Martillo de Oro

Introducción

En el desarrollo de aplicaciones que manejan transacciones financieras—por ejemplo, billeteras virtuales, plataformas de pagos o cualquier sistema que registre movimientos de dinero—existe un desafío común: cómo representar y mantener de manera confiable los flujos de dinero.

Tradicionalmente, se opta por crear tablas con campos de “origen”, “destino” y “monto”, con la esperanza de que estas estructuras sean suficientes para reflejar la actividad financiera. Sin embargo, a medida que crece la complejidad (múltiples monedas, múltiples posibles fuentes y destinos, reversas, interacciones con terceros, etc.), esta aproximación puede volverse difícil de mantener y propensa a errores.

Aquí es donde aparece la idea de utilizar un ledger (o libro mayor digital), que permite llevar un registro contable centralizado y confiable. Formance ofrece precisamente una API de ledger que simplifica y potencia la manera en que se modelan y consultan estos flujos.

¿Qué es un ledger y por qué utilizarlo en aplicaciones financieras?

Un ledger o “libro mayor” es, en esencia, un registro que consolida todos los movimientos de dinero del sistema de manera coherente y auditada. Permite:

  • Descomponer las transacciones en asientos contables (postings), especificando las cuentas involucradas (fuente y destino) y los montos.
  • Mantener los saldos y volúmenes (cuánto entró y salió en total) por cada moneda o activo.
  • Registrar metadatos (tipo de operación, referencias externas, identificadores de pago, etc.), lo que facilita trazabilidad y búsquedas.
  • Asegurar que, en un buen diseño de doble entrada, al final del día las cuentas cuadren si algo sale de una, debe entrar a otra (sean cero en la suma algebraica global o, dicho de otro modo, si en una cuenta sale dinero, necesariamente tiene que entrar en otra/s cuenta/s). Esto minimiza inconsistencias y problemas contables.

Formance: una API de ledger “accounts all the way down”

It’s accounts all the way down!

Formance propone un modelo muy enfocado en la contabilidad de doble entrada, ofreciendo conceptos clave:

    • Cuentas: representan entidades o “contenedores” donde se almacena el saldo de uno o varios activos/monedas.
    • Transacciones: describen los movimientos de dinero que alteran el saldo de dos o más cuentas.
    • Postings: cada una de las líneas contables o asientos concretos dentro de una transacción.
    • Metadatos: información adicional (en formato JSON) que se asocia tanto a cuentas como a transacciones, permitiendo búsquedas y filtrados muy flexibles.
    • Direcciones tokenizadas: nombres de cuentas con estructura jerárquica (separada por dos puntos “:”), lo que permite agruparlas y hacer consultas con wildcards.

Por ejemplo, users:001:wallet, users:001:payments:1001, etc.

Direcciones y búsquedas con comodines

Las cuentas en Formance tienen direcciones como users:1234:wallet. Este formato no es solo una convención estética; es parte del modelo. Permite, por ejemplo, buscar cuentas o transacciones (o agregar saldos) de manera eficiente:

  • Todas las cuentas de un usuario: users:1234:
  • Todos los pagos de todos los usuarios: users::payments (usando * o un wildcard donde sea necesario)

Esto simplifica mucho la implementación de reportes, dashboards, y cualquier operación que requiera agrupar cuentas, ya que se basa en índices preparados para este tipo de patrones.

Trabajar con múltiples monedas y múltiples destinos

Formance soporta múltiples monedas en una misma cuenta y en el mismo ledger. Cada moneda (o activo) se identifica con un nombre y también con la cantidad de decimales que maneja (por ejemplo, ARS/2 si se cuentan centavos, BTC/8 si se llega a 8 decimales).

Además, en una misma transacción pueden haber múltiples orígenes y múltiples destinos. Esto es útil para:

  • Distribuir un pago: por ejemplo, un 80% a una cuenta de usuario, un 20% distribuido a su vez en un 70% para la plataforma, 15% para impuestos y 15% para donaciones, todo dentro de la misma operación.
  • Combinar fondos desde diferentes cuentas de origen cuando una de ellas no tiene saldo suficiente.
  • Generar esquemas complejos de repartos de comisiones, cashbacks y retenciones de manera clara y centralizada.

 

Ejemplo práctico: construir una billetera (wallet) en un “circuito cerrado”

Un escenario sencillo que nos permite explorar como modelar el negocio con Formance es el de una wallet de circuito cerrado, donde los usuarios (personas o comercios) tienen cuentas internas y, opcionalmente, se interactúa con el sistema financiero externo para ingresar o extraer dinero.

1. Ingreso de fondos (Cash In)

Para “cargar” dinero en la wallet, se registra una transacción desde la cuenta especial world (o “mundo exterior”), que representa el dinero que entra al circuito cerrado, hacia la cuenta interna del usuario. Por ejemplo:

send [ARS/2 500000] (
source = @world
destination = @users:001:wallet
)

set_tx_meta(«tx_type», «CASH_IN»)

 

Aquí, 500000 en ARS/2 equivaldría a 5000.00 pesos (depende de la configuración de decimales). El ledger actualiza inmediatamente el balance en la cuenta del usuario.

El statement set_tx_meta es totalmente opcional, lo estamos usando para registrar metadatos en la transacción, en este caso para poder hacer una búsqueda de transacciones por el tipo.

 

2. Transferencia entre cuentas internas

Para mover dinero entre dos usuarios dentro del sistema, se registra otra transacción:

send [ARS/2 1000] (
source = @users:001:wallet
destination = @users:002:wallet
)

set_tx_meta(«tx_type», «TRANSFER»)

 

En este caso, se descuenta el saldo en la cuenta users:001:wallet y se acredita en users:002:wallet de forma atómica.

3. Extracción de fondos (Cash Out)

Cuando el usuario quiere sacar dinero al mundo exterior (por ejemplo, a su cuenta bancaria), se realiza un movimiento inverso:

send [ARS/2 1000] (
source = @users:001:wallet
destination = @world
)

set_tx_meta(«tx_type», «CASH_OUT»)

 

 

El sistema descuenta el saldo interno y, en la lógica de la aplicación, se efectúa la transferencia real con el tercero (banco, red de pago, etc.).

En casos reales, a menudo se bloquea primero el saldo en una cuenta “de tránsito” dentro del ledger (por ejemplo, users:001:transfers:pending) antes de hacer la operación externa. Luego, si la operación con el servicio externo se completa con éxito, se cierra la transacción y se refleja definitivamente el cashout. Si falla, se “revierte” moviendo de nuevo el dinero al saldo disponible del usuario.

 

 

Interacciones con el sistema financiero externo

Una de las grandes ventajas de separar la lógica de ledger (Formance) de la lógica de integración externa es que:

  • El ledger no se “entera” de los protocolos específicos para hacer transferencias bancarias, cobros con tarjetas, pagos con QR, etc.
  • Cada vez que ocurre una interacción con un tercero, la aplicación puede, por ejemplo, bloquear los fondos (pasarlos a una cuenta de “transferencias pendientes”) mientras se concreta la operación.
  • Una vez confirmada la operación externa, se registra la transacción final en el ledger (asiento contable definitivo). Si la operación externa falla, simplemente se revierte el primer paso y se regresa el saldo a la cuenta de origen.

Este modelo de “el mundo de las ideas”—donde se asume que todo el movimiento de dinero se hace primero a nivel contable y luego se concreta con integraciones—simplifica el control de errores y la trazabilidad.

Ejemplo de diseño de una transferencia al exterior

 

Metadatos: enriqueciendo la información

Formance permite asociar, tanto a cuentas como a transacciones, un objeto JSON arbitrario llamado metadata. Allí puede almacenarse información adicional como:

  • Referencias a ID de usuarios (por ejemplo, user_id, nombre)
  • Campos para indicar el tipo de transacción (tx_type = «PAYMENT», «CASH_IN», «CASH_OUT», etc.)
  • Datos de auditoría o seguimiento de flujos (fechas, IDs externos, etc.)

Lo interesante es que estos metadatos pueden ser indexados para permitir búsquedas rápidas. Por ejemplo, es viable filtrar o listar todas las transacciones con tx_type = «TRANSFER» en un rango de fechas específico, sin tener que añadir tablas ad hoc en la base de datos.

 

Modelos más avanzados: pagos, cupones y adelantos

El ledger se puede extrapolar a muchas otras situaciones más complejas:

 

  • Cupones de tarjeta de crédito: Registrar un cupón como una cuenta especial, donde ingresa el monto cuando se hace la transacción con la tarjeta. El comercio puede ver sus cupones pendientes de liquidar, se hacen consultas agregadas y se aplican costos o descuentos al hacerle adelantos de esos cupones.
  • Pagos parciales o split de comisiones: Mandar un % al comercio, otro % a la plataforma, otro % a impuestos, etc., todo dentro de una única transacción atómica.
  • Adelantos: Otorgar un adelanto del total de pagos pendientes a un comercio, quedándose con un fee en alguna cuenta definida.

 

La clave está en que todo se resuelve con transacciones—atómicas e inmutables—y con cuentas (o subconjuntos de cuentas) que representan cada entidad de negocio.

 

Conclusiones

  1. Diseño más simple y robusto: En lugar de implementar la lógica contable a mano (con riesgo de inconsistencias y dificultades para escalar), adoptar un ledger como Formance agiliza la definición y auditoría de los flujos de dinero.
  2. Trazabilidad y auditoría: Cualquier transacción queda registrada con toda la información necesaria para realizar auditorías, conciliaciones y reportes.
  3. Extensible a cualquier caso: Desde billeteras de circuito cerrado hasta pagos con tarjeta, retenciones de impuestos, comisiones en marketplace, devoluciones o cupones a futuro: todo se modela uniformemente con cuentas y transacciones.
  4. Interacciones con sistemas externos más seguras: Separar la operación contable del intercambio real de dinero minimiza riesgos. Se puede primero bloquear fondos y, tras confirmar la operación externa, asentar definitivamente la transacción.

 

Con Formance y su API de ledger, se adopta un enfoque sólido—heredado de la contabilidad tradicional—para construir aplicaciones financieras que sean, desde el inicio, fáciles de mantener, auditar y escalar.