From c0613a8d42e0d2db250ea24e7b80a528612cb58f Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Thu, 5 Feb 2026 19:22:02 -0800 Subject: [PATCH] Cap values to max supply --- .../calculator/calculator.component.ts | 39 +++++++++++++++---- .../app/shared/pipes/bitcoinsatoshis.pipe.ts | 7 +++- .../app/shared/pipes/fiat-currency.pipe.ts | 6 ++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/components/calculator/calculator.component.ts b/frontend/src/app/components/calculator/calculator.component.ts index 94732f86e..148fbe502 100644 --- a/frontend/src/app/components/calculator/calculator.component.ts +++ b/frontend/src/app/components/calculator/calculator.component.ts @@ -53,12 +53,15 @@ export class CalculatorComponent implements OnInit { this.price$, this.form.get('fiat').valueChanges ]).subscribe(([price, value]) => { - const rate = (value / price).toFixed(8); - const satsRate = Math.round(value / price * 100_000_000); + let rate = parseFloat((value / price).toFixed(8)); + if (rate > 21000000) { + rate = 21000000; + } + const satsRate = Math.round(rate * 100_000_000); if (isNaN(value)) { return; } - this.form.get('bitcoin').setValue(rate, { emitEvent: false }); + this.form.get('bitcoin').setValue(rate.toFixed(8), { emitEvent: false }); this.form.get('satoshis').setValue(satsRate, { emitEvent: false } ); }); @@ -70,7 +73,7 @@ export class CalculatorComponent implements OnInit { if (isNaN(value)) { return; } - this.form.get('fiat').setValue(rate, { emitEvent: false } ); + this.form.get('fiat').setValue(this.formatFiat(rate), { emitEvent: false } ); this.form.get('satoshis').setValue(Math.round(value * 100_000_000), { emitEvent: false } ); }); @@ -78,12 +81,17 @@ export class CalculatorComponent implements OnInit { this.price$, this.form.get('satoshis').valueChanges ]).subscribe(([price, value]) => { - const rate = parseFloat((value / 100_000_000 * price).toFixed(8)); - const bitcoinRate = (value / 100_000_000).toFixed(8); + let bitcoinValue = value / 100_000_000; + if (bitcoinValue > 21000000) { + bitcoinValue = 21000000; + value = 21000000 * 100_000_000; + } + const rate = parseFloat((bitcoinValue * price).toFixed(8)); + const bitcoinRate = bitcoinValue.toFixed(8); if (isNaN(value)) { return; } - this.form.get('fiat').setValue(rate, { emitEvent: false } ); + this.form.get('fiat').setValue(this.formatFiat(rate), { emitEvent: false } ); this.form.get('bitcoin').setValue(bitcoinRate, { emitEvent: false }); }); @@ -110,6 +118,12 @@ export class CalculatorComponent implements OnInit { if (name === 'satoshis') { sanitizedValue = parseFloat(sanitizedValue).toFixed(0); } + if (name === 'bitcoin' && parseFloat(sanitizedValue) >= 21000000) { + sanitizedValue = '21000000'; + } + if (name === 'satoshis' && parseFloat(sanitizedValue) > 2100000000000000) { + sanitizedValue = '2100000000000000'; + } formControl.setValue(sanitizedValue, {emitEvent: true}); } @@ -137,4 +151,15 @@ export class CalculatorComponent implements OnInit { selectAll(event): void { event.target.select(); } + + formatFiat(num: number): string | number { + if (Math.abs(num) >= 1000) { + // For values >= 1000: show 2 decimals, or 0 if whole number + if (num % 1 === 0) { + return Math.round(num); + } + return (Math.round(num * 100) / 100).toFixed(2); + } + return num; + } } diff --git a/frontend/src/app/shared/pipes/bitcoinsatoshis.pipe.ts b/frontend/src/app/shared/pipes/bitcoinsatoshis.pipe.ts index 5f1f97b40..348319f19 100644 --- a/frontend/src/app/shared/pipes/bitcoinsatoshis.pipe.ts +++ b/frontend/src/app/shared/pipes/bitcoinsatoshis.pipe.ts @@ -10,7 +10,12 @@ export class BitcoinsatoshisPipe implements PipeTransform { constructor(private sanitizer: DomSanitizer) { } transform(value: string, firstPartClass?: string): SafeHtml { - const newValue = this.insertSpaces(parseFloat(value || '0').toFixed(8)); + const numValue = parseFloat(value || '0'); + // Don't show decimals at max supply (21M BTC) + if (numValue >= 21000000) { + return this.sanitizer.bypassSecurityTrustHtml('21 000 000'); + } + const newValue = this.insertSpaces(numValue.toFixed(8)); const position = (newValue || '0').search(/[1-9]/); const firstPart = newValue.slice(0, position); diff --git a/frontend/src/app/shared/pipes/fiat-currency.pipe.ts b/frontend/src/app/shared/pipes/fiat-currency.pipe.ts index 0b211d4cf..ffaef26d3 100644 --- a/frontend/src/app/shared/pipes/fiat-currency.pipe.ts +++ b/frontend/src/app/shared/pipes/fiat-currency.pipe.ts @@ -25,7 +25,11 @@ export class FiatCurrencyPipe implements PipeTransform { const currency = args[1] || this.currency || 'USD'; if (Math.abs(num) >= 1000) { - return new Intl.NumberFormat(this.locale, { style: 'currency', currency, maximumFractionDigits: 0 }).format(num); + // Check if decimals are exactly 0 + if (num % 1 === 0) { + return new Intl.NumberFormat(this.locale, { style: 'currency', currency, maximumFractionDigits: 0 }).format(num); + } + return new Intl.NumberFormat(this.locale, { style: 'currency', currency, minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(num); } else { return new Intl.NumberFormat(this.locale, { style: 'currency', currency }).format(num); }