UNPKG

@iden3/js-merkletree

Version:

javascript sparse merkle tree library

77 lines (63 loc) 2.4 kB
/* eslint-disable no-case-declarations */ import { Bytes, Node } from '../../types'; import { ITreeStorage } from '../../types/storage'; import { Hash, ZERO_HASH } from '../hash/hash'; import { NODE_TYPE_EMPTY, NODE_TYPE_LEAF, NODE_TYPE_MIDDLE } from '../../constants'; import { NodeEmpty, NodeLeaf, NodeMiddle } from '../node/node'; import { bytes2Hex } from '../utils'; export class LocalStorageDB implements ITreeStorage { private _currentRoot: Hash; constructor(private readonly _prefix: Bytes) { const rootStr = localStorage.getItem(bytes2Hex(_prefix)); if (rootStr) { const bytes: number[] = JSON.parse(rootStr); this._currentRoot = new Hash(Uint8Array.from(bytes)); } else { this._currentRoot = ZERO_HASH; } } async get(k: Bytes): Promise<Node | undefined> { const kBytes = new Uint8Array([...this._prefix, ...k]); const key = bytes2Hex(kBytes); const val = localStorage.getItem(key); if (val === null) { return undefined; } const obj = JSON.parse(val); switch (obj.type) { case NODE_TYPE_EMPTY: return new NodeEmpty(); case NODE_TYPE_MIDDLE: const cL = new Hash(Uint8Array.from(obj.childL)); const cR = new Hash(Uint8Array.from(obj.childR)); return new NodeMiddle(cL, cR); case NODE_TYPE_LEAF: const k = new Hash(Uint8Array.from(obj.entry[0])); const v = new Hash(Uint8Array.from(obj.entry[1])); return new NodeLeaf(k, v); } throw `error: value found for key ${bytes2Hex(kBytes)} is not of type Node`; } async put(k: Bytes, n: Node): Promise<void> { const kBytes = new Uint8Array([...this._prefix, ...k]); const key = bytes2Hex(kBytes); const toSerialize: Record<string, unknown> = { type: n.type }; if (n instanceof NodeMiddle) { toSerialize.childL = Array.from(n.childL.bytes); toSerialize.childR = Array.from(n.childR.bytes); } else if (n instanceof NodeLeaf) { toSerialize.entry = [Array.from(n.entry[0].bytes), Array.from(n.entry[1].bytes)]; } const val = JSON.stringify(toSerialize); localStorage.setItem(key, val); } async getRoot(): Promise<Hash> { return this._currentRoot; } async setRoot(r: Hash): Promise<void> { this._currentRoot = r; localStorage.setItem(bytes2Hex(this._prefix), JSON.stringify(Array.from(r.bytes))); } }