js-moi-logic
Version:
Module to interact with MOI Logic Objects.
143 lines • 4.29 kB
JavaScript
import { blake2b } from "@noble/hashes/blake2b";
import BN from "bn.js";
import { encodeToString } from "js-moi-utils";
import { Polorizer } from "js-polo";
export class StorageKey {
value;
constructor(value) {
this.value = new BN(value);
}
hex() {
return encodeToString(this.toBuffer());
}
toBuffer() {
return this.value.toBuffer("be", 32);
}
}
/**
* AbstractAccessor class provides a base implementation of the Accessor interface.
*/
export class AbstractAccessor {
/**
* Calculates the sum256 hash of a Uint8Array using the blake2b algorithm.
* @param hash - The input Uint8Array to be hashed.
* @returns The calculated sum256 hash as a Uint8Array.
*/
sum256(hash) {
return blake2b(hash, { dkLen: 32 });
}
}
/**
* Represents a LengthAccessor class that extends the AbstractAccessor class.
*
* It generates slot hash for accessing the length of an Array/VArray or a Map.
*/
export class LengthAccessor extends AbstractAccessor {
access(hash) {
return hash;
}
}
/**
* Generates a slot hash for accessing the key of Map.
*/
export class PropertyAccessor extends AbstractAccessor {
key;
/**
* Creates a new instance of PropertyAccessor.
* @param key The label of the property.
*/
constructor(key) {
super();
this.key = this.sum256(this.polorize(key));
}
/**
* Polorizes the given key.
* @param key The key to polorize.
* @returns The polorized key as a bytes.
*/
polorize(key) {
const polorizer = new Polorizer();
switch (true) {
case typeof key === "string":
polorizer.polorizeString(key);
break;
case typeof key === "number":
if (Number.isInteger(key)) {
polorizer.polorizeInteger(key);
}
if (!Number.isInteger(key)) {
polorizer.polorizeFloat(key);
}
break;
case typeof key === "boolean":
polorizer.polorizeBool(key);
break;
case key instanceof Uint8Array:
case key instanceof Buffer:
polorizer.polorizeBytes(key);
break;
default:
throw new Error(`Unsupported type: ${typeof key}`);
}
return polorizer.bytes();
}
/**
* Accesses the property with the given hash and returns the resulting hash.
* @param hash The hash of the property.
* @returns The resulting hash after accessing the property.
*/
access(hash) {
const separator = Buffer.from(".");
const buffer = Buffer.concat([hash.toBuffer(), separator, this.key]);
return new StorageKey(this.sum256(buffer));
}
}
/**
* Represents an accessor for accessing elements in an array by index.
*/
export class ArrayIndexAccessor extends AbstractAccessor {
index;
/**
* Creates a new instance of ArrayIndexAccessor.
* @param index The index of the element to access.
*/
constructor(index) {
super();
this.index = index;
}
/**
* Generates a slot hash for accessing the element at the given index.
* @param hash The input hash.
* @returns The updated hash after accessing the element.
*/
access(hash) {
const bytes = this.sum256(hash.toBuffer());
const slot = new BN(bytes).add(new BN(this.index));
return new StorageKey(slot);
}
}
/**
* Represents an accessor for accessing fields of a class.
*/
export class ClassFieldAccessor extends AbstractAccessor {
index;
constructor(index) {
super();
this.index = index;
}
access(hash) {
let blob = hash.toBuffer();
blob = this.sum256(blob);
const bn = new BN(blob).add(new BN(this.index));
return new StorageKey(bn);
}
}
export function generateStorageKey(base, ...args) {
let slot = typeof base === "number" ? new StorageKey(base) : base;
const accessors = Array.isArray(args[0]) ? args[0] : args;
for (const accessor of accessors) {
slot = accessor.access(slot);
}
return slot;
}
//# sourceMappingURL=accessor.js.map