From 1b477d476a666ccffafc6eb266d1732b90bc28f9 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 8 Jan 2025 07:40:34 -0800 Subject: [PATCH] feat(store): add getRecord and getStaticDataLocation helpers (#3430) --- .changeset/sharp-lions-cover.md | 5 ++ packages/protocol-parser/src/getKeyTuple.ts | 2 +- packages/store/ts/exports/internal.ts | 2 + packages/store/ts/getRecord.ts | 78 +++++++++++++++++++++ packages/store/ts/getStaticDataLocation.ts | 10 +++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 .changeset/sharp-lions-cover.md create mode 100644 packages/store/ts/getRecord.ts create mode 100644 packages/store/ts/getStaticDataLocation.ts diff --git a/.changeset/sharp-lions-cover.md b/.changeset/sharp-lions-cover.md new file mode 100644 index 0000000000..e94ead112b --- /dev/null +++ b/.changeset/sharp-lions-cover.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store": patch +--- + +Added internal `getRecord` and `getStaticDataLocation` helpers. diff --git a/packages/protocol-parser/src/getKeyTuple.ts b/packages/protocol-parser/src/getKeyTuple.ts index 17c6ab0237..b368ae6330 100644 --- a/packages/protocol-parser/src/getKeyTuple.ts +++ b/packages/protocol-parser/src/getKeyTuple.ts @@ -7,7 +7,7 @@ type PartialTable = Pick; export type getKeyTuple = { [i in keyof key]: Hex; -}; +} & unknown; export function getKeyTuple( table: table, diff --git a/packages/store/ts/exports/internal.ts b/packages/store/ts/exports/internal.ts index 0765dc8d68..0ae3f3cc9a 100644 --- a/packages/store/ts/exports/internal.ts +++ b/packages/store/ts/exports/internal.ts @@ -2,6 +2,8 @@ export * from "../common"; export * from "../getStoreLogs"; export * from "../flattenStoreLogs"; export * from "../logToRecord"; +export * from "../getRecord"; +export * from "../getStaticDataLocation"; export * from "../config/v2/codegen"; export * from "../config/v2/defaults"; diff --git a/packages/store/ts/getRecord.ts b/packages/store/ts/getRecord.ts new file mode 100644 index 0000000000..56b17ba3d9 --- /dev/null +++ b/packages/store/ts/getRecord.ts @@ -0,0 +1,78 @@ +import { Address, Client, Hex } from "viem"; +import { Table } from "@latticexyz/config"; +import { + decodeValueArgs, + getKeySchema, + getKeyTuple, + getSchemaPrimitives, + getSchemaTypes, + getValueSchema, +} from "@latticexyz/protocol-parser/internal"; +import { readContract } from "viem/actions"; +import { getAction } from "viem/utils"; + +export type GetRecordOptions
= { + address: Address; + table: table; + key: getSchemaPrimitives>; + blockTag?: "latest" | "pending"; +}; + +export async function getRecord
( + client: Client, + { address, table, key, blockTag }: GetRecordOptions
, +): Promise> { + const [staticData, encodedLengths, dynamicData] = await getAction( + client, + readContract, + "readContract", + )({ + address, + abi, + functionName: "getRecord", + args: [table.tableId, getKeyTuple(table, key) as readonly Hex[]], + blockTag, + }); + + return { + ...key, + ...decodeValueArgs(getSchemaTypes(getValueSchema(table)), { staticData, encodedLengths, dynamicData }), + }; +} + +const abi = [ + { + type: "function", + name: "getRecord", + inputs: [ + { + name: "tableId", + type: "bytes32", + internalType: "ResourceId", + }, + { + name: "keyTuple", + type: "bytes32[]", + internalType: "bytes32[]", + }, + ], + outputs: [ + { + name: "staticData", + type: "bytes", + internalType: "bytes", + }, + { + name: "encodedLengths", + type: "bytes32", + internalType: "EncodedLengths", + }, + { + name: "dynamicData", + type: "bytes", + internalType: "bytes", + }, + ], + stateMutability: "view", + }, +] as const; diff --git a/packages/store/ts/getStaticDataLocation.ts b/packages/store/ts/getStaticDataLocation.ts new file mode 100644 index 0000000000..ad0f14771a --- /dev/null +++ b/packages/store/ts/getStaticDataLocation.ts @@ -0,0 +1,10 @@ +import { Hex, concatHex, hexToBigInt, keccak256, numberToHex, toBytes } from "viem"; + +// TODO: move to protocol-parser? +// equivalent of StoreCore._getStaticDataLocation + +const SLOT = hexToBigInt(keccak256(toBytes("mud.store"))); + +export function getStaticDataLocation(tableId: Hex, keyTuple: readonly Hex[]): Hex { + return numberToHex(SLOT ^ hexToBigInt(keccak256(concatHex([tableId, ...keyTuple]))), { size: 32 }); +}