Spaces:
Sleeping
Sleeping
| ; | |
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | |
| if (k2 === undefined) k2 = k; | |
| Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | |
| }) : (function(o, m, k, k2) { | |
| if (k2 === undefined) k2 = k; | |
| o[k2] = m[k]; | |
| })); | |
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | |
| Object.defineProperty(o, "default", { enumerable: true, value: v }); | |
| }) : function(o, v) { | |
| o["default"] = v; | |
| }); | |
| var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | |
| var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; | |
| if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); | |
| else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; | |
| return c > 3 && r && Object.defineProperty(target, key, r), r; | |
| }; | |
| var __importStar = (this && this.__importStar) || function (mod) { | |
| if (mod && mod.__esModule) return mod; | |
| var result = {}; | |
| if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | |
| __setModuleDefault(result, mod); | |
| return result; | |
| }; | |
| var __importDefault = (this && this.__importDefault) || function (mod) { | |
| return (mod && mod.__esModule) ? mod : { "default": mod }; | |
| }; | |
| Object.defineProperty(exports, "__esModule", { value: true }); | |
| exports.deserializeUnchecked = exports.deserialize = exports.serialize = exports.BinaryReader = exports.BinaryWriter = exports.BorshError = exports.baseDecode = exports.baseEncode = void 0; | |
| const bn_js_1 = __importDefault(require("bn.js")); | |
| const bs58_1 = __importDefault(require("bs58")); | |
| // TODO: Make sure this polyfill not included when not required | |
| const encoding = __importStar(require("text-encoding-utf-8")); | |
| const ResolvedTextDecoder = typeof TextDecoder !== "function" ? encoding.TextDecoder : TextDecoder; | |
| const textDecoder = new ResolvedTextDecoder("utf-8", { fatal: true }); | |
| function baseEncode(value) { | |
| if (typeof value === "string") { | |
| value = Buffer.from(value, "utf8"); | |
| } | |
| return bs58_1.default.encode(Buffer.from(value)); | |
| } | |
| exports.baseEncode = baseEncode; | |
| function baseDecode(value) { | |
| return Buffer.from(bs58_1.default.decode(value)); | |
| } | |
| exports.baseDecode = baseDecode; | |
| const INITIAL_LENGTH = 1024; | |
| class BorshError extends Error { | |
| constructor(message) { | |
| super(message); | |
| this.fieldPath = []; | |
| this.originalMessage = message; | |
| } | |
| addToFieldPath(fieldName) { | |
| this.fieldPath.splice(0, 0, fieldName); | |
| // NOTE: Modifying message directly as jest doesn't use .toString() | |
| this.message = this.originalMessage + ": " + this.fieldPath.join("."); | |
| } | |
| } | |
| exports.BorshError = BorshError; | |
| /// Binary encoder. | |
| class BinaryWriter { | |
| constructor() { | |
| this.buf = Buffer.alloc(INITIAL_LENGTH); | |
| this.length = 0; | |
| } | |
| maybeResize() { | |
| if (this.buf.length < 16 + this.length) { | |
| this.buf = Buffer.concat([this.buf, Buffer.alloc(INITIAL_LENGTH)]); | |
| } | |
| } | |
| writeU8(value) { | |
| this.maybeResize(); | |
| this.buf.writeUInt8(value, this.length); | |
| this.length += 1; | |
| } | |
| writeU16(value) { | |
| this.maybeResize(); | |
| this.buf.writeUInt16LE(value, this.length); | |
| this.length += 2; | |
| } | |
| writeU32(value) { | |
| this.maybeResize(); | |
| this.buf.writeUInt32LE(value, this.length); | |
| this.length += 4; | |
| } | |
| writeU64(value) { | |
| this.maybeResize(); | |
| this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 8))); | |
| } | |
| writeU128(value) { | |
| this.maybeResize(); | |
| this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 16))); | |
| } | |
| writeU256(value) { | |
| this.maybeResize(); | |
| this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 32))); | |
| } | |
| writeU512(value) { | |
| this.maybeResize(); | |
| this.writeBuffer(Buffer.from(new bn_js_1.default(value).toArray("le", 64))); | |
| } | |
| writeBuffer(buffer) { | |
| // Buffer.from is needed as this.buf.subarray can return plain Uint8Array in browser | |
| this.buf = Buffer.concat([ | |
| Buffer.from(this.buf.subarray(0, this.length)), | |
| buffer, | |
| Buffer.alloc(INITIAL_LENGTH), | |
| ]); | |
| this.length += buffer.length; | |
| } | |
| writeString(str) { | |
| this.maybeResize(); | |
| const b = Buffer.from(str, "utf8"); | |
| this.writeU32(b.length); | |
| this.writeBuffer(b); | |
| } | |
| writeFixedArray(array) { | |
| this.writeBuffer(Buffer.from(array)); | |
| } | |
| writeArray(array, fn) { | |
| this.maybeResize(); | |
| this.writeU32(array.length); | |
| for (const elem of array) { | |
| this.maybeResize(); | |
| fn(elem); | |
| } | |
| } | |
| toArray() { | |
| return this.buf.subarray(0, this.length); | |
| } | |
| } | |
| exports.BinaryWriter = BinaryWriter; | |
| function handlingRangeError(target, propertyKey, propertyDescriptor) { | |
| const originalMethod = propertyDescriptor.value; | |
| propertyDescriptor.value = function (...args) { | |
| try { | |
| return originalMethod.apply(this, args); | |
| } | |
| catch (e) { | |
| if (e instanceof RangeError) { | |
| const code = e.code; | |
| if (["ERR_BUFFER_OUT_OF_BOUNDS", "ERR_OUT_OF_RANGE"].indexOf(code) >= 0) { | |
| throw new BorshError("Reached the end of buffer when deserializing"); | |
| } | |
| } | |
| throw e; | |
| } | |
| }; | |
| } | |
| class BinaryReader { | |
| constructor(buf) { | |
| this.buf = buf; | |
| this.offset = 0; | |
| } | |
| readU8() { | |
| const value = this.buf.readUInt8(this.offset); | |
| this.offset += 1; | |
| return value; | |
| } | |
| readU16() { | |
| const value = this.buf.readUInt16LE(this.offset); | |
| this.offset += 2; | |
| return value; | |
| } | |
| readU32() { | |
| const value = this.buf.readUInt32LE(this.offset); | |
| this.offset += 4; | |
| return value; | |
| } | |
| readU64() { | |
| const buf = this.readBuffer(8); | |
| return new bn_js_1.default(buf, "le"); | |
| } | |
| readU128() { | |
| const buf = this.readBuffer(16); | |
| return new bn_js_1.default(buf, "le"); | |
| } | |
| readU256() { | |
| const buf = this.readBuffer(32); | |
| return new bn_js_1.default(buf, "le"); | |
| } | |
| readU512() { | |
| const buf = this.readBuffer(64); | |
| return new bn_js_1.default(buf, "le"); | |
| } | |
| readBuffer(len) { | |
| if (this.offset + len > this.buf.length) { | |
| throw new BorshError(`Expected buffer length ${len} isn't within bounds`); | |
| } | |
| const result = this.buf.slice(this.offset, this.offset + len); | |
| this.offset += len; | |
| return result; | |
| } | |
| readString() { | |
| const len = this.readU32(); | |
| const buf = this.readBuffer(len); | |
| try { | |
| // NOTE: Using TextDecoder to fail on invalid UTF-8 | |
| return textDecoder.decode(buf); | |
| } | |
| catch (e) { | |
| throw new BorshError(`Error decoding UTF-8 string: ${e}`); | |
| } | |
| } | |
| readFixedArray(len) { | |
| return new Uint8Array(this.readBuffer(len)); | |
| } | |
| readArray(fn) { | |
| const len = this.readU32(); | |
| const result = Array(); | |
| for (let i = 0; i < len; ++i) { | |
| result.push(fn()); | |
| } | |
| return result; | |
| } | |
| } | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU8", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU16", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU32", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU64", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU128", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU256", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readU512", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readString", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readFixedArray", null); | |
| __decorate([ | |
| handlingRangeError | |
| ], BinaryReader.prototype, "readArray", null); | |
| exports.BinaryReader = BinaryReader; | |
| function capitalizeFirstLetter(string) { | |
| return string.charAt(0).toUpperCase() + string.slice(1); | |
| } | |
| function serializeField(schema, fieldName, value, fieldType, writer) { | |
| try { | |
| // TODO: Handle missing values properly (make sure they never result in just skipped write) | |
| if (typeof fieldType === "string") { | |
| writer[`write${capitalizeFirstLetter(fieldType)}`](value); | |
| } | |
| else if (fieldType instanceof Array) { | |
| if (typeof fieldType[0] === "number") { | |
| if (value.length !== fieldType[0]) { | |
| throw new BorshError(`Expecting byte array of length ${fieldType[0]}, but got ${value.length} bytes`); | |
| } | |
| writer.writeFixedArray(value); | |
| } | |
| else if (fieldType.length === 2 && typeof fieldType[1] === "number") { | |
| if (value.length !== fieldType[1]) { | |
| throw new BorshError(`Expecting byte array of length ${fieldType[1]}, but got ${value.length} bytes`); | |
| } | |
| for (let i = 0; i < fieldType[1]; i++) { | |
| serializeField(schema, null, value[i], fieldType[0], writer); | |
| } | |
| } | |
| else { | |
| writer.writeArray(value, (item) => { | |
| serializeField(schema, fieldName, item, fieldType[0], writer); | |
| }); | |
| } | |
| } | |
| else if (fieldType.kind !== undefined) { | |
| switch (fieldType.kind) { | |
| case "option": { | |
| if (value === null || value === undefined) { | |
| writer.writeU8(0); | |
| } | |
| else { | |
| writer.writeU8(1); | |
| serializeField(schema, fieldName, value, fieldType.type, writer); | |
| } | |
| break; | |
| } | |
| case "map": { | |
| writer.writeU32(value.size); | |
| value.forEach((val, key) => { | |
| serializeField(schema, fieldName, key, fieldType.key, writer); | |
| serializeField(schema, fieldName, val, fieldType.value, writer); | |
| }); | |
| break; | |
| } | |
| default: | |
| throw new BorshError(`FieldType ${fieldType} unrecognized`); | |
| } | |
| } | |
| else { | |
| serializeStruct(schema, value, writer); | |
| } | |
| } | |
| catch (error) { | |
| if (error instanceof BorshError) { | |
| error.addToFieldPath(fieldName); | |
| } | |
| throw error; | |
| } | |
| } | |
| function serializeStruct(schema, obj, writer) { | |
| if (typeof obj.borshSerialize === "function") { | |
| obj.borshSerialize(writer); | |
| return; | |
| } | |
| const structSchema = schema.get(obj.constructor); | |
| if (!structSchema) { | |
| throw new BorshError(`Class ${obj.constructor.name} is missing in schema`); | |
| } | |
| if (structSchema.kind === "struct") { | |
| structSchema.fields.map(([fieldName, fieldType]) => { | |
| serializeField(schema, fieldName, obj[fieldName], fieldType, writer); | |
| }); | |
| } | |
| else if (structSchema.kind === "enum") { | |
| const name = obj[structSchema.field]; | |
| for (let idx = 0; idx < structSchema.values.length; ++idx) { | |
| const [fieldName, fieldType] = structSchema.values[idx]; | |
| if (fieldName === name) { | |
| writer.writeU8(idx); | |
| serializeField(schema, fieldName, obj[fieldName], fieldType, writer); | |
| break; | |
| } | |
| } | |
| } | |
| else { | |
| throw new BorshError(`Unexpected schema kind: ${structSchema.kind} for ${obj.constructor.name}`); | |
| } | |
| } | |
| /// Serialize given object using schema of the form: | |
| /// { class_name -> [ [field_name, field_type], .. ], .. } | |
| function serialize(schema, obj, Writer = BinaryWriter) { | |
| const writer = new Writer(); | |
| serializeStruct(schema, obj, writer); | |
| return writer.toArray(); | |
| } | |
| exports.serialize = serialize; | |
| function deserializeField(schema, fieldName, fieldType, reader) { | |
| try { | |
| if (typeof fieldType === "string") { | |
| return reader[`read${capitalizeFirstLetter(fieldType)}`](); | |
| } | |
| if (fieldType instanceof Array) { | |
| if (typeof fieldType[0] === "number") { | |
| return reader.readFixedArray(fieldType[0]); | |
| } | |
| else if (typeof fieldType[1] === "number") { | |
| const arr = []; | |
| for (let i = 0; i < fieldType[1]; i++) { | |
| arr.push(deserializeField(schema, null, fieldType[0], reader)); | |
| } | |
| return arr; | |
| } | |
| else { | |
| return reader.readArray(() => deserializeField(schema, fieldName, fieldType[0], reader)); | |
| } | |
| } | |
| if (fieldType.kind === "option") { | |
| const option = reader.readU8(); | |
| if (option) { | |
| return deserializeField(schema, fieldName, fieldType.type, reader); | |
| } | |
| return undefined; | |
| } | |
| if (fieldType.kind === "map") { | |
| let map = new Map(); | |
| const length = reader.readU32(); | |
| for (let i = 0; i < length; i++) { | |
| const key = deserializeField(schema, fieldName, fieldType.key, reader); | |
| const val = deserializeField(schema, fieldName, fieldType.value, reader); | |
| map.set(key, val); | |
| } | |
| return map; | |
| } | |
| return deserializeStruct(schema, fieldType, reader); | |
| } | |
| catch (error) { | |
| if (error instanceof BorshError) { | |
| error.addToFieldPath(fieldName); | |
| } | |
| throw error; | |
| } | |
| } | |
| function deserializeStruct(schema, classType, reader) { | |
| if (typeof classType.borshDeserialize === "function") { | |
| return classType.borshDeserialize(reader); | |
| } | |
| const structSchema = schema.get(classType); | |
| if (!structSchema) { | |
| throw new BorshError(`Class ${classType.name} is missing in schema`); | |
| } | |
| if (structSchema.kind === "struct") { | |
| const result = {}; | |
| for (const [fieldName, fieldType] of schema.get(classType).fields) { | |
| result[fieldName] = deserializeField(schema, fieldName, fieldType, reader); | |
| } | |
| return new classType(result); | |
| } | |
| if (structSchema.kind === "enum") { | |
| const idx = reader.readU8(); | |
| if (idx >= structSchema.values.length) { | |
| throw new BorshError(`Enum index: ${idx} is out of range`); | |
| } | |
| const [fieldName, fieldType] = structSchema.values[idx]; | |
| const fieldValue = deserializeField(schema, fieldName, fieldType, reader); | |
| return new classType({ [fieldName]: fieldValue }); | |
| } | |
| throw new BorshError(`Unexpected schema kind: ${structSchema.kind} for ${classType.constructor.name}`); | |
| } | |
| /// Deserializes object from bytes using schema. | |
| function deserialize(schema, classType, buffer, Reader = BinaryReader) { | |
| const reader = new Reader(buffer); | |
| const result = deserializeStruct(schema, classType, reader); | |
| if (reader.offset < buffer.length) { | |
| throw new BorshError(`Unexpected ${buffer.length - reader.offset} bytes after deserialized data`); | |
| } | |
| return result; | |
| } | |
| exports.deserialize = deserialize; | |
| /// Deserializes object from bytes using schema, without checking the length read | |
| function deserializeUnchecked(schema, classType, buffer, Reader = BinaryReader) { | |
| const reader = new Reader(buffer); | |
| return deserializeStruct(schema, classType, reader); | |
| } | |
| exports.deserializeUnchecked = deserializeUnchecked; | |