Dados e ledger
O que o banco de dados guarda, por que ele não é a autoridade sobre saldo, e como o extrato é montado.
A divisão de responsabilidade
| Pergunta | Respondida por |
|---|---|
| Quanto o usuário tem? | A chain (saldo BRLA da carteira dele) |
| Esse PIX de ontem foi pra quem? | O banco (ledger_entries) |
| Aquele saque está em que etapa? | O banco (tabela da rail) |
| Esse QR já foi pago? | Chain + banco, cruzados |
O banco nunca é consultado para saber se o usuário pode gastar. Isso é decidido pelo saldo on-chain no momento em que a transação é assinada — e, em última instância, pelo próprio contrato do BRLA, que rejeita uma transferência sem saldo.
Representação de dinheiro
Uma escolha pequena com grandes consequências: todo valor monetário é um inteiro em centavos. Não existe ponto flutuante em nenhum caminho de dinheiro.
O BRLA é um ERC-20 com 18 casas decimais e paridade 1:1 com o real, então a conversão para unidades on-chain é exata:
// lib/evm/token.ts
export const BRLA_DECIMALS = 18;
export function centsToTokenRaw(cents: number): bigint {
return BigInt(cents) * 10n ** BigInt(BRLA_DECIMALS - 2); // cents * 10^16
}A API da Hodle também trabalha em centavos, então não existe fronteira de conversão para reais fracionários em lugar nenhum do sistema.
As tabelas
O schema é cumulativo e vive em supabase/schema.sql. Os grupos:
O ledger
ledger_entries é a fonte do extrato exibido ao usuário. Cada rail publica
sua entrada num ponto bem definido do fluxo — on-ramp quando o crédito
on-chain é observado, off-ramp quando o débito é confirmado, e assim por
diante.
Duas propriedades importam:
Referência idempotente. Cada entrada carrega um ledgerRef derivado do
tipo da rail e do id da linha de origem (onramp:<qrId>, por exemplo). Postar
a mesma entrada duas vezes não duplica o extrato — é o que permite que o
webhook e o poll de reconciliação disputem a mesma conclusão sem estragar a
contabilidade.
Valor observado, não nominal. No on-ramp, a Hodle deduz a taxa dela do BRLA entregue. Quando o valor realmente creditado on-chain é conhecido, é ele que vai para o ledger — não o valor nominal do PIX. O extrato reflete o que aconteceu na chain, não o que era esperado.
Cruzamento com a chain
Como o banco é derivado, ele pode divergir. O sistema trata isso como normal e tem dois mecanismos de convergência — o poll de reconciliação e a varredura periódica — descritos em Webhooks e reconciliação.