UNPKG

9.81 kBJavaScriptView Raw
1"use strict";
2/**
3 * BigNumber
4 *
5 * A wrapper around the BN.js object. We use the BN.js library
6 * because it is used by elliptic, so it is required regardless.
7 *
8 */
9import _BN from "bn.js";
10var BN = _BN.BN;
11import { hexlify, isBytes, isHexString } from "@ethersproject/bytes";
12import { Logger } from "@ethersproject/logger";
13import { version } from "./_version";
14const logger = new Logger(version);
15const _constructorGuard = {};
16const MAX_SAFE = 0x1fffffffffffff;
17export function isBigNumberish(value) {
18 return (value != null) && (BigNumber.isBigNumber(value) ||
19 (typeof (value) === "number" && (value % 1) === 0) ||
20 (typeof (value) === "string" && !!value.match(/^-?[0-9]+$/)) ||
21 isHexString(value) ||
22 (typeof (value) === "bigint") ||
23 isBytes(value));
24}
25// Only warn about passing 10 into radix once
26let _warnedToStringRadix = false;
27export class BigNumber {
28 constructor(constructorGuard, hex) {
29 logger.checkNew(new.target, BigNumber);
30 if (constructorGuard !== _constructorGuard) {
31 logger.throwError("cannot call constructor directly; use BigNumber.from", Logger.errors.UNSUPPORTED_OPERATION, {
32 operation: "new (BigNumber)"
33 });
34 }
35 this._hex = hex;
36 this._isBigNumber = true;
37 Object.freeze(this);
38 }
39 fromTwos(value) {
40 return toBigNumber(toBN(this).fromTwos(value));
41 }
42 toTwos(value) {
43 return toBigNumber(toBN(this).toTwos(value));
44 }
45 abs() {
46 if (this._hex[0] === "-") {
47 return BigNumber.from(this._hex.substring(1));
48 }
49 return this;
50 }
51 add(other) {
52 return toBigNumber(toBN(this).add(toBN(other)));
53 }
54 sub(other) {
55 return toBigNumber(toBN(this).sub(toBN(other)));
56 }
57 div(other) {
58 const o = BigNumber.from(other);
59 if (o.isZero()) {
60 throwFault("division-by-zero", "div");
61 }
62 return toBigNumber(toBN(this).div(toBN(other)));
63 }
64 mul(other) {
65 return toBigNumber(toBN(this).mul(toBN(other)));
66 }
67 mod(other) {
68 const value = toBN(other);
69 if (value.isNeg()) {
70 throwFault("division-by-zero", "mod");
71 }
72 return toBigNumber(toBN(this).umod(value));
73 }
74 pow(other) {
75 const value = toBN(other);
76 if (value.isNeg()) {
77 throwFault("negative-power", "pow");
78 }
79 return toBigNumber(toBN(this).pow(value));
80 }
81 and(other) {
82 const value = toBN(other);
83 if (this.isNegative() || value.isNeg()) {
84 throwFault("unbound-bitwise-result", "and");
85 }
86 return toBigNumber(toBN(this).and(value));
87 }
88 or(other) {
89 const value = toBN(other);
90 if (this.isNegative() || value.isNeg()) {
91 throwFault("unbound-bitwise-result", "or");
92 }
93 return toBigNumber(toBN(this).or(value));
94 }
95 xor(other) {
96 const value = toBN(other);
97 if (this.isNegative() || value.isNeg()) {
98 throwFault("unbound-bitwise-result", "xor");
99 }
100 return toBigNumber(toBN(this).xor(value));
101 }
102 mask(value) {
103 if (this.isNegative() || value < 0) {
104 throwFault("negative-width", "mask");
105 }
106 return toBigNumber(toBN(this).maskn(value));
107 }
108 shl(value) {
109 if (this.isNegative() || value < 0) {
110 throwFault("negative-width", "shl");
111 }
112 return toBigNumber(toBN(this).shln(value));
113 }
114 shr(value) {
115 if (this.isNegative() || value < 0) {
116 throwFault("negative-width", "shr");
117 }
118 return toBigNumber(toBN(this).shrn(value));
119 }
120 eq(other) {
121 return toBN(this).eq(toBN(other));
122 }
123 lt(other) {
124 return toBN(this).lt(toBN(other));
125 }
126 lte(other) {
127 return toBN(this).lte(toBN(other));
128 }
129 gt(other) {
130 return toBN(this).gt(toBN(other));
131 }
132 gte(other) {
133 return toBN(this).gte(toBN(other));
134 }
135 isNegative() {
136 return (this._hex[0] === "-");
137 }
138 isZero() {
139 return toBN(this).isZero();
140 }
141 toNumber() {
142 try {
143 return toBN(this).toNumber();
144 }
145 catch (error) {
146 throwFault("overflow", "toNumber", this.toString());
147 }
148 return null;
149 }
150 toBigInt() {
151 try {
152 return BigInt(this.toString());
153 }
154 catch (e) { }
155 return logger.throwError("this platform does not support BigInt", Logger.errors.UNSUPPORTED_OPERATION, {
156 value: this.toString()
157 });
158 }
159 toString() {
160 // Lots of people expect this, which we do not support, so check (See: #889)
161 if (arguments.length > 0) {
162 if (arguments[0] === 10) {
163 if (!_warnedToStringRadix) {
164 _warnedToStringRadix = true;
165 logger.warn("BigNumber.toString does not accept any parameters; base-10 is assumed");
166 }
167 }
168 else if (arguments[0] === 16) {
169 logger.throwError("BigNumber.toString does not accept any parameters; use bigNumber.toHexString()", Logger.errors.UNEXPECTED_ARGUMENT, {});
170 }
171 else {
172 logger.throwError("BigNumber.toString does not accept parameters", Logger.errors.UNEXPECTED_ARGUMENT, {});
173 }
174 }
175 return toBN(this).toString(10);
176 }
177 toHexString() {
178 return this._hex;
179 }
180 toJSON(key) {
181 return { type: "BigNumber", hex: this.toHexString() };
182 }
183 static from(value) {
184 if (value instanceof BigNumber) {
185 return value;
186 }
187 if (typeof (value) === "string") {
188 if (value.match(/^-?0x[0-9a-f]+$/i)) {
189 return new BigNumber(_constructorGuard, toHex(value));
190 }
191 if (value.match(/^-?[0-9]+$/)) {
192 return new BigNumber(_constructorGuard, toHex(new BN(value)));
193 }
194 return logger.throwArgumentError("invalid BigNumber string", "value", value);
195 }
196 if (typeof (value) === "number") {
197 if (value % 1) {
198 throwFault("underflow", "BigNumber.from", value);
199 }
200 if (value >= MAX_SAFE || value <= -MAX_SAFE) {
201 throwFault("overflow", "BigNumber.from", value);
202 }
203 return BigNumber.from(String(value));
204 }
205 const anyValue = value;
206 if (typeof (anyValue) === "bigint") {
207 return BigNumber.from(anyValue.toString());
208 }
209 if (isBytes(anyValue)) {
210 return BigNumber.from(hexlify(anyValue));
211 }
212 if (anyValue) {
213 // Hexable interface (takes priority)
214 if (anyValue.toHexString) {
215 const hex = anyValue.toHexString();
216 if (typeof (hex) === "string") {
217 return BigNumber.from(hex);
218 }
219 }
220 else {
221 // For now, handle legacy JSON-ified values (goes away in v6)
222 let hex = anyValue._hex;
223 // New-form JSON
224 if (hex == null && anyValue.type === "BigNumber") {
225 hex = anyValue.hex;
226 }
227 if (typeof (hex) === "string") {
228 if (isHexString(hex) || (hex[0] === "-" && isHexString(hex.substring(1)))) {
229 return BigNumber.from(hex);
230 }
231 }
232 }
233 }
234 return logger.throwArgumentError("invalid BigNumber value", "value", value);
235 }
236 static isBigNumber(value) {
237 return !!(value && value._isBigNumber);
238 }
239}
240// Normalize the hex string
241function toHex(value) {
242 // For BN, call on the hex string
243 if (typeof (value) !== "string") {
244 return toHex(value.toString(16));
245 }
246 // If negative, prepend the negative sign to the normalized positive value
247 if (value[0] === "-") {
248 // Strip off the negative sign
249 value = value.substring(1);
250 // Cannot have multiple negative signs (e.g. "--0x04")
251 if (value[0] === "-") {
252 logger.throwArgumentError("invalid hex", "value", value);
253 }
254 // Call toHex on the positive component
255 value = toHex(value);
256 // Do not allow "-0x00"
257 if (value === "0x00") {
258 return value;
259 }
260 // Negate the value
261 return "-" + value;
262 }
263 // Add a "0x" prefix if missing
264 if (value.substring(0, 2) !== "0x") {
265 value = "0x" + value;
266 }
267 // Normalize zero
268 if (value === "0x") {
269 return "0x00";
270 }
271 // Make the string even length
272 if (value.length % 2) {
273 value = "0x0" + value.substring(2);
274 }
275 // Trim to smallest even-length string
276 while (value.length > 4 && value.substring(0, 4) === "0x00") {
277 value = "0x" + value.substring(4);
278 }
279 return value;
280}
281function toBigNumber(value) {
282 return BigNumber.from(toHex(value));
283}
284function toBN(value) {
285 const hex = BigNumber.from(value).toHexString();
286 if (hex[0] === "-") {
287 return (new BN("-" + hex.substring(3), 16));
288 }
289 return new BN(hex.substring(2), 16);
290}
291function throwFault(fault, operation, value) {
292 const params = { fault: fault, operation: operation };
293 if (value != null) {
294 params.value = value;
295 }
296 return logger.throwError(fault, Logger.errors.NUMERIC_FAULT, params);
297}
298// value should have no prefix
299export function _base36To16(value) {
300 return (new BN(value, 36)).toString(16);
301}
302// value should have no prefix
303export function _base16To36(value) {
304 return (new BN(value, 16)).toString(36);
305}
306//# sourceMappingURL=bignumber.js.map
\No newline at end of file