Confirmações
Quando um pagamento conta, o que o comprador e o merchant veem enquanto ele confirma, e por que ele é "confirmado", não "final".
Última atualização 27 de out. de 2026
Os limiares
Uma invoice só é creditada depois que o transfer atinge o limiar de confirmações da sua rede. A contagem usa a mesma fórmula em todo lugar (confirmationsAt): head − block + 1, então o bloco que contém o transfer é a confirmação 1.
| Rede | Limiar | Bloco típico | ≈ Espera |
|---|---|---|---|
| Polygon PoS / Amoy | 64 | 2 s | ~2 min |
| BNB Chain / BSC Testnet | 15 | 3 s | ~45 s |
| Base / Base Sepolia | 30 | 2 s | ~1 min |
Os limiares das testnets podem ser reduzidos para desenvolvimento com CRYPTO_CONFIRMATIONS_<NETWORK> (ex.: CRYPTO_CONFIRMATIONS_POLYGON_AMOY=5). Overrides de mainnet são recusados no boot em produção. Cada invoice guarda o limiar com que foi criada (required_confirmations), então mudar o env nunca altera uma invoice que já está confirmando.
Como um transfer é acompanhado
O job scan do worker roda a cada 2 s por rede:
- Lê os logs de todos os contratos de token canônicos da rede enviados aos endereços de depósito ativos (
eth_getLogs, em intervalos de no máximoCRYPTO_LOGS_MAX_RANGE_<NETWORK>blocos, padrão 200, e no máximo 20 endereços por consulta; um intervalo que o provider recusa é dividido pela metade até passar). - Re-escaneia os últimos 12 blocos a cada tick e re-verifica os hashes dos blocos: um transfer cujo bloco foi substituído por um reorg é marcado como
ORPHANED, e uma invoice que só tinha transfers órfãos volta deDETECTEDparaPENDING. - Atualiza as confirmações e roda a máquina de estados da invoice. Status, posting no ledger, refunds e os eventos do outbox de uma avaliação são gravados em uma única transação de banco de dados.
A primeira detecção move a invoice para DETECTED (o comprador é avisado de que o pagamento está a caminho e pode fechar a página). Atingir o limiar a move para PAID, OVERPAID ou UNDERPAID e lança a liquidação no ledger. Uma invoice DETECTED nunca expira: o comprador pagou a tempo.
O que cada lado vê:
- Checkout: uma barra de confirmações
n / requiredcom ETA, enviada via Server-Sent Events (GET /api/v1/public/pay/:id/stream, com fallback para polling a cada 4 s). - Dashboard: a linha da invoice diz "Confirming n/required"; a barra de split é desenhada vazada até a invoice ser liquidada.
- Webhooks:
invoice.detectedna primeira detecção,invoice.paid(einvoice.overpaid) ao atingir o limiar.
"Confirmado", não "final"
Os limiares são uma política de risco escolhida por rede: profundos o bastante para que um reorg que volte além deles não seja uma preocupação prática, curtos o bastante para o checkout. Eles não são a finalidade de protocolo da chain, que o gateway não acompanha. É por isso que o produto diz "Confirmed at 64/64 confirmations" e nunca "final", "irreversível" ou "liquidado para sempre", no checkout, no dashboard, nos emails e nesta documentação. Mantenha essa regra ao escrever copy.
Os mesmos limiares controlam o dinheiro que sai: um sweep, um payout ou um refund só fica COMPLETED quando a sua própria transação atinge o limiar da rede, e um refund só é enviado depois que o sweep do depósito está confirmado.