@greymass/eosio
Advanced tools
Comparing version 0.3.2 to 0.4.0
{ | ||
"name": "@greymass/eosio", | ||
"description": "Library for working with EOSIO blockchains", | ||
"version": "0.3.2", | ||
"version": "0.4.0", | ||
"homepage": "https://github.com/greymass/eosio-core", | ||
@@ -44,3 +44,3 @@ "license": "BSD-3-Clause", | ||
"rollup": "^2.38.2", | ||
"rollup-plugin-dts": "^2.0.0", | ||
"rollup-plugin-dts": "^3.0.1", | ||
"ts-node": "^9.1.0", | ||
@@ -47,0 +47,0 @@ "typescript": "^4.1.2" |
@@ -9,4 +9,2 @@ import {APIClient} from '../client' | ||
Float64, | ||
Int128, | ||
Int64, | ||
Name, | ||
@@ -17,2 +15,3 @@ NameType, | ||
SignedTransactionType, | ||
UInt128, | ||
UInt32, | ||
@@ -130,5 +129,5 @@ UInt64, | ||
// determine key type from bounds type | ||
if (isInstanceOf(someBound, Int64)) { | ||
if (isInstanceOf(someBound, UInt64)) { | ||
key_type = 'i64' | ||
} else if (isInstanceOf(someBound, Int128)) { | ||
} else if (isInstanceOf(someBound, UInt128)) { | ||
key_type = 'i128' | ||
@@ -160,2 +159,4 @@ } else if (isInstanceOf(someBound, Checksum256)) { | ||
scope = String(Name.from(params.code)) | ||
} else if (typeof scope !== 'string') { | ||
scope = String(scope) | ||
} | ||
@@ -166,2 +167,3 @@ // eslint-disable-next-line prefer-const | ||
params: { | ||
...params, | ||
code: Name.from(params.code), | ||
@@ -177,2 +179,10 @@ table: Name.from(params.table), | ||
}) | ||
let ram_payers: Name[] | undefined | ||
if (params.show_payer) { | ||
ram_payers = [] | ||
rows = rows.map(({data, payer}) => { | ||
ram_payers!.push(Name.from(payer)) | ||
return data | ||
}) | ||
} | ||
if (type) { | ||
@@ -199,6 +209,6 @@ if (json) { | ||
case 'i64': | ||
indexType = Int64 | ||
indexType = UInt64 | ||
break | ||
case 'i128': | ||
indexType = Int128 | ||
indexType = UInt128 | ||
break | ||
@@ -232,4 +242,4 @@ case 'name': | ||
} | ||
return {rows, more, next_key} | ||
return {rows, more, next_key, ram_payers} | ||
} | ||
} |
@@ -10,3 +10,2 @@ import { | ||
Float64, | ||
Int128, | ||
Int64, | ||
@@ -22,2 +21,3 @@ Name, | ||
TransactionReceipt, | ||
UInt128, | ||
UInt16, | ||
@@ -40,5 +40,5 @@ UInt32, | ||
export class AccountResourceLimit extends Struct { | ||
@Struct.field('uint64') used!: UInt64 | ||
@Struct.field('uint64') available!: UInt64 | ||
@Struct.field('uint64') max!: UInt64 | ||
@Struct.field('int64') used!: Int64 | ||
@Struct.field('int64') available!: Int64 | ||
@Struct.field('int64') max!: Int64 | ||
} | ||
@@ -287,3 +287,3 @@ | ||
expiration, | ||
ref_block_num: this.last_irreversible_block_num.value & 0xffff, | ||
ref_block_num: Number(this.last_irreversible_block_num) & 0xffff, | ||
ref_block_prefix: prefix, | ||
@@ -312,4 +312,4 @@ }) | ||
float64: Float64 | ||
i128: Int128 | ||
i64: Int64 | ||
i128: UInt128 | ||
i64: UInt64 | ||
name: Name | ||
@@ -320,3 +320,3 @@ ripemd160: Checksum160 | ||
export type TableIndexType = Name | Int64 | Int128 | Float64 | Checksum256 | Checksum160 | ||
export type TableIndexType = Name | UInt64 | UInt128 | Float64 | Checksum256 | Checksum160 | ||
@@ -329,3 +329,3 @@ export interface GetTableRowsParams<Index = TableIndexType | string> { | ||
/** The account to which this data belongs, if omitted will be set to be same as `code`. */ | ||
scope?: string | ||
scope?: string | TableIndexType | ||
/** Lower lookup bound. */ | ||
@@ -356,2 +356,6 @@ lower_bound?: Index | ||
json?: boolean | ||
/** | ||
* Set to true to populate the ram_payers array in the response. | ||
*/ | ||
show_payer?: boolean | ||
} | ||
@@ -374,3 +378,4 @@ | ||
more: boolean | ||
ram_payers?: Name[] | ||
next_key?: Index | ||
} |
@@ -1,3 +0,1 @@ | ||
import BN from 'bn.js' | ||
import {ABISerializableObject} from '../serializer/serializable' | ||
@@ -210,3 +208,3 @@ import {ABIEncoder} from '../serializer/encoder' | ||
if (typeof value === 'string') { | ||
value = UInt64.from(new BN(toRawSymbolCode(value), 'le')) | ||
value = UInt64.from(toRawSymbolCode(value)) | ||
} | ||
@@ -301,14 +299,16 @@ return new this(UInt64.from(value)) | ||
function toRawSymbol(name: string, precision: number) { | ||
const array = toRawSymbolCode(name) | ||
array.unshift(precision) | ||
return UInt64.from(new BN(array, 'le')) | ||
const code = toRawSymbolCode(name) | ||
const bytes = new Uint8Array(code.length + 1) | ||
bytes[0] = precision | ||
bytes.set(code, 1) | ||
return UInt64.from(bytes) | ||
} | ||
function toRawSymbolCode(name: string) { | ||
const array: number[] = [] | ||
const length = Math.min(name.length, 7) | ||
const bytes = new Uint8Array(length) | ||
for (let i = 0; i < length; i++) { | ||
array.push(name.charCodeAt(i)) | ||
bytes[i] = name.charCodeAt(i) | ||
} | ||
return array | ||
return bytes | ||
} |
@@ -72,3 +72,3 @@ import { | ||
/** Weight a key needs to sign for this authority. */ | ||
get keyTreshhold(): number { | ||
get keyThreshold(): number { | ||
return this.threshold.toNumber() - this.waitThreshold | ||
@@ -90,3 +90,3 @@ } | ||
hasPermission(publicKey: PublicKeyType, includePartial = false): boolean { | ||
const threshold = includePartial ? 1 : this.keyTreshhold | ||
const threshold = includePartial ? 1 : this.keyThreshold | ||
const weight = this.keyWeight(publicKey) | ||
@@ -93,0 +93,0 @@ return weight >= threshold |
@@ -8,5 +8,33 @@ import BN from 'bn.js' | ||
type IntType = Int | BNInt | number | string | BN | ||
type IntType = Int | number | string | BN | ||
class Int implements ABISerializableObject { | ||
interface IntDescriptor { | ||
isSigned: boolean | ||
byteWidth: number | ||
} | ||
/** | ||
* How to handle integer overflow. | ||
* - `throw`: Throws an error if value overflows (or underflows). | ||
* - `truncate`: Truncates or extends bit-pattern with sign extension (C++11 behavior). | ||
* - `clamp`: Clamps the value within the supported range. | ||
*/ | ||
export type OverflowBehavior = 'throw' | 'truncate' | 'clamp' | ||
/** | ||
* How to handle remainder when dividing integers. | ||
* - `floor`: Round down to nearest integer. | ||
* - `round`: Round to nearest integer. | ||
* - `ceil`: Round up to nearest integer. | ||
*/ | ||
export type DivisionBehavior = 'floor' | 'round' | 'ceil' | ||
/** | ||
* Binary integer with the underlying value represented by a BN.js instance. | ||
* Follows C++11 standard for arithmetic operators and conversions. | ||
* @note This type is optimized for correctness not speed, if you plan to manipulate | ||
* integers in a tight loop you're advised to use the underlying BN.js value or | ||
* convert to a JavaScript number first. | ||
*/ | ||
export class Int implements ABISerializableObject { | ||
static abiName = '__int' | ||
@@ -16,29 +44,131 @@ static isSigned: boolean | ||
static get max(): number { | ||
return Math.pow(2, this.byteWidth * 8 - (this.isSigned ? 1 : 0)) - 1 | ||
/** Largest value that can be represented by this integer type. */ | ||
static get max() { | ||
return new BN(2).pow(new BN(this.byteWidth * 8 - (this.isSigned ? 1 : 0))).isubn(1) | ||
} | ||
static get min(): number { | ||
return this.isSigned ? -(this.max + 1) : 0 | ||
/** Smallest value that can be represented by this integer type. */ | ||
static get min() { | ||
return this.isSigned ? this.max.ineg().isubn(1) : new BN(0) | ||
} | ||
static from<T extends typeof Int>(this: T, value: IntType): InstanceType<T> | ||
static from(value: any): unknown | ||
static from(value: any): any { | ||
/** Add `lhs` to `rhs` and return the resulting value. */ | ||
static add(lhs: Int, rhs: Int, overflow: OverflowBehavior = 'truncate'): Int { | ||
return Int.operator(lhs, rhs, overflow, (a, b) => a.add(b)) | ||
} | ||
/** Add `lhs` to `rhs` and return the resulting value. */ | ||
static sub(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int { | ||
return Int.operator(lhs, rhs, overflow, (a, b) => a.sub(b)) | ||
} | ||
/** Multiply `lhs` by `rhs` and return the resulting value. */ | ||
static mul(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int { | ||
return Int.operator(lhs, rhs, overflow, (a, b) => a.mul(b)) | ||
} | ||
/** | ||
* Divide `lhs` by `rhs` and return the quotient, dropping the remainder. | ||
* @throws When dividing by zero. | ||
*/ | ||
static div(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int { | ||
return Int.operator(lhs, rhs, overflow, (a, b) => { | ||
if (b.isZero()) { | ||
throw new Error('Division by zero') | ||
} | ||
return a.div(b) | ||
}) | ||
} | ||
/** | ||
* Divide `lhs` by `rhs` and return the quotient + remainder rounded to the closest integer. | ||
* @throws When dividing by zero. | ||
*/ | ||
static divRound(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int { | ||
return Int.operator(lhs, rhs, overflow, (a, b) => { | ||
if (b.isZero()) { | ||
throw new Error('Division by zero') | ||
} | ||
return a.divRound(b) | ||
}) | ||
} | ||
/** | ||
* Divide `lhs` by `rhs` and return the quotient + remainder rounded up to the closest integer. | ||
* @throws When dividing by zero. | ||
*/ | ||
static divCeil(lhs: Int, rhs: Int, overflow?: OverflowBehavior): Int { | ||
return Int.operator(lhs, rhs, overflow, (a, b) => { | ||
if (b.isZero()) { | ||
throw new Error('Division by zero') | ||
} | ||
const dm = (a as any).divmod(b) | ||
if (dm.mod.isZero()) return dm.div | ||
return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1) | ||
}) | ||
} | ||
/** | ||
* Can be used to implement custom operator. | ||
* @internal | ||
*/ | ||
static operator( | ||
lhs: Int, | ||
rhs: Int, | ||
overflow: OverflowBehavior = 'truncate', | ||
fn: (lhs: BN, rhs: BN) => BN | ||
) { | ||
const {a, b} = convert(lhs, rhs) | ||
const type = a.constructor as typeof Int | ||
const result = fn(a.value, b.value) | ||
return type.from(result, overflow) | ||
} | ||
/** | ||
* Create a new instance from value. | ||
* @param value Value to create new Int instance from, can be a string, number, | ||
* little-endian byte array or another Int instance. | ||
* @param overflow How to handle integer overflow, default behavior is to throw. | ||
*/ | ||
static from<T extends typeof Int>( | ||
this: T, | ||
value: IntType | Uint8Array, | ||
overflow?: OverflowBehavior | ||
): InstanceType<T> | ||
static from(value: any, overflow?: OverflowBehavior): unknown | ||
static from(value: IntType | Uint8Array, overflow?: OverflowBehavior): any { | ||
if (isInstanceOf(value, this)) { | ||
return value | ||
} | ||
if (typeof value === 'string') { | ||
value = Number.parseInt(value, 10) | ||
} else if (isInstanceOf(value, BNInt)) { | ||
value = value.value.toNumber() | ||
} else if (isInstanceOf(value, Int)) { | ||
value = value.value | ||
} else if (BN.isBN(value)) { | ||
value = value.toNumber() | ||
let fromType: IntDescriptor = this | ||
let bn: BN | ||
if (isInstanceOf(value, Int)) { | ||
fromType = value.constructor as typeof Int | ||
bn = value.value.clone() | ||
} else if (value instanceof Uint8Array) { | ||
bn = new BN(value, undefined, 'le') | ||
if (fromType.isSigned) { | ||
bn = bn.fromTwos(fromType.byteWidth * 8) | ||
} | ||
} else { | ||
if ( | ||
(typeof value === 'string' && !/[0-9]+/.test(value)) || | ||
(typeof value === 'number' && !Number.isFinite(value)) | ||
) { | ||
throw new Error('Invalid number') | ||
} | ||
bn = BN.isBN(value) ? value.clone() : new BN(value, 10) | ||
if (bn.isNeg() && !fromType.isSigned) { | ||
fromType = {byteWidth: fromType.byteWidth, isSigned: true} | ||
} | ||
} | ||
if (typeof value !== 'number') { | ||
throw new Error('Invalid integer') | ||
switch (overflow) { | ||
case 'clamp': | ||
bn = clamp(bn, this.min, this.max) | ||
break | ||
case 'truncate': | ||
bn = truncate(bn, fromType, this) | ||
break | ||
} | ||
return new this(value) | ||
return new this(bn) | ||
} | ||
@@ -49,3 +179,3 @@ | ||
static fromABI(decoder: ABIDecoder) { | ||
return new this(decoder.readNum(this.byteWidth, this.isSigned)) | ||
return this.from(decoder.readArray(this.byteWidth)) | ||
} | ||
@@ -56,106 +186,141 @@ | ||
static random() { | ||
const bytes = secureRandom(this.byteWidth) | ||
const decoder = new ABIDecoder(bytes) | ||
return this.fromABI(decoder) | ||
return this.from(secureRandom(this.byteWidth)) | ||
} | ||
value: number | ||
/** | ||
* The underlying BN.js instance – don't modify this | ||
* directly – take a copy first using `.clone()`. | ||
*/ | ||
value: BN | ||
constructor(value: number) { | ||
if (!Number.isFinite(value)) { | ||
throw new Error('Invalid number') | ||
/** | ||
* Create a new instance, don't use this directly. Use the `.from` factory method instead. | ||
* @throws If the value over- or under-flows the integer type. | ||
*/ | ||
constructor(value: BN) { | ||
const self = this.constructor as typeof Int | ||
if (self.isSigned === undefined || self.byteWidth === undefined) { | ||
throw new Error('Cannot instantiate abstract class Int') | ||
} | ||
this.value = clamp(value, this.constructor['min'], this.constructor['max']) | ||
if (value.gt(self.max)) { | ||
throw new Error(`Number ${value} overflows ${self.abiName}`) | ||
} | ||
if (value.lt(self.min)) { | ||
throw new Error(`Number ${value} underflows ${self.abiName}`) | ||
} | ||
this.value = value | ||
} | ||
equals(other: IntType) { | ||
/** | ||
* Cast this integer to other type. | ||
* @param overflow How to handle overflow, default is to preserve bit-pattern (C++11 behavior). | ||
*/ | ||
cast<T extends typeof Int>(type: T, overflow?: OverflowBehavior): InstanceType<T> | ||
cast(type: typeof Int, overflow: OverflowBehavior = 'truncate'): InstanceType<typeof Int> { | ||
if (this.constructor === type) { | ||
return this | ||
} | ||
return type.from(this, overflow) | ||
} | ||
/** Number as bytes in little endian (matches memory layout in C++ contract). */ | ||
get byteArray(): Uint8Array { | ||
const self = this.constructor as typeof Int | ||
return this.value === self.from(other).value | ||
const value = self.isSigned ? this.value.toTwos(self.byteWidth * 8) : this.value | ||
return value.toArrayLike(Uint8Array as any, 'le', self.byteWidth) | ||
} | ||
toABI(encoder: ABIEncoder) { | ||
/** | ||
* Compare two integers, if strict is set to true the test will only consider integers | ||
* of the exact same type. I.e. Int64.from(1).equals(UInt64.from(1)) will return false. | ||
*/ | ||
equals(other: IntType | Uint8Array, strict = false) { | ||
const self = this.constructor as typeof Int | ||
encoder.writeNum(this.value, self.byteWidth, self.isSigned) | ||
if (strict === true && isInstanceOf(other, Int)) { | ||
const otherType = other.constructor as typeof Int | ||
if (self.byteWidth !== otherType.byteWidth || self.isSigned !== otherType.isSigned) { | ||
return false | ||
} | ||
} | ||
try { | ||
return this.value.eq(self.from(other).value) | ||
} catch { | ||
return false | ||
} | ||
} | ||
toNumber() { | ||
return this.value | ||
/** Mutating add. */ | ||
add(num: IntType) { | ||
this.value = this.operator(num, Int.add).value | ||
} | ||
toString() { | ||
return this.value.toFixed(0) | ||
/** Non-mutating add. */ | ||
adding(num: IntType) { | ||
return this.operator(num, Int.add) | ||
} | ||
toJSON() { | ||
return this.value | ||
/** Mutating subtract. */ | ||
subtract(num: IntType) { | ||
this.value = this.operator(num, Int.sub).value | ||
} | ||
} | ||
class BNInt implements ABISerializableObject { | ||
static abiName = '__bn_int' | ||
static isSigned: boolean | ||
static byteWidth: number | ||
/** Non-mutating subtract. */ | ||
subtracting(num: IntType) { | ||
return this.operator(num, Int.sub) | ||
} | ||
static from<T extends typeof BNInt>(this: T, value: IntType | Uint8Array): InstanceType<T> | ||
static from(value: any): unknown | ||
static from(value: any): any { | ||
if (isInstanceOf(value, this)) { | ||
return value | ||
} | ||
if (isInstanceOf(value, BNInt)) { | ||
return new this(value.value) | ||
} | ||
if (isInstanceOf(value, Uint8Array)) { | ||
return new this(new BN(value, undefined, 'le')) | ||
} | ||
if (isInstanceOf(value, Int)) { | ||
value = value.value | ||
} | ||
return new this(new BN(value)) | ||
/** Mutating multiply. */ | ||
multiply(by: IntType) { | ||
this.value = this.operator(by, Int.mul).value | ||
} | ||
static fromABI<T extends typeof BNInt>(this: T, decoder: ABIDecoder): InstanceType<T> | ||
static fromABI(decoder: ABIDecoder): unknown | ||
static fromABI(decoder: ABIDecoder) { | ||
return new this(decoder.readBn(this.byteWidth, this.isSigned)) | ||
/** Non-mutating multiply. */ | ||
multiplying(by: IntType) { | ||
return this.operator(by, Int.mul) | ||
} | ||
static random<T extends typeof BNInt>(this: T): InstanceType<T> | ||
static random(): unknown | ||
static random() { | ||
const bytes = secureRandom(this.byteWidth) | ||
const decoder = new ABIDecoder(bytes) | ||
return this.fromABI(decoder) | ||
/** | ||
* Mutating divide. | ||
* @param behavior How to handle the remainder, default is to floor (round down). | ||
* @throws When dividing by zero. | ||
*/ | ||
divide(by: IntType, behavior?: DivisionBehavior) { | ||
this.value = this.dividing(by, behavior).value | ||
} | ||
value: BN | ||
constructor(value: BN) { | ||
const self = this.constructor as typeof BNInt | ||
if (value.byteLength() > self.byteWidth) { | ||
throw new Error('Number too wide') | ||
/** | ||
* Non-mutating divide. | ||
* @param behavior How to handle the remainder, default is to floor (round down). | ||
* @throws When dividing by zero. | ||
*/ | ||
dividing(by: IntType, behavior?: DivisionBehavior) { | ||
let op = Int.div | ||
switch (behavior) { | ||
case 'ceil': | ||
op = Int.divCeil | ||
break | ||
case 'round': | ||
op = Int.divRound | ||
break | ||
} | ||
this.value = value | ||
return this.operator(by, op) | ||
} | ||
equals(other: IntType | Uint8Array, allowCast = false) { | ||
const self = this.constructor as typeof BNInt | ||
if ( | ||
!allowCast && | ||
typeof (other.constructor as any).byteWidth === 'number' && | ||
(other.constructor as any).byteWidth !== self.byteWidth | ||
) { | ||
return false | ||
/** | ||
* Run operator with C++11 implicit conversion. | ||
* @internal | ||
*/ | ||
private operator(other: IntType, fn: (lhs: Int, rhs: Int) => Int): this { | ||
let rhs: Int | ||
if (isInstanceOf(other, Int)) { | ||
rhs = other | ||
} else { | ||
rhs = Int64.from(other, 'truncate') | ||
} | ||
return this.value.eq(self.from(other).value) | ||
return fn(this, rhs).cast(this.constructor as typeof Int) as this | ||
} | ||
toABI(encoder: ABIEncoder) { | ||
const self = this.constructor as typeof BNInt | ||
encoder.writeBn(this.value, self.byteWidth, self.isSigned) | ||
} | ||
/** | ||
* Return JavaScript number for this instance. | ||
* @throws If the number is larger than 53-bits. | ||
* Convert to a JavaScript number. | ||
* @throws If the number cannot be represented by 53-bits. | ||
**/ | ||
@@ -170,4 +335,8 @@ toNumber() { | ||
toABI(encoder: ABIEncoder) { | ||
encoder.writeArray(this.byteArray) | ||
} | ||
toJSON() { | ||
// match FCs behavior and return strings for anything above Uint32 | ||
// match FCs behavior and return strings for anything above 32-bit | ||
if (this.value.bitLength() > 32) { | ||
@@ -203,3 +372,3 @@ return this.value.toString() | ||
export type Int64Type = Int64 | IntType | ||
export class Int64 extends BNInt { | ||
export class Int64 extends Int { | ||
static abiName = 'int64' | ||
@@ -211,3 +380,3 @@ static byteWidth = 8 | ||
export type Int128Type = Int128 | IntType | ||
export class Int128 extends BNInt { | ||
export class Int128 extends Int { | ||
static abiName = 'int128' | ||
@@ -240,3 +409,3 @@ static byteWidth = 16 | ||
export type UInt64Type = UInt64 | IntType | ||
export class UInt64 extends BNInt { | ||
export class UInt64 extends Int { | ||
static abiName = 'uint64' | ||
@@ -248,3 +417,3 @@ static byteWidth = 8 | ||
export type UInt128Type = UInt128 | IntType | ||
export class UInt128 extends BNInt { | ||
export class UInt128 extends Int { | ||
static abiName = 'uint128' | ||
@@ -262,7 +431,7 @@ static byteWidth = 16 | ||
static fromABI(decoder: ABIDecoder) { | ||
return new this(decoder.readVarint32()) | ||
return new this(new BN(decoder.readVarint32())) | ||
} | ||
toABI(encoder: ABIEncoder) { | ||
encoder.writeVarint32(this.value) | ||
encoder.writeVarint32(Number(this)) | ||
} | ||
@@ -277,7 +446,7 @@ } | ||
static fromABI(decoder: ABIDecoder) { | ||
return new this(decoder.readVaruint32()) | ||
return new this(new BN(decoder.readVaruint32())) | ||
} | ||
toABI(encoder: ABIEncoder) { | ||
encoder.writeVaruint32(this.value) | ||
encoder.writeVaruint32(Number(this)) | ||
} | ||
@@ -300,4 +469,110 @@ } | ||
function clamp(num: number, min: number, max: number) { | ||
return Math.min(Math.max(num, min), max) | ||
/** Clamp number between min and max. */ | ||
function clamp(num: BN, min: BN, max: BN) { | ||
return BN.min(BN.max(num, min), max) | ||
} | ||
/** | ||
* Create new BN with the same bit pattern as the passed value, | ||
* extending or truncating the value’s representation as necessary. | ||
*/ | ||
function truncate(value: BN, from: IntDescriptor, to: IntDescriptor): BN { | ||
const fill = value.isNeg() ? 255 : 0 | ||
const fromValue = from.isSigned ? value.toTwos(from.byteWidth * 8) : value | ||
const fromBytes = fromValue.toArrayLike(Uint8Array as any, 'le') as Uint8Array | ||
const toBytes = new Uint8Array(to.byteWidth) | ||
toBytes.fill(fill) | ||
toBytes.set(fromBytes.slice(0, to.byteWidth)) | ||
const toValue = new BN(toBytes, undefined, 'le') | ||
return to.isSigned ? toValue.fromTwos(to.byteWidth * 8) : toValue | ||
} | ||
/** C++11 implicit integer conversions. */ | ||
function convert(a: Int, b: Int) { | ||
// The integral promotions (4.5) shall be performed on both operands. | ||
a = promote(a) | ||
b = promote(b) | ||
const aType = a.constructor as typeof Int | ||
const bType = b.constructor as typeof Int | ||
// If both operands have the same type, no further conversion is needed | ||
if (aType !== bType) { | ||
// Otherwise, if both operands have signed integer types or both have unsigned integer types, | ||
// the operand with the type of lesser integer conversion rank shall be converted to the type | ||
// of the operand with greater rank. | ||
if (aType.isSigned === bType.isSigned) { | ||
if (aType.byteWidth > bType.byteWidth) { | ||
b = b.cast(aType) | ||
} else if (bType.byteWidth > aType.byteWidth) { | ||
a = a.cast(bType) | ||
} | ||
} else { | ||
// Otherwise, if the operand that has unsigned integer type has rank greater than or equal | ||
// to the rank of the type of the other operand, the operand with signed integer type | ||
// shall be converted to the type of the operand with unsigned integer type. | ||
if (aType.isSigned === false && aType.byteWidth >= bType.byteWidth) { | ||
b = b.cast(aType) | ||
} else if (bType.isSigned === false && bType.byteWidth >= aType.byteWidth) { | ||
a = a.cast(bType) | ||
} else { | ||
// Otherwise, if the type of the operand with signed integer type can represent all of the | ||
// values of the type of the operand with unsigned integer type, the operand with unsigned | ||
// integer type shall be converted to the type of the operand with signed integer type. | ||
if ( | ||
aType.isSigned === true && | ||
aType.max.gte(bType.max) && | ||
aType.min.lte(bType.min) | ||
) { | ||
b = b.cast(aType) | ||
} else if ( | ||
bType.isSigned === true && | ||
bType.max.gte(aType.max) && | ||
bType.min.lte(aType.min) | ||
) { | ||
a = a.cast(bType) | ||
} else { | ||
// Otherwise, both operands shall be converted to the unsigned integer type | ||
// corresponding to the type of the operand with signed integer type. | ||
// --- | ||
// Dead code: this can't happen™ with the types we have. | ||
// --- | ||
// const signedType = aType.isSigned ? aType : bType | ||
// let unsignedType: typeof Int | ||
// switch (signedType.byteWidth) { | ||
// case 4: | ||
// unsignedType = UInt32 | ||
// break | ||
// case 8: | ||
// unsignedType = UInt64 | ||
// break | ||
// case 16: | ||
// unsignedType = UInt128 | ||
// break | ||
// default: | ||
// throw new Error( | ||
// `No corresponding unsigned type for ${signedType.abiName}` | ||
// ) | ||
// } | ||
// a = a.cast(unsignedType) | ||
// b = b.cast(unsignedType) | ||
} | ||
} | ||
} | ||
} | ||
return {a, b} | ||
} | ||
/** C++11 integral promotion. */ | ||
function promote(n: Int) { | ||
// An rvalue of type char, signed char, unsigned char, short int, or | ||
// unsigned short int can be converted to an rvalue of type int if int | ||
// can represent all the values of the source type; otherwise, the source | ||
// rvalue can be converted to an rvalue of type unsigned int. | ||
let rv = n | ||
const type = n.constructor as typeof Int | ||
if (type.byteWidth < 4) { | ||
rv = n.cast(Int32) | ||
} | ||
return rv | ||
} |
@@ -1,3 +0,1 @@ | ||
import BN from 'bn.js' | ||
import {ABIDecoder} from '../serializer/decoder' | ||
@@ -8,3 +6,3 @@ import {ABIEncoder} from '../serializer/encoder' | ||
import {AnyInt, Int64, Int64Type, UInt32, UInt32Type} from '../' | ||
import {AnyInt, Int64, Int64Type, UInt32, UInt32Type, UInt64} from '../' | ||
@@ -112,3 +110,3 @@ export type TimePointType = TimePoint | TimePointSec | string | Date | AnyInt | ||
toMilliseconds() { | ||
return this.value.value.divRound(new BN(1000)).toNumber() | ||
return Number(this.value.dividing(1000, 'round')) | ||
} | ||
@@ -140,3 +138,3 @@ } | ||
toMilliseconds() { | ||
return this.value.value * 1000 | ||
return Number(this.value.cast(UInt64).multiplying(1000)) | ||
} | ||
@@ -167,4 +165,4 @@ } | ||
toMilliseconds() { | ||
return this.value.value * 500 + 946684800000 | ||
return Number(this.value.cast(UInt64).multiplying(500).adding(946684800000)) | ||
} | ||
} |
@@ -187,3 +187,3 @@ import {abiEncode} from '../serializer/encoder' | ||
getTransaction(): Transaction { | ||
if (this.compression.value !== 0) { | ||
if (Number(this.compression) !== 0) { | ||
throw new Error('Transaction compression not supported yet') | ||
@@ -190,0 +190,0 @@ } |
@@ -5,4 +5,2 @@ /** | ||
import BN from 'bn.js' | ||
import {ABI, ABIDef, Bytes, BytesType, Variant} from '../chain' | ||
@@ -341,46 +339,2 @@ | ||
/** Read integer as JavaScript number, up to 32 bits. */ | ||
readNum(byteWidth: number, isSigned: boolean) { | ||
this.ensure(byteWidth) | ||
const d = this.data, | ||
p = this.pos | ||
let rv: number | ||
switch (byteWidth * (isSigned ? -1 : 1)) { | ||
case 1: | ||
rv = d.getUint8(p) | ||
break | ||
case 2: | ||
rv = d.getUint16(p, true) | ||
break | ||
case 4: | ||
rv = d.getUint32(p, true) | ||
break | ||
case -1: | ||
rv = d.getInt8(p) | ||
break | ||
case -2: | ||
rv = d.getInt16(p, true) | ||
break | ||
case -4: | ||
rv = d.getInt32(p, true) | ||
break | ||
default: | ||
throw new Error('Invalid integer width') | ||
} | ||
this.pos += byteWidth | ||
return rv | ||
} | ||
/** Read integer as a bn.js number. */ | ||
readBn(bytes: number, signed: boolean) { | ||
this.ensure(bytes) | ||
const bn = new BN(this.array.subarray(this.pos, this.pos + bytes), 'le') | ||
this.pos += bytes | ||
if (signed) { | ||
return bn.fromTwos(bytes * 8) | ||
} else { | ||
return bn | ||
} | ||
} | ||
/** Read floating point as JavaScript number, 32 or 64 bits. */ | ||
@@ -387,0 +341,0 @@ readFloat(byteWidth: number) { |
/** | ||
* EOSIO ABI Encoder | ||
*/ | ||
import BN from 'bn.js' | ||
import {ABI, ABIDef, Bytes, Variant} from '../chain' | ||
@@ -296,40 +293,2 @@ import {isInstanceOf} from '../utils' | ||
/** Write a JavaScript number as integer, up to 32 bits. */ | ||
writeNum(value: number, byteWidth: number, isSigned: boolean) { | ||
this.ensure(byteWidth) | ||
const d = this.data, | ||
p = this.pos | ||
switch (byteWidth * (isSigned ? -1 : 1)) { | ||
case 1: | ||
d.setUint8(p, value) | ||
break | ||
case 2: | ||
d.setUint16(p, value, true) | ||
break | ||
case 4: | ||
d.setUint32(p, value, true) | ||
break | ||
case -1: | ||
d.setInt8(p, value) | ||
break | ||
case -2: | ||
d.setInt16(p, value, true) | ||
break | ||
case -4: | ||
d.setInt32(p, value, true) | ||
break | ||
default: | ||
throw new Error('Invalid integer width') | ||
} | ||
this.pos += byteWidth | ||
} | ||
/** Write a bn.js number. */ | ||
writeBn(value: BN, byteWidth: number, isSigned: boolean) { | ||
if (isSigned) { | ||
value = value.toTwos(byteWidth * 8) | ||
} | ||
this.writeArray(value.toArrayLike(Uint8Array as any, 'le', byteWidth)) | ||
} | ||
writeFloat(value: number, byteWidth: number) { | ||
@@ -336,0 +295,0 @@ this.ensure(byteWidth) |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
740648
14752