Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix currency rounding #524

Merged
merged 3 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 1 addition & 8 deletions scripts/dashboard/WalletBalance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,7 @@ const balanceValue = computed(() => {
const nCoins = (publicMode.value ? balance : shieldBalance).value / COIN;
const { nValue, cLocale } = optimiseCurrencyLocale(nCoins * price.value);

cLocale.minimumFractionDigits = 0;
cLocale.maximumFractionDigits = 0;

return `${nValue.toLocaleString('en-gb', cLocale)}${beautifyNumber(
nValue.toFixed(2),
'13px',
false
)}`;
return `${beautifyNumber(nValue, '13px', cLocale)}`;
});

const ticker = computed(() => cChainParams.current.TICKER);
Expand Down
1 change: 0 additions & 1 deletion scripts/masternode/Masternode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ async function destroyMasternode() {
* @param {import('../transaction.js').UTXO} utxo - Masternode utxo. Must be of exactly `cChainParams.current.collateralInSats` of value
*/
function importMasternode(privateKey, ip, utxo) {
console.log(privateKey, ip, utxo);
const address = parseIpAddress(ip);
if (!address) {
createAlert('warning', ALERTS.MN_BAD_IP, 5000);
Expand Down
37 changes: 25 additions & 12 deletions scripts/misc.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,29 +310,42 @@ export function sanitizeHTML(text) {

/**
* "Beautifies" a number with HTML, by displaying decimals in a lower opacity
* @param {string} strNumber - The number in String form to beautify
* @param {string} strNumber - The number in String form to beautify. This can contain a currency too.
* @param {string?} strDecFontSize - The optional font size to display decimals in
* @param {Intl.NumberFormattingOptions} locale - Locale options to format with
* @returns {string} - A HTML string with beautified number handling
*/
export function beautifyNumber(
strNumber,
strDecFontSize = '',
showFirstNumber = true
) {
if (typeof strNumber === 'number') strNumber = strNumber.toString();
export function beautifyNumber(strNumber, strDecFontSize = '', locale) {
if (typeof strNumber === 'number')
strNumber = strNumber.toLocaleString('en-gb', locale).replace(',', '');

// Only run this for numbers with decimals
if (!strNumber.includes('.'))
return parseInt(strNumber).toLocaleString('en-GB');
return parseInt(strNumber).toLocaleString('en-GB', locale);

// Split the number in to Full and Decimal parts
const arrNumParts = strNumber.split('.');
let arrNumParts = strNumber.split('.');

for (let i = 0; i < arrNumParts[0].length; i++) {
if (parseInt(arrNumParts[0][i])) {
// We have reached the end of the currency part
const currency = arrNumParts[0].slice(0, i);
let number = parseInt(arrNumParts[0].slice(i)).toLocaleString(
'en-gb',
{
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}
);

arrNumParts[0] = [...currency, ...number].join('');
break;
}
}

// Return a HTML that renders the decimal in a lower opacity
const strFontSize = strDecFontSize ? 'font-size: ' + strDecFontSize : '';
return `${
showFirstNumber ? parseInt(arrNumParts[0]).toLocaleString('en-GB') : ''
}<span style="opacity: 0.55; ${strFontSize}">.${arrNumParts[1]}</span>`;
return `${arrNumParts[0]}<span style="opacity: 0.55; ${strFontSize}">.${arrNumParts[1]}</span>`;
}

/**
Expand Down
53 changes: 53 additions & 0 deletions tests/unit/misc.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { describe, it, expect } from 'vitest';
import { beautifyNumber } from '../../scripts/misc.js';

describe('beautifyNumber', () => {
it('should format a number without decimals correctly', () => {
expect(beautifyNumber(12345)).toBe('12,345');
expect(beautifyNumber('12345')).toBe('12,345');
});

it('should format a number with decimals and include HTML for the decimals', () => {
expect(beautifyNumber('12345.67')).toBe(
'12,345<span style="opacity: 0.55; ">.' + '67</span>'
);
expect(beautifyNumber(12345.67)).toBe(
'12,345<span style="opacity: 0.55; ">.' + '67</span>'
);
});

it('should handle numbers with a custom font size for the decimals', () => {
expect(beautifyNumber('12345.67', '14px')).toBe(
'12,345<span style="opacity: 0.55; font-size: 14px">.' + '67</span>'
);
});

it('should handle numbers with leading 0 correctly', () => {
expect(beautifyNumber('0.67', '')).toBe(
'0<span style="opacity: 0.55; ">.' + '67</span>'
);
});

it('should handle currency symbols correctly', () => {
expect(beautifyNumber('USD 0.67', '')).toBe(
'USD 0<span style="opacity: 0.55; ">.' + '67</span>'
);
expect(beautifyNumber('$1340139.67', '')).toBe(
'$1,340,139<span style="opacity: 0.55; ">.' + '67</span>'
);
});

it('should handle edge cases gracefully', () => {
// Empty string input
expect(beautifyNumber('')).toBe('NaN');

// Zero as input
expect(beautifyNumber('0')).toBe('0');
expect(beautifyNumber(0)).toBe('0');

// Negative number input
expect(beautifyNumber('-12345.67')).toBe(
'-12,345<span style="opacity: 0.55; ">.' + '67</span>'
);
});
});
Loading