Skip to content

Commit 4c201ed

Browse files
authored
fix: usd precision (#1866)
1 parent 2447ed6 commit 4c201ed

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

.changeset/giant-frogs-develop.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"fuels-wallet": patch
3+
---
4+
5+
fix: improve precision handling for USD conversion with really low rates (e.g. 0.0000007427)

packages/app/src/systems/Core/utils/convertToUsd.test.ts

+32-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import { DECIMAL_FUEL, bn } from 'fuels';
1+
import { DECIMAL_FUEL, DECIMAL_WEI, bn } from 'fuels';
22
import { convertToUsd } from './convertToUsd';
33

44
const MOCK_ETH_RATE = 2742.15;
55
const MOCK_FUEL_RATE = 0.01167;
6+
const MOCK_SCIENTIFIC_RATE = 1e-7;
67
const MOCK_REALLY_LOW_RATE = 0.0000007427;
78

89
describe('Convert to USD', () => {
@@ -56,6 +57,36 @@ describe('Convert to USD', () => {
5657
expect(value).toBe(24699091436.38);
5758
});
5859

60+
it('should be able to handle large amounts with high precision and regular rate', () => {
61+
const { formatted, value } = convertToUsd(
62+
bn('123456789999999999900000000000000001'),
63+
DECIMAL_WEI,
64+
MOCK_ETH_RATE
65+
);
66+
expect(formatted).toBe('$338,537,036,698,499,999,725.78');
67+
expect(value).toBe(338537036698500000000);
68+
});
69+
70+
it('should be able to handle large amounts with high precision decimal and low rate', () => {
71+
const { formatted, value } = convertToUsd(
72+
bn('123456789999999999900000000000000001'),
73+
DECIMAL_WEI,
74+
MOCK_REALLY_LOW_RATE
75+
);
76+
expect(formatted).toBe('$91,691,357,932.99');
77+
expect(value).toBe(91691357932.99);
78+
});
79+
80+
it('should be able to handle scientific notation', () => {
81+
const { formatted, value } = convertToUsd(
82+
bn('10000000'),
83+
DECIMAL_WEI,
84+
MOCK_SCIENTIFIC_RATE
85+
);
86+
expect(formatted).toBe('$0.000000000000000001');
87+
expect(value).toBe(1e-18);
88+
});
89+
5990
it('should be able to handle lower rates', () => {
6091
const { formatted, value } = convertToUsd(
6192
bn(100_000_000_000),

packages/app/src/systems/Core/utils/convertToUsd.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ function countDecimals(value: number): number {
1010

1111
// Handle scientific notation
1212
if (str.includes('e-')) {
13-
const [, exp] = str.split('e-');
13+
const [nonExp, exp] = str.split('e-');
14+
if (nonExp.includes('.')) {
15+
const [, decimals] = nonExp.split('.');
16+
return Number(exp) + decimals.length;
17+
}
1418
return Number(exp);
1519
}
1620
return str.split('.')[1]?.length || 0;
@@ -31,11 +35,11 @@ export function convertToUsd(
3135
const rateDecimals = countDecimals(rate);
3236
const targetPrecision = getTargetPrecision(rateDecimals, decimals);
3337

34-
// Convert the rate to a fixed-point integer (truncated to avoid rounding errors).
35-
// If the amount has more decimals than the rate, we need to add zeros to the rate.
36-
// If not, we don't need to do anything.
37-
const ratePrecision = 10 ** targetPrecision;
38-
const rateFixed = Math.trunc(rate * ratePrecision);
38+
// Get how many decimal places we need to apply to the rate to match the amount precision.
39+
// Usually the amount has more decimals than the rate, so we need to add zeros to the rate.
40+
const ratePrecision = Math.max(decimals - rateDecimals, 0);
41+
const rateUnits = bn.parseUnits(rate.toFixed(rateDecimals), rateDecimals);
42+
const rateFixed = rateUnits.mul(bn(10).pow(ratePrecision));
3943

4044
// Get how many decimal places we need to apply to the amount to match the rate precision.
4145
// Sometimes the rate has more decimals than the amount, so we need to add zeros to the amount.

0 commit comments

Comments
 (0)