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

allow fromwei and toWei to accept numbers as units #7052

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

- Fixed grammar and spelling in `transactionTimeoutHint` (#6559)

## [Unreleased]
## [Unreleased]

### Added

- Added `InvalidIntegerError` error for fromWei and toWei (#7052)
1 change: 1 addition & 0 deletions packages/web3-errors/src/error_codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ export const ERR_INVALID_LARGE_VALUE = 1011;
export const ERR_INVALID_BLOCK = 1012;
export const ERR_INVALID_TYPE_ABI = 1013;
export const ERR_INVALID_NIBBLE_WIDTH = 1014;
export const ERR_INVALID_INTEGER = 1015;

// Validation error codes
export const ERR_VALIDATION = 1100;
Expand Down
10 changes: 10 additions & 0 deletions packages/web3-errors/src/errors/utils_errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
ERR_INVALID_TYPE,
ERR_INVALID_TYPE_ABI,
ERR_INVALID_UNIT,
ERR_INVALID_INTEGER,
ERR_INVALID_UNSIGNED_INTEGER,
} from '../error_codes.js';
import { InvalidValueError } from '../web3_error_base.js';
Expand Down Expand Up @@ -75,6 +76,15 @@ export class InvalidUnitError extends InvalidValueError {
}
}

export class InvalidIntegerError extends InvalidValueError {
public code = ERR_INVALID_INTEGER;

public constructor(value: unknown) {
super(value, 'not a valid unit. Must be a positive integer');

}
}

export class HexProcessingError extends InvalidValueError {
public code = ERR_INVALID_HEX;

Expand Down
3 changes: 2 additions & 1 deletion packages/web3-utils/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ Documentation:
### Added

- `toWei` add warning when using large numbers or large decimals that may cause precision loss (#6908)
- `toWei` and `fromWei` now supports integers as a unit. (#7053)

### Fixed

- `toWei` support numbers in scientific notation (#6908)
- `toWei` and `fromWei` trims according to ether unit successfuly (#7044)
- `toWei` and `fromWei` trims according to ether unit successfuly (#7044)
37 changes: 28 additions & 9 deletions packages/web3-utils/src/converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
InvalidBytesError,
InvalidNumberError,
InvalidUnitError,
InvalidIntegerError,
} from 'web3-errors';
import { isUint8Array } from './uint8array.js';

Expand Down Expand Up @@ -492,13 +493,22 @@ export const toBigInt = (value: unknown): bigint => {
* > 0.000000001
* ```
*/
export const fromWei = (number: Numbers, unit: EtherUnits): string => {
const denomination = ethUnitMap[unit];
export const fromWei = (number: Numbers, unit: EtherUnits | number): string => {
let denomination;
if (typeof unit === 'string') {
denomination = ethUnitMap[unit];

if (!denomination) {
throw new InvalidUnitError(unit);
if (!denomination) {
throw new InvalidUnitError(unit);
}
} else {
if (unit < 0 || !Number.isInteger(unit)) {
throw new InvalidIntegerError(unit);
}
denomination = BigInt(10)**BigInt(unit);
}


// value in wei would always be integer
// 13456789, 1234
const value = String(toNumber(number));
Expand Down Expand Up @@ -551,14 +561,23 @@ export const fromWei = (number: Numbers, unit: EtherUnits): string => {
* ```
*/
// todo in 1.x unit defaults to 'ether'
export const toWei = (number: Numbers, unit: EtherUnits): string => {
export const toWei = (number: Numbers, unit: EtherUnits | number): string => {
validator.validate(['number'], [number]);

const denomination = ethUnitMap[unit];

if (!denomination) {
throw new InvalidUnitError(unit);
let denomination;
if (typeof unit === 'string') {
denomination = ethUnitMap[unit];
if (!denomination) {
throw new InvalidUnitError(unit);
}
} else {
if (unit < 0 || !Number.isInteger(unit)) {
throw new InvalidIntegerError(unit);
}

denomination = BigInt(10)**BigInt(unit);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this ** will cause an issue. More at: #6506

}

let parsedNumber = number;
if (typeof parsedNumber === 'number') {
if (parsedNumber < 1e-15) {
Expand Down
34 changes: 31 additions & 3 deletions packages/web3-utils/test/fixtures/converters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export const toHexInvalidData: [any, string][] = [
[undefined, 'Invalid value given "undefined". Error: can not be converted to hex.'],
];

const conversionBaseData: [[Numbers, EtherUnits], string][] = [
const conversionBaseData: [[Numbers, EtherUnits | number], string][] = [
[[0, 'wei'], '0'],
[[123, 'wei'], '123'],
[['123', 'wei'], '123'],
Expand Down Expand Up @@ -290,9 +290,35 @@ const conversionBaseData: [[Numbers, EtherUnits], string][] = [
[['178373938391829348', 'ether'], '0.178373938391829348'],
[['879123456788877661', 'gwei'], '879123456.788877661'],
[['879123456788877661', 'tether'], '0.000000000000879123456788877661'],
[['1', 0], '1'],
[['1', 1], '0.1'],
[['1', 2], '0.01'],
[['1', 3], '0.001'],
[['1', 4], '0.0001'],
[['1', 5], '0.00001'],
[['1', 6], '0.000001'],
[['1', 7], '0.0000001'],
[['1', 8], '0.00000001'],
[['1', 9], '0.000000001'],
[['1', 10], '0.0000000001'],
[[1, 18], '0.000000000000000001'],
[[100, 2], '1'],
[['100', 2], '1'],
[['1000', 3], '1'],
[['10000', 4], '1'],
[['100000', 5], '1'],
[['1000000', 6], '1'],
[['10000000', 7], '1'],
[['100000000', 8], '1'],
[['1000000000', 9], '1'],
[['10000000000', 10], '1'],
[['100000000000', 11], '1'],
[['1000000000000', 12], '1'],
[['10000000000000', 13], '1'],
[['1000000000000000000', 18], '1'],
];

export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
export const fromWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [
...conversionBaseData,
[['0xff', 'wei'], '255'],
[[1e+22, 'ether'], '10000'],
Expand All @@ -305,7 +331,7 @@ export const fromWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
[['3308685546611893', 'ether'], '0.003308685546611893']
];

export const toWeiValidData: [[Numbers, EtherUnits], Numbers][] = [
export const toWeiValidData: [[Numbers, EtherUnits | number], Numbers][] = [
...conversionBaseData,
[['255', 'wei'], '0xFF'],
[['100000000000', 'ether'], 0.0000001],
Expand Down Expand Up @@ -336,6 +362,8 @@ export const fromWeiInvalidData: [[any, any], string][] = [
[[{}, 'kwei'], 'Invalid value given "{}". Error: can not parse as number data'],
[['data', 'kwei'], 'Invalid value given "data". Error: can not parse as number data.'],
[['1234', 'uwei'], 'Invalid value given "uwei". Error: invalid unit.'],
[['1234', -1], 'Invalid value given "-1". Error: not a valid unit. Must be a positive integer.'],
[['1234', 3.3], 'Invalid value given "3.3". Error: not a valid unit. Must be a positive integer.']
];

export const toWeiInvalidData: [[any, any], string][] = [
Expand Down
Loading