Repository navigation
v0.1.11 — cross-currency payouts detect-and-reject
Changed
-
Cross-currency payouts are now detected and rejected with a clear
error instead of silently producing wrong journal entries. Previously,
a CAD-settling account paying out to a USD bank account would produce
a clean-looking1000 debit / 1010 credittransfer in CAD that didn't
account for Stripe's FX conversion fee or the destination amount. The
journal balanced internally but didn't match the operator's actual
books. The receiver'sexpand.tsnow requests
expand: ['destination']on payout events; bothpayoutPaidand
payoutFailedcomparedestination.currencytopayout.currencyand
throw on mismatch with the actual currencies plus a pointer to open an
issue with the BT shape so the case can be modeled against real data.This is not an implementation of cross-currency payouts — the
Stripe BT shape (FX fee inline on the payout BT vs separate adjustment
BT,destination_amountsemantics, reverse-conversion behavior on
payout.failed) isn't documented well enough to implement against
without real payloads. Refusing loudly is the honest interim: operators
hitting this know immediately that their setup isn't supported, can
open an issue with their actual BT structure, and the implementation
can follow against real data.
Added
-
New
src/events/payouts/crossCurrency.tswith
detectCrossCurrencyPayout(returns the destination currency on
mismatch, null otherwise) andrejectCrossCurrencyPayout(throw-on-
mismatch convenience wrapper). Both payout handlers call the rejector
immediately after extracting the payout, before any accounting work. -
New
test/events/payouts/crossCurrency.spec.tscovering the detection
logic across all 5 input shapes (string destination, null destination,
same-currency object, mismatched currency, object missing currency)
plus integration tests assertingmapEventthrows on cross-currency
payout.paid/payout.failedand the actionable error message
format. Sanity check: same-currency expanded destination still
produces a normal 1000/1010 entry.
Compatibility
Existing payout_paid_standard and payout_failed_standard fixtures
use string destination IDs (predate this expansion). They pass
byte-identical because the detector returns null on string
destinations, falling through to the same accounting as v0.1.10.
The server.spec.ts test suite mocks stripe.payouts.retrieve at
module scope so the existing webhook-flow tests stay off the Stripe
network now that payout events get expanded.