UNPKG

@velas/account-agent

Version:

sdk

121 lines (104 loc) 2.96 kB
import { serialize, BinaryReader, BorshError } from 'borsh'; // Class wrapping a plain object export class Assignable { constructor(properties) { Object.keys(properties).forEach((key) => { this[key] = properties[key]; }); } encode() { return Buffer.from(serialize(SCHEMA, this)); } static decode(data) { return deserializeExtraBytes(SCHEMA, this, data); } } // Class representing a Rust-compatible enum, since enums are only strings or // numbers in pure JS export class Enum extends Assignable { constructor(properties) { super(properties); if (Object.keys(properties).length !== 1) { throw new Error('Enum can only take single value'); } this.enum = ''; Object.keys(properties).forEach(key => { this.enum = key; }); } } export const SCHEMA = new Map(); // TODO PR for leaving extra bytes, a lot of code copied from // https://github.com/near/borsh-js/blob/master/borsh-ts/index.ts function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); } 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]); } return reader.readArray(() => deserializeField(schema, fieldName, fieldType[0], reader) ); } return deserializeStruct(schema, fieldType, reader); } catch (error) { if (error instanceof BorshError) { error.addToFieldPath(fieldName); } throw error; } } function deserializeStruct( schema, classType, 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. export function deserializeExtraBytes( schema, classType, buffer ){ const reader = new BinaryReader(buffer); return deserializeStruct(schema, classType, reader); }