Skip to content

fix(sell): keep buy-fiat payout liability until bank booking#3871

Draft
TaprootFreak wants to merge 1 commit into
developfrom
fix/buy-fiat-pending-output-until-booked
Draft

fix(sell): keep buy-fiat payout liability until bank booking#3871
TaprootFreak wants to merge 1 commit into
developfrom
fix/buy-fiat-pending-output-until-booked

Conversation

@TaprootFreak

Copy link
Copy Markdown
Collaborator

Problem

BuyFiat.pendingOutputAmount zeroes the customer liability for Yapeal payouts as soon as fiatOutput.isTransmittedDate is set (payment instruction transmitted). The bank balance only drops when the bank actually books the debit. For weekend/cut-off batches this happens days later, so the FinancialDataLog total balance shows phantom equity in between.

Verified production case: payout of 14'980.12 CHF transmitted Friday 2026-06-05 14:32 (liability dropped from the log, entry 1539090), booked by Yapeal on Sunday 2026-06-07 23:02 (balance drop, entry 1545843, bank_tx 202000 created 23:00:48). Total balance overstated by +14'980 CHF for 2.3 days. This single payout explains the +19k/-15k day-over-day anomalies between Jun 4 and Jun 8.

A transmitted payment can also still fail — the shortcut would then have removed the liability permanently.

Fix

Remove the transmission shortcut: the output amount stays a liability until the entity completes, i.e. until the booked outgoing bank transaction is matched (complete() cron). Bank booking import is webhook-based and the matching/complete crons run every minute, so the remaining inconsistency window is 1–3 minutes — the same noise floor as all other balance sources. The per-bank attribution from #2650/#2678 (count only under the actual payout bank asset) is unchanged.

Weekday Yapeal payouts book in the same minute as transmission, so for them this change only adds the 1–3 minute completion window — compared to days of phantom equity in the batch case.

Tests

  • New buy-fiat.entity.spec.ts covering pendingOutputAmount; the first case (transmitted but not completed keeps the liability) fails against the previous implementation.
  • jest src/subdomains/supporting/log src/subdomains/core/sell-crypto: 31 passed.
  • format:check, type-check, lint: clean.

The Yapeal shortcut in pendingOutputAmount dropped the customer liability
from the financial log as soon as the payment was transmitted. The bank
only debits the account when it books the payment, which can be days
later for weekend/cut-off batches. During that window the total balance
showed phantom equity (verified case: transmitted Friday 14:32, booked
Sunday 23:00, +14'980 CHF overstated for 2.3 days). A transmitted
payment can also still fail, which would have removed the liability
permanently.

The liability now stays counted until the entity completes, i.e. the
booked bank transaction is matched. Booking import (webhook) and the
complete cron both run within 1-2 minutes, so the remaining window
matches the general sync noise floor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant