From 712866f5fb392a4e39b59cd4565da61adc3c005f Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Sun, 12 Nov 2023 08:28:41 +0000 Subject: [PATCH] fix(store-sync): create table registration logs from indexer records (#1919) --- .changeset/khaki-months-add.md | 5 +++ packages/store-sync/src/common.ts | 4 +++ packages/store-sync/src/createStoreSync.ts | 35 ++++++++++++--------- packages/store-sync/src/index.ts | 1 - packages/store-sync/src/internalTableIds.ts | 23 -------------- packages/store-sync/src/logToTable.ts | 2 -- packages/store-sync/src/tableToLog.test.ts | 34 ++++++++++++++++++++ packages/store-sync/src/tableToLog.ts | 28 +++++++++++++++++ 8 files changed, 91 insertions(+), 41 deletions(-) create mode 100644 .changeset/khaki-months-add.md delete mode 100644 packages/store-sync/src/internalTableIds.ts create mode 100644 packages/store-sync/src/tableToLog.test.ts create mode 100644 packages/store-sync/src/tableToLog.ts diff --git a/.changeset/khaki-months-add.md b/.changeset/khaki-months-add.md new file mode 100644 index 0000000000..6fc17eed60 --- /dev/null +++ b/.changeset/khaki-months-add.md @@ -0,0 +1,5 @@ +--- +"@latticexyz/store-sync": patch +--- + +`createStoreSync` now correctly creates table registration logs from indexer records. diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index fa4989dca5..11418e2186 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -12,6 +12,10 @@ export const storeTables = resolveConfig(storeConfig).tables; /** @internal Temporary workaround until we redo our config parsing and can pull this directly from the config (https://github.com/latticexyz/mud/issues/1668) */ export const worldTables = resolveConfig(worldConfig).tables; +export const internalTableIds = [...Object.values(storeTables), ...Object.values(worldTables)].map( + (table) => table.tableId +); + export type ChainId = number; export type WorldId = `${ChainId}:${Address}`; diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index c8d926d23c..aa0f0bb874 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -1,5 +1,5 @@ import { StoreConfig, storeEventsAbi } from "@latticexyz/store"; -import { Hex, TransactionReceiptNotFoundError } from "viem"; +import { Hex, TransactionReceiptNotFoundError, encodeAbiParameters, parseAbiParameters } from "viem"; import { StorageAdapter, StorageAdapterBlock, @@ -8,6 +8,8 @@ import { SyncOptions, SyncResult, TableWithRecords, + internalTableIds, + storeTables, } from "./common"; import { createBlockStream, blockRangeToLogs, groupLogsByBlockNumber } from "@latticexyz/block-logs-stream"; import { @@ -33,7 +35,7 @@ import { createIndexerClient } from "./trpc-indexer"; import { SyncStep } from "./SyncStep"; import { chunk, isDefined } from "@latticexyz/common/utils"; import { encodeKey, encodeValueArgs } from "@latticexyz/protocol-parser"; -import { internalTableIds } from "./internalTableIds"; +import { tableToLog } from "./tableToLog"; const debug = parentDebug.extend("createStoreSync"); @@ -140,19 +142,22 @@ export async function createStoreSync message: "Hydrating from snapshot", }); - const logs: StorageAdapterLog[] = tables.flatMap((table) => - table.records.map( - (record): StorageAdapterLog => ({ - eventName: "Store_SetRecord", - address: table.address, - args: { - tableId: table.tableId, - keyTuple: encodeKey(table.keySchema, record.key), - ...encodeValueArgs(table.valueSchema, record.value), - }, - }) - ) - ); + const logs: StorageAdapterLog[] = [ + ...tables.map(tableToLog), + ...tables.flatMap((table) => + table.records.map( + (record): StorageAdapterLog => ({ + eventName: "Store_SetRecord", + address: table.address, + args: { + tableId: table.tableId, + keyTuple: encodeKey(table.keySchema, record.key), + ...encodeValueArgs(table.valueSchema, record.value), + }, + }) + ) + ), + ]; // Split snapshot operations into chunks so we can update the progress callback (and ultimately render visual progress for the user). // This isn't ideal if we want to e.g. batch load these into a DB in a single DB tx, but we'll take it. diff --git a/packages/store-sync/src/index.ts b/packages/store-sync/src/index.ts index d974a10a67..2e0771488d 100644 --- a/packages/store-sync/src/index.ts +++ b/packages/store-sync/src/index.ts @@ -1,4 +1,3 @@ export * from "./common"; export * from "./createStoreSync"; -export * from "./internalTableIds"; export * from "./SyncStep"; diff --git a/packages/store-sync/src/internalTableIds.ts b/packages/store-sync/src/internalTableIds.ts deleted file mode 100644 index af9e254e43..0000000000 --- a/packages/store-sync/src/internalTableIds.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { resourceToHex } from "@latticexyz/common"; -import storeConfig from "@latticexyz/store/mud.config"; -import worldConfig from "@latticexyz/world/mud.config"; - -// TODO: refactor config to include table IDs (https://github.com/latticexyz/mud/pull/1561) - -export const storeTableIds = Object.keys(storeConfig.tables).map((name) => - resourceToHex({ - type: storeConfig.tables[name as keyof typeof storeConfig.tables].offchainOnly ? "offchainTable" : "table", - namespace: storeConfig.namespace, - name, - }) -); - -const worldTableIds = Object.keys(worldConfig.tables).map((name) => - resourceToHex({ - type: worldConfig.tables[name as keyof typeof worldConfig.tables].offchainOnly ? "offchainTable" : "table", - namespace: worldConfig.namespace, - name, - }) -); - -export const internalTableIds = [...storeTableIds, ...worldTableIds]; diff --git a/packages/store-sync/src/logToTable.ts b/packages/store-sync/src/logToTable.ts index 362329f684..0572c6f3f0 100644 --- a/packages/store-sync/src/logToTable.ts +++ b/packages/store-sync/src/logToTable.ts @@ -3,8 +3,6 @@ import { Hex, concatHex, decodeAbiParameters, parseAbiParameters } from "viem"; import { StorageAdapterLog, Table, schemasTable } from "./common"; import { hexToResource } from "@latticexyz/common"; -// TODO: add tableToLog - export function logToTable(log: StorageAdapterLog & { eventName: "Store_SetRecord" }): Table { const [tableId, ...otherKeys] = log.args.keyTuple; if (otherKeys.length) { diff --git a/packages/store-sync/src/tableToLog.test.ts b/packages/store-sync/src/tableToLog.test.ts new file mode 100644 index 0000000000..0b58c4c45a --- /dev/null +++ b/packages/store-sync/src/tableToLog.test.ts @@ -0,0 +1,34 @@ +/* eslint-disable max-len */ +import { describe, it, expect } from "vitest"; +import { tableToLog } from "./tableToLog"; +import { storeTables } from "./common"; +import { flattenSchema } from "./flattenSchema"; + +describe("tableToLog", () => { + it("should convert a table object to table registration log", async () => { + expect( + tableToLog({ + address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + tableId: storeTables.Tables.tableId, + namespace: storeTables.Tables.namespace, + name: storeTables.Tables.name, + keySchema: flattenSchema(storeTables.Tables.keySchema), + valueSchema: flattenSchema(storeTables.Tables.valueSchema), + }) + ).toMatchInlineSnapshot(` + { + "address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + "args": { + "dynamicData": "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", + "encodedLengths": "0x000000000000000000000000000000000000022000000000a0000000000002c0", + "keyTuple": [ + "0x746273746f72650000000000000000005461626c657300000000000000000000", + ], + "staticData": "0x0060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c40000000000000000000000000000000000000000000000", + "tableId": "0x746273746f72650000000000000000005461626c657300000000000000000000", + }, + "eventName": "Store_SetRecord", + } + `); + }); +}); diff --git a/packages/store-sync/src/tableToLog.ts b/packages/store-sync/src/tableToLog.ts new file mode 100644 index 0000000000..67e13f4b4b --- /dev/null +++ b/packages/store-sync/src/tableToLog.ts @@ -0,0 +1,28 @@ +import { + encodeKey, + encodeValueArgs, + keySchemaToHex, + valueSchemaToFieldLayoutHex, + valueSchemaToHex, +} from "@latticexyz/protocol-parser"; +import { encodeAbiParameters, parseAbiParameters } from "viem"; +import { StorageAdapterLog, Table, storeTables } from "./common"; +import { flattenSchema } from "./flattenSchema"; + +export function tableToLog(table: Table): StorageAdapterLog & { eventName: "Store_SetRecord" } { + return { + eventName: "Store_SetRecord", + address: table.address, + args: { + tableId: storeTables.Tables.tableId, + keyTuple: encodeKey(flattenSchema(storeTables.Tables.keySchema), { tableId: table.tableId }), + ...encodeValueArgs(flattenSchema(storeTables.Tables.valueSchema), { + fieldLayout: valueSchemaToFieldLayoutHex(table.valueSchema), + keySchema: keySchemaToHex(table.keySchema), + valueSchema: valueSchemaToHex(table.valueSchema), + abiEncodedKeyNames: encodeAbiParameters(parseAbiParameters("string[]"), [Object.keys(table.keySchema)]), + abiEncodedFieldNames: encodeAbiParameters(parseAbiParameters("string[]"), [Object.keys(table.valueSchema)]), + }), + }, + }; +}