Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

fix(#7044): toWei trim strings with more than 20 decimal places #7045

Merged
merged 5 commits into from
May 21, 2024
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
3 changes: 2 additions & 1 deletion packages/web3-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,5 @@ Documentation:

### Fixed

- `toWei` support numbers in scientific notation (#6908)
- `toWei` support numbers in scientific notation (#6908)
- `toWei` and `fromWei` trims according to ether unit successfuly (#7044)
41 changes: 21 additions & 20 deletions packages/web3-utils/src/converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,9 @@ export const fromWei = (number: Numbers, unit: EtherUnits): string => {
if (fraction === '') {
return integer;
}
const updatedValue = `${integer}.${fraction}`;

return `${integer}.${fraction}`;
return updatedValue.slice(0, integer.length + numberOfZerosInDenomination + 1);
};

/**
Expand All @@ -559,50 +560,50 @@ export const toWei = (number: Numbers, unit: EtherUnits): string => {
throw new InvalidUnitError(unit);
}
let parsedNumber = number;
if (typeof parsedNumber === 'number'){
if (parsedNumber < 1e-15){
console.warn(PrecisionLossWarning)
if (typeof parsedNumber === 'number') {
if (parsedNumber < 1e-15) {
console.warn(PrecisionLossWarning);
}
if (parsedNumber > 1e+20) {
console.warn(PrecisionLossWarning)
if (parsedNumber > 1e20) {
console.warn(PrecisionLossWarning);

parsedNumber = BigInt(parsedNumber);
parsedNumber = BigInt(parsedNumber);
} else {
// in case there is a decimal point, we need to convert it to string
parsedNumber = parsedNumber.toLocaleString('fullwide', {useGrouping: false, maximumFractionDigits: 20})
parsedNumber = parsedNumber.toLocaleString('fullwide', {
useGrouping: false,
maximumFractionDigits: 20,
});
}
}

// if value is decimal e.g. 24.56 extract `integer` and `fraction` part
// to avoid `fraction` to be null use `concat` with empty string
const [integer, fraction] = String(
typeof parsedNumber === 'string' && !isHexStrict(parsedNumber) ? parsedNumber : toNumber(parsedNumber),
typeof parsedNumber === 'string' && !isHexStrict(parsedNumber)
? parsedNumber
: toNumber(parsedNumber),
)
.split('.')
.concat('');

// join the value removing `.` from
// 24.56 -> 2456

const value = BigInt(`${integer}${fraction}`);

// multiply value with denomination
// 2456 * 1000000 -> 2456000000
const updatedValue = value * denomination;

// count number of zeros in denomination
const numberOfZerosInDenomination = denomination.toString().length - 1;

// check which either `fraction` or `denomination` have lower number of zeros
const decimals = Math.min(fraction.length, numberOfZerosInDenomination);

// check if whole number was passed in
const decimals = fraction.length;
if (decimals === 0) {
return updatedValue.toString();
}

// Add zeros to make length equal to required decimal points
// If string is larger than decimal points required then remove last zeros
return updatedValue.toString().padStart(decimals, '0').slice(0, -decimals);
// trim the value to remove extra zeros
return updatedValue.toString().slice(0, -decimals);
};

/**
Expand Down
14 changes: 12 additions & 2 deletions packages/web3-utils/test/fixtures/converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,20 +292,30 @@ const conversionBaseData: [[Numbers, EtherUnits], string][] = [
[['879123456788877661', 'tether'], '0.000000000000879123456788877661'],
];

export const fromWeiValidData: [[Numbers, EtherUnits], string][] = [
export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
...conversionBaseData,
[['0xff', 'wei'], '255'],
[[1e+22, 'ether'], '10000'],
[[19999999999999991611392, 'ether'], '19999.999999999991611392'],
[[1.9999999999999991611392e+22, 'ether'], '19999.999999999991611392'],
[['1000000', 'ether'], '0.000000000001'],
[['1123456789123456789', 'ether'], '1.123456789123456789'],
[['1123', 'kwei'], '1.123'],
[['1234100' ,'kwei'], '1234.1'],
[['3308685546611893', 'ether'], '0.003308685546611893']
];

export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
...conversionBaseData,
[['255', 'wei'], '0xFF'],
[['100000000000', 'ether'], 0.0000001],
[['1000000000', 'ether'], 0.000000001],
[['1000000', 'ether'], 0.000000000001]
[['1000000', 'ether'], 0.000000000001],
[['1123456789123456789', 'ether'], '1.123456789123456789123'],
[['1123', 'kwei'], '1.12345'],
[['1234100' ,'kwei'], '1234.1'],
[['3308685546611893', 'ether'], '0.0033086855466118933'],
[['1123', 'kwei'], 1.12345],

];

Expand Down