DEV Community

Daniel Parkson Tano
Daniel Parkson Tano

Posted on AI-assisted

Why “Send All” Requires Reverse Calculation

Calculating the maximum transferable amount correctly across currencies, rates, fees, and rounding.

“Send All” is difficult when the sender and recipient use different currencies and fees are charged on the destination side.

The calculation must work backward from the available source balance:

available source balance
→ subtract source-side fees
→ convert using the executable rate
→ account for destination-side provider costs
→ apply currency precision
→ verify the final debit again
Enter fullscreen mode Exit fullscreen mode

If the frontend converts the entire balance first and the backend adds a provider fee afterward, execution fails for insufficient funds.

Quotation and execution must share the same calculation service, rounding mode, rate snapshot, and fee configuration. The server should return explicit values for source debit, recipient amount, customer fee, and fee currency.

Before committing the debit, repeat the affordability check while holding the wallet lock. Balances and rates can change between quotation and execution.

“Send All” is a reverse-pricing operation. Treating it as a UI shortcut is how small discrepancies become failed financial transactions.

Distinguish the amounts in the quote

A multi-currency quote should state the source amount, source fee, exchange rate, destination amount, destination-side covered fee, and total source debit. Every amount needs an explicit currency and precision.

For a normal amount entry, the user may define either what they spend or what the recipient receives. The pricing service solves in the appropriate direction. “Send All” fixes the maximum total source debit, so the service must solve backward for the largest valid recipient amount.

Use executable rates

A displayed reference rate may not be the rate used during execution. Store a quote identifier, rate snapshot, fee rules, expiry time, and rounding policy. Reject or refresh expired quotes rather than silently producing a materially different outcome.

Round at defined boundaries

Binary floating-point values are unsuitable for money. Use decimal arithmetic and define rounding per currency. Rounding only at the end can still produce a provider amount with unsupported precision, while rounding at every intermediate step can compound errors. Document exactly where conversion and fee rounding occur.

Recheck under a wallet lock

The balance can change between quote and confirmation. Lock the wallet, calculate the final debit from the accepted quote, and confirm sufficient available balance inside the debit transaction. Holds and pending debits must be included in the available-balance definition.

Return the affordable maximum

When an entered amount is too high, the API can return a newly calculated maximum rather than only “insufficient funds.” This lets the interface recover gracefully while keeping the server authoritative.

A correct “Send All” flow is a compact demonstration of rate, fee, precision, and concurrency design working together.

Implementation checklist

Test Send All with fixed fees, percentage fees, minimum fees, destination deductions, zero-decimal currencies, high-precision currencies, expired rates, and a balance changing after quotation. Include boundary values where rounding changes affordability by the smallest currency unit.

Return a transparent breakdown from the backend and render those same values in confirmation and receipt screens. Never let the client independently reconstruct the total from a subset of fields.

Instrument quote-to-execution differences. Repeated insufficient-funds failures after a Send All quote indicate that the pricing and debit paths have diverged, even if each calculation appears correct in isolation.

Top comments (0)