UNPKG

@mavrykdynamics/taquito-michel-codec

Version:

Michelson parser/validator/formatter

322 lines (321 loc) 10.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hexBytes = exports.parseHex = exports.parseDate = exports.isPairData = exports.isPairType = exports.unpackComb = exports.encodeMavrykID = exports.checkDecodeMavrykID = exports.mavrykPrefix = exports.unpackAnnotations = exports.isNatural = exports.isDecimal = exports.compareBytes = exports.parseBytes = exports.LongInteger = exports.MichelsonTypeError = exports.isMichelsonError = exports.MichelsonError = void 0; const base58_1 = require("./base58"); const errors_1 = require("./errors"); const taquito_core_1 = require("@mavrykdynamics/taquito-core"); /** * @category Error * @description Error that indicates a Michelson failure occurring */ class MichelsonError extends taquito_core_1.TaquitoError { /** * @param val Value of a AST node caused the error * @param path Path to a node caused the error * @param message An error message */ constructor(val, message) { super(); this.val = val; this.message = message; this.name = 'MichelsonError'; } } exports.MichelsonError = MichelsonError; function isMichelsonError(err) { return err instanceof MichelsonError; } exports.isMichelsonError = isMichelsonError; class MichelsonTypeError extends MichelsonError { /** * @param val Value of a type node caused the error * @param data Value of a data node caused the error * @param message An error message */ constructor(val, message, data) { super(val, message); this.val = val; this.message = message; this.name = 'MichelsonTypeError'; if (data !== undefined) { this.data = data; } } } exports.MichelsonTypeError = MichelsonTypeError; // Ad hoc big integer parser class LongInteger { append(c) { let i = 0; while (c !== 0 || i < this.buf.length) { const m = (this.buf[i] || 0) * 10 + c; this.buf[i++] = m % 256; c = Math.floor(m / 256); } } constructor(arg) { this.neg = false; this.buf = []; if (arg === undefined) { return; } if (typeof arg === 'string') { for (let i = 0; i < arg.length; i++) { const c = arg.charCodeAt(i); if (i === 0 && c === 0x2d) { this.neg = true; } else { if (c < 0x30 || c > 0x39) { throw new errors_1.LongIntegerError(`unexpected character in integer constant "${arg[i]}"`); } this.append(c - 0x30); } } } else if (arg < 0) { this.neg = true; this.append(-arg); } else { this.append(arg); } } cmp(arg) { if (this.neg !== arg.neg) { return (arg.neg ? 1 : 0) - (this.neg ? 1 : 0); } else { let ret = 0; if (this.buf.length !== arg.buf.length) { ret = this.buf.length < arg.buf.length ? -1 : 1; } else if (this.buf.length !== 0) { let i = arg.buf.length - 1; while (i >= 0 && this.buf[i] === arg.buf[i]) { i--; } ret = i < 0 ? 0 : this.buf[i] < arg.buf[i] ? -1 : 1; } return !this.neg ? ret : ret === 0 ? 0 : -ret; } } get sign() { return this.buf.length === 0 ? 0 : this.neg ? -1 : 1; } } exports.LongInteger = LongInteger; function parseBytes(s) { const ret = []; for (let i = 0; i < s.length; i += 2) { const x = parseInt(s.slice(i, i + 2), 16); if (Number.isNaN(x)) { return null; } ret.push(x); } return ret; } exports.parseBytes = parseBytes; function compareBytes(a, b) { if (a.length !== b.length) { return a.length < b.length ? -1 : 1; } else if (a.length !== 0) { let i = 0; while (i < a.length && a[i] === b[i]) { i++; } return i === a.length ? 0 : a[i] < b[i] ? -1 : 1; } else { return 0; } } exports.compareBytes = compareBytes; function isDecimal(x) { try { new LongInteger(x); return true; } catch (_a) { return false; } } exports.isDecimal = isDecimal; function isNatural(x) { try { return new LongInteger(x).sign >= 0; } catch (_a) { return false; } } exports.isNatural = isNatural; const annRe = /^(@%|@%%|%@|[@:%]([_0-9a-zA-Z][_0-9a-zA-Z.%@]*)?)$/; function unpackAnnotations(p, opt) { if (Array.isArray(p)) { return {}; } let field; let type; let vars; if (p.annots !== undefined) { for (const v of p.annots) { if (v.length !== 0) { if (!annRe.test(v) || (!(opt === null || opt === void 0 ? void 0 : opt.specialVar) && (v === '@%' || v === '@%%')) || (!(opt === null || opt === void 0 ? void 0 : opt.specialFields) && v === '%@')) { throw new MichelsonError(p, `${p.prim}: unexpected annotation: ${v}`); } switch (v[0]) { case '%': if ((opt === null || opt === void 0 ? void 0 : opt.emptyFields) || v.length > 1) { field = field || []; field.push(v); } break; case ':': if (v.length > 1) { type = type || []; type.push(v); } break; case '@': if ((opt === null || opt === void 0 ? void 0 : opt.emptyVar) || v.length > 1) { vars = vars || []; vars.push(v); } break; } } } } return { f: field, t: type, v: vars }; } exports.unpackAnnotations = unpackAnnotations; exports.mavrykPrefix = { BlockHash: [32, [1, 52]], OperationHash: [32, [5, 116]], OperationListHash: [32, [133, 233]], OperationListListHash: [32, [29, 159, 109]], ProtocolHash: [32, [2, 170]], ContextHash: [32, [79, 199]], ED25519PublicKeyHash: [20, [5, 186, 196]], SECP256K1PublicKeyHash: [20, [5, 186, 199]], P256PublicKeyHash: [20, [5, 186, 201]], ContractHash: [20, [2, 90, 121]], CryptoboxPublicKeyHash: [16, [153, 103]], ED25519Seed: [32, [13, 15, 58, 7]], ED25519PublicKey: [32, [13, 15, 37, 217]], SECP256K1SecretKey: [32, [17, 162, 224, 201]], P256SecretKey: [32, [16, 81, 238, 189]], ED25519EncryptedSeed: [56, [7, 90, 60, 179, 41]], SECP256K1EncryptedSecretKey: [56, [9, 237, 241, 174, 150]], P256EncryptedSecretKey: [56, [9, 48, 57, 115, 171]], SECP256K1PublicKey: [33, [3, 254, 226, 86]], P256PublicKey: [33, [3, 178, 139, 127]], SECP256K1Scalar: [33, [38, 248, 136]], SECP256K1Element: [33, [5, 92, 0]], ED25519SecretKey: [64, [43, 246, 78, 7]], ED25519Signature: [64, [9, 245, 205, 134, 18]], SECP256K1Signature: [64, [13, 115, 101, 19, 63]], P256Signature: [64, [54, 240, 44, 52]], GenericSignature: [64, [4, 130, 43]], ChainID: [4, [87, 82, 0]], RollupAddress: [20, [1, 128, 120, 31]], }; function checkDecodeMavrykID(id, ...types) { const buf = (0, base58_1.decodeBase58Check)(id); for (const t of types) { const [plen, p] = exports.mavrykPrefix[t]; if (buf.length === plen + p.length) { let i = 0; while (i < p.length && buf[i] === p[i]) { i++; } if (i === p.length) { return [t, buf.slice(p.length)]; } } } return null; } exports.checkDecodeMavrykID = checkDecodeMavrykID; function encodeMavrykID(id, data) { const [plen, p] = exports.mavrykPrefix[id]; if (data.length !== plen) { throw new errors_1.MavrykIdEncodeError(`Incorrect data length for ${id}: ${data.length}`); } return (0, base58_1.encodeBase58Check)([...p, ...data]); } exports.encodeMavrykID = encodeMavrykID; function unpackComb(id, v) { const vv = v; const args = Array.isArray(vv) ? vv : vv.args; if (args.length === 2) { // it's a way to make a union of two interfaces not an interface with two independent properties of union types const ret = id === 'pair' ? { prim: 'pair', args, } : { prim: 'Pair', args, }; return ret; } return Object.assign(Object.assign({}, (Array.isArray(vv) ? { prim: id } : vv)), { args: [ args[0], { prim: id, args: args.slice(1), }, ] }); } exports.unpackComb = unpackComb; function isPairType(t) { return Array.isArray(t) || t.prim === 'pair'; } exports.isPairType = isPairType; function isPairData(d) { return Array.isArray(d) || ('prim' in d && d.prim === 'Pair'); } exports.isPairData = isPairData; const rfc3339Re = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])[T ]([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|[+-]([01][0-9]|2[0-3]):([0-5][0-9]))$/; function parseDate(a) { if ('string' in a) { if (isNatural(a.string)) { return new Date(parseInt(a.string, 10)); } else if (rfc3339Re.test(a.string)) { const x = new Date(a.string); if (!Number.isNaN(x.valueOf)) { return x; } } } else if (isDecimal(a.int)) { return new Date(parseInt(a.int, 10)); } return null; } exports.parseDate = parseDate; function parseHex(s) { const res = []; for (let i = 0; i < s.length; i += 2) { const ss = s.slice(i, i + 2); const x = parseInt(ss, 16); if (Number.isNaN(x)) { throw new errors_1.HexParseError(ss); } res.push(x); } return res; } exports.parseHex = parseHex; function hexBytes(bytes) { return bytes.map((x) => ((x >> 4) & 0xf).toString(16) + (x & 0xf).toString(16)).join(''); } exports.hexBytes = hexBytes;