@ton/core
Version:
Core TypeScript library that implements low level primitives for TON blockchain.
208 lines (207 loc) • 6.45 kB
JavaScript
"use strict";
/**
* Copyright (c) Whales Corp.
* All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cell = void 0;
const symbol_inspect_1 = __importDefault(require("symbol.inspect"));
const BitString_1 = require("./BitString");
const CellType_1 = require("./CellType");
const Slice_1 = require("./Slice");
const resolveExotic_1 = require("./cell/resolveExotic");
const wonderCalculator_1 = require("./cell/wonderCalculator");
const serialization_1 = require("./cell/serialization");
const BitReader_1 = require("./BitReader");
const Builder_1 = require("./Builder");
/**
* Cell as described in TVM spec
*/
class Cell {
/**
* Deserialize cells from BOC
* @param src source buffer
* @returns array of cells
*/
static fromBoc(src) {
return (0, serialization_1.deserializeBoc)(src);
}
/**
* Helper class that deserializes a single cell from BOC in base64
* @param src source string
*/
static fromBase64(src) {
let parsed = Cell.fromBoc(Buffer.from(src, 'base64'));
if (parsed.length !== 1) {
throw new Error("Deserialized more than one cell");
}
return parsed[0];
}
constructor(opts) {
// Level and depth information
this._hashes = [];
this._depths = [];
/**
* Beging cell parsing
* @returns a new slice
*/
this.beginParse = (allowExotic = false) => {
if (this.isExotic && !allowExotic) {
throw new Error("Exotic cells cannot be parsed");
}
return new Slice_1.Slice(new BitReader_1.BitReader(this.bits), this.refs);
};
/**
* Get cell hash
* @param level level
* @returns cell hash
*/
this.hash = (level = 3) => {
return this._hashes[Math.min(this._hashes.length - 1, level)];
};
/**
* Get cell depth
* @param level level
* @returns cell depth
*/
this.depth = (level = 3) => {
return this._depths[Math.min(this._depths.length - 1, level)];
};
/**
* Get cell level
* @returns cell level
*/
this.level = () => {
return this.mask.level;
};
/**
* Checks cell to be euqal to another cell
* @param other other cell
* @returns true if cells are equal
*/
this.equals = (other) => {
return this.hash().equals(other.hash());
};
this[_a] = () => this.toString();
// Resolve bits
let bits = BitString_1.BitString.EMPTY;
if (opts && opts.bits) {
bits = opts.bits;
}
// Resolve refs
let refs = [];
if (opts && opts.refs) {
refs = [...opts.refs];
}
// Resolve type
let hashes;
let depths;
let mask;
let type = CellType_1.CellType.Ordinary;
if (opts && opts.exotic) {
// Resolve exotic cell
let resolved = (0, resolveExotic_1.resolveExotic)(bits, refs);
// Perform wonders
let wonders = (0, wonderCalculator_1.wonderCalculator)(resolved.type, bits, refs);
// Copy results
mask = wonders.mask;
depths = wonders.depths;
hashes = wonders.hashes;
type = resolved.type;
}
else {
// Check correctness
if (refs.length > 4) {
throw new Error("Invalid number of references");
}
if (bits.length > 1023) {
throw new Error(`Bits overflow: ${bits.length} > 1023`);
}
// Perform wonders
let wonders = (0, wonderCalculator_1.wonderCalculator)(CellType_1.CellType.Ordinary, bits, refs);
// Copy results
mask = wonders.mask;
depths = wonders.depths;
hashes = wonders.hashes;
type = CellType_1.CellType.Ordinary;
}
// Set fields
this.type = type;
this.bits = bits;
this.refs = refs;
this.mask = mask;
this._depths = depths;
this._hashes = hashes;
Object.freeze(this);
Object.freeze(this.refs);
Object.freeze(this.bits);
Object.freeze(this.mask);
Object.freeze(this._depths);
Object.freeze(this._hashes);
}
/**
* Check if cell is exotic
*/
get isExotic() {
return this.type !== CellType_1.CellType.Ordinary;
}
/**
* Serializes cell to BOC
* @param opts options
*/
toBoc(opts) {
let idx = (opts && opts.idx !== null && opts.idx !== undefined) ? opts.idx : false;
let crc32 = (opts && opts.crc32 !== null && opts.crc32 !== undefined) ? opts.crc32 : true;
return (0, serialization_1.serializeBoc)(this, { idx, crc32 });
}
/**
* Format cell to string
* @param indent indentation
* @returns string representation
*/
toString(indent) {
let id = indent || '';
let t = 'x';
if (this.isExotic) {
if (this.type === CellType_1.CellType.MerkleProof) {
t = 'p';
}
else if (this.type === CellType_1.CellType.MerkleUpdate) {
t = 'u';
}
else if (this.type === CellType_1.CellType.PrunedBranch) {
t = 'p';
}
}
let s = id + (this.isExotic ? t : 'x') + '{' + this.bits.toString() + '}';
for (let k in this.refs) {
const i = this.refs[k];
s += '\n' + i.toString(id + ' ');
}
return s;
}
/**
* Covnert cell to slice
* @returns slice
*/
asSlice() {
return this.beginParse();
}
/**
* Convert cell to a builder that has this cell stored
* @returns builder
*/
asBuilder() {
return (0, Builder_1.beginCell)().storeSlice(this.asSlice());
}
}
exports.Cell = Cell;
_a = symbol_inspect_1.default;
Cell.EMPTY = new Cell();