UNPKG

lotus-sdk

Version:

Central repository for several classes of tools for integrating with, and building for, the Lotusia ecosystem

236 lines (235 loc) 6.6 kB
import BN from 'bn.js'; class BNWrapper { _bn; static Zero = new BNWrapper(0); static One = new BNWrapper(1); static Minus1 = new BNWrapper(-1); constructor(n, base) { if (n instanceof BN) { this._bn = n.clone(); } else if (Buffer.isBuffer(n)) { if (base === 'le' || base === 'be') { this._bn = new BN(n, undefined, base); } else { this._bn = new BN(n, base || 'hex'); } } else { const validBase = base === 'hex' || typeof base === 'number' ? base : undefined; this._bn = new BN(n, validBase); } } static fromString(str, base) { return new BNWrapper(str, base); } static fromBuffer(buf, opts) { let buffer = buf; if (opts?.size) { buffer = Buffer.alloc(opts.size); buf.copy(buffer, opts.size - buf.length); } if (opts?.endian === 'little') { buffer = BNWrapper.reversebuf(buffer); } return new BNWrapper(buffer, 'hex'); } static fromSM(buf, opts) { if (buf.length === 0) { return BNWrapper.fromBuffer(Buffer.from([0])); } let endian = 'big'; if (opts) { endian = opts.endian || 'big'; } let buffer = buf; if (endian === 'little') { buffer = BNWrapper.reversebuf(buf); } let result; if (buffer[0] & 0x80) { buffer[0] = buffer[0] & 0x7f; result = BNWrapper.fromBuffer(buffer); result = result.neg(); } else { result = BNWrapper.fromBuffer(buffer); } return result; } static fromScriptNumBuffer(buf, fRequireMinimal, size) { const nMaxNumSize = size || 4; if (buf.length > nMaxNumSize) { throw new Error('script number overflow'); } if (fRequireMinimal && buf.length > 0) { if ((buf[buf.length - 1] & 0x7f) === 0) { if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) { throw new Error('non-minimally encoded script number'); } } } return BNWrapper.fromSM(buf, { endian: 'little' }); } static reversebuf(buf) { const buf2 = Buffer.alloc(buf.length); for (let i = 0; i < buf.length; i++) { buf2[i] = buf[buf.length - 1 - i]; } return buf2; } static trim(buf, natlen) { return buf.subarray(natlen - buf.length, buf.length); } static pad(buf, natlen, size) { const rbuf = Buffer.alloc(size); for (let i = 0; i < buf.length; i++) { rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i]; } for (let i = 0; i < size - natlen; i++) { rbuf[i] = 0; } return rbuf; } static fromNumber(n) { return new BNWrapper(n); } toNumber() { return parseInt(this.toString(10), 10); } add(r) { return new BNWrapper(this._bn.add(r._bn)); } mod(r) { return new BNWrapper(this._bn.mod(r._bn)); } umod(r) { return new BNWrapper(this._bn.umod(r._bn)); } get bn() { return this._bn; } toString(base) { return this._bn.toString(base); } toBuffer(opts) { let buf; if (opts && opts.size) { buf = this._bn.toArrayLike(Buffer, opts.endian === 'little' ? 'le' : 'be'); if (buf.length === opts.size) { } else if (buf.length > opts.size) { buf = buf.subarray(buf.length - opts.size); } else if (buf.length < opts.size) { const padded = Buffer.alloc(opts.size); buf.copy(padded, opts.size - buf.length); buf = padded; } } else { buf = this._bn.toArrayLike(Buffer, opts?.endian === 'little' ? 'le' : 'be'); } return buf; } toArrayLike(ArrayType, endian, length) { return this._bn.toArrayLike(ArrayType, endian || 'be', length); } mul(r) { return new BNWrapper(this._bn.mul(r._bn)); } sub(r) { return new BNWrapper(this._bn.sub(r._bn)); } pow(r) { return new BNWrapper(this._bn.pow(r._bn)); } div(r) { return new BNWrapper(this._bn.div(r._bn)); } modPow(exponent, modulus) { return new BNWrapper(this._bn.pow(exponent._bn).mod(modulus._bn)); } and(other) { const otherBN = other instanceof BNWrapper ? other._bn : new BN(other); return new BNWrapper(this._bn.and(otherBN)); } neg() { return new BNWrapper(this._bn.neg()); } invm(r) { return new BNWrapper(this._bn.invm(r._bn)); } eq(other) { return this._bn.eq(other._bn); } lt(other) { return this._bn.lt(other._bn); } gt(other) { return this._bn.gt(other._bn); } lte(other) { return this._bn.lte(other._bn); } gte(other) { return this._bn.gte(other._bn); } isZero() { return this._bn.isZero(); } isNeg() { return this._bn.isNeg(); } isOdd() { return this._bn.isOdd(); } isEven() { return this._bn.isEven(); } toSMBigEndian() { let buf; if (this.cmp(BNWrapper.Zero) === -1) { buf = this.neg().toBuffer(); if (buf[0] & 0x80) { buf = Buffer.concat([Buffer.from([0x80]), buf]); } else { buf[0] = buf[0] | 0x80; } } else { buf = this.toBuffer(); if (buf[0] & 0x80) { buf = Buffer.concat([Buffer.from([0x00]), buf]); } } if (buf.length === 1 && buf[0] === 0) { buf = Buffer.from([]); } return buf; } toSM(opts) { const endian = opts ? opts.endian : 'big'; let buf = this.toSMBigEndian(); if (endian === 'little') { buf = BNWrapper.reversebuf(buf); } return buf; } toScriptNumBuffer() { return this.toSM({ endian: 'little' }); } cmp(other) { return this._bn.cmp(other._bn); } copy(other) { this._bn = other._bn.clone(); return this; } clone() { return new BNWrapper(this._bn.clone()); } } export { BNWrapper as BN };