@ckb-lumos/base
Advanced tools
Comparing version 0.18.0-rc4 to 0.18.0-rc5
@@ -1,2 +0,3 @@ | ||
const { Reader } = require("ckb-js-toolkit"); | ||
const { BI } = require("@ckb-lumos/bi"); | ||
const { Reader } = require("@ckb-lumos/toolkit"); | ||
@@ -7,3 +8,3 @@ function DenormalizeOutPoint(outPoint) { | ||
index: | ||
"0x" + BigInt(outPoint.getIndex().toLittleEndianUint32()).toString(16), | ||
"0x" + BI.from(outPoint.getIndex().toLittleEndianUint32()).toString(16), | ||
}; | ||
@@ -10,0 +11,0 @@ } |
const { ScriptValue } = require("./values"); | ||
const { BI } = require("@ckb-lumos/bi"); | ||
@@ -104,3 +105,3 @@ function isCellMatchQueryOptions( | ||
cell.block_number && | ||
BigInt(cell.block_number) < BigInt(fromBlock) | ||
BI.from(cell.block_number).lt(BI.from(fromBlock)) | ||
) { | ||
@@ -112,3 +113,3 @@ return false; | ||
cell.block_number && | ||
BigInt(cell.block_number) > BigInt(toBlock) | ||
BI.from(cell.block_number).gt(BI.from(toBlock)) | ||
) { | ||
@@ -115,0 +116,0 @@ return false; |
@@ -1,2 +0,2 @@ | ||
const { validators } = require("ckb-js-toolkit"); | ||
const { validators } = require("@ckb-lumos/toolkit"); | ||
const utils = require("./utils"); | ||
@@ -3,0 +3,0 @@ |
/** | ||
* HexString represents string starts with "0x" and followed by even number(including empty) of [0-9a-fA-F] characters. | ||
*/ | ||
export type HexString = string; | ||
/** | ||
* Hexadecimal represents string starts with "0x" and followed by any number(excluding empty) of [0-9a-fA-F] characters. | ||
*/ | ||
export type Hexadecimal = string; | ||
export type Hash = HexString; | ||
export type HexNumber = Hexadecimal; | ||
export type PackedSince = string; | ||
export type PackedDao = string; | ||
export type Address = string; | ||
export type HexadecimalRange = [Hexadecimal, Hexadecimal]; | ||
export type HexString = string; | ||
/** | ||
* Hexadecimal represents string starts with "0x" and followed by any number(excluding empty) of [0-9a-fA-F] characters. | ||
*/ | ||
export type Hexadecimal = string; | ||
export type Hash = HexString; | ||
export type HexNumber = Hexadecimal; | ||
export type PackedSince = string; | ||
export type PackedDao = string; | ||
export type Address = string; | ||
export type HexadecimalRange = [Hexadecimal, Hexadecimal]; |
@@ -0,1 +1,2 @@ | ||
import { BIish, BI } from "@ckb-lumos/bi"; | ||
import { HexNumber, PackedSince, HexString } from "./primitive"; | ||
@@ -36,2 +37,16 @@ | ||
export function parseSinceCompatible( | ||
since: PackedSince | ||
): | ||
| { | ||
relative: boolean; | ||
type: "epochNumber"; | ||
value: EpochSinceValue; | ||
} | ||
| { | ||
relative: boolean; | ||
type: "blockNumber" | "blockTimestamp"; | ||
value: BI; | ||
}; | ||
/** | ||
@@ -100,3 +115,3 @@ * parse epoch from blockHeader.epoch | ||
type: SinceType; | ||
value: bigint; | ||
value: BIish; | ||
} | ||
@@ -103,0 +118,0 @@ | { |
167
lib/since.js
@@ -0,20 +1,28 @@ | ||
const { BI, isBIish } = require("@ckb-lumos/bi"); | ||
function parseSince(since) { | ||
since = BigInt(since); | ||
const flag = since >> BigInt(56); | ||
const metricFlag = (flag >> BigInt(5)) & BigInt("0b11"); | ||
const result = parseSinceCompatible(since); | ||
if (result.type === "epochNumber") return result; | ||
return { ...result, value: result.value.toBigInt() }; | ||
} | ||
function parseSinceCompatible(since) { | ||
since = BI.from(since); | ||
const flag = since.shr(56); | ||
const metricFlag = flag.shr(5).and("0b11"); | ||
let type; | ||
let value; | ||
if (metricFlag === BigInt(0b00)) { | ||
if (metricFlag.eq(0b00)) { | ||
type = "blockNumber"; | ||
value = since & BigInt("0xFFFFFFFFFFFFFF"); | ||
} else if (metricFlag === BigInt(0b01)) { | ||
value = since.and("0xFFFFFFFFFFFFFF"); | ||
} else if (metricFlag.eq(0b01)) { | ||
type = "epochNumber"; | ||
value = { | ||
length: Number((since >> BigInt(40)) & BigInt(0xffff)), | ||
index: Number((since >> BigInt(24)) & BigInt(0xffff)), | ||
number: Number(since & BigInt(0xffffff)), | ||
length: since.shr(40).and(0xffff).toNumber(), | ||
index: since.shr(24).and(0xffff).toNumber(), | ||
number: since.and(0xffffff).toNumber(), | ||
}; | ||
} else if (metricFlag === BigInt(0b10)) { | ||
} else if (metricFlag.eq(0b10)) { | ||
type = "blockTimestamp"; | ||
value = since & BigInt("0xFFFFFFFFFFFFFF"); | ||
value = since.and("0xFFFFFFFFFFFFFF"); | ||
} else { | ||
@@ -25,3 +33,3 @@ throw new Error("Invalid metric flag!"); | ||
return { | ||
relative: (flag & BigInt("0x80")) !== BigInt(0), | ||
relative: !flag.and("0x80").eq(0), | ||
type, | ||
@@ -33,30 +41,31 @@ value, | ||
function generateSince({ relative, type, value }) { | ||
let flag = BigInt(0); | ||
let flag = BI.from(0); | ||
if (relative) { | ||
flag += BigInt(0b10000000); | ||
flag = flag.add(0b10000000); | ||
} | ||
if (type === "epochNumber") { | ||
flag += BigInt(0b00100000); | ||
flag = flag.add(0b00100000); | ||
} else if (type === "blockTimestamp") { | ||
flag += BigInt(0b01000000); | ||
flag = flag.add(0b01000000); | ||
} | ||
let v; | ||
if (typeof value === "object") { | ||
v = BigInt(generateHeaderEpoch(value)); | ||
if (isBIish(value)) { | ||
v = BI.from(value); | ||
} else if (typeof value === "object") { | ||
v = generateHeaderEpoch(value); | ||
} else { | ||
v = BigInt(value); | ||
v = BI.from(value); | ||
} | ||
// TODO: check v is valid | ||
return _toHex((flag << BigInt(56)) + v); | ||
return _toHex(flag.shl(56).add(v)); | ||
} | ||
function parseEpoch(epoch) { | ||
epoch = BigInt(epoch); | ||
epoch = BI.from(epoch); | ||
return { | ||
length: Number((epoch >> BigInt(40)) & BigInt(0xffff)), | ||
index: Number((epoch >> BigInt(24)) & BigInt(0xffff)), | ||
number: Number(epoch & BigInt(0xffffff)), | ||
length: epoch.shr(40).and(0xffff).toNumber(), | ||
index: epoch.shr(24).and(0xffff).toNumber(), | ||
number: epoch.and(0xffffff).toNumber(), | ||
}; | ||
@@ -69,9 +78,10 @@ } | ||
const maxArgs = parsedArgs.filter((arg) => arg.number === maxNumber); | ||
let max = maxArgs[0]; | ||
let max = maxArgs[0]; | ||
for (let i = 1; i < maxArgs.length; ++i) { | ||
const current = maxArgs[i]; | ||
if ( | ||
BigInt(current.index) * BigInt(max.length) >= | ||
BigInt(max.index) * BigInt(current.length) | ||
BI.from(current.index) | ||
.mul(max.length) | ||
.gte(BI.from(max.index).mul(current.length)) | ||
) { | ||
@@ -95,5 +105,3 @@ max = current; | ||
return _toHex( | ||
(BigInt(length) << BigInt(40)) + | ||
(BigInt(index) << BigInt(24)) + | ||
BigInt(number) | ||
BI.from(length).shl(40).add(BI.from(index).shl(24)).add(number) | ||
); | ||
@@ -103,6 +111,8 @@ } | ||
function parseAbsoluteEpochSince(since) { | ||
const { relative, type, value } = parseSince(since); | ||
const { relative, type, value } = parseSinceCompatible(since); | ||
if (!(relative === false && type === "epochNumber")) { | ||
throw new Error("Since format error!"); | ||
} | ||
return value; | ||
@@ -112,10 +122,10 @@ } | ||
function validateAbsoluteEpochSince(since, tipHeaderEpoch) { | ||
const { value } = parseSince(since); | ||
const headerEpochParams = parseEpoch(BigInt(tipHeaderEpoch)); | ||
const { value } = parseSinceCompatible(since); | ||
const headerEpochParams = parseEpoch(tipHeaderEpoch); | ||
return ( | ||
value.number < headerEpochParams.number || | ||
(value.number === headerEpochParams.number && | ||
BigInt(value.index) * BigInt(headerEpochParams.length) <= | ||
BigInt(headerEpochParams.index) * BigInt(value.length)) | ||
BI.from(value.number).lt(headerEpochParams.number) || | ||
(BI.from(value.number).eq(headerEpochParams.number) && | ||
BI.from(value.index) | ||
.mul(headerEpochParams.length) | ||
.lte(BI.from(headerEpochParams.index).mul(value.length))) | ||
); | ||
@@ -125,3 +135,4 @@ } | ||
function validateSince(since, tipSinceValidationInfo, cellSinceValidationInfo) { | ||
const { relative, type, value } = parseSince(since); | ||
const { relative, type, value } = parseSinceCompatible(since); | ||
if (!relative) { | ||
@@ -131,5 +142,7 @@ if (type === "epochNumber") { | ||
} | ||
if (type === "blockNumber") { | ||
return value <= BigInt(tipSinceValidationInfo.block_number); | ||
return BI.from(value).lte(tipSinceValidationInfo.block_number); | ||
} | ||
if (type === "blockTimestamp") { | ||
@@ -139,43 +152,49 @@ if (!tipSinceValidationInfo.median_timestamp) { | ||
} | ||
return value * 1000n <= BigInt(tipSinceValidationInfo.median_timestamp); | ||
return BI.from(value) | ||
.mul(1000) | ||
.lte(tipSinceValidationInfo.median_timestamp); | ||
} | ||
} else { | ||
if (type === "epochNumber") { | ||
const tipHeaderEpoch = parseEpoch(BigInt(tipSinceValidationInfo.epoch)); | ||
const sinceHeaderEpoch = parseEpoch( | ||
BigInt(cellSinceValidationInfo.epoch) | ||
); | ||
const tipHeaderEpoch = parseEpoch(tipSinceValidationInfo.epoch); | ||
const sinceHeaderEpoch = parseEpoch(cellSinceValidationInfo.epoch); | ||
const added = { | ||
number: BigInt(value.number + sinceHeaderEpoch.number), | ||
index: | ||
BigInt(value.index) * BigInt(sinceHeaderEpoch.length) + | ||
BigInt(sinceHeaderEpoch.index) * BigInt(value.length), | ||
length: BigInt(value.length) * BigInt(sinceHeaderEpoch.length), | ||
number: BI.from(value.number).add(sinceHeaderEpoch.number), | ||
index: BI.from(value.index) | ||
.mul(sinceHeaderEpoch.length) | ||
.add(BI.from(sinceHeaderEpoch.index).mul(value.length)), | ||
length: BI.from(value.length).mul(sinceHeaderEpoch.length), | ||
}; | ||
if (value.length === 0 && sinceHeaderEpoch.length !== 0) { | ||
added.index = BigInt(sinceHeaderEpoch.index); | ||
added.length = BigInt(sinceHeaderEpoch.length); | ||
added.index = sinceHeaderEpoch.index; | ||
added.length = sinceHeaderEpoch.length; | ||
} else if (sinceHeaderEpoch.length === 0 && value.length !== 0) { | ||
added.index = BigInt(value.index); | ||
added.length = BigInt(value.length); | ||
added.index = BI.from(value.index); | ||
added.length = BI.from(value.length); | ||
} | ||
if (added.length && added.index >= added.length) { | ||
added.number += added.index / added.length; | ||
added.index = added.index % added.length; | ||
if ( | ||
!BI.from(added.length).eq(0) && | ||
BI.from(added.index).gte(added.length) | ||
) { | ||
added.number = added.index.div(added.length).add(added.number); | ||
added.index = added.index.mod(added.length); | ||
} | ||
return ( | ||
added.number < BigInt(tipHeaderEpoch.number) || | ||
(added.number === BigInt(tipHeaderEpoch.number) && | ||
added.index * BigInt(tipHeaderEpoch.length) <= | ||
BigInt(tipHeaderEpoch.index) * added.length) | ||
BI.from(added.number).lt(tipHeaderEpoch.number) || | ||
(BI.from(added.number).eq(tipHeaderEpoch.number) && | ||
BI.from(added.index) | ||
.mul(tipHeaderEpoch.length) | ||
.lte(BI.from(tipHeaderEpoch.index).mul(added.length))) | ||
); | ||
} | ||
if (type === "blockNumber") { | ||
return ( | ||
value + BigInt(cellSinceValidationInfo.block_number) <= | ||
BigInt(tipSinceValidationInfo.block_number) | ||
); | ||
return BI.from(value) | ||
.add(cellSinceValidationInfo.block_number) | ||
.lte(tipSinceValidationInfo.block_number); | ||
} | ||
if (type === "blockTimestamp") { | ||
@@ -188,7 +207,6 @@ if ( | ||
} | ||
return ( | ||
value * 1000n + BigInt(cellSinceValidationInfo.median_timestamp) <= | ||
BigInt(tipSinceValidationInfo.median_timestamp) | ||
); | ||
return BI.from(value) | ||
.mul(1000) | ||
.add(cellSinceValidationInfo.median_timestamp) | ||
.lte(tipSinceValidationInfo.median_timestamp); | ||
} | ||
@@ -204,2 +222,3 @@ } | ||
parseSince, | ||
parseSinceCompatible, | ||
parseEpoch, | ||
@@ -206,0 +225,0 @@ maximumAbsoluteEpochSince, |
@@ -1,3 +0,4 @@ | ||
import { Reader } from "ckb-js-toolkit"; | ||
import { Reader } from "@ckb-lumos/toolkit"; | ||
import { HexNumber } from ".."; | ||
import { BI, BIish } from "@ckb-lumos/bi"; | ||
import { Script, Input } from "./api"; | ||
@@ -21,3 +22,3 @@ import { Hash, HexString } from "./primitive"; | ||
*/ | ||
export function toBigUInt64LE(num: bigint): HexString; | ||
export function toBigUInt64LE(num: BIish): HexString; | ||
@@ -30,2 +31,3 @@ /** | ||
export function readBigUInt64LE(hex: HexString): bigint; | ||
export function readBigUInt64LECompatible(hex: HexString): BI; | ||
@@ -37,3 +39,3 @@ /** | ||
*/ | ||
export function toBigUInt128LE(u128: bigint): string; | ||
export function toBigUInt128LE(u128: BIish): string; | ||
@@ -46,2 +48,3 @@ /** | ||
export function readBigUInt128LE(leHex: HexString): bigint; | ||
export function readBigUInt128LECompatible(leHex: HexString): BI; | ||
@@ -65,2 +68,3 @@ /** | ||
export function isDeepEqual(a: unknown, b: unknown): boolean; | ||
export function generateTypeIdScript( | ||
@@ -67,0 +71,0 @@ input: Input, |
const blake2b = require("blake2b"); | ||
const { validators, normalizers, Reader } = require("ckb-js-toolkit"); | ||
const { validators, normalizers, Reader } = require("@ckb-lumos/toolkit"); | ||
const isEqual = require("lodash.isequal"); | ||
const { SerializeScript, SerializeCellInput } = require("./core"); | ||
const { xxHash32 } = require("js-xxhash"); | ||
const { BI } = require("@ckb-lumos/bi"); | ||
@@ -39,5 +41,11 @@ class CKBHasher { | ||
function toBigUInt64LE(num) { | ||
num = BigInt(num); | ||
return toBigUInt64LECompatible(num); | ||
} | ||
function toBigUInt64LECompatible(num) { | ||
num = BI.from(num); | ||
const buf = Buffer.alloc(8); | ||
buf.writeBigUInt64LE(num); | ||
buf.writeUInt32LE(num.and("0xffffffff").toNumber(), 0); | ||
num = num.shr(32); | ||
buf.writeUInt32LE(num.and("0xffffffff").toNumber(), 4); | ||
return `0x${buf.toString("hex")}`; | ||
@@ -51,18 +59,36 @@ } | ||
const U128_MIN = BigInt(0); | ||
// create-react-app@4.0.3 default config will transform `**` to `Math.pow`. | ||
// However, Math.pow(BigInt(), BigInt()) will cause an error | ||
// const U128_MAX = BigInt(2) ** BigInt(128) - BigInt(1); | ||
const U128_MAX = 340282366920938463463374607431768211455n; | ||
function readBigUInt64LECompatible(hex) { | ||
const buf = Buffer.from(hex.slice(2), "hex"); | ||
return BI.from(buf.readUInt32LE()).add(BI.from(buf.readUInt32LE(4)).shl(32)); | ||
} | ||
// const U128_MIN = BigInt(0); | ||
// const U128_MAX = BigInt("340282366920938463463374607431768211455"); | ||
function toBigUInt128LE(u128) { | ||
if (u128 < U128_MIN) { | ||
throw new Error(`u128 ${u128} too small`); | ||
return toBigUInt128LECompatible(u128); | ||
} | ||
const U128_MIN_COMPATIBLE = BI.from(0); | ||
const U128_MAX_COMPATIBLE = BI.from("340282366920938463463374607431768211455"); | ||
function toBigUInt128LECompatible(num) { | ||
num = BI.from(num); | ||
if (num.lt(U128_MIN_COMPATIBLE)) { | ||
throw new Error(`u128 ${num} too small`); | ||
} | ||
if (u128 > U128_MAX) { | ||
throw new Error(`u128 ${u128} too large`); | ||
if (num.gt(U128_MAX_COMPATIBLE)) { | ||
throw new Error(`u128 ${num} too large`); | ||
} | ||
const buf = Buffer.alloc(16); | ||
buf.writeBigUInt64LE(u128 & BigInt("0xFFFFFFFFFFFFFFFF"), 0); | ||
buf.writeBigUInt64LE(u128 >> BigInt(64), 8); | ||
return "0x" + buf.toString("hex"); | ||
buf.writeUInt32LE(num.and(0xffffffff).toNumber(), 0); | ||
num = num.shr(32); | ||
buf.writeUInt32LE(num.and(0xffffffff).toNumber(), 4); | ||
num = num.shr(32); | ||
buf.writeUInt32LE(num.and(0xffffffff).toNumber(), 8); | ||
num = num.shr(32); | ||
buf.writeUInt32LE(num.and(0xffffffff).toNumber(), 12); | ||
return `0x${buf.toString("hex")}`; | ||
} | ||
@@ -78,2 +104,16 @@ | ||
function readBigUInt128LECompatible(leHex) { | ||
if (leHex.length < 34 || !leHex.startsWith("0x")) { | ||
throw new Error(`leHex format error`); | ||
} | ||
const buf = Buffer.from(leHex.slice(2, 34), "hex"); | ||
return BI.from(buf.readUInt32LE(0)) | ||
.shl(0) | ||
.add(BI.from(buf.readUInt32LE(4)).shl(32)) | ||
.add(BI.from(buf.readUInt32LE(8)).shl(64)) | ||
.add(BI.from(buf.readUInt32LE(12)).shl(96)); | ||
} | ||
function computeScriptHash(script, { validate = true } = {}) { | ||
@@ -105,2 +145,5 @@ if (validate) { | ||
function isDeepEqual(a, b) { | ||
return isEqual(a, b); | ||
} | ||
// Buffer.from('TYPE_ID') | ||
@@ -135,5 +178,9 @@ const TYPE_ID_CODE_HASH = | ||
toBigUInt64LE, | ||
toBigUInt64LECompatible, | ||
readBigUInt64LE, | ||
readBigUInt64LECompatible, | ||
toBigUInt128LE, | ||
toBigUInt128LECompatible, | ||
readBigUInt128LE, | ||
readBigUInt128LECompatible, | ||
computeScriptHash, | ||
@@ -143,3 +190,4 @@ hashCode, | ||
assertHexadecimal, | ||
isDeepEqual, | ||
generateTypeIdScript, | ||
}; |
// This module provides a ValueObject implementation for CKB related data | ||
// structures to allow seamless immutable.js integration. | ||
const { validators, normalizers, Reader } = require("ckb-js-toolkit"); | ||
const { validators, normalizers, Reader } = require("@ckb-lumos/toolkit"); | ||
const { xxHash32 } = require("js-xxhash"); | ||
@@ -5,0 +5,0 @@ const core = require("./core"); |
{ | ||
"name": "@ckb-lumos/base", | ||
"version": "0.18.0-rc4", | ||
"version": "0.18.0-rc5", | ||
"description": "Base data structures and utilities used in lumos", | ||
@@ -39,7 +39,13 @@ "author": "Xuejie Xiao <xxuejie@gmail.com>", | ||
"dependencies": { | ||
"@ckb-lumos/bi": "0.18.0-rc5", | ||
"@ckb-lumos/toolkit": "0.18.0-rc5", | ||
"@types/lodash.isequal": "^4.5.5", | ||
"blake2b": "^2.1.3", | ||
"ckb-js-toolkit": "^0.100.0-rc1", | ||
"js-xxhash": "^1.0.4" | ||
"js-xxhash": "^1.0.4", | ||
"lodash.isequal": "^4.5.0" | ||
}, | ||
"gitHead": "42c93e1d61df6004d3aab6a2684c1f74ad6efebf" | ||
"peerDependencies": { | ||
"jsbi": "^4.1.0" | ||
}, | ||
"gitHead": "842d5853f8ac8ae6ae74b9c9fa1d99b8aa161b66" | ||
} |
94689
2759
7
+ Added@ckb-lumos/bi@0.18.0-rc5
+ Added@types/lodash.isequal@^4.5.5
+ Addedlodash.isequal@^4.5.0
+ Added@ckb-lumos/bi@0.18.0-rc5(transitive)
+ Added@ckb-lumos/toolkit@0.18.0-rc5(transitive)
+ Added@types/lodash@4.17.15(transitive)
+ Added@types/lodash.isequal@4.5.8(transitive)
+ Addedjsbi@4.3.0(transitive)
+ Addedlodash.isequal@4.5.0(transitive)
- Removedckb-js-toolkit@^0.100.0-rc1
- Removedckb-js-toolkit@0.100.0-rc1(transitive)
- Removedjsbi@3.2.5(transitive)