Fiat sentinel strings ("Disabled"/"N/A") leak into editable amount inputs when no fiat rate is available
@TheSeydiCharyyev is already working on this.
Since Sep 13, 2026.
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 247
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 129
Description
Spawned from @ajaysehwal's review note on #4625: https://github.com/ZeusLN/zeus/pull/4625#pullrequestreview-5170149054
Problem
getUnformattedAmount() returns a localized sentinel string in its amount field in all three fiat failure branches:
- no fiat currency configured while units are
fiat(utils/AmountUtils.tsL147-L153, the branch with theTODO: is this the right place to catch this?comment) - rates fetched but no rate for the selected currency (L158-L164)
- no rates at all (L186-L192)
Because the sentinel ("Disabled" in English) is truthy, callers that do getUnformattedAmount(...).amount || fallback never hit their fallback. With #4625 this pattern is centralized in getRawAmountFromSats(), which feeds the editable amount state in views/Send.tsx and views/ClinkPay/ClinkPay.tsx. So with fiat as the active unit and no rate available, scanning a BIP21 QR or opening Send with a preset amount puts the literal text "Disabled" into the editable AmountInput field.
This predates #4625: the Send constructor used the identical getUnformattedAmount(...).amount || satAmount expression before the extraction, and the param-update path used getAmountFromSats(), whose own sentinel is "N/A" (general.notAvailable, L268). Same bug class either way, so not a regression from #4625.
Impact
Low. getSatAmount() in fiat mode with no rate computes with rate = 0 and returns 0 for any input, so there is no NaN and no wrong-amount send. The symptom is sentinel text sitting in an editable input.
Why the obvious fix is not enough
Making the || fallback fire (raw sats string) would be wrong-unit: with the input in fiat mode, 12618 reads as 12,618 fiat units. The sentinel needs to be handled structurally instead:
getUnformattedAmount()already sets anerrorfield in two of the three branches; add it to the no-currency branch too, and have callers key offerror/unitrather than comparing display strings.getRawAmountFromSats()should detect the failure and either return the sats-unit raw value while forcing the input's unit to sats, or return an empty string and leave the parsedsatAmountintact.
Relation to existing issues
Same root-cause family as #2261 and #3831: amount formatters return localized sentinel strings instead of signaling failure structurally, and callers either render them ("N/A" everywhere in Amount.tsx) or, here, feed them into editable inputs. #3831 covers the display/UX side (and the FiatStore rate-clobbering behavior discussed there); this issue covers the editable-input side. A structural error signal from getUnformattedAmount() (point 1 above) would serve both.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.