Skip to content

Commit

Permalink
allow fromwei and toWei to accept numbers as units (#7052)
Browse files Browse the repository at this point in the history
* allow fromwei and toWei to accept numbers as units

* add error and testcases
  • Loading branch information
luu-alex committed May 22, 2024
1 parent 553f270 commit 3904a46
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 14 deletions.
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);
}

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

1 comment on commit 3904a46

@github-actions
Copy link

Choose a reason for hiding this comment

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

Benchmark

Benchmark suite Current: 3904a46 Previous: 553f270 Ratio
processingTx 9074 ops/sec (±5.00%) 9223 ops/sec (±3.52%) 1.02
processingContractDeploy 40926 ops/sec (±5.60%) 38080 ops/sec (±7.25%) 0.93
processingContractMethodSend 20386 ops/sec (±7.30%) 19561 ops/sec (±4.97%) 0.96
processingContractMethodCall 40611 ops/sec (±6.33%) 38511 ops/sec (±5.89%) 0.95
abiEncode 45322 ops/sec (±7.04%) 43655 ops/sec (±6.63%) 0.96
abiDecode 30998 ops/sec (±7.93%) 29655 ops/sec (±8.94%) 0.96
sign 1602 ops/sec (±3.59%) 1555 ops/sec (±3.84%) 0.97
verify 379 ops/sec (±0.71%) 371 ops/sec (±0.51%) 0.98

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.