@ickb/sdk
Version:
iCKB SDK built on top of CCC
58 lines • 1.83 kB
JavaScript
import { ccc, mol } from "@ckb-ccc/core";
import { max } from "@ickb/utils";
const N = 1024;
export const PoolSnapshot = mol.Codec.from({
encode: (bins) => {
if (bins.length !== N) {
throw new Error("Expected 1024 bins");
}
const bitsPerBin = computeBits(bins);
const buffer = new Uint8Array((bitsPerBin * N) >> 3);
let bitOffset = 0;
for (const count of bins) {
packBits(buffer, bitOffset, bitsPerBin, count);
bitOffset += bitsPerBin;
}
return buffer;
},
decode: (bufferLike) => {
const buffer = ccc.bytesFrom(bufferLike);
const bitsPerBin = (buffer.byteLength * 8) / N;
if (!Number.isInteger(bitsPerBin)) {
throw new Error("Invalid buffer length for 1024 bins");
}
const bins = new Array(N);
let bitOffset = 0;
for (let i = 0; i < N; i++) {
bins[i] = unpackBits(buffer, bitOffset, bitsPerBin);
bitOffset += bitsPerBin;
}
return bins;
},
});
function computeBits(bins) {
return Math.ceil(Math.log2(1 + max(1, ...bins)));
}
function packBits(buffer, bitOffset, width, value) {
let offset = bitOffset;
for (let i = 0; i < width; i++) {
const byteIndex = offset >> 3;
const bitInByte = offset % 8;
const bit = (value >> i) & 1;
buffer[byteIndex] |= bit << bitInByte;
offset++;
}
}
function unpackBits(buffer, bitOffset, width) {
let value = 0;
let offset = bitOffset;
for (let i = 0; i < width; i++) {
const byteIndex = offset >> 3;
const bitInByte = offset % 8;
const bit = (buffer[byteIndex] >> bitInByte) & 1;
value |= bit << i;
offset++;
}
return value;
}
//# sourceMappingURL=codec.js.map