function hexToWord(hex, WordClass) {
if (!hex || !WordClass) return undefined;
try {
return WordClass.fromHex(hex);
} catch {
return undefined;
}
}
export class StorageView {
#storage;
#WordClass;
constructor(wasmStorage, WordClass) {
this.#storage = wasmStorage;
this.#WordClass = WordClass;
}
get raw() {
return this.#storage;
}
commitment() {
return this.#storage.commitment();
}
getSlotNames() {
return this.#storage.getSlotNames();
}
getItem(slotName) {
const rawEntries = this.#storage.getMapEntries(slotName);
if (rawEntries !== undefined && rawEntries !== null) {
const firstWord =
rawEntries.length > 0
? hexToWord(rawEntries[0].value, this.#WordClass)
: undefined;
return new StorageResult(firstWord, true, rawEntries, this.#WordClass);
}
const word = this.#storage.getItem(slotName);
if (!word) return undefined;
return new StorageResult(word, false, undefined, this.#WordClass);
}
getMapItem(slotName, key) {
return this.#storage.getMapItem(slotName, key);
}
getMapEntries(slotName) {
return this.#storage.getMapEntries(slotName);
}
getCommitment(slotName) {
return this.#storage.getItem(slotName);
}
}
export class StorageResult {
#word;
#isMap;
#rawEntries; #parsedEntries; #WordClass;
constructor(word, isMap, rawEntries, WordClass) {
this.#word = word;
this.#isMap = isMap;
this.#rawEntries = rawEntries;
this.#WordClass = WordClass;
}
get isMap() {
return this.#isMap;
}
get entries() {
if (!this.#isMap) return undefined;
if (this.#parsedEntries) return this.#parsedEntries;
if (!this.#rawEntries) return [];
this.#parsedEntries = this.#rawEntries.map((e) => ({
key: e.key,
value: e.value,
word: hexToWord(e.value, this.#WordClass),
}));
this.#rawEntries = undefined; return this.#parsedEntries;
}
get word() {
return this.#word;
}
toFelts() {
if (!this.#word) return [];
return this.#word.toFelts();
}
felt() {
if (!this.#word) return undefined;
const felts = this.#word.toFelts();
return felts?.[0];
}
toBigInt() {
if (!this.#word) return 0n;
return wordToBigInt(this.#word);
}
toHex() {
if (!this.#word) return "0x" + "0".repeat(64);
return this.#word.toHex();
}
toString() {
return this.toBigInt().toString();
}
toJSON() {
return this.toBigInt().toString();
}
valueOf() {
const big = this.toBigInt();
if (big > BigInt(Number.MAX_SAFE_INTEGER)) {
throw new RangeError(
`StorageResult value ${big} exceeds Number.MAX_SAFE_INTEGER ` +
`(${Number.MAX_SAFE_INTEGER}) — use .toBigInt() to read the exact value.`
);
}
return Number(big);
}
}
export function wordToBigInt(word) {
try {
const hex = word.toHex();
const feltHex = hex.slice(2, 18);
const bytes = feltHex.match(/../g);
if (!bytes) return 0n;
return BigInt("0x" + bytes.reverse().join(""));
} catch {
return 0n;
}
}
export function installStorageView(wasmModule) {
const AccountProto = wasmModule.Account?.prototype;
if (!AccountProto || !AccountProto.storage) return;
const originalStorage = AccountProto.storage;
const WordClass = wasmModule.Word;
AccountProto.storage = function () {
const raw = originalStorage.call(this);
return new StorageView(raw, WordClass);
};
}