diff --git a/packages/store-indexer/src/postgres/createQueryAdapter.ts b/packages/store-indexer/src/postgres/createQueryAdapter.ts index 17600fca5d..02eba0a39e 100644 --- a/packages/store-indexer/src/postgres/createQueryAdapter.ts +++ b/packages/store-indexer/src/postgres/createQueryAdapter.ts @@ -13,11 +13,10 @@ import { getAddress } from "viem"; */ export async function createQueryAdapter(database: PgDatabase): Promise { const adapter: QueryAdapter = { - async findAll(chainId, address) { - const internalTables = buildInternalTables(); - const tables = (await getTables(database)).filter( - (table) => address != null && getAddress(address) === getAddress(table.address) - ); + async findAll({ chainId, address, tableIds = [] }) { + const tables = (await getTables(database)) + .filter((table) => address == null || getAddress(address) === getAddress(table.address)) + .filter((table) => !tableIds.length || tableIds.includes(table.tableId)); const tablesWithRecords = await Promise.all( tables.map(async (table) => { @@ -33,6 +32,7 @@ export async function createQueryAdapter(database: PgDatabase): Promise): Promise { const adapter: QueryAdapter = { - async findAll(chainId, address) { - const tables = getTables(database).filter((table) => table.address === address); + async findAll({ chainId, address, tableIds = [] }) { + const tables = getTables(database) + .filter((table) => address == null || getAddress(address) === getAddress(table.address)) + .filter((table) => !tableIds.length || tableIds.includes(table.tableId)); const tablesWithRecords = tables.map((table) => { const sqliteTable = buildTable(table); diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index 56211edb3d..cde25daf0d 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -41,6 +41,10 @@ export type SyncOptions = { * MUD Store/World contract address */ address?: Address; + /** + * Optional table IDs to filter indexer state and RPC state. + */ + tableIds?: Hex[]; /** * Optional block number to start indexing from. Useful for resuming the indexer from a particular point in time or starting after a particular contract deployment. */ diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index 4bdd9a6996..858316e059 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -32,6 +32,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"; const debug = parentDebug.extend("createStoreSync"); @@ -49,13 +50,15 @@ type CreateStoreSyncOptions = SyncOpt export async function createStoreSync({ storageAdapter, onProgress, - address, publicClient, + address, + tableIds = [], startBlock: initialStartBlock = 0n, maxBlockRange, initialState, indexerUrl, }: CreateStoreSyncOptions): Promise { + const includedTableIds = new Set(tableIds.length ? [...internalTableIds, ...tableIds] : []); const initialState$ = defer( async (): Promise< | { @@ -79,7 +82,7 @@ export async function createStoreSync const indexer = createIndexerClient({ url: indexerUrl }); const chainId = publicClient.chain?.id ?? (await publicClient.getChainId()); - const result = await indexer.findAll.query({ chainId, address }); + const result = await indexer.findAll.query({ chainId, address, tableIds: Array.from(includedTableIds) }); onProgress?.({ step: SyncStep.SNAPSHOT, diff --git a/packages/store-sync/src/index.ts b/packages/store-sync/src/index.ts index 2e0771488d..d974a10a67 100644 --- a/packages/store-sync/src/index.ts +++ b/packages/store-sync/src/index.ts @@ -1,3 +1,4 @@ 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 new file mode 100644 index 0000000000..d78bbf4807 --- /dev/null +++ b/packages/store-sync/src/internalTableIds.ts @@ -0,0 +1,23 @@ +import { resourceIdToHex } 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) => + resourceIdToHex({ + type: storeConfig.tables[name as keyof typeof storeConfig.tables].offchainOnly ? "offchainTable" : "table", + namespace: storeConfig.namespace, + name, + }) +); + +const worldTableIds = Object.keys(worldConfig.tables).map((name) => + resourceIdToHex({ + 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/trpc-indexer/common.ts b/packages/store-sync/src/trpc-indexer/common.ts index c9ca712880..dc5d7005f4 100644 --- a/packages/store-sync/src/trpc-indexer/common.ts +++ b/packages/store-sync/src/trpc-indexer/common.ts @@ -2,10 +2,7 @@ import { Hex } from "viem"; import { TableWithRecords } from "../common"; export type QueryAdapter = { - findAll: ( - chainId: number, - address?: Hex - ) => Promise<{ + findAll: (opts: { chainId: number; address?: Hex; tableIds?: Hex[] }) => Promise<{ blockNumber: bigint | null; tables: TableWithRecords[]; }>; diff --git a/packages/store-sync/src/trpc-indexer/createAppRouter.ts b/packages/store-sync/src/trpc-indexer/createAppRouter.ts index c965dac7c5..71a4fae085 100644 --- a/packages/store-sync/src/trpc-indexer/createAppRouter.ts +++ b/packages/store-sync/src/trpc-indexer/createAppRouter.ts @@ -16,12 +16,13 @@ export function createAppRouter() { z.object({ chainId: z.number(), address: z.string().refine(isHex).optional(), + tableIds: z.array(z.string().refine(isHex)).optional(), }) ) .query(async (opts): ReturnType => { const { queryAdapter } = opts.ctx; - const { chainId, address } = opts.input; - return queryAdapter.findAll(chainId, address); + const { chainId, address, tableIds } = opts.input; + return queryAdapter.findAll({ chainId, address, tableIds }); }), }); }