mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-24 19:10:22 +01:00
add numeric module (#17324)
This commit is contained in:
parent
b87f89b7b4
commit
a9ef2a049a
@ -42,8 +42,8 @@ module.exports = {
|
|||||||
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js',
|
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js',
|
||||||
'<rootDir>/app/scripts/migrations/*.test.js',
|
'<rootDir>/app/scripts/migrations/*.test.js',
|
||||||
'<rootDir>/app/scripts/platforms/*.test.js',
|
'<rootDir>/app/scripts/platforms/*.test.js',
|
||||||
'<rootDir>/shared/**/*.test.js',
|
'<rootDir>/shared/**/*.test.(js|ts)',
|
||||||
'<rootDir>/ui/**/*.test.js',
|
'<rootDir>/ui/**/*.test.(js|ts)',
|
||||||
],
|
],
|
||||||
testTimeout: 2500,
|
testTimeout: 2500,
|
||||||
// We have to specify the environment we are running in, which is jsdom. The
|
// We have to specify the environment we are running in, which is jsdom. The
|
||||||
|
@ -602,7 +602,7 @@
|
|||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true,
|
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"node-fetch": true
|
"node-fetch": true
|
||||||
@ -954,7 +954,7 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"@metamask/rpc-methods>@metamask/key-tree": true,
|
"@metamask/rpc-methods>@metamask/key-tree": true,
|
||||||
"@metamask/snaps-utils>@noble/hashes": true,
|
"@metamask/snaps-utils>@noble/hashes": true,
|
||||||
"eth-block-tracker>@metamask/utils": true
|
"@metamask/utils": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@metamask/rpc-methods>@metamask/browser-passworder": {
|
"@metamask/rpc-methods>@metamask/browser-passworder": {
|
||||||
@ -978,7 +978,7 @@
|
|||||||
"@metamask/rpc-methods>@metamask/key-tree>@scure/bip39": true,
|
"@metamask/rpc-methods>@metamask/key-tree>@scure/bip39": true,
|
||||||
"@metamask/snaps-utils>@noble/hashes": true,
|
"@metamask/snaps-utils>@noble/hashes": true,
|
||||||
"@metamask/snaps-utils>@scure/base": true,
|
"@metamask/snaps-utils>@scure/base": true,
|
||||||
"eth-block-tracker>@metamask/utils": true
|
"@metamask/utils": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": {
|
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": {
|
||||||
@ -1062,6 +1062,18 @@
|
|||||||
"@metamask/base-controller": true
|
"@metamask/base-controller": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@metamask/utils": {
|
||||||
|
"globals": {
|
||||||
|
"TextDecoder": true,
|
||||||
|
"TextEncoder": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@metamask/utils>superstruct": true,
|
||||||
|
"browserify>buffer": true,
|
||||||
|
"nock>debug": true,
|
||||||
|
"semver": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"@ngraveio/bc-ur": {
|
"@ngraveio/bc-ur": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ngraveio/bc-ur>@apocentre/alias-sampling": true,
|
"@ngraveio/bc-ur>@apocentre/alias-sampling": true,
|
||||||
@ -2124,23 +2136,12 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-block-tracker>pify": true,
|
"eth-block-tracker>pify": true,
|
||||||
"eth-query>json-rpc-random-id": true,
|
"eth-query>json-rpc-random-id": true,
|
||||||
"json-rpc-engine>@metamask/safe-event-emitter": true
|
"json-rpc-engine>@metamask/safe-event-emitter": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eth-block-tracker>@metamask/utils": {
|
|
||||||
"globals": {
|
|
||||||
"TextDecoder": true,
|
|
||||||
"TextEncoder": true
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@metamask/snaps-ui>superstruct": true,
|
|
||||||
"browserify>buffer": true,
|
|
||||||
"nock>debug": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"eth-ens-namehash": {
|
"eth-ens-namehash": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"name": "write"
|
"name": "write"
|
||||||
@ -2193,8 +2194,8 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
|
"@metamask/utils": true,
|
||||||
"browserify>browser-resolve": true,
|
"browserify>browser-resolve": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
|
||||||
"eth-json-rpc-middleware>@metamask/eth-sig-util": true,
|
"eth-json-rpc-middleware>@metamask/eth-sig-util": true,
|
||||||
"eth-json-rpc-middleware>pify": true,
|
"eth-json-rpc-middleware>pify": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
@ -4104,6 +4105,20 @@
|
|||||||
"webpack>events": true
|
"webpack>events": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"semver": {
|
||||||
|
"globals": {
|
||||||
|
"console.error": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"browserify>process": true,
|
||||||
|
"semver>lru-cache": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver>lru-cache": {
|
||||||
|
"packages": {
|
||||||
|
"semver>lru-cache>yallist": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"sinon>nise>path-to-regexp": {
|
"sinon>nise>path-to-regexp": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"sinon>nise>path-to-regexp>isarray": true
|
"sinon>nise>path-to-regexp>isarray": true
|
||||||
|
@ -602,7 +602,7 @@
|
|||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true,
|
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"node-fetch": true
|
"node-fetch": true
|
||||||
@ -1048,7 +1048,7 @@
|
|||||||
"@metamask/snaps-ui>superstruct": true,
|
"@metamask/snaps-ui>superstruct": true,
|
||||||
"@metamask/snaps-utils": true,
|
"@metamask/snaps-utils": true,
|
||||||
"@metamask/snaps-utils>@noble/hashes": true,
|
"@metamask/snaps-utils>@noble/hashes": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-rpc-errors": true
|
"eth-rpc-errors": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1073,7 +1073,7 @@
|
|||||||
"@metamask/rpc-methods>@metamask/key-tree>@scure/bip39": true,
|
"@metamask/rpc-methods>@metamask/key-tree>@scure/bip39": true,
|
||||||
"@metamask/snaps-utils>@noble/hashes": true,
|
"@metamask/snaps-utils>@noble/hashes": true,
|
||||||
"@metamask/snaps-utils>@scure/base": true,
|
"@metamask/snaps-utils>@scure/base": true,
|
||||||
"eth-block-tracker>@metamask/utils": true
|
"@metamask/utils": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": {
|
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": {
|
||||||
@ -1164,7 +1164,7 @@
|
|||||||
"@metamask/snaps-controllers>tar-stream": true,
|
"@metamask/snaps-controllers>tar-stream": true,
|
||||||
"@metamask/snaps-utils": true,
|
"@metamask/snaps-utils": true,
|
||||||
"@metamask/subject-metadata-controller": true,
|
"@metamask/subject-metadata-controller": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"pump": true
|
"pump": true
|
||||||
@ -1329,7 +1329,7 @@
|
|||||||
"@metamask/snaps-ui": {
|
"@metamask/snaps-ui": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"@metamask/snaps-ui>superstruct": true,
|
"@metamask/snaps-ui>superstruct": true,
|
||||||
"eth-block-tracker>@metamask/utils": true
|
"@metamask/utils": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@metamask/snaps-utils": {
|
"@metamask/snaps-utils": {
|
||||||
@ -1344,7 +1344,7 @@
|
|||||||
"@metamask/snaps-utils>cron-parser": true,
|
"@metamask/snaps-utils>cron-parser": true,
|
||||||
"@metamask/snaps-utils>rfdc": true,
|
"@metamask/snaps-utils>rfdc": true,
|
||||||
"@metamask/snaps-utils>validate-npm-package-name": true,
|
"@metamask/snaps-utils>validate-npm-package-name": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"semver": true
|
"semver": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1387,6 +1387,18 @@
|
|||||||
"@metamask/base-controller": true
|
"@metamask/base-controller": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@metamask/utils": {
|
||||||
|
"globals": {
|
||||||
|
"TextDecoder": true,
|
||||||
|
"TextEncoder": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@metamask/utils>superstruct": true,
|
||||||
|
"browserify>buffer": true,
|
||||||
|
"nock>debug": true,
|
||||||
|
"semver": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"@ngraveio/bc-ur": {
|
"@ngraveio/bc-ur": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ngraveio/bc-ur>@apocentre/alias-sampling": true,
|
"@ngraveio/bc-ur>@apocentre/alias-sampling": true,
|
||||||
@ -2449,23 +2461,12 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-block-tracker>pify": true,
|
"eth-block-tracker>pify": true,
|
||||||
"eth-query>json-rpc-random-id": true,
|
"eth-query>json-rpc-random-id": true,
|
||||||
"json-rpc-engine>@metamask/safe-event-emitter": true
|
"json-rpc-engine>@metamask/safe-event-emitter": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eth-block-tracker>@metamask/utils": {
|
|
||||||
"globals": {
|
|
||||||
"TextDecoder": true,
|
|
||||||
"TextEncoder": true
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@metamask/snaps-ui>superstruct": true,
|
|
||||||
"browserify>buffer": true,
|
|
||||||
"nock>debug": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"eth-ens-namehash": {
|
"eth-ens-namehash": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"name": "write"
|
"name": "write"
|
||||||
@ -2518,8 +2519,8 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
|
"@metamask/utils": true,
|
||||||
"browserify>browser-resolve": true,
|
"browserify>browser-resolve": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
|
||||||
"eth-json-rpc-middleware>@metamask/eth-sig-util": true,
|
"eth-json-rpc-middleware>@metamask/eth-sig-util": true,
|
||||||
"eth-json-rpc-middleware>pify": true,
|
"eth-json-rpc-middleware>pify": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
|
@ -602,7 +602,7 @@
|
|||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true,
|
"@metamask/eth-json-rpc-infura>eth-json-rpc-middleware": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
"json-rpc-engine": true,
|
"json-rpc-engine": true,
|
||||||
"node-fetch": true
|
"node-fetch": true
|
||||||
@ -954,7 +954,7 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"@metamask/rpc-methods>@metamask/key-tree": true,
|
"@metamask/rpc-methods>@metamask/key-tree": true,
|
||||||
"@metamask/snaps-utils>@noble/hashes": true,
|
"@metamask/snaps-utils>@noble/hashes": true,
|
||||||
"eth-block-tracker>@metamask/utils": true
|
"@metamask/utils": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@metamask/rpc-methods>@metamask/browser-passworder": {
|
"@metamask/rpc-methods>@metamask/browser-passworder": {
|
||||||
@ -978,7 +978,7 @@
|
|||||||
"@metamask/rpc-methods>@metamask/key-tree>@scure/bip39": true,
|
"@metamask/rpc-methods>@metamask/key-tree>@scure/bip39": true,
|
||||||
"@metamask/snaps-utils>@noble/hashes": true,
|
"@metamask/snaps-utils>@noble/hashes": true,
|
||||||
"@metamask/snaps-utils>@scure/base": true,
|
"@metamask/snaps-utils>@scure/base": true,
|
||||||
"eth-block-tracker>@metamask/utils": true
|
"@metamask/utils": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": {
|
"@metamask/rpc-methods>@metamask/key-tree>@noble/ed25519": {
|
||||||
@ -1062,6 +1062,18 @@
|
|||||||
"@metamask/base-controller": true
|
"@metamask/base-controller": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@metamask/utils": {
|
||||||
|
"globals": {
|
||||||
|
"TextDecoder": true,
|
||||||
|
"TextEncoder": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"@metamask/utils>superstruct": true,
|
||||||
|
"browserify>buffer": true,
|
||||||
|
"nock>debug": true,
|
||||||
|
"semver": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"@ngraveio/bc-ur": {
|
"@ngraveio/bc-ur": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"@ngraveio/bc-ur>@apocentre/alias-sampling": true,
|
"@ngraveio/bc-ur>@apocentre/alias-sampling": true,
|
||||||
@ -2124,23 +2136,12 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
"@metamask/utils": true,
|
||||||
"eth-block-tracker>pify": true,
|
"eth-block-tracker>pify": true,
|
||||||
"eth-query>json-rpc-random-id": true,
|
"eth-query>json-rpc-random-id": true,
|
||||||
"json-rpc-engine>@metamask/safe-event-emitter": true
|
"json-rpc-engine>@metamask/safe-event-emitter": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eth-block-tracker>@metamask/utils": {
|
|
||||||
"globals": {
|
|
||||||
"TextDecoder": true,
|
|
||||||
"TextEncoder": true
|
|
||||||
},
|
|
||||||
"packages": {
|
|
||||||
"@metamask/snaps-ui>superstruct": true,
|
|
||||||
"browserify>buffer": true,
|
|
||||||
"nock>debug": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"eth-ens-namehash": {
|
"eth-ens-namehash": {
|
||||||
"globals": {
|
"globals": {
|
||||||
"name": "write"
|
"name": "write"
|
||||||
@ -2193,8 +2194,8 @@
|
|||||||
"setTimeout": true
|
"setTimeout": true
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
|
"@metamask/utils": true,
|
||||||
"browserify>browser-resolve": true,
|
"browserify>browser-resolve": true,
|
||||||
"eth-block-tracker>@metamask/utils": true,
|
|
||||||
"eth-json-rpc-middleware>@metamask/eth-sig-util": true,
|
"eth-json-rpc-middleware>@metamask/eth-sig-util": true,
|
||||||
"eth-json-rpc-middleware>pify": true,
|
"eth-json-rpc-middleware>pify": true,
|
||||||
"eth-rpc-errors": true,
|
"eth-rpc-errors": true,
|
||||||
@ -4104,6 +4105,20 @@
|
|||||||
"webpack>events": true
|
"webpack>events": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"semver": {
|
||||||
|
"globals": {
|
||||||
|
"console.error": true
|
||||||
|
},
|
||||||
|
"packages": {
|
||||||
|
"browserify>process": true,
|
||||||
|
"semver>lru-cache": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"semver>lru-cache": {
|
||||||
|
"packages": {
|
||||||
|
"semver>lru-cache>yallist": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"sinon>nise>path-to-regexp": {
|
"sinon>nise>path-to-regexp": {
|
||||||
"packages": {
|
"packages": {
|
||||||
"sinon>nise>path-to-regexp>isarray": true
|
"sinon>nise>path-to-regexp>isarray": true
|
||||||
|
@ -1910,7 +1910,6 @@
|
|||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
"chokidar>braces": true,
|
"chokidar>braces": true,
|
||||||
"chokidar>fsevents": true,
|
|
||||||
"chokidar>glob-parent": true,
|
"chokidar>glob-parent": true,
|
||||||
"chokidar>is-binary-path": true,
|
"chokidar>is-binary-path": true,
|
||||||
"chokidar>normalize-path": true,
|
"chokidar>normalize-path": true,
|
||||||
@ -5220,7 +5219,6 @@
|
|||||||
"gulp-watch>path-is-absolute": true,
|
"gulp-watch>path-is-absolute": true,
|
||||||
"gulp>glob-watcher>anymatch": true,
|
"gulp>glob-watcher>anymatch": true,
|
||||||
"gulp>glob-watcher>chokidar>braces": true,
|
"gulp>glob-watcher>chokidar>braces": true,
|
||||||
"gulp>glob-watcher>chokidar>fsevents": true,
|
|
||||||
"gulp>glob-watcher>chokidar>glob-parent": true,
|
"gulp>glob-watcher>chokidar>glob-parent": true,
|
||||||
"gulp>glob-watcher>chokidar>is-binary-path": true,
|
"gulp>glob-watcher>chokidar>is-binary-path": true,
|
||||||
"gulp>glob-watcher>chokidar>readdirp": true,
|
"gulp>glob-watcher>chokidar>readdirp": true,
|
||||||
|
@ -241,6 +241,7 @@
|
|||||||
"@metamask/snaps-ui": "^0.27.1",
|
"@metamask/snaps-ui": "^0.27.1",
|
||||||
"@metamask/snaps-utils": "^0.27.1",
|
"@metamask/snaps-utils": "^0.27.1",
|
||||||
"@metamask/subject-metadata-controller": "^1.0.0",
|
"@metamask/subject-metadata-controller": "^1.0.0",
|
||||||
|
"@metamask/utils": "^3.4.1",
|
||||||
"@ngraveio/bc-ur": "^1.1.6",
|
"@ngraveio/bc-ur": "^1.1.6",
|
||||||
"@popperjs/core": "^2.4.0",
|
"@popperjs/core": "^2.4.0",
|
||||||
"@reduxjs/toolkit": "^1.6.2",
|
"@reduxjs/toolkit": "^1.6.2",
|
||||||
|
5
shared/constants/common.ts
Normal file
5
shared/constants/common.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum EtherDenomination {
|
||||||
|
ETH = 'ETH',
|
||||||
|
GWEI = 'GWEI',
|
||||||
|
WEI = 'WEI',
|
||||||
|
}
|
541
shared/modules/Numeric.test.ts
Normal file
541
shared/modules/Numeric.test.ts
Normal file
@ -0,0 +1,541 @@
|
|||||||
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
import { BN } from 'bn.js';
|
||||||
|
import { EtherDenomination } from '../constants/common';
|
||||||
|
import { Numeric } from './Numeric';
|
||||||
|
|
||||||
|
const ONE_ETH = new Numeric(1, 10, EtherDenomination.ETH);
|
||||||
|
const ONE_GWEI = new Numeric(1, 10, EtherDenomination.GWEI);
|
||||||
|
const ONE_WEI = new Numeric(1, 10, EtherDenomination.WEI);
|
||||||
|
|
||||||
|
describe('Numeric', () => {
|
||||||
|
describe('Basic Numeric Construction', () => {
|
||||||
|
describe('From hexadeciaml strings', () => {
|
||||||
|
it('Should create a new Numeric from a hexadecimal string', () => {
|
||||||
|
const numeric = new Numeric('0xa', 16);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(10, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a hexadecimal string with a decimal', () => {
|
||||||
|
const numeric = new Numeric('0xa.7', 16);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(10.4375, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a hexadecimal string with negation', () => {
|
||||||
|
const numeric = new Numeric('-0xa', 16);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(-10, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a hexadecimal string with negation and decimal', () => {
|
||||||
|
const numeric = new Numeric('-0xa.7', 16);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(-10.4375, 10));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('From decimal strings', () => {
|
||||||
|
it('Should create a new Numeric from a decimal string', () => {
|
||||||
|
const numeric = new Numeric('10', 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(10, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a decimal string with a decimal', () => {
|
||||||
|
const numeric = new Numeric('10.4375', 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(10.4375, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a decimal string with negation', () => {
|
||||||
|
const numeric = new Numeric('-10', 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(-10, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a decimal string with negation and decimal', () => {
|
||||||
|
const numeric = new Numeric('-10.4375', 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(-10.4375, 10));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('From decimal numbers', () => {
|
||||||
|
it('Should create a new Numeric from a hexadecimal number', () => {
|
||||||
|
const numeric = new Numeric(10, 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(10, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a hexadecimal string with a decimal', () => {
|
||||||
|
const numeric = new Numeric(10.4375, 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(10.4375, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a hexadecimal string with negation', () => {
|
||||||
|
const numeric = new Numeric(-10, 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(-10, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a hexadecimal string with negation and decimal', () => {
|
||||||
|
const numeric = new Numeric(-10.4375, 16);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(-10.4375, 10));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('From BigNumbers or BN', () => {
|
||||||
|
it('Should create a new Numeric from a BigNumber', () => {
|
||||||
|
const numeric = new Numeric(new BigNumber(100, 10));
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(100, 10));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should create a new Numeric from a BN', () => {
|
||||||
|
const numeric = new Numeric(new BN(100, 10), 10);
|
||||||
|
expect(numeric.value).toEqual(new BigNumber(100, 10));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Error checking', () => {
|
||||||
|
it('Should throw an error for a non numeric string', () => {
|
||||||
|
expect(() => new Numeric('Hello there', 10)).toThrow(
|
||||||
|
'String provided to stringToBigNumber is not a hexadecimal or decimal string: Hello there, 10',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should throw an error for a numeric string without a base', () => {
|
||||||
|
expect(() => new Numeric('10')).toThrow(
|
||||||
|
'You must specify the base of the provided number if the value is not already a BigNumber',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should throw an error for a non numeric type', () => {
|
||||||
|
expect(() => new Numeric(true as unknown as number, 10)).toThrow(
|
||||||
|
'Value: true is not a string, number, BigNumber or BN. Type is: boolean.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Erroneous behaviors that we are temporarily continuing', () => {
|
||||||
|
it('Handles values that are undefined, setting the value to 0', () => {
|
||||||
|
expect(new Numeric(undefined as unknown as number).toString()).toEqual(
|
||||||
|
'0',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Handles values that are NaN, setting the value to 0', () => {
|
||||||
|
expect(new Numeric(NaN).toString()).toEqual('0');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Ether denomination conversion', () => {
|
||||||
|
it('should convert 1 ETH to 1000000000 GWEI', () => {
|
||||||
|
expect(ONE_ETH.toDenomination(EtherDenomination.GWEI).toString()).toEqual(
|
||||||
|
'1000000000',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert 1 ETH to 1000000000000000000 WEI', () => {
|
||||||
|
expect(ONE_ETH.toDenomination(EtherDenomination.WEI).toString()).toEqual(
|
||||||
|
'1000000000000000000',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert 1 GWEI to 0.000000001 ETH', () => {
|
||||||
|
expect(ONE_GWEI.toDenomination(EtherDenomination.ETH).toString()).toEqual(
|
||||||
|
'0.000000001',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert 1 GWEI to 1000000000 WEI', () => {
|
||||||
|
expect(ONE_GWEI.toDenomination(EtherDenomination.WEI).toString()).toEqual(
|
||||||
|
'1000000000',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert 1 WEI to 0 ETH due to rounding', () => {
|
||||||
|
expect(ONE_WEI.toDenomination(EtherDenomination.ETH).toString()).toEqual(
|
||||||
|
'0',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert 1 WEI to 0.000000001 GWEI', () => {
|
||||||
|
expect(ONE_WEI.toDenomination(EtherDenomination.GWEI).toString()).toEqual(
|
||||||
|
'0.000000001',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Math operations', () => {
|
||||||
|
describe('Multiplication', () => {
|
||||||
|
it('Should compute correct results for simple multiplication', () => {
|
||||||
|
expect(new Numeric(5, 10).times(5, 10).toNumber()).toEqual(25);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(5, 10).times(new Numeric(10, 10)).toNumber(),
|
||||||
|
).toEqual(50);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(25, 10).times(new Numeric(10, 10)).toNumber(),
|
||||||
|
).toEqual(250);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for multiplication of big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).times('686216', 10).toString(),
|
||||||
|
).toEqual('120548547381312');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.times(new Numeric('686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('1205485473813120');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('41756714320', 10)
|
||||||
|
.times(new Numeric('6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('286541254738131200');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for multiplication of negative big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).times('-686216', 10).toString(),
|
||||||
|
).toEqual('-120548547381312');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.times(new Numeric('-686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('-1205485473813120');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('-41756714320', 10)
|
||||||
|
.times(new Numeric('-6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('286541254738131200');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Division', () => {
|
||||||
|
it('Should compute correct results for simple division', () => {
|
||||||
|
expect(new Numeric(25, 10).divide(5, 10).toNumber()).toEqual(5);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(50, 10).divide(new Numeric(10, 10)).toNumber(),
|
||||||
|
).toEqual(5);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(250, 10).divide(new Numeric(10, 10)).toNumber(),
|
||||||
|
).toEqual(25);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for division of big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).divide('686216', 10).toString(),
|
||||||
|
).toEqual('256.00019818832554181191');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.divide(new Numeric('686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('2560.00198188325541811908');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('41756714320', 10)
|
||||||
|
.divide(new Numeric('6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('6085.06859647691106007438');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for division of negative big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).divide('-686216', 10).toString(),
|
||||||
|
).toEqual('-256.00019818832554181191');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.divide(new Numeric('-686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('-2560.00198188325541811908');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('-41756714320', 10)
|
||||||
|
.divide(new Numeric('-6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('6085.06859647691106007438');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Addition', () => {
|
||||||
|
it('Should compute correct results for simple addition', () => {
|
||||||
|
expect(new Numeric(25, 10).add(5, 10).toNumber()).toEqual(30);
|
||||||
|
|
||||||
|
expect(new Numeric(50, 10).add(new Numeric(10, 10)).toNumber()).toEqual(
|
||||||
|
60,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(250, 10).add(new Numeric(100, 10)).toNumber(),
|
||||||
|
).toEqual(350);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for addition of big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).add('686216', 10).toString(),
|
||||||
|
).toEqual('176357648');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.add(new Numeric('686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('1757400536');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('41756714320', 10)
|
||||||
|
.add(new Numeric('6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('41763576480');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for addition of negative big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).add('-686216', 10).toString(),
|
||||||
|
).toEqual('174985216');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.add(new Numeric('-686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('1756028104');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('-41756714320', 10)
|
||||||
|
.add(new Numeric('-6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('-41763576480');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Subtraction', () => {
|
||||||
|
it('Should compute correct results for simple subtraction', () => {
|
||||||
|
expect(new Numeric(25, 10).minus(5, 10).toNumber()).toEqual(20);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(50, 10).minus(new Numeric(10, 10)).toNumber(),
|
||||||
|
).toEqual(40);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric(250, 10).minus(new Numeric(100, 10)).toNumber(),
|
||||||
|
).toEqual(150);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for subtraction of big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).minus('686216', 10).toString(),
|
||||||
|
).toEqual('174985216');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.minus(new Numeric('686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('1756028104');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('41756714320', 10)
|
||||||
|
.minus(new Numeric('6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('41749852160');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should compute correct results for subtraction of negative big numbers', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric('175671432', 10).minus('-686216', 10).toString(),
|
||||||
|
).toEqual('176357648');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('1756714320', 10)
|
||||||
|
.minus(new Numeric('-686216', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('1757400536');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
new Numeric('-41756714320', 10)
|
||||||
|
.minus(new Numeric('-6862160', 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('-41749852160');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('applyConversionRate', () => {
|
||||||
|
it('Should multiply the value by the conversionRate supplied', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric(10, 10).applyConversionRate(468.5).toString(),
|
||||||
|
).toEqual('4685');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should multiply the value by the conversionRate supplied when conversionRate is a BigNumber', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric(10, 10)
|
||||||
|
.applyConversionRate(new BigNumber(468.5, 10))
|
||||||
|
.toString(),
|
||||||
|
).toEqual('4685');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should multiply the value by the inverse of conversionRate supplied when second parameter is true', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric(10, 10).applyConversionRate(468.5, true).toString(),
|
||||||
|
).toEqual('0.0213447171824973319');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should multiply the value by the inverse of the BigNumber conversionRate supplied when second parameter is true', () => {
|
||||||
|
expect(
|
||||||
|
new Numeric(10, 10)
|
||||||
|
.applyConversionRate(new BigNumber(468.5, 10), true)
|
||||||
|
.toString(),
|
||||||
|
).toEqual('0.0213447171824973319');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Base conversion', () => {
|
||||||
|
it('should convert a hexadecimal string to a decimal string', () => {
|
||||||
|
expect(new Numeric('0x5208', 16).toBase(10).toString()).toEqual('21000');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert a decimal string to a hexadecimal string', () => {
|
||||||
|
expect(new Numeric('21000', 10).toBase(16).toString()).toEqual('5208');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert a decimal string to a 0x prefixed hexadecimal string', () => {
|
||||||
|
expect(new Numeric('21000', 10).toPrefixedHexString()).toEqual('0x5208');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert a decimal number to a hexadecimal string', () => {
|
||||||
|
expect(new Numeric(21000, 10).toBase(16).toString()).toEqual('5208');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert a decimal number to a 0x prefixed hexadecimal string', () => {
|
||||||
|
expect(new Numeric(21000, 10).toPrefixedHexString()).toEqual('0x5208');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Comparisons', () => {
|
||||||
|
it('Should correctly identify that 0xa is greater than 0x9', () => {
|
||||||
|
expect(new Numeric('0xa', 16).greaterThan('0x9', 16)).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should correctly identify that 0x9 is less than 0xa', () => {
|
||||||
|
expect(new Numeric('0x9', 16).lessThan('0xa', 16)).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should correctly identify that 0xa is greater than or equal to 0xa', () => {
|
||||||
|
expect(new Numeric('0xa', 16).greaterThanOrEqualTo('0xa', 16)).toEqual(
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('Should correctly identify that 0xa is less than or equal to 0xa', () => {
|
||||||
|
expect(new Numeric('0xa', 16).lessThanOrEqualTo('0xa', 16)).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should correctly identify that 0xa is greater than 9', () => {
|
||||||
|
expect(new Numeric('0xa', 16).greaterThan(9, 10)).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should correctly identify that 0x9 is less than 10', () => {
|
||||||
|
expect(new Numeric('0x9', 16).lessThan(10, 10)).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should correctly identify that 10 is greater than or equal to 0xa', () => {
|
||||||
|
expect(new Numeric(10, 10).greaterThanOrEqualTo('0xa', 16)).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should correctly identify that 10 is less than or equal to 0xa', () => {
|
||||||
|
expect(new Numeric(10, 10).lessThanOrEqualTo('0xa', 16)).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Positive and Negative determination', () => {
|
||||||
|
it('Should correctly identify a negative number with isNegative', () => {
|
||||||
|
expect(new Numeric(-10, 10).isNegative()).toEqual(true);
|
||||||
|
expect(new Numeric('-10', 10).isNegative()).toEqual(true);
|
||||||
|
expect(new Numeric('-0xa', 16).isNegative()).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should return false for isNegative when number is positive', () => {
|
||||||
|
expect(new Numeric(10, 10).isNegative()).toEqual(false);
|
||||||
|
expect(new Numeric('10', 10).isNegative()).toEqual(false);
|
||||||
|
expect(new Numeric('0xa', 16).isNegative()).toEqual(false);
|
||||||
|
});
|
||||||
|
it('Should correctly identify a positive number with isPositive', () => {
|
||||||
|
expect(new Numeric(10, 10).isPositive()).toEqual(true);
|
||||||
|
expect(new Numeric('10', 10).isPositive()).toEqual(true);
|
||||||
|
expect(new Numeric('0xa', 16).isPositive()).toEqual(true);
|
||||||
|
});
|
||||||
|
it('Should return false for isPositive when number is negative', () => {
|
||||||
|
expect(new Numeric(-10, 10).isPositive()).toEqual(false);
|
||||||
|
expect(new Numeric('-10', 10).isPositive()).toEqual(false);
|
||||||
|
expect(new Numeric('-0xa', 16).isPositive()).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Terminating functions, return values', () => {
|
||||||
|
describe('toString', () => {
|
||||||
|
it('Should return a string representation of provided hex', () => {
|
||||||
|
expect(new Numeric('0xa', 16).toString()).toEqual('a');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided decimal string', () => {
|
||||||
|
expect(new Numeric('10', 10).toString()).toEqual('10');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided number', () => {
|
||||||
|
expect(new Numeric(10, 10).toString()).toEqual('10');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided float', () => {
|
||||||
|
expect(new Numeric(10.5, 10).toString()).toEqual('10.5');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided BigNumber', () => {
|
||||||
|
expect(new Numeric(new BigNumber(10, 10)).toString()).toEqual('10');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided BN', () => {
|
||||||
|
expect(new Numeric(new BN(10, 10)).toString()).toEqual('10');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('toNumber', () => {
|
||||||
|
it('Should return a number representing provided hex', () => {
|
||||||
|
expect(new Numeric('0xa', 16).toNumber()).toEqual(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a number representation of provided decimal string', () => {
|
||||||
|
expect(new Numeric('10', 10).toNumber()).toEqual(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a number representation of provided number', () => {
|
||||||
|
expect(new Numeric(10, 10).toNumber()).toEqual(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a number representation of provided float', () => {
|
||||||
|
expect(new Numeric(10.5, 10).toNumber()).toEqual(10.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a number representation of provided BigNumber', () => {
|
||||||
|
expect(new Numeric(new BigNumber(10, 10)).toNumber()).toEqual(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a number representation of provided BN', () => {
|
||||||
|
expect(new Numeric(new BN(10, 10)).toNumber()).toEqual(10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('toFixed', () => {
|
||||||
|
it('Should return a string representing provided hex to 2 decimal places', () => {
|
||||||
|
expect(new Numeric('0xa.7', 16).toFixed(2)).toEqual('10.44');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided decimal string to 2 decimal places', () => {
|
||||||
|
expect(new Numeric('10.4375', 10).toFixed(2)).toEqual('10.44');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a string representation of provided float to 2 decimal places', () => {
|
||||||
|
expect(new Numeric(10.4375, 10).toFixed(2)).toEqual('10.44');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return a number representation of provided BigNumber to 2 decimal places', () => {
|
||||||
|
expect(new Numeric(new BigNumber(10.4375, 10)).toFixed(2)).toEqual(
|
||||||
|
'10.44',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
620
shared/modules/Numeric.ts
Normal file
620
shared/modules/Numeric.ts
Normal file
@ -0,0 +1,620 @@
|
|||||||
|
import { BigNumber } from 'bignumber.js';
|
||||||
|
import BN from 'bn.js';
|
||||||
|
import { isHexString, isNullOrUndefined } from '@metamask/utils';
|
||||||
|
import { addHexPrefix } from 'ethereumjs-util';
|
||||||
|
import { EtherDenomination } from '../constants/common';
|
||||||
|
import { stripHexPrefix } from './hexstring-utils';
|
||||||
|
|
||||||
|
export type NumericValue = string | number | BN | BigNumber;
|
||||||
|
export type NumericBase = 10 | 16;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All variations of isHexString from our own utilities and etherumjs-utils
|
||||||
|
* return false for a '-' prefixed hex string. This utility method strips the
|
||||||
|
* possible '-' from the string before testing its validity so that negative
|
||||||
|
* hex values can be properly handled.
|
||||||
|
*
|
||||||
|
* @param value - The string to check
|
||||||
|
* @returns true if the value is a hex string (negative or otherwise)
|
||||||
|
*/
|
||||||
|
function isHexStringOrNegatedHexString(value: string): value is string {
|
||||||
|
return isHexString(value.replace('-', '')) || isHexString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BigNumber supports hex strings with '.' (aka decimals) in the string.
|
||||||
|
* No version of isHexString returs true if the string contains a decimal so
|
||||||
|
* this method is used to check if both parts of the string split by the
|
||||||
|
* decimal are hex strings. If so we can feed this value into BigNumber to get
|
||||||
|
* a valid Numeric.
|
||||||
|
*
|
||||||
|
* @param value - The string to check
|
||||||
|
* @returns true if the string is a hexadecimal split by '.'
|
||||||
|
*/
|
||||||
|
function isDecimalHex(value: string): boolean {
|
||||||
|
const parts = value.split('.');
|
||||||
|
if (parts.length === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return parts.every((part) => isHexStringOrNegatedHexString(part));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a hexadecimal in string or number format to a BigNumber.
|
||||||
|
* Note that in many places in our codebase we call 'addHexPrefix' on a negated
|
||||||
|
* hexadecimal string resulting in '0x-a' which will fail checks for
|
||||||
|
* isHexString. Sometimes we DO not add the 0x so we have to check for '-a'
|
||||||
|
* as well.
|
||||||
|
*
|
||||||
|
* @param value - hexadecimal value in string or number format.
|
||||||
|
* @returns A BigNumber representation of the value
|
||||||
|
*/
|
||||||
|
function hexadecimalToBigNumber(value: string | number): BigNumber {
|
||||||
|
const stringified = typeof value === 'number' ? `${value}` : value;
|
||||||
|
const isNegative = stripHexPrefix(stringified)[0] === '-';
|
||||||
|
const valueWithoutNegation = stringified.replace('-', '');
|
||||||
|
|
||||||
|
const valueAsBigNumber = new BigNumber(
|
||||||
|
stripHexPrefix(valueWithoutNegation),
|
||||||
|
16,
|
||||||
|
);
|
||||||
|
|
||||||
|
return isNegative ? valueAsBigNumber.negated() : valueAsBigNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a decimal in string or number format to a BigNumber.
|
||||||
|
*
|
||||||
|
* @param value - decimal value in string or number format.
|
||||||
|
* @returns A BigNumber representation of the value
|
||||||
|
*/
|
||||||
|
function decimalToBigNumber(value: string | number) {
|
||||||
|
return new BigNumber(String(value), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is used to safely convert a string type value to a BigNumber.
|
||||||
|
* The only valid strings for this method are those that are either hexadecimal
|
||||||
|
* numeric values OR numeric strings that can be converted to BigNumbers. It is
|
||||||
|
* impossible to tell the difference between a hex value of 100000 vs a decimal
|
||||||
|
* value of 100000 so a second parameter indicating the numeric base of the
|
||||||
|
* string value must be provided.
|
||||||
|
*
|
||||||
|
* @param value - A hexadecimal or decimal string
|
||||||
|
* @param numericBase - Either 16 for a hexadeciaml or 10 for a decimal
|
||||||
|
* @returns A BigNumber representation of the value
|
||||||
|
*/
|
||||||
|
function stringToBigNumber(value: string, numericBase: NumericBase) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
`Value of type ${typeof value} passed to stringToBigNumber`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
numericBase === 16 &&
|
||||||
|
(isHexStringOrNegatedHexString(value) || isDecimalHex(value))
|
||||||
|
) {
|
||||||
|
return hexadecimalToBigNumber(value);
|
||||||
|
} else if (
|
||||||
|
numericBase === 10 &&
|
||||||
|
// check if we have a finite integer or float
|
||||||
|
(isFinite(parseInt(value, 10)) || isFinite(parseFloat(value)))
|
||||||
|
) {
|
||||||
|
return decimalToBigNumber(value);
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`String provided to stringToBigNumber is not a hexadecimal or decimal string: ${value}, ${numericBase}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will convert a hexadecimal or deciaml number into a BigNumber.
|
||||||
|
* The second parameter must be supplied and determines whether to treat the
|
||||||
|
* value as a hexadecimal or decimal value.
|
||||||
|
*
|
||||||
|
* @param value - hexadecimal or decimal number[]
|
||||||
|
* @param numericBase - 10 for decimal, 16 for hexadecimal
|
||||||
|
* @returns BigNumber representation of the value
|
||||||
|
*/
|
||||||
|
function numberToBigNumber(value: number, numericBase: NumericBase) {
|
||||||
|
if (typeof value !== 'number') {
|
||||||
|
throw new Error(
|
||||||
|
`Value of type ${typeof value} passed to numberToBigNumber`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (numericBase === 16 && isHexString(`${value}`)) {
|
||||||
|
return new BigNumber(`${value}`, 16);
|
||||||
|
}
|
||||||
|
return new BigNumber(value, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to convert a BN to a BigNumber
|
||||||
|
*
|
||||||
|
* @param value - A BN representation of a value
|
||||||
|
* @returns A BigNumber representation of the BN's underlying value
|
||||||
|
*/
|
||||||
|
function bnToBigNumber(value: BN) {
|
||||||
|
if (value instanceof BN === false) {
|
||||||
|
throw new Error(
|
||||||
|
`value passed to bnToBigNumber is not a BN. Received type ${typeof value}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new BigNumber(value.toString(16), 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a value of the supported types (string, number, BN) to a BigNumber.
|
||||||
|
*
|
||||||
|
* @param value - The value to convert to a BigNumber
|
||||||
|
* @param numericBase - The numeric base of the underlying value
|
||||||
|
* @returns A BigNumber representation of the value
|
||||||
|
*/
|
||||||
|
function valueToBigNumber(value: string | number, numericBase: NumericBase) {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return stringToBigNumber(value, numericBase);
|
||||||
|
} else if (typeof value === 'number' && isNaN(value) === false) {
|
||||||
|
return numberToBigNumber(value, numericBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Value: ${value} is not a string, number, BigNumber or BN. Type is: ${typeof value}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Big Number Constants
|
||||||
|
const BIG_NUMBER_WEI_MULTIPLIER = new BigNumber('1000000000000000000');
|
||||||
|
const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000');
|
||||||
|
const BIG_NUMBER_ETH_MULTIPLIER = new BigNumber('1');
|
||||||
|
|
||||||
|
const toNormalizedDenomination = {
|
||||||
|
WEI: (bigNumber: BigNumber) => bigNumber.div(BIG_NUMBER_WEI_MULTIPLIER),
|
||||||
|
GWEI: (bigNumber: BigNumber) => bigNumber.div(BIG_NUMBER_GWEI_MULTIPLIER),
|
||||||
|
ETH: (bigNumber: BigNumber) => bigNumber.div(BIG_NUMBER_ETH_MULTIPLIER),
|
||||||
|
};
|
||||||
|
const toSpecifiedDenomination = {
|
||||||
|
WEI: (bigNumber: BigNumber) =>
|
||||||
|
bigNumber.times(BIG_NUMBER_WEI_MULTIPLIER).round(),
|
||||||
|
GWEI: (bigNumber: BigNumber) =>
|
||||||
|
bigNumber.times(BIG_NUMBER_GWEI_MULTIPLIER).round(9),
|
||||||
|
ETH: (bigNumber: BigNumber) =>
|
||||||
|
bigNumber.times(BIG_NUMBER_ETH_MULTIPLIER).round(9),
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value in ETH of the numeric supplied, used in this file only to
|
||||||
|
* convert to ETH prior to converting to another denomination. The following
|
||||||
|
* quirks were programmed into this method to replicate behavior of the
|
||||||
|
* predecessor to Numeric, which was 'conversionUtil'. If a denomination is
|
||||||
|
* not supplied, and toDenomination is called, then we assume the denomination
|
||||||
|
* was originally ETH, otherwise we convert it to ETH.
|
||||||
|
*
|
||||||
|
* @param numeric
|
||||||
|
* @returns value in ETH
|
||||||
|
*/
|
||||||
|
function getValueInETH(numeric: Numeric) {
|
||||||
|
if (
|
||||||
|
numeric.denomination === EtherDenomination.ETH ||
|
||||||
|
typeof numeric.denomination === 'undefined'
|
||||||
|
) {
|
||||||
|
return numeric.value;
|
||||||
|
}
|
||||||
|
return toNormalizedDenomination[numeric.denomination](numeric.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When applying operands to Numerics that have a specified Denomination then
|
||||||
|
* we should first convert the provided inputNumeric to the same Denomination
|
||||||
|
* as the baseNumeric. There are cases where this doesn't apply:
|
||||||
|
*
|
||||||
|
* 1. If the denominations are already the same. No conversion is necessary.
|
||||||
|
* 2. If the inputNumeric does not have a denomination set. We assume in this
|
||||||
|
* case that the value is already in the appropriate denomination.
|
||||||
|
*
|
||||||
|
* @param baseNumeric
|
||||||
|
* @param inputNumeric
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
function alignOperandDenominations(
|
||||||
|
baseNumeric: Numeric,
|
||||||
|
inputNumeric: Numeric,
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
typeof inputNumeric.denomination !== 'undefined' &&
|
||||||
|
baseNumeric.denomination !== inputNumeric.denomination
|
||||||
|
) {
|
||||||
|
return inputNumeric.toDenomination(baseNumeric.denomination);
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputNumeric;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Numeric is a class whose methods will always return a new, not mutated,
|
||||||
|
* value. This allows for chaining of non-terminating methods. Previously we
|
||||||
|
* had near a hundred helper methods that composed one-another, making tracking
|
||||||
|
* through the chain near impossible. This API is designed such that no helper
|
||||||
|
* methods should be needed. Take the case of hexWEIToDecGWEI, a helper method
|
||||||
|
* for taking a hex string representing a value in WEI and converting that to a
|
||||||
|
* decimal of GWEI. Prior to this class the method would call into our root
|
||||||
|
* level 'conversionUtil' which was the proverbial kitchen sink doing
|
||||||
|
* everything from denomination conversion, currency conversion (with provided
|
||||||
|
* conversionRate prop) and more. The same opeartion can now be expressed as:
|
||||||
|
* new Numeric(hexString, 16, EtherDenomination.WEI)
|
||||||
|
* .toDenomination(EtherDenomination.GWEI)
|
||||||
|
* .toBase(10)
|
||||||
|
* .toString();
|
||||||
|
* This has the benefit of being fairly transparent as you can read each step
|
||||||
|
* in the chain and have a good sense of what is being done. It also is highly
|
||||||
|
* composable so that we shouldn't need tons of helper methods for shortcuts.
|
||||||
|
*/
|
||||||
|
export class Numeric {
|
||||||
|
/**
|
||||||
|
* The underlying value of the Numeric, always in BigNumber form
|
||||||
|
*/
|
||||||
|
value: BigNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The numeric base for this Numeric, either 10 for decimal or 16 for Hex
|
||||||
|
*/
|
||||||
|
base?: NumericBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current denomination, if any. The only supported denominations are
|
||||||
|
* ETH, GWEI, WEI.
|
||||||
|
*/
|
||||||
|
denomination?: EtherDenomination;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
value: NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
this.base = base;
|
||||||
|
this.denomination = denomination;
|
||||||
|
if (value instanceof BigNumber) {
|
||||||
|
this.value = value;
|
||||||
|
} else if (value instanceof BN) {
|
||||||
|
this.value = bnToBigNumber(value);
|
||||||
|
} else if (
|
||||||
|
isNullOrUndefined(value) ||
|
||||||
|
(typeof value === 'number' && isNaN(value))
|
||||||
|
) {
|
||||||
|
// There are parts of the codebase that call this method without a value,
|
||||||
|
// or with a 'NaN' (which is probably a bug somewhere in our tests?).
|
||||||
|
// Over time of converting to TypeScript we will eradicate those, but the
|
||||||
|
// helper methods that those instances employ would default the value to
|
||||||
|
// 0. This block keeps that intact.
|
||||||
|
this.value = new BigNumber('0', 10);
|
||||||
|
this.base = 10;
|
||||||
|
} else if (base) {
|
||||||
|
this.value = valueToBigNumber(value, base);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
`You must specify the base of the provided number if the value is not already a BigNumber`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a tool used internally to check if a value is already a Numeric
|
||||||
|
* and return it if it is, otherwise it uses the other provided arguments to
|
||||||
|
* create a new Numeric.
|
||||||
|
*
|
||||||
|
* @param value - The value of the Numeric
|
||||||
|
* @param base - Either undefined, 10 for decimal or 16 for hexadecimal
|
||||||
|
* @param denomination - The Ether denomination to set, if any
|
||||||
|
*/
|
||||||
|
static from(
|
||||||
|
value: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
if (value instanceof Numeric) {
|
||||||
|
if (base || denomination) {
|
||||||
|
throw new Error(
|
||||||
|
`Numeric.from was called with a value (${value.toString()}) that is already a Numeric but a base and/or denomination was provided. Only supply base or denomination when creating a new Numeric`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return new Numeric(value, base, denomination);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Conversions */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new Numeric with the base value changed to the provided base,
|
||||||
|
* or the original Numeric if the base provided is the same as the current
|
||||||
|
* base. No computation or conversion happens here but rather the result of
|
||||||
|
* toString will be changed depending on the value of this.base when that
|
||||||
|
* method is invoked.
|
||||||
|
*
|
||||||
|
* @param base - The numeric base to change the Numeric to, either 10 or 16
|
||||||
|
* @returns A new Numeric with the base updated
|
||||||
|
*/
|
||||||
|
toBase(base: NumericBase) {
|
||||||
|
if (this.base !== base) {
|
||||||
|
return new Numeric(this.value, base, this.denomination);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the value to the specified denomination. The following quirks of
|
||||||
|
* the predecessor to Numeric, 'conversionUtil', were programmed into this
|
||||||
|
* method:
|
||||||
|
* 1. You may supply a denomination that is undefined, which will result in
|
||||||
|
* nothing happening. Coincidently this is also useful due to the nature of
|
||||||
|
* chaining operations on Numeric. You may pass an undefined value in this
|
||||||
|
* method without breaking the chain to conditionally apply a operator.
|
||||||
|
* 2. If the numeric that .toDenomination is called on does not have a
|
||||||
|
* denomination set, that is it was constructed without the third parameter,
|
||||||
|
* then it is assumed to be in ETH. Otherwise we convert it to ETH prior to
|
||||||
|
* attempting to convert it to another denomination because all of the
|
||||||
|
* toSpecifiedDenomination methods assume a value in ETH is passed.
|
||||||
|
*
|
||||||
|
* @param denomination - The denomination to convert to
|
||||||
|
* @returns A new numeric with the same base as the previous, but the
|
||||||
|
* value and denomination changed accordingly
|
||||||
|
*/
|
||||||
|
toDenomination(denomination?: EtherDenomination) {
|
||||||
|
if (denomination && this.denomination !== denomination) {
|
||||||
|
const result = new Numeric(
|
||||||
|
toSpecifiedDenomination[denomination](getValueInETH(this)),
|
||||||
|
this.base,
|
||||||
|
denomination,
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replicates a method of BigNumber that is not in the version of BigNumber
|
||||||
|
* that we use currently. Essentially shifting the decimal point backwards by
|
||||||
|
* an amount equal to the positive number supplied to the decimals operator.
|
||||||
|
* For example, calling shiftedBy(10) on the value 10000000000 will result in
|
||||||
|
* a value of 1.0000000000. If passing a negative number, then the decimal
|
||||||
|
* position will move forward. 1.0000000000 shiftedBy(-10) yields 10000000000
|
||||||
|
*
|
||||||
|
* @param decimals - The number of decimal places to move. Positive moves
|
||||||
|
* decimal backwards, creating a smaller number. Negative values move the
|
||||||
|
* decimal forwards, creating a larger number.
|
||||||
|
* @returns A new numeric with the same base and denomination as the current
|
||||||
|
* but with a new value.
|
||||||
|
*/
|
||||||
|
shiftedBy(decimals: number) {
|
||||||
|
const powerOf = new Numeric(Math.pow(10, decimals), 10);
|
||||||
|
return this.divide(powerOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a conversion rate to the Numeric. If rate is undefined returns the
|
||||||
|
* same instance that was operated on. Allowing an undefined value makes
|
||||||
|
* chaining this operator feasible with undefined values from the user or
|
||||||
|
* state without manipulating the number. For example:
|
||||||
|
*
|
||||||
|
* new Numeric(5, 10)
|
||||||
|
* .applyConversionRate(possiblyUndefinedRate)
|
||||||
|
* .toBase(16)
|
||||||
|
* .toString();
|
||||||
|
*
|
||||||
|
* Will return a valid result as long as possiblyUndefinedRate is undefined,
|
||||||
|
* a BigNumber or a number. In some areas of the codebase we check to see if
|
||||||
|
* the target currency is different from the current currency before applying
|
||||||
|
* a conversionRate. This functionality is not built into Numeric and will
|
||||||
|
* require breaking the chain before calling this method:
|
||||||
|
* let value = new Numeric(5, 10);
|
||||||
|
*
|
||||||
|
* if (fromCurrency !== toCurrency) {
|
||||||
|
* value = value.applyConversionRate(possiblyUndefinedRate);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* return value.toBase(16).toString();
|
||||||
|
*
|
||||||
|
* @param rate - The multiplier to apply
|
||||||
|
* @param invert - if true, inverts the rate
|
||||||
|
* @returns New Numeric value with conversion rate applied.
|
||||||
|
*/
|
||||||
|
applyConversionRate(rate?: number | BigNumber, invert?: boolean) {
|
||||||
|
if (typeof rate === 'undefined') {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
let conversionRate = new Numeric(rate, 10);
|
||||||
|
if (invert) {
|
||||||
|
conversionRate = new Numeric(new BigNumber(1.0)).divide(conversionRate);
|
||||||
|
}
|
||||||
|
return this.times(conversionRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
round(
|
||||||
|
numberOfDecimals?: number,
|
||||||
|
roundingMode: number = BigNumber.ROUND_HALF_DOWN,
|
||||||
|
) {
|
||||||
|
if (numberOfDecimals) {
|
||||||
|
return new Numeric(
|
||||||
|
this.value.round(numberOfDecimals, roundingMode),
|
||||||
|
this.base,
|
||||||
|
this.denomination,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: make it possible to add ETH + GWEI value. So if you have
|
||||||
|
* Numeric 1 with denomination ETH and Numeric 2 with Denomination WEI,
|
||||||
|
* first convert Numeric 2 to ETH then add the amount to Numeric 1.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param base
|
||||||
|
* @param denomination
|
||||||
|
*/
|
||||||
|
add(
|
||||||
|
value: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
const numeric = Numeric.from(value, base, denomination);
|
||||||
|
return new Numeric(
|
||||||
|
this.value.add(alignOperandDenominations(this, numeric).value),
|
||||||
|
this.base,
|
||||||
|
this.denomination,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: make it possible to subtract ETH - GWEI value. So if you have
|
||||||
|
* Numeric 1 with denomination ETH and Numeric 2 with Denomination WEI,
|
||||||
|
* first convert Numeric 2 to ETH then subtract the amount from Numeric 1.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @param base
|
||||||
|
* @param denomination
|
||||||
|
*/
|
||||||
|
minus(
|
||||||
|
value: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
const numeric = Numeric.from(value, base, denomination);
|
||||||
|
|
||||||
|
return new Numeric(
|
||||||
|
this.value.minus(alignOperandDenominations(this, numeric).value),
|
||||||
|
this.base,
|
||||||
|
this.denomination,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
times(
|
||||||
|
multiplier: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
const multiplierNumeric = Numeric.from(multiplier, base, denomination);
|
||||||
|
return new Numeric(
|
||||||
|
this.value.times(
|
||||||
|
alignOperandDenominations(this, multiplierNumeric).value,
|
||||||
|
),
|
||||||
|
this.base,
|
||||||
|
this.denomination,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Divides the Numeric by another supplied Numeric, carrying over the base
|
||||||
|
* and denomination from the current Numeric.
|
||||||
|
*
|
||||||
|
* @param divisor - The Numeric to divide this Numeric by
|
||||||
|
* @param base
|
||||||
|
* @param denomination
|
||||||
|
* @returns A new Numeric that contains the result of the division
|
||||||
|
*/
|
||||||
|
divide(
|
||||||
|
divisor: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
return new Numeric(
|
||||||
|
this.value.div(
|
||||||
|
alignOperandDenominations(
|
||||||
|
this,
|
||||||
|
Numeric.from(divisor, base, denomination),
|
||||||
|
).value,
|
||||||
|
),
|
||||||
|
this.base,
|
||||||
|
this.denomination,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
greaterThan(
|
||||||
|
comparator: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
return this.value.greaterThan(
|
||||||
|
Numeric.from(comparator, base, denomination).value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
greaterThanOrEqualTo(
|
||||||
|
comparator: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
return this.value.greaterThanOrEqualTo(
|
||||||
|
Numeric.from(comparator, base, denomination).value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
lessThan(
|
||||||
|
comparator: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
return this.value.lessThan(
|
||||||
|
Numeric.from(comparator, base, denomination).value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
lessThanOrEqualTo(
|
||||||
|
comparator: Numeric | NumericValue,
|
||||||
|
base?: NumericBase,
|
||||||
|
denomination?: EtherDenomination,
|
||||||
|
) {
|
||||||
|
return this.value.lessThanOrEqualTo(
|
||||||
|
Numeric.from(comparator, base, denomination).value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
isNegative() {
|
||||||
|
return this.value.isNegative();
|
||||||
|
}
|
||||||
|
|
||||||
|
isPositive() {
|
||||||
|
return this.isNegative() === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a base 16 hexadecimal string representation of the Numeric that is
|
||||||
|
* 0x prefixed. This operation bypasses the currently set base of the
|
||||||
|
* Numeric.
|
||||||
|
*
|
||||||
|
* @returns 0x prefixed hexstring.
|
||||||
|
*/
|
||||||
|
toPrefixedHexString() {
|
||||||
|
return addHexPrefix(this.value.toString(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the string representation of the Numeric, using the current value of
|
||||||
|
* this.base to determine if it should be a decimal or hexadecimal string.
|
||||||
|
*
|
||||||
|
* @returns the string representation of the Numeric
|
||||||
|
*/
|
||||||
|
toString() {
|
||||||
|
return this.value.toString(this.base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a fixed-point decimal string representation of the Numeric
|
||||||
|
*
|
||||||
|
* @param decimals - the amount of decimal precision to use when rounding
|
||||||
|
* @returns A fixed point decimal string represenation of the Numeric
|
||||||
|
*/
|
||||||
|
toFixed(decimals: number) {
|
||||||
|
return this.value.toFixed(decimals);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the value to a JavaScript Number, with all of the inaccuracy that
|
||||||
|
* could come with that.
|
||||||
|
*
|
||||||
|
* @returns The value as a JS Number
|
||||||
|
*/
|
||||||
|
toNumber() {
|
||||||
|
return this.value.toNumber();
|
||||||
|
}
|
||||||
|
}
|
21
yarn.lock
21
yarn.lock
@ -4219,14 +4219,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@metamask/utils@npm:^3.0.1, @metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.3.0, @metamask/utils@npm:^3.3.1":
|
"@metamask/utils@npm:^3.0.1, @metamask/utils@npm:^3.0.3, @metamask/utils@npm:^3.3.0, @metamask/utils@npm:^3.3.1, @metamask/utils@npm:^3.4.1":
|
||||||
version: 3.3.1
|
version: 3.4.1
|
||||||
resolution: "@metamask/utils@npm:3.3.1"
|
resolution: "@metamask/utils@npm:3.4.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/debug": ^4.1.7
|
"@types/debug": ^4.1.7
|
||||||
debug: ^4.3.4
|
debug: ^4.3.4
|
||||||
superstruct: ^0.16.7
|
semver: ^7.3.8
|
||||||
checksum: 5b6b6b54fdff4bc3f77b31ef50c23adca8fdf21d81d4f68d3d9c2b383b145cd61c2435f5ba0a11344484ae1f6d2355fab82eec58ce6b19eb35b476928b2e4ee6
|
superstruct: ^1.0.3
|
||||||
|
checksum: 0799cefc17effecba4b4cd34879113f9f826a7aff4d21bfdcca64ef31c117be3e6a30cdd49c0b91289f22efbf7e56901322f4ce1b4d638dd2fc3bc3e81e3c87d
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -24155,6 +24156,7 @@ __metadata:
|
|||||||
"@metamask/snaps-utils": ^0.27.1
|
"@metamask/snaps-utils": ^0.27.1
|
||||||
"@metamask/subject-metadata-controller": ^1.0.0
|
"@metamask/subject-metadata-controller": ^1.0.0
|
||||||
"@metamask/test-dapp": ^5.2.1
|
"@metamask/test-dapp": ^5.2.1
|
||||||
|
"@metamask/utils": ^3.4.1
|
||||||
"@ngraveio/bc-ur": ^1.1.6
|
"@ngraveio/bc-ur": ^1.1.6
|
||||||
"@popperjs/core": ^2.4.0
|
"@popperjs/core": ^2.4.0
|
||||||
"@reduxjs/toolkit": ^1.6.2
|
"@reduxjs/toolkit": ^1.6.2
|
||||||
@ -30711,7 +30713,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"semver@npm:^7.0.0, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7":
|
"semver@npm:^7.0.0, semver@npm:^7.3.2, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.3.8":
|
||||||
version: 7.3.8
|
version: 7.3.8
|
||||||
resolution: "semver@npm:7.3.8"
|
resolution: "semver@npm:7.3.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -32409,6 +32411,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"superstruct@npm:^1.0.3":
|
||||||
|
version: 1.0.3
|
||||||
|
resolution: "superstruct@npm:1.0.3"
|
||||||
|
checksum: 761790bb111e6e21ddd608299c252f3be35df543263a7ebbc004e840d01fcf8046794c274bcb351bdf3eae4600f79d317d085cdbb19ca05803a4361840cc9bb1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"supports-color@npm:6.0.0":
|
"supports-color@npm:6.0.0":
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
resolution: "supports-color@npm:6.0.0"
|
resolution: "supports-color@npm:6.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user