diff options
| -rw-r--r-- | src/app.js | 21 | ||||
| -rw-r--r-- | tools/amount-field-unit-test.js | 5 |
2 files changed, 19 insertions, 7 deletions
@@ -1154,11 +1154,22 @@ function toggleUnit() { // A sats figure as the amount field types it in the current unit — what a // Max button or a fixed-amount invoice fills in. Fiat is floored to the // cent so a filled-in maximum never parses back to more than was offered. +// The figure it filled is remembered with its exact sats: a fiat maximum +// rounded to the cent would otherwise parse back a few sats short and leave +// them behind. Typing anything else parses as typed. +let lastFill = null; function amountField(sat) { - if (unit === 'sats') return String(sat); + let s; const r = unit === 'fiat' && rateNow(); - if (r) return (Math.floor((sat / 1e8) * r * 100) / 100).toFixed(2); - return (sat / 1e8).toFixed(8); + if (unit === 'sats') s = String(sat); + else if (r) s = (Math.floor((sat / 1e8) * r * 100) / 100).toFixed(2); + else s = (sat / 1e8).toFixed(8); + lastFill = { s, unit, sat }; + return s; +} +function parseField(v, u = unit) { + if (lastFill && lastFill.unit === u && String(v).trim() === lastFill.s) return lastFill.sat; + return parseAmount(v, u, rateNow()); } const unitLabel = () => (unit === 'sats' ? 'sats' : unit === 'fiat' ? getCurrency() : 'BTC'); @@ -5583,7 +5594,7 @@ function reviewSend() { recipients = s.recipients.map((r, i) => { const addr = r.address.trim(); if (!addr) throw new Error(t('enterAddrForN', { n: i + 1 })); - const sats = parseAmount(r.amount, unit, rateNow()); + const sats = parseField(r.amount); if (!sats || sats <= 0) throw new Error(t('enterValidAmtForN', { n: i + 1 })); return { address: addr, amount: sats }; }); @@ -5963,7 +5974,7 @@ const ctx = { openSettingsPage: (page) => { clearFeatureNav(); ui.screen = 'wallet'; ui.tab = 'settings'; ui.settingsPage = page; render(); try { window.scrollTo(0, 0); } catch {} }, fmtAmount, unitLabel, unitTag, getUnit: () => unit, toggleUnit, download, amountField, // in fiat the typed figure is money, so it needs today's price to become sats - parseAmount: (v, u) => parseAmount(v, u, rateNow()), + parseAmount: parseField, worthLine, openImage: (src) => { ui.lightbox = src; render(); }, // What woke this run, if anything did, and how to say we're finished. diff --git a/tools/amount-field-unit-test.js b/tools/amount-field-unit-test.js index 26c5357..b984064 100644 --- a/tools/amount-field-unit-test.js +++ b/tools/amount-field-unit-test.js @@ -33,7 +33,7 @@ try { await page.waitForFunction(() => window.amtApp); const r = await page.evaluate(() => { const { ctx } = amtApp; - const out = { unit: amtApp.unit, fiat: ctx.amountField(62212), back: ctx.parseAmount(ctx.amountField(62212), 'fiat') }; + const out = { unit: amtApp.unit, fiat: ctx.amountField(62212), back: ctx.parseAmount(ctx.amountField(62212), 'fiat'), typed: ctx.parseAmount('93.310', 'fiat') }; while (amtApp.unit !== 'sats') amtApp.toggleUnit(); out.sats = ctx.amountField(62212); amtApp.toggleUnit(); out.btc = ctx.amountField(62212); @@ -42,7 +42,8 @@ try { console.log(r); assert.equal(r.unit, 'fiat'); assert.equal(r.fiat, '93.31', '62,212 sats at 150,000 CAD/BTC = 93.318 → floored to 93.31'); - assert(r.back <= 62212 && r.back > 62200, 'parses back to at most the maximum'); + assert.equal(r.back, 62212, 'the filled figure parses back to the exact sats — none left behind'); + assert.equal(r.typed, 62207, 'the same money typed as something else parses as typed'); assert.equal(r.sats, '62212'); assert.equal(r.btc, '0.00062212'); assert.deepEqual(errors, []); |
