From 252a1852dc76c8e3f923c4f066620278ca69c430 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 20 Mar 2024 19:16:16 +0000 Subject: [PATCH] feat: use new config (#2483) --- .changeset/yellow-bulldogs-boil.md | 11 + .../client-vanilla/src/mud/setupNetwork.ts | 8 +- e2e/packages/contracts/mud.config.ts | 34 ++- e2e/packages/sync-test/data/encodeTestData.ts | 5 +- .../sync-test/data/expectClientData.ts | 5 +- e2e/packages/sync-test/data/types.ts | 6 +- e2e/packages/sync-test/package.json | 1 + e2e/pnpm-lock.yaml | 3 + .../minimal/packages/contracts/mud.config.ts | 22 +- .../packages/contracts/mud.config.ts | 9 +- packages/cli/scripts/generate-test-tables.ts | 166 +++++++------ packages/cli/src/build.ts | 13 +- packages/cli/src/commands/build.ts | 5 +- packages/cli/src/commands/dev-contracts.ts | 7 +- packages/cli/src/commands/tablegen.ts | 4 +- packages/cli/src/commands/trace.ts | 9 +- packages/cli/src/commands/worldgen.ts | 13 +- packages/cli/src/deploy/common.ts | 6 +- packages/cli/src/runDeploy.ts | 8 +- .../src/codegen/render-solidity/common.ts | 18 +- packages/dev-tools/src/common.ts | 2 +- packages/dev-tools/src/mount.tsx | 6 +- packages/store-sync/src/common.ts | 11 +- packages/store-sync/src/createStoreSync.ts | 9 +- .../postgres-decoded/createStorageAdapter.ts | 6 +- .../src/postgres-decoded/syncToPostgres.ts | 8 +- .../src/postgres/createStorageAdapter.ts | 6 +- .../store-sync/src/postgres/syncToPostgres.ts | 8 +- .../query-cache/createStorageAdapter.test.ts | 3 +- .../store-sync/src/query-cache/getTables.ts | 28 --- .../src/query-cache/syncToQueryCache.ts | 3 +- .../query-cache/test/createHydratedStore.ts | 3 +- .../store-sync/src/recs/recsStorage.test.ts | 3 +- packages/store-sync/src/recs/recsStorage.ts | 5 +- packages/store-sync/src/recs/syncToRecs.ts | 14 +- .../store-sync/src/sqlite/sqliteStorage.ts | 6 +- .../store-sync/src/sqlite/syncToSqlite.ts | 8 +- packages/store-sync/src/zustand/index.ts | 1 - .../store-sync/src/zustand/logToTable.test.ts | 52 ---- packages/store-sync/src/zustand/logToTable.ts | 35 --- .../store-sync/src/zustand/syncToZustand.ts | 12 +- packages/store-sync/test/mockGame.ts | 8 +- packages/store/mud.config.ts | 38 +-- packages/store/ts/codegen/tablegen.ts | 6 +- .../store/ts/scripts/generate-test-tables.ts | 30 ++- packages/store/ts/scripts/tablegen.ts | 4 +- packages/world-modules/mud.config.ts | 222 ++++++++++-------- packages/world-modules/ts/scripts/tablegen.ts | 4 +- packages/world-modules/ts/scripts/worldgen.ts | 11 +- packages/world/mud.config.ts | 83 ++++--- packages/world/ts/config/v2/index.ts | 1 + .../world/ts/node/render-solidity/worldgen.ts | 7 +- .../world/ts/scripts/generate-test-tables.ts | 31 ++- ...ist-tables-from-store-and-world-configs.ts | 32 +-- packages/world/ts/scripts/tablegen.ts | 4 +- packages/world/ts/scripts/worldgen.ts | 11 +- .../phaser/packages/contracts/mud.config.ts | 10 +- .../packages/contracts/mud.config.ts | 10 +- templates/react/packages/client/src/App.tsx | 4 +- .../client/src/mud/createSystemCalls.ts | 10 +- .../react/packages/contracts/mud.config.ts | 8 +- .../contracts/src/codegen/tables/Tasks.sol | 126 +++++----- .../src/codegen/world/ITasksSystem.sol | 8 +- .../contracts/src/systems/TasksSystem.sol | 18 +- .../threejs/packages/contracts/mud.config.ts | 8 +- .../contracts/src/codegen/tables/Position.sol | 86 +++---- .../vanilla/packages/contracts/mud.config.ts | 10 +- test/mock-game-contracts/mud.config.ts | 63 +---- 68 files changed, 665 insertions(+), 770 deletions(-) create mode 100644 .changeset/yellow-bulldogs-boil.md delete mode 100644 packages/store-sync/src/query-cache/getTables.ts delete mode 100644 packages/store-sync/src/zustand/logToTable.test.ts delete mode 100644 packages/store-sync/src/zustand/logToTable.ts diff --git a/.changeset/yellow-bulldogs-boil.md b/.changeset/yellow-bulldogs-boil.md new file mode 100644 index 0000000000..cd53942b7c --- /dev/null +++ b/.changeset/yellow-bulldogs-boil.md @@ -0,0 +1,11 @@ +--- +"@latticexyz/cli": major +"@latticexyz/dev-tools": major +"@latticexyz/store-sync": major +"@latticexyz/store": major +"@latticexyz/world-modules": major +"@latticexyz/world": major +"create-mud": major +--- + +Migrated to new config format. diff --git a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts index 8b6fdea78e..ea404d4344 100644 --- a/e2e/packages/client-vanilla/src/mud/setupNetwork.ts +++ b/e2e/packages/client-vanilla/src/mud/setupNetwork.ts @@ -4,7 +4,7 @@ import { encodeEntity, syncToRecs } from "@latticexyz/store-sync/recs"; import { getNetworkConfig } from "./getNetworkConfig"; import { world } from "./world"; import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; -import { createBurnerAccount, getContract, resourceToHex, transportObserver } from "@latticexyz/common"; +import { createBurnerAccount, getContract, transportObserver } from "@latticexyz/common"; import mudConfig from "contracts/mud.config"; export type SetupNetworkResult = Awaited>; @@ -40,11 +40,7 @@ export async function setupNetwork() { startBlock: BigInt(networkConfig.initialBlockNumber), indexerUrl: networkConfig.indexerUrl ?? undefined, filters: Object.entries(mudConfig.tables).map(([, table]) => { - const tableId = resourceToHex({ - type: table.offchainOnly ? "offchainTable" : "table", - namespace: mudConfig.namespace, - name: table.name, - }); + const tableId = table.tableId; if (table.name === mudConfig.tables.Position.name) { return { tableId, diff --git a/e2e/packages/contracts/mud.config.ts b/e2e/packages/contracts/mud.config.ts index 8ef93cf956..d82882c295 100644 --- a/e2e/packages/contracts/mud.config.ts +++ b/e2e/packages/contracts/mud.config.ts @@ -1,55 +1,53 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ tables: { Number: { - keySchema: { + schema: { key: "uint32", - }, - valueSchema: { value: "uint32", }, + key: ["key"], }, Vector: { - keySchema: { + schema: { key: "uint32", - }, - valueSchema: { x: "int32", y: "int32", }, + key: ["key"], }, NumberList: { - keySchema: {}, - valueSchema: { + schema: { value: "uint32[]", }, + key: [], }, Multi: { - keySchema: { + schema: { a: "uint32", b: "bool", c: "uint256", d: "int120", - }, - valueSchema: { num: "int256", value: "bool", }, + key: ["a", "b", "c", "d"], }, Position: { - keySchema: { + schema: { zone: "bytes32", x: "int32", y: "int32", - }, - valueSchema: { player: "address", }, + key: ["zone", "x", "y"], }, StaticArray: { - keySchema: {}, - valueSchema: "uint256[3]", + schema: { + value: "uint256[3]", + }, + key: [], }, }, }); diff --git a/e2e/packages/sync-test/data/encodeTestData.ts b/e2e/packages/sync-test/data/encodeTestData.ts index 1ff78b6cb5..58bf05ce88 100644 --- a/e2e/packages/sync-test/data/encodeTestData.ts +++ b/e2e/packages/sync-test/data/encodeTestData.ts @@ -1,7 +1,10 @@ import { mapObject } from "@latticexyz/utils"; import { encodeKey, encodeValueArgs, valueSchemaToFieldLayoutHex } from "@latticexyz/protocol-parser/internal"; import { Data, EncodedData } from "./types"; -import config from "../../contracts/mud.config"; +import configV2 from "../../contracts/mud.config"; +import { worldToV1 } from "@latticexyz/world/config/v2"; + +const config = worldToV1(configV2); /** * Turns the typed data into encoded data in the format expected by `world.setRecord` diff --git a/e2e/packages/sync-test/data/expectClientData.ts b/e2e/packages/sync-test/data/expectClientData.ts index e2861f15cd..4ecc181ae2 100644 --- a/e2e/packages/sync-test/data/expectClientData.ts +++ b/e2e/packages/sync-test/data/expectClientData.ts @@ -1,8 +1,11 @@ import { Page, expect } from "@playwright/test"; import { Data } from "./types"; -import config from "../../contracts/mud.config"; +import configV2 from "../../contracts/mud.config"; import { encodeEntity } from "@latticexyz/store-sync/recs"; import { callPageFunction } from "./callPageFunction"; +import { worldToV1 } from "@latticexyz/world/config/v2"; + +const config = worldToV1(configV2); /** * Confirms that the client state equals the given state by reading from the client's data store diff --git a/e2e/packages/sync-test/data/types.ts b/e2e/packages/sync-test/data/types.ts index 84a38cc93f..3ba0a40da5 100644 --- a/e2e/packages/sync-test/data/types.ts +++ b/e2e/packages/sync-test/data/types.ts @@ -1,7 +1,11 @@ // Note: this expects the config to not use shortcuts but the full definitions for table schemas import { SchemaAbiType, SchemaAbiTypeToPrimitiveType } from "@latticexyz/schema-type/internal"; -import config from "../../contracts/mud.config"; +import configV2 from "../../contracts/mud.config"; import { Hex } from "viem"; +import { worldToV1 } from "@latticexyz/world/config/v2"; + +const config = worldToV1(configV2); + type SchemaToPrimitive = Schema extends Record ? { [key in keyof Schema]: SchemaAbiTypeToPrimitiveType } diff --git a/e2e/packages/sync-test/package.json b/e2e/packages/sync-test/package.json index d577e6bee5..0e342593e1 100644 --- a/e2e/packages/sync-test/package.json +++ b/e2e/packages/sync-test/package.json @@ -19,6 +19,7 @@ "@latticexyz/store": "link:../../../packages/store", "@latticexyz/store-sync": "link:../../../packages/store-sync", "@latticexyz/utils": "link:../../../packages/utils", + "@latticexyz/world": "link:../../../packages/world", "@viem/anvil": "^0.0.6", "abitype": "1.0.0", "chalk": "^5.2.0", diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index 05cda99868..d3a9bbe58e 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -153,6 +153,9 @@ importers: '@latticexyz/utils': specifier: link:../../../packages/utils version: link:../../../packages/utils + '@latticexyz/world': + specifier: link:../../../packages/world + version: link:../../../packages/world '@viem/anvil': specifier: ^0.0.6 version: 0.0.6 diff --git a/examples/minimal/packages/contracts/mud.config.ts b/examples/minimal/packages/contracts/mud.config.ts index 60e81c1d94..56860f5861 100644 --- a/examples/minimal/packages/contracts/mud.config.ts +++ b/examples/minimal/packages/contracts/mud.config.ts @@ -1,8 +1,7 @@ -import { mudConfig } from "@latticexyz/world/register"; - +import { defineWorld } from "@latticexyz/world/config/v2"; import { resolveTableId } from "@latticexyz/config/library"; -export default mudConfig({ +export default defineWorld({ systems: { IncrementSystem: { name: "increment", @@ -15,26 +14,27 @@ export default mudConfig({ ], tables: { CounterTable: { - keySchema: {}, - valueSchema: { + schema: { value: "uint32", }, - storeArgument: true, + key: [], + codegen: { storeArgument: true }, }, MessageTable: { - keySchema: {}, - valueSchema: { + type: "offchainTable", + schema: { value: "string", }, - offchainOnly: true, + key: [], }, Inventory: { - keySchema: { + schema: { owner: "address", item: "uint32", itemVariant: "uint32", + amount: "uint32", }, - valueSchema: { amount: "uint32" }, + key: ["owner", "item", "itemVariant"], }, }, modules: [ diff --git a/examples/multiple-accounts/packages/contracts/mud.config.ts b/examples/multiple-accounts/packages/contracts/mud.config.ts index 5d3d4f0cb1..f3bf22fc9c 100644 --- a/examples/multiple-accounts/packages/contracts/mud.config.ts +++ b/examples/multiple-accounts/packages/contracts/mud.config.ts @@ -1,16 +1,15 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ namespace: "LastCall", tables: { LastCall: { - keySchema: { + schema: { caller: "address", - }, - valueSchema: { callTime: "uint256", sender: "address", }, + key: ["caller"], }, }, }); diff --git a/packages/cli/scripts/generate-test-tables.ts b/packages/cli/scripts/generate-test-tables.ts index 450dda72fc..21e81469ee 100644 --- a/packages/cli/scripts/generate-test-tables.ts +++ b/packages/cli/scripts/generate-test-tables.ts @@ -1,104 +1,98 @@ import path from "path"; import { tablegen } from "@latticexyz/store/codegen"; -import { mudConfig } from "@latticexyz/world/register"; +import { defineStore } from "@latticexyz/store/config/v2"; import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry"; -import { logError } from "../src/utils/errors"; // This config is used only for tests. // Aside from avoiding `mud.config.ts` in cli package (could cause issues), // this also tests that mudConfig and tablegen can work as standalone functions -let config; -try { - config = mudConfig({ - tables: { - Statics: { - keySchema: { - k1: "uint256", - k2: "int32", - k3: "bytes16", - k4: "address", - k5: "bool", - k6: "Enum2", - }, - valueSchema: { - v1: "uint256", - v2: "int32", - v3: "bytes16", - v4: "address", - v5: "bool", - v6: "Enum1", - }, +const config = defineStore({ + enums: { + Enum1: ["E1", "E2", "E3"], + Enum2: ["E1"], + }, + userTypes: { + TestTypeAddress: { filePath: "./contracts/src/types.sol", type: "address" }, + TestTypeInt64: { filePath: "./contracts/src/types.sol", type: "int64" }, + TestTypeBool: { filePath: "./contracts/src/types.sol", type: "bool" }, + TestTypeUint128: { filePath: "./contracts/src/types.sol", type: "uint128" }, + ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", type: "bytes32" }, + }, + tables: { + Statics: { + schema: { + k1: "uint256", + k2: "int32", + k3: "bytes16", + k4: "address", + k5: "bool", + k6: "Enum2", + v1: "uint256", + v2: "int32", + v3: "bytes16", + v4: "address", + v5: "bool", + v6: "Enum1", }, - Dynamics1: { - valueSchema: { - staticB32: "bytes32[1]", - staticI32: "int32[2]", - staticU128: "uint128[3]", - staticAddrs: "address[4]", - staticBools: "bool[5]", - }, - }, - Dynamics2: { - valueSchema: { - u64: "uint64[]", - str: "string", - b: "bytes", - }, - }, - Singleton: { - keySchema: {}, - valueSchema: { - v1: "int256", - v2: "uint32[2]", - v3: "uint32[2]", - v4: "uint32[1]", - }, - dataStruct: false, + key: ["k1", "k2", "k3", "k4", "k5", "k6"], + }, + Dynamics1: { + schema: { + key: "bytes32", + staticB32: "bytes32[1]", + staticI32: "int32[2]", + staticU128: "uint128[3]", + staticAddrs: "address[4]", + staticBools: "bool[5]", }, - Offchain: { - valueSchema: "uint256", - offchainOnly: true, + key: ["key"], + }, + Dynamics2: { + schema: { + key: "bytes32", + u64: "uint64[]", + str: "string", + b: "bytes", }, - UserTyped: { - keySchema: { - k1: "TestTypeAddress", - k2: "TestTypeInt64", - k3: "TestTypeBool", - k4: "TestTypeUint128", - k5: "ResourceId", - }, - valueSchema: { - v1: "TestTypeAddress", - v2: "TestTypeInt64", - v3: "TestTypeBool", - v4: "TestTypeUint128", - v5: "ResourceId", - }, + key: ["key"], + }, + Singleton: { + schema: { + v1: "int256", + v2: "uint32[2]", + v3: "uint32[2]", + v4: "uint32[1]", }, + key: [], + codegen: { dataStruct: false }, }, - - enums: { - Enum1: ["E1", "E2", "E3"], - Enum2: ["E1"], + Offchain: { + type: "offchainTable", + schema: { + key: "bytes32", + value: "uint256", + }, + key: ["key"], }, - - userTypes: { - TestTypeAddress: { filePath: "./contracts/src/types.sol", internalType: "address" }, - TestTypeInt64: { filePath: "./contracts/src/types.sol", internalType: "int64" }, - TestTypeBool: { filePath: "./contracts/src/types.sol", internalType: "bool" }, - TestTypeUint128: { filePath: "./contracts/src/types.sol", internalType: "uint128" }, - ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", internalType: "bytes32" }, + UserTyped: { + schema: { + k1: "TestTypeAddress", + k2: "TestTypeInt64", + k3: "TestTypeBool", + k4: "TestTypeUint128", + k5: "ResourceId", + v1: "TestTypeAddress", + v2: "TestTypeInt64", + v3: "TestTypeBool", + v4: "TestTypeUint128", + v5: "ResourceId", + }, + key: ["k1", "k2", "k3", "k4", "k5"], }, - }); -} catch (error: unknown) { - logError(error); -} + }, +}); const srcDirectory = await getSrcDirectory(); const remappings = await getRemappings(); -if (config !== undefined) { - tablegen(config, path.join(srcDirectory, config.codegenDirectory), remappings); -} else { - process.exit(1); -} +await tablegen(config, path.join(srcDirectory, config.codegen.outputDirectory), remappings); diff --git a/packages/cli/src/build.ts b/packages/cli/src/build.ts index 879bc1bdc3..d89c700583 100644 --- a/packages/cli/src/build.ts +++ b/packages/cli/src/build.ts @@ -2,8 +2,7 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs"; import path from "node:path"; import { tablegen } from "@latticexyz/store/codegen"; import { worldgen } from "@latticexyz/world/node"; -import { StoreConfig } from "@latticexyz/store"; -import { WorldConfig } from "@latticexyz/world"; +import { World as WorldConfig, worldToV1 } from "@latticexyz/world/config/v2"; import { forge, getForgeConfig, getRemappings } from "@latticexyz/common/foundry"; import { getExistingContracts } from "./utils/getExistingContracts"; import { debug as parentDebug } from "./debug"; @@ -14,17 +13,21 @@ const debug = parentDebug.extend("runDeploy"); type BuildOptions = { foundryProfile?: string; srcDir: string; - config: StoreConfig & WorldConfig; + config: WorldConfig; }; export async function build({ - config, + config: configV2, srcDir, foundryProfile = process.env.FOUNDRY_PROFILE, }: BuildOptions): Promise { + const config = worldToV1(configV2); const outPath = path.join(srcDir, config.codegenDirectory); const remappings = await getRemappings(foundryProfile); - await Promise.all([tablegen(config, outPath, remappings), worldgen(config, getExistingContracts(srcDir), outPath)]); + await Promise.all([ + tablegen(configV2, outPath, remappings), + worldgen(configV2, getExistingContracts(srcDir), outPath), + ]); // TODO remove when https://github.com/foundry-rs/foundry/issues/6241 is resolved const forgeConfig = await getForgeConfig(foundryProfile); diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index 4faec86ff9..5ea6382d52 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -1,7 +1,6 @@ import type { CommandModule } from "yargs"; import { loadConfig } from "@latticexyz/config/node"; -import { StoreConfig } from "@latticexyz/store"; -import { WorldConfig } from "@latticexyz/world"; +import { World as WorldConfig } from "@latticexyz/world/config/v2"; import { getSrcDirectory } from "@latticexyz/common/foundry"; import { build } from "../build"; @@ -24,7 +23,7 @@ const commandModule: CommandModule = { }, async handler({ configPath, profile }) { - const config = (await loadConfig(configPath)) as StoreConfig & WorldConfig; + const config = (await loadConfig(configPath)) as WorldConfig; const srcDir = await getSrcDirectory(); await build({ config, srcDir, foundryProfile: profile }); diff --git a/packages/cli/src/commands/dev-contracts.ts b/packages/cli/src/commands/dev-contracts.ts index 61b6b75431..6ceaf97949 100644 --- a/packages/cli/src/commands/dev-contracts.ts +++ b/packages/cli/src/commands/dev-contracts.ts @@ -3,9 +3,8 @@ import { anvil, getScriptDirectory, getSrcDirectory } from "@latticexyz/common/f import chalk from "chalk"; import chokidar from "chokidar"; import { loadConfig, resolveConfigPath } from "@latticexyz/config/node"; -import { StoreConfig } from "@latticexyz/store"; import path from "path"; -import { WorldConfig } from "@latticexyz/world"; +import { World as WorldConfig } from "@latticexyz/world/config/v2"; import { homedir } from "os"; import { rmSync } from "fs"; import { deployOptions, runDeploy } from "../runDeploy"; @@ -34,7 +33,7 @@ const commandModule: CommandModule = { const srcDir = await getSrcDirectory(); const remappings = await getRemappings(); - await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings); + await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings); process.exit(0); }, diff --git a/packages/cli/src/commands/trace.ts b/packages/cli/src/commands/trace.ts index e8659eb089..1926c56933 100644 --- a/packages/cli/src/commands/trace.ts +++ b/packages/cli/src/commands/trace.ts @@ -5,20 +5,20 @@ import { ethers } from "ethers"; import { loadConfig } from "@latticexyz/config/node"; import { MUDError } from "@latticexyz/common/errors"; import { cast, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry"; -import { StoreConfig } from "@latticexyz/store"; -import { resolveWorldConfig, WorldConfig } from "@latticexyz/world"; +import { resolveWorldConfig } from "@latticexyz/world"; import IBaseWorldAbi from "@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json" assert { type: "json" }; import worldConfig from "@latticexyz/world/mud.config"; import { resourceToHex } from "@latticexyz/common"; import { getExistingContracts } from "../utils/getExistingContracts"; import { createClient, http } from "viem"; import { getChainId } from "viem/actions"; +import { World as WorldConfig, worldToV1 } from "@latticexyz/world/config/v2"; // TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994) const systemsTableId = resourceToHex({ type: "system", namespace: worldConfig.namespace, - name: worldConfig.tables.Systems.name, + name: worldConfig.tables.world__Systems.name, }); type Options = { @@ -59,7 +59,8 @@ const commandModule: CommandModule = { const existingContracts = getExistingContracts(srcDir); // Load the config - const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig; + const configV2 = (await loadConfig(configPath)) as WorldConfig; + const mudConfig = worldToV1(configV2); const resolvedConfig = resolveWorldConfig( mudConfig, diff --git a/packages/cli/src/commands/worldgen.ts b/packages/cli/src/commands/worldgen.ts index 63cb98291f..324ad0c10f 100644 --- a/packages/cli/src/commands/worldgen.ts +++ b/packages/cli/src/commands/worldgen.ts @@ -1,7 +1,6 @@ import type { CommandModule } from "yargs"; import { loadConfig } from "@latticexyz/config/node"; -import { StoreConfig } from "@latticexyz/store"; -import { WorldConfig } from "@latticexyz/world"; +import { World as WorldConfig } from "@latticexyz/world/config/v2"; import { worldgen } from "@latticexyz/world/node"; import { getSrcDirectory } from "@latticexyz/common/foundry"; import path from "path"; @@ -12,7 +11,7 @@ type Options = { configPath?: string; clean?: boolean; srcDir?: string; - config?: StoreConfig & WorldConfig; + config?: WorldConfig; }; const commandModule: CommandModule = { @@ -43,12 +42,14 @@ export async function worldgenHandler(args: Options) { const existingContracts = getExistingContracts(srcDir); // Load the config - const mudConfig = args.config ?? ((await loadConfig(args.configPath)) as StoreConfig & WorldConfig); + const mudConfig = args.config ?? ((await loadConfig(args.configPath)) as WorldConfig); - const outputBaseDirectory = path.join(srcDir, mudConfig.codegenDirectory); + const outputBaseDirectory = path.join(srcDir, mudConfig.codegen.outputDirectory); // clear the worldgen directory - if (args.clean) rmSync(path.join(outputBaseDirectory, mudConfig.worldgenDirectory), { recursive: true, force: true }); + if (args.clean) { + rmSync(path.join(outputBaseDirectory, mudConfig.codegen.worldgenDirectory), { recursive: true, force: true }); + } // generate new interfaces await worldgen(mudConfig, existingContracts, outputBaseDirectory); diff --git a/packages/cli/src/deploy/common.ts b/packages/cli/src/deploy/common.ts index 184083c5d2..87be77529d 100644 --- a/packages/cli/src/deploy/common.ts +++ b/packages/cli/src/deploy/common.ts @@ -6,6 +6,8 @@ import IModuleAbi from "@latticexyz/world-modules/out/IModule.sol/IModule.abi.js import { Tables, configToTables } from "./configToTables"; import { StoreConfig, helloStoreEvent } from "@latticexyz/store"; import { WorldConfig, helloWorldEvent } from "@latticexyz/world"; +import { storeToV1 } from "@latticexyz/store/config/v2"; +import { worldToV1 } from "@latticexyz/world/config/v2"; export const salt = padHex("0x", { size: 32 }); @@ -13,8 +15,8 @@ export const salt = padHex("0x", { size: 32 }); export const contractSizeLimit = parseInt("6000", 16); // TODO: add `as const` to mud config so these get more strongly typed (blocked by current config parsing not using readonly) -export const storeTables = configToTables(storeConfig); -export const worldTables = configToTables(worldConfig); +export const storeTables = configToTables(storeToV1(storeConfig)); +export const worldTables = configToTables(worldToV1(worldConfig)); export const worldDeployEvents = [helloStoreEvent, helloWorldEvent] as const; diff --git a/packages/cli/src/runDeploy.ts b/packages/cli/src/runDeploy.ts index 837026c9da..9375330b66 100644 --- a/packages/cli/src/runDeploy.ts +++ b/packages/cli/src/runDeploy.ts @@ -5,8 +5,7 @@ import { deploy } from "./deploy/deploy"; import { createWalletClient, http, Hex, isHex } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { loadConfig } from "@latticexyz/config/node"; -import { StoreConfig } from "@latticexyz/store"; -import { WorldConfig } from "@latticexyz/world"; +import { World as WorldConfig, worldToV1 } from "@latticexyz/world/config/v2"; import { getOutDirectory, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry"; import chalk from "chalk"; import { MUDError } from "@latticexyz/common/errors"; @@ -57,7 +56,8 @@ export async function runDeploy(opts: DeployOptions): Promise { const profile = opts.profile ?? process.env.FOUNDRY_PROFILE; - const config = (await loadConfig(opts.configPath)) as StoreConfig & WorldConfig; + const configV2 = (await loadConfig(opts.configPath)) as WorldConfig; + const config = worldToV1(configV2); if (opts.printConfig) { console.log(chalk.green("\nResolved config:\n"), JSON.stringify(config, null, 2)); } @@ -74,7 +74,7 @@ export async function runDeploy(opts: DeployOptions): Promise { // Run build if (!opts.skipBuild) { - await build({ config, srcDir, foundryProfile: profile }); + await build({ config: configV2, srcDir, foundryProfile: profile }); } const privateKey = process.env.PRIVATE_KEY as Hex; diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index 58bbdf4b99..f0b284d169 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -9,6 +9,7 @@ import { } from "./types"; import { posixPath } from "../utils"; import { resourceToHex } from "../../resourceToHex"; +import { hexToResource } from "../../hexToResource"; /** * Common header for all codegenerated solidity files @@ -212,15 +213,18 @@ export function renderTableId({ name, offchainOnly, }: Pick): string { + const tableId = resourceToHex({ + type: offchainOnly ? "offchainTable" : "table", + namespace, + name, + }); + // turn table ID back into arguments that would be valid in `WorldResourceIdLib.encode` (like truncated names) + const resource = hexToResource(tableId); return ` // Hex below is the result of \`WorldResourceIdLib.encode({ namespace: ${JSON.stringify( - namespace, - )}, name: ${JSON.stringify(name)}, typeId: ${offchainOnly ? "RESOURCE_OFFCHAIN_TABLE" : "RESOURCE_TABLE"} });\` - ResourceId constant _tableId = ResourceId.wrap(${resourceToHex({ - type: offchainOnly ? "offchainTable" : "table", - namespace, - name, - })}); + resource.namespace, + )}, name: ${JSON.stringify(resource.name)}, typeId: ${offchainOnly ? "RESOURCE_OFFCHAIN_TABLE" : "RESOURCE_TABLE"} });\` + ResourceId constant _tableId = ResourceId.wrap(${tableId}); `; } diff --git a/packages/dev-tools/src/common.ts b/packages/dev-tools/src/common.ts index 93a7da14cf..c473018e60 100644 --- a/packages/dev-tools/src/common.ts +++ b/packages/dev-tools/src/common.ts @@ -1,6 +1,6 @@ import { Observable } from "rxjs"; import { Abi, Block, Chain, PublicClient, Transport, WalletClient } from "viem"; -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { StorageAdapterBlock } from "@latticexyz/store-sync"; import { ZustandStore } from "@latticexyz/store-sync/zustand"; import { ContractWrite } from "@latticexyz/common"; diff --git a/packages/dev-tools/src/mount.tsx b/packages/dev-tools/src/mount.tsx index c54976211d..cace1570a1 100644 --- a/packages/dev-tools/src/mount.tsx +++ b/packages/dev-tools/src/mount.tsx @@ -1,11 +1,11 @@ -import type { StoreConfig } from "@latticexyz/store"; +import type { Store as StoreConfig } from "@latticexyz/store/config/v2"; import type { DevToolsOptions } from "./common"; const containerId = "mud-dev-tools"; // TODO: rework to always return a unmount function (not a promise or possibly undefined) -export async function mount( - opts: DevToolsOptions, +export async function mount( + opts: DevToolsOptions, ): Promise<(() => void) | undefined> { if (typeof window === "undefined") { console.warn("MUD dev-tools should only be used in browser bundles"); diff --git a/packages/store-sync/src/common.ts b/packages/store-sync/src/common.ts index 8c86305fb7..2bd8f2219a 100644 --- a/packages/store-sync/src/common.ts +++ b/packages/store-sync/src/common.ts @@ -1,16 +1,17 @@ import { Address, Block, Hex, Log, PublicClient } from "viem"; -import { StoreConfig, StoreEventsAbiItem, StoreEventsAbi, resolveConfig } from "@latticexyz/store"; +import { StoreEventsAbiItem, StoreEventsAbi, resolveConfig } from "@latticexyz/store"; import { Observable } from "rxjs"; import { UnionPick } from "@latticexyz/common/type-utils"; import { KeySchema, TableRecord, ValueSchema } from "@latticexyz/protocol-parser/internal"; import storeConfig from "@latticexyz/store/mud.config"; import worldConfig from "@latticexyz/world/mud.config"; import { flattenSchema } from "./flattenSchema"; +import { Store as StoreConfig, storeToV1 } from "@latticexyz/store/config/v2"; /** @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 storeTables = resolveConfig(storeConfig).tables; +export const storeTables = resolveConfig(storeToV1(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 worldTables = resolveConfig(storeToV1(worldConfig)).tables; export const internalTableIds = [...Object.values(storeTables), ...Object.values(worldTables)].map( (table) => table.tableId, @@ -54,11 +55,11 @@ export type SyncFilter = { key1?: Hex; }; -export type SyncOptions = { +export type SyncOptions = { /** * MUD config */ - config?: TConfig; + config?: config; /** * [viem `PublicClient`][0] used for fetching logs from the RPC. * diff --git a/packages/store-sync/src/createStoreSync.ts b/packages/store-sync/src/createStoreSync.ts index ae2cf619be..0b7488759d 100644 --- a/packages/store-sync/src/createStoreSync.ts +++ b/packages/store-sync/src/createStoreSync.ts @@ -1,4 +1,4 @@ -import { StoreConfig, storeEventsAbi } from "@latticexyz/store"; +import { storeEventsAbi } from "@latticexyz/store"; import { Hex, TransactionReceiptNotFoundError } from "viem"; import { StorageAdapter, @@ -32,12 +32,13 @@ import { SyncStep } from "./SyncStep"; import { bigIntMax, chunk, isDefined, waitForIdle } from "@latticexyz/common/utils"; import { getSnapshot } from "./getSnapshot"; import { fetchAndStoreLogs } from "./fetchAndStoreLogs"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; const debug = parentDebug.extend("createStoreSync"); const defaultFilters: SyncFilter[] = internalTableIds.map((tableId) => ({ tableId })); -type CreateStoreSyncOptions = SyncOptions & { +type CreateStoreSyncOptions = SyncOptions & { storageAdapter: StorageAdapter; onProgress?: (opts: { step: SyncStep; @@ -48,7 +49,7 @@ type CreateStoreSyncOptions = SyncOpt }) => void; }; -export async function createStoreSync({ +export async function createStoreSync({ storageAdapter, onProgress, publicClient, @@ -61,7 +62,7 @@ export async function createStoreSync initialState, initialBlockLogs, indexerUrl, -}: CreateStoreSyncOptions): Promise { +}: CreateStoreSyncOptions): Promise { const filters: SyncFilter[] = initialFilters.length || tableIds.length ? [...initialFilters, ...tableIds.map((tableId) => ({ tableId })), ...defaultFilters] diff --git a/packages/store-sync/src/postgres-decoded/createStorageAdapter.ts b/packages/store-sync/src/postgres-decoded/createStorageAdapter.ts index 321362b674..26a89320c1 100644 --- a/packages/store-sync/src/postgres-decoded/createStorageAdapter.ts +++ b/packages/store-sync/src/postgres-decoded/createStorageAdapter.ts @@ -2,7 +2,7 @@ import { Hex, PublicClient, concatHex, getAddress } from "viem"; import { PgDatabase, QueryResultHKT } from "drizzle-orm/pg-core"; import { and, eq } from "drizzle-orm"; import { buildTable } from "./buildTable"; -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { debug } from "./debug"; import { StorageAdapter, StorageAdapterBlock } from "../common"; import { isTableRegistrationLog } from "../isTableRegistrationLog"; @@ -22,14 +22,14 @@ export type PostgresStorageAdapter = { cleanUp: () => Promise; }; -export async function createStorageAdapter({ +export async function createStorageAdapter({ database, publicClient, config, }: { database: PgDatabase; publicClient: PublicClient; - config?: TConfig; + config?: config; }): Promise { const bytesStorageAdapter = await createBytesStorageAdapter({ database, publicClient, config }); const cleanUp: (() => Promise)[] = []; diff --git a/packages/store-sync/src/postgres-decoded/syncToPostgres.ts b/packages/store-sync/src/postgres-decoded/syncToPostgres.ts index 3515a9aff3..87ffc4e91f 100644 --- a/packages/store-sync/src/postgres-decoded/syncToPostgres.ts +++ b/packages/store-sync/src/postgres-decoded/syncToPostgres.ts @@ -1,10 +1,10 @@ -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { PgDatabase } from "drizzle-orm/pg-core"; import { SyncOptions, SyncResult } from "../common"; import { createStorageAdapter } from "./createStorageAdapter"; import { createStoreSync } from "../createStoreSync"; -type SyncToPostgresOptions = SyncOptions & { +type SyncToPostgresOptions = SyncOptions & { /** * [Postgres database object from Drizzle][0]. * @@ -25,13 +25,13 @@ type SyncToPostgresResult = SyncResult & { * @param {CreateIndexerOptions} options See `CreateIndexerOptions`. * @returns A function to unsubscribe from the block stream, effectively stopping the indexer. */ -export async function syncToPostgres({ +export async function syncToPostgres({ config, database, publicClient, startSync = true, ...syncOptions -}: SyncToPostgresOptions): Promise { +}: SyncToPostgresOptions): Promise { const { storageAdapter } = await createStorageAdapter({ database, publicClient, config }); const storeSync = await createStoreSync({ storageAdapter, diff --git a/packages/store-sync/src/postgres/createStorageAdapter.ts b/packages/store-sync/src/postgres/createStorageAdapter.ts index 91cfe6f225..ed5e138fa0 100644 --- a/packages/store-sync/src/postgres/createStorageAdapter.ts +++ b/packages/store-sync/src/postgres/createStorageAdapter.ts @@ -1,7 +1,7 @@ import { PublicClient, encodePacked, size } from "viem"; import { PgDatabase, QueryResultHKT } from "drizzle-orm/pg-core"; import { and, eq } from "drizzle-orm"; -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { debug } from "./debug"; import { tables } from "./tables"; import { spliceHex } from "@latticexyz/common"; @@ -17,13 +17,13 @@ export type PostgresStorageAdapter = { cleanUp: () => Promise; }; -export async function createStorageAdapter({ +export async function createStorageAdapter({ database, publicClient, }: { database: PgDatabase; publicClient: PublicClient; - config?: TConfig; + config?: config; }): Promise { const cleanUp: (() => Promise)[] = []; diff --git a/packages/store-sync/src/postgres/syncToPostgres.ts b/packages/store-sync/src/postgres/syncToPostgres.ts index 3515a9aff3..87ffc4e91f 100644 --- a/packages/store-sync/src/postgres/syncToPostgres.ts +++ b/packages/store-sync/src/postgres/syncToPostgres.ts @@ -1,10 +1,10 @@ -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { PgDatabase } from "drizzle-orm/pg-core"; import { SyncOptions, SyncResult } from "../common"; import { createStorageAdapter } from "./createStorageAdapter"; import { createStoreSync } from "../createStoreSync"; -type SyncToPostgresOptions = SyncOptions & { +type SyncToPostgresOptions = SyncOptions & { /** * [Postgres database object from Drizzle][0]. * @@ -25,13 +25,13 @@ type SyncToPostgresResult = SyncResult & { * @param {CreateIndexerOptions} options See `CreateIndexerOptions`. * @returns A function to unsubscribe from the block stream, effectively stopping the indexer. */ -export async function syncToPostgres({ +export async function syncToPostgres({ config, database, publicClient, startSync = true, ...syncOptions -}: SyncToPostgresOptions): Promise { +}: SyncToPostgresOptions): Promise { const { storageAdapter } = await createStorageAdapter({ database, publicClient, config }); const storeSync = await createStoreSync({ storageAdapter, diff --git a/packages/store-sync/src/query-cache/createStorageAdapter.test.ts b/packages/store-sync/src/query-cache/createStorageAdapter.test.ts index 28da190311..3b89245c55 100644 --- a/packages/store-sync/src/query-cache/createStorageAdapter.test.ts +++ b/packages/store-sync/src/query-cache/createStorageAdapter.test.ts @@ -7,7 +7,6 @@ import { fetchAndStoreLogs } from "../fetchAndStoreLogs"; import { testClient } from "../../test/common"; import { getBlockNumber } from "viem/actions"; import { Address } from "viem"; -import { getTables } from "./getTables"; describe("createStorageAdapter", async () => { // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -17,7 +16,7 @@ describe("createStorageAdapter", async () => { }); it("sets component values from logs", async () => { - const useStore = createStore({ tables: getTables(config) }); + const useStore = createStore({ tables: config.tables }); const storageAdapter = createStorageAdapter({ store: useStore }); console.log("fetching blocks"); diff --git a/packages/store-sync/src/query-cache/getTables.ts b/packages/store-sync/src/query-cache/getTables.ts deleted file mode 100644 index e9cf6fb888..0000000000 --- a/packages/store-sync/src/query-cache/getTables.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { resourceToHex } from "@latticexyz/common"; -import { Store } from "@latticexyz/store/config/v2"; - -// TODO(alvrs): table resolver doesn't yet provide `tableId` so we'll use this helper to inject it for now - -export function getTables(config: config): config["tables"] { - const tables = Object.fromEntries( - Object.entries(config.tables).map(([tableName, table]) => [ - tableName, - { - ...table, - tableId: resourceToHex({ - // hardcoded for now because table doesn't have a `type` yet - // TODO: use table type if available before `tableId` - type: "table", - // use config's namespace because table doesn't have `namespace` yet - // TODO: fix `config.namespace` being `string | undefined` - it should always be set in resolved output - // TODO: replace wih `table.namespace` - namespace: config.namespace ?? "", - // TODO: replace with `table.name` if available before `tableId` - name: tableName, - }), - }, - ]), - ); - - return tables; -} diff --git a/packages/store-sync/src/query-cache/syncToQueryCache.ts b/packages/store-sync/src/query-cache/syncToQueryCache.ts index 2fb7ee0b89..e33a6f81bc 100644 --- a/packages/store-sync/src/query-cache/syncToQueryCache.ts +++ b/packages/store-sync/src/query-cache/syncToQueryCache.ts @@ -4,7 +4,6 @@ import { Address } from "viem"; import { Store } from "@latticexyz/store/config/v2"; import { createStore } from "./createStore"; import { createStorageAdapter } from "./createStorageAdapter"; -import { getTables } from "./getTables"; type SyncToQueryCacheOptions = Omit & { // require address for now to keep the data model + retrieval simpler @@ -22,7 +21,7 @@ export async function syncToQueryCache({ startSync = true, ...syncOptions }: SyncToQueryCacheOptions): Promise { - const useStore = createStore({ tables: getTables(config) }); + const useStore = createStore({ tables: config.tables }); const storageAdapter = createStorageAdapter({ store: useStore }); const storeSync = await createStoreSync({ diff --git a/packages/store-sync/src/query-cache/test/createHydratedStore.ts b/packages/store-sync/src/query-cache/test/createHydratedStore.ts index 2b781e2c73..42e7621b51 100644 --- a/packages/store-sync/src/query-cache/test/createHydratedStore.ts +++ b/packages/store-sync/src/query-cache/test/createHydratedStore.ts @@ -6,7 +6,6 @@ import { Address } from "viem"; import { getBlock, getBlockNumber } from "viem/actions"; import { QueryCacheStore, createStore } from "../createStore"; import { createStorageAdapter } from "../createStorageAdapter"; -import { getTables } from "../getTables"; export { config }; @@ -14,7 +13,7 @@ export async function createHydratedStore(worldAddress: Address): Promise<{ store: QueryCacheStore<(typeof config)["tables"]>; fetchLatestLogs: () => Promise; }> { - const store = createStore({ tables: getTables(config) }); + const store = createStore({ tables: config.tables }); const storageAdapter = createStorageAdapter({ store }); let lastBlockProcessed = (await getBlock(testClient, { blockTag: "earliest" })).number - 1n; diff --git a/packages/store-sync/src/recs/recsStorage.test.ts b/packages/store-sync/src/recs/recsStorage.test.ts index 1af1bcc16d..f0ad3fd0ab 100644 --- a/packages/store-sync/src/recs/recsStorage.test.ts +++ b/packages/store-sync/src/recs/recsStorage.test.ts @@ -8,8 +8,9 @@ import { StoreEventsLog } from "../common"; import { singletonEntity } from "./singletonEntity"; import { RpcLog, formatLog, decodeEventLog, Hex } from "viem"; import { resolveConfig, storeEventsAbi } from "@latticexyz/store"; +import { storeToV1 } from "@latticexyz/store/config/v2"; -const tables = resolveConfig(mudConfig).tables; +const tables = resolveConfig(storeToV1(mudConfig)).tables; // TODO: make test-data a proper package and export this const blocks = groupLogsByBlockNumber( diff --git a/packages/store-sync/src/recs/recsStorage.ts b/packages/store-sync/src/recs/recsStorage.ts index d594624cd6..6b12c55bb7 100644 --- a/packages/store-sync/src/recs/recsStorage.ts +++ b/packages/store-sync/src/recs/recsStorage.ts @@ -14,9 +14,10 @@ import { singletonEntity } from "./singletonEntity"; import storeConfig from "@latticexyz/store/mud.config"; import worldConfig from "@latticexyz/world/mud.config"; import { TablesToComponents, tablesToComponents } from "./tablesToComponents"; +import { storeToV1 } from "@latticexyz/store/config/v2"; -const storeTables = resolveConfig(storeConfig).tables; -const worldTables = resolveConfig(worldConfig).tables; +const storeTables = resolveConfig(storeToV1(storeConfig)).tables; +const worldTables = resolveConfig(storeToV1(worldConfig)).tables; export type RecsStorageOptions> = { world: RecsWorld; diff --git a/packages/store-sync/src/recs/syncToRecs.ts b/packages/store-sync/src/recs/syncToRecs.ts index 22c4892ed8..c15f11aea9 100644 --- a/packages/store-sync/src/recs/syncToRecs.ts +++ b/packages/store-sync/src/recs/syncToRecs.ts @@ -1,4 +1,5 @@ -import { StoreConfig, Table, ResolvedStoreConfig, resolveConfig } from "@latticexyz/store"; +import { Table, ResolvedStoreConfig, resolveConfig } from "@latticexyz/store"; +import { Store as StoreConfig, storeToV1 } from "@latticexyz/store/config/v2"; import { Component as RecsComponent, World as RecsWorld, getComponentValue, setComponent } from "@latticexyz/recs"; import { SyncOptions, SyncResult } from "../common"; import { RecsStorageAdapter, recsStorage } from "./recsStorage"; @@ -6,7 +7,10 @@ import { createStoreSync } from "../createStoreSync"; import { singletonEntity } from "./singletonEntity"; import { SyncStep } from "../SyncStep"; -type SyncToRecsOptions> = SyncOptions & { +type SyncToRecsOptions> = Omit< + SyncOptions, + "config" +> & { world: RecsWorld; config: config; tables?: extraTables; @@ -14,7 +18,7 @@ type SyncToRecsOptions> = SyncResult & { - components: RecsStorageAdapter["tables"] & extraTables>["components"]; + components: RecsStorageAdapter>["tables"] & extraTables>["components"]; stopSync: () => void; }; @@ -26,9 +30,9 @@ export async function syncToRecs): Promise> { const tables = { - ...resolveConfig(config).tables, + ...resolveConfig(storeToV1(config as StoreConfig)).tables, ...extraTables, - } as ResolvedStoreConfig["tables"] & extraTables; + } as ResolvedStoreConfig>["tables"] & extraTables; const { storageAdapter, components } = recsStorage({ world, diff --git a/packages/store-sync/src/sqlite/sqliteStorage.ts b/packages/store-sync/src/sqlite/sqliteStorage.ts index 9e7b572b6a..a23d701e29 100644 --- a/packages/store-sync/src/sqlite/sqliteStorage.ts +++ b/packages/store-sync/src/sqlite/sqliteStorage.ts @@ -3,7 +3,7 @@ import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; import { and, eq, sql } from "drizzle-orm"; import { sqliteTableToSql } from "./sqliteTableToSql"; import { buildTable } from "./buildTable"; -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { debug } from "./debug"; import { getTableName } from "./getTableName"; import { chainState, mudStoreTables } from "./internalTables"; @@ -17,13 +17,13 @@ import { decodeKey, decodeValueArgs } from "@latticexyz/protocol-parser/internal // TODO: upgrade drizzle and use async sqlite interface for consistency -export async function sqliteStorage({ +export async function sqliteStorage({ database, publicClient, }: { database: BaseSQLiteDatabase<"sync", void>; publicClient: PublicClient; - config?: TConfig; + config?: config; }): Promise { const chainId = publicClient.chain?.id ?? (await publicClient.getChainId()); diff --git a/packages/store-sync/src/sqlite/syncToSqlite.ts b/packages/store-sync/src/sqlite/syncToSqlite.ts index 79282fed63..2bff8d2830 100644 --- a/packages/store-sync/src/sqlite/syncToSqlite.ts +++ b/packages/store-sync/src/sqlite/syncToSqlite.ts @@ -1,10 +1,10 @@ -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core"; import { SyncOptions, SyncResult } from "../common"; import { sqliteStorage } from "./sqliteStorage"; import { createStoreSync } from "../createStoreSync"; -type SyncToSqliteOptions = SyncOptions & { +type SyncToSqliteOptions = SyncOptions & { /** * [SQLite database object from Drizzle][0]. * @@ -25,13 +25,13 @@ type SyncToSqliteResult = SyncResult & { * @param {SyncToSqliteOptions} options See `SyncToSqliteOptions`. * @returns A function to unsubscribe from the block stream, effectively stopping the indexer. */ -export async function syncToSqlite({ +export async function syncToSqlite({ config, database, publicClient, startSync = true, ...syncOptions -}: SyncToSqliteOptions): Promise { +}: SyncToSqliteOptions): Promise { const storeSync = await createStoreSync({ storageAdapter: await sqliteStorage({ database, publicClient, config }), config, diff --git a/packages/store-sync/src/zustand/index.ts b/packages/store-sync/src/zustand/index.ts index 4709dc2367..93a15904c5 100644 --- a/packages/store-sync/src/zustand/index.ts +++ b/packages/store-sync/src/zustand/index.ts @@ -2,5 +2,4 @@ export * from "./common"; export * from "./createStorageAdapter"; export * from "./createStore"; export * from "./getId"; -export * from "./logToTable"; export * from "./syncToZustand"; diff --git a/packages/store-sync/src/zustand/logToTable.test.ts b/packages/store-sync/src/zustand/logToTable.test.ts deleted file mode 100644 index fbaf89cd0c..0000000000 --- a/packages/store-sync/src/zustand/logToTable.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { describe, it, expect } from "vitest"; -import { logToTable } from "./logToTable"; - -describe("logToTable", () => { - it("should convert a table registration log to table object", async () => { - expect( - logToTable({ - address: "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", - eventName: "Store_SetRecord", - args: { - tableId: "0x74626d756473746f72650000000000005461626c657300000000000000000000", - keyTuple: ["0x74626d756473746f72650000000000005461626c657300000000000000000000"], - staticData: - // eslint-disable-next-line max-len - "0x0060030220202000000000000000000000000000000000000000000000000000002001005f000000000000000000000000000000000000000000000000000000006003025f5f5fc4c40000000000000000000000000000000000000000000000", - encodedLengths: "0x000000000000000000000000000000000000022000000000a0000000000002c0", - dynamicData: - // eslint-disable-next-line max-len - "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000077461626c654964000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000b6669656c644c61796f757400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096b6579536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b76616c7565536368656d610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012616269456e636f6465644b65794e616d657300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014616269456e636f6465644669656c644e616d6573000000000000000000000000", - }, - }), - ).toMatchInlineSnapshot(` - { - "keySchema": { - "tableId": { - "type": "bytes32", - }, - }, - "name": "Tables", - "namespace": "mudstore", - "tableId": "0x74626d756473746f72650000000000005461626c657300000000000000000000", - "valueSchema": { - "abiEncodedFieldNames": { - "type": "bytes", - }, - "abiEncodedKeyNames": { - "type": "bytes", - }, - "fieldLayout": { - "type": "bytes32", - }, - "keySchema": { - "type": "bytes32", - }, - "valueSchema": { - "type": "bytes32", - }, - }, - } - `); - }); -}); diff --git a/packages/store-sync/src/zustand/logToTable.ts b/packages/store-sync/src/zustand/logToTable.ts deleted file mode 100644 index 8b57d6468e..0000000000 --- a/packages/store-sync/src/zustand/logToTable.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { hexToResource } from "@latticexyz/common"; -import { hexToSchema, decodeValue } from "@latticexyz/protocol-parser/internal"; -import { concatHex, decodeAbiParameters, parseAbiParameters } from "viem"; -import { StorageAdapterLog, schemasTable } from "../common"; -import { Table } from "@latticexyz/store"; - -export function logToTable(log: StorageAdapterLog & { eventName: "Store_SetRecord" }): Table { - const [tableId, ...otherKeys] = log.args.keyTuple; - if (otherKeys.length) { - console.warn("registerSchema event is expected to have only one key in key tuple, but got multiple", log); - } - - const table = hexToResource(tableId); - - const value = decodeValue( - schemasTable.valueSchema, - concatHex([log.args.staticData, log.args.encodedLengths, log.args.dynamicData]), - ); - - const keySchema = hexToSchema(value.keySchema); - const valueSchema = hexToSchema(value.valueSchema); - - const keyNames = decodeAbiParameters(parseAbiParameters("string[]"), value.abiEncodedKeyNames)[0]; - const fieldNames = decodeAbiParameters(parseAbiParameters("string[]"), value.abiEncodedFieldNames)[0]; - - const valueAbiTypes = [...valueSchema.staticFields, ...valueSchema.dynamicFields]; - - return { - tableId, - namespace: table.namespace, - name: table.name, - keySchema: Object.fromEntries(keySchema.staticFields.map((abiType, i) => [keyNames[i], { type: abiType }])), - valueSchema: Object.fromEntries(valueAbiTypes.map((abiType, i) => [fieldNames[i], { type: abiType }])), - }; -} diff --git a/packages/store-sync/src/zustand/syncToZustand.ts b/packages/store-sync/src/zustand/syncToZustand.ts index d5df3c0e80..69cdec1864 100644 --- a/packages/store-sync/src/zustand/syncToZustand.ts +++ b/packages/store-sync/src/zustand/syncToZustand.ts @@ -1,4 +1,4 @@ -import { ResolvedStoreConfig, StoreConfig, Tables, resolveConfig } from "@latticexyz/store"; +import { ResolvedStoreConfig, Tables, resolveConfig } from "@latticexyz/store"; import { SyncOptions, SyncResult, storeTables, worldTables } from "../common"; import { createStoreSync } from "../createStoreSync"; import { ZustandStore } from "./createStore"; @@ -6,11 +6,11 @@ import { createStore } from "./createStore"; import { createStorageAdapter } from "./createStorageAdapter"; import { Address } from "viem"; import { SyncStep } from "../SyncStep"; +import { Store as StoreConfig, storeToV1 } from "@latticexyz/store/config/v2"; -type AllTables< - config extends StoreConfig, - extraTables extends Tables | undefined, -> = ResolvedStoreConfig["tables"] & +type AllTables = ResolvedStoreConfig< + storeToV1 +>["tables"] & (extraTables extends Tables ? extraTables : Record) & typeof storeTables & typeof worldTables; @@ -39,7 +39,7 @@ export async function syncToZustand): Promise> { // TODO: migrate this once we redo config to return fully resolved tables (https://github.com/latticexyz/mud/issues/1668) // TODO: move store/world tables into `resolveConfig` - const resolvedConfig = resolveConfig(config); + const resolvedConfig = resolveConfig(storeToV1(config as StoreConfig)); const tables = { ...resolvedConfig.tables, ...extraTables, diff --git a/packages/store-sync/test/mockGame.ts b/packages/store-sync/test/mockGame.ts index b173a79239..de70479bf9 100644 --- a/packages/store-sync/test/mockGame.ts +++ b/packages/store-sync/test/mockGame.ts @@ -1,13 +1,13 @@ import { execa } from "execa"; import { anvilRpcUrl } from "./common"; -import mudConfig from "mock-game-contracts/mud.config"; +import configV2 from "mock-game-contracts/mud.config"; import { resolveConfig } from "@latticexyz/store"; import { Hex, isHex } from "viem"; import worldAbi from "mock-game-contracts/out/IWorld.sol/IWorld.abi.json"; +import { storeToV1 } from "@latticexyz/store/config/v2"; -export { configV2 } from "mock-game-contracts/mud.config"; -export const deprecatedConfig = mudConfig; -export const config = resolveConfig(mudConfig); +export { configV2 }; +export const config = resolveConfig(storeToV1(configV2)); export { worldAbi }; export async function deployMockGame(): Promise { diff --git a/packages/store/mud.config.ts b/packages/store/mud.config.ts index 63463c29f7..c5fd5335e1 100644 --- a/packages/store/mud.config.ts +++ b/packages/store/mud.config.ts @@ -1,51 +1,51 @@ -import { mudConfig } from "./ts/register"; +import { defineStore } from "./ts/config/v2/store"; -export default mudConfig({ - storeImportPath: "../../", +export default defineStore({ + codegen: { + storeImportPath: "../../", + }, namespace: "store" as const, userTypes: { - ResourceId: { filePath: "./src/ResourceId.sol", internalType: "bytes32" }, - FieldLayout: { filePath: "./src/FieldLayout.sol", internalType: "bytes32" }, - Schema: { filePath: "./src/Schema.sol", internalType: "bytes32" }, + ResourceId: { filePath: "./src/ResourceId.sol", type: "bytes32" }, + FieldLayout: { filePath: "./src/FieldLayout.sol", type: "bytes32" }, + Schema: { filePath: "./src/Schema.sol", type: "bytes32" }, }, tables: { StoreHooks: { - keySchema: { + schema: { tableId: "ResourceId", - }, - valueSchema: { hooks: "bytes21[]", }, + key: ["tableId"], }, Tables: { - keySchema: { + schema: { tableId: "ResourceId", - }, - valueSchema: { fieldLayout: "FieldLayout", keySchema: "Schema", valueSchema: "Schema", abiEncodedKeyNames: "bytes", abiEncodedFieldNames: "bytes", }, + key: ["tableId"], }, ResourceIds: { - keySchema: { + schema: { resourceId: "ResourceId", - }, - valueSchema: { exists: "bool", }, + key: ["resourceId"], }, // The Hooks table is a generic table used by the `filterFromList` util in `Hook.sol` Hooks: { - keySchema: { + schema: { resourceId: "ResourceId", - }, - valueSchema: { hooks: "bytes21[]", }, - tableIdArgument: true, + key: ["resourceId"], + codegen: { + tableIdArgument: true, + }, }, }, }); diff --git a/packages/store/ts/codegen/tablegen.ts b/packages/store/ts/codegen/tablegen.ts index 02cd7a62c2..baa78e8bd1 100644 --- a/packages/store/ts/codegen/tablegen.ts +++ b/packages/store/ts/codegen/tablegen.ts @@ -5,9 +5,11 @@ import { renderTable } from "./renderTable"; import { renderTypesFromConfig } from "./renderTypesFromConfig"; import { renderTableIndex } from "./renderTableIndex"; import { rm } from "fs/promises"; -import { StoreConfig } from "../config"; +import { Store as StoreConfig } from "../config/v2/output"; +import { storeToV1 } from "../config/v2/compat"; -export async function tablegen(config: StoreConfig, outputBaseDirectory: string, remappings: [string, string][]) { +export async function tablegen(configV2: StoreConfig, outputBaseDirectory: string, remappings: [string, string][]) { + const config = storeToV1(configV2); const solidityUserTypes = loadAndExtractUserTypes(config.userTypes, outputBaseDirectory, remappings); const allTableOptions = getTableOptions(config, solidityUserTypes); diff --git a/packages/store/ts/scripts/generate-test-tables.ts b/packages/store/ts/scripts/generate-test-tables.ts index 7c0ea6926c..b54bd841cf 100644 --- a/packages/store/ts/scripts/generate-test-tables.ts +++ b/packages/store/ts/scripts/generate-test-tables.ts @@ -1,41 +1,51 @@ import path from "path"; import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry"; import { tablegen } from "../codegen"; -import { mudConfig } from "../register"; +import { defineStore } from "../config/v2/store"; -const config = mudConfig({ - storeImportPath: "../../../src/", +const config = defineStore({ + codegen: { + storeImportPath: "../../../src/", + outputDirectory: "../test/codegen", + }, namespace: "store", - codegenDirectory: "../test/codegen", enums: { ExampleEnum: ["None", "First", "Second", "Third"], }, tables: { - Callbacks: "bytes24[]", + Callbacks: { + schema: { key: "bytes32", value: "bytes24[]" }, + key: ["key"], + }, Mixed: { - valueSchema: { + schema: { + key: "bytes32", u32: "uint32", u128: "uint128", a32: "uint32[]", s: "string", }, + key: ["key"], }, Vector2: { - valueSchema: { + schema: { + key: "bytes32", x: "uint32", y: "uint32", }, + key: ["key"], }, KeyEncoding: { - keySchema: { + schema: { k1: "uint256", k2: "int32", k3: "bytes16", k4: "address", k5: "bool", k6: "ExampleEnum", + value: "bool", }, - valueSchema: "bool", + key: ["k1", "k2", "k3", "k4", "k5", "k6"], }, }, }); @@ -43,4 +53,4 @@ const config = mudConfig({ const srcDir = await getSrcDirectory(); const remappings = await getRemappings(); -await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings); +await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings); diff --git a/packages/store/ts/scripts/tablegen.ts b/packages/store/ts/scripts/tablegen.ts index 6a1b7aaec3..a0a413b894 100644 --- a/packages/store/ts/scripts/tablegen.ts +++ b/packages/store/ts/scripts/tablegen.ts @@ -2,10 +2,10 @@ import path from "path"; import { loadConfig } from "@latticexyz/config/node"; import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry"; import { tablegen } from "../codegen"; -import { StoreConfig } from ".."; +import { Store as StoreConfig } from "../config/v2/output"; const config = (await loadConfig()) as StoreConfig; const srcDir = await getSrcDirectory(); const remappings = await getRemappings(); -await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings); +await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings); diff --git a/packages/world-modules/mud.config.ts b/packages/world-modules/mud.config.ts index 73629beac0..ecb008acaa 100644 --- a/packages/world-modules/mud.config.ts +++ b/packages/world-modules/mud.config.ts @@ -1,11 +1,13 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ - worldgenDirectory: "interfaces", - worldInterfaceName: "IBaseWorld", - codegenDirectory: ".", +export default defineWorld({ + codegen: { + worldgenDirectory: "interfaces", + worldInterfaceName: "IBaseWorld", + outputDirectory: ".", + }, userTypes: { - ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", internalType: "bytes32" }, + ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", type: "bytes32" }, }, tables: { /************************************************************************ @@ -14,15 +16,16 @@ export default mudConfig({ * ************************************************************************/ KeysWithValue: { - directory: "modules/keyswithvalue/tables", - keySchema: { + schema: { valueHash: "bytes32", - }, - valueSchema: { keysWithValue: "bytes32[]", // For now only supports 1 key per value }, - tableIdArgument: true, - storeArgument: true, + key: ["valueHash"], + codegen: { + outputDirectory: "modules/keyswithvalue/tables", + tableIdArgument: true, + storeArgument: true, + }, }, /************************************************************************ * @@ -30,26 +33,33 @@ export default mudConfig({ * ************************************************************************/ KeysInTable: { - directory: "modules/keysintable/tables", - keySchema: { sourceTableId: "ResourceId" }, - valueSchema: { + schema: { + sourceTableId: "ResourceId", keys0: "bytes32[]", keys1: "bytes32[]", keys2: "bytes32[]", keys3: "bytes32[]", keys4: "bytes32[]", }, - storeArgument: true, + key: ["sourceTableId"], + codegen: { + outputDirectory: "modules/keysintable/tables", + storeArgument: true, + }, }, UsedKeysIndex: { - directory: "modules/keysintable/tables", - keySchema: { + schema: { sourceTableId: "ResourceId", keysHash: "bytes32", + has: "bool", + index: "uint40", + }, + key: ["sourceTableId", "keysHash"], + codegen: { + outputDirectory: "modules/keysintable/tables", + dataStruct: false, + storeArgument: true, }, - valueSchema: { has: "bool", index: "uint40" }, - dataStruct: false, - storeArgument: true, }, /************************************************************************ * @@ -57,11 +67,15 @@ export default mudConfig({ * ************************************************************************/ UniqueEntity: { - directory: "modules/uniqueentity/tables", - keySchema: {}, - valueSchema: "uint256", - tableIdArgument: true, - storeArgument: true, + schema: { + value: "uint256", + }, + key: [], + codegen: { + outputDirectory: "modules/uniqueentity/tables", + tableIdArgument: true, + storeArgument: true, + }, }, /************************************************************************ * @@ -69,37 +83,40 @@ export default mudConfig({ * ************************************************************************/ CallboundDelegations: { - directory: "modules/std-delegations/tables", - keySchema: { + schema: { delegator: "address", delegatee: "address", systemId: "ResourceId", callDataHash: "bytes32", - }, - valueSchema: { availableCalls: "uint256", }, + key: ["delegator", "delegatee", "systemId", "callDataHash"], + codegen: { + outputDirectory: "modules/std-delegations/tables", + }, }, SystemboundDelegations: { - directory: "modules/std-delegations/tables", - keySchema: { + schema: { delegator: "address", delegatee: "address", systemId: "ResourceId", - }, - valueSchema: { availableCalls: "uint256", }, + key: ["delegator", "delegatee", "systemId"], + codegen: { + outputDirectory: "modules/std-delegations/tables", + }, }, TimeboundDelegations: { - directory: "modules/std-delegations/tables", - keySchema: { + schema: { delegator: "address", delegatee: "address", - }, - valueSchema: { maxTimestamp: "uint256", }, + key: ["delegator", "delegatee"], + codegen: { + outputDirectory: "modules/std-delegations/tables", + }, }, /************************************************************************ * @@ -107,14 +124,15 @@ export default mudConfig({ * ************************************************************************/ PuppetRegistry: { - directory: "modules/puppet/tables", - keySchema: { + schema: { systemId: "ResourceId", - }, - valueSchema: { puppet: "address", }, - tableIdArgument: true, + key: ["systemId"], + codegen: { + outputDirectory: "modules/puppet/tables", + tableIdArgument: true, + }, }, /************************************************************************ * @@ -122,14 +140,15 @@ export default mudConfig({ * ************************************************************************/ Balances: { - directory: "modules/tokens/tables", - keySchema: { + schema: { account: "address", - }, - valueSchema: { value: "uint256", }, - tableIdArgument: true, + key: ["account"], + codegen: { + outputDirectory: "modules/tokens/tables", + tableIdArgument: true, + }, }, /************************************************************************ * @@ -137,43 +156,49 @@ export default mudConfig({ * ************************************************************************/ ERC20Metadata: { - directory: "modules/erc20-puppet/tables", - keySchema: {}, - valueSchema: { + schema: { decimals: "uint8", name: "string", symbol: "string", }, - tableIdArgument: true, + key: [], + codegen: { + outputDirectory: "modules/erc20-puppet/tables", + tableIdArgument: true, + }, }, Allowances: { - directory: "modules/erc20-puppet/tables", - keySchema: { + schema: { account: "address", spender: "address", - }, - valueSchema: { value: "uint256", }, - tableIdArgument: true, + key: ["account", "spender"], + codegen: { + outputDirectory: "modules/erc20-puppet/tables", + tableIdArgument: true, + }, }, TotalSupply: { - directory: "modules/erc20-puppet/tables", - keySchema: {}, - valueSchema: { + schema: { totalSupply: "uint256", }, - tableIdArgument: true, + key: [], + codegen: { + outputDirectory: "modules/erc20-puppet/tables", + tableIdArgument: true, + }, }, ERC20Registry: { - directory: "modules/erc20-puppet/tables", - keySchema: { + schema: { namespaceId: "ResourceId", - }, - valueSchema: { tokenAddress: "address", }, - tableIdArgument: true, + key: ["namespaceId"], + codegen: { + outputDirectory: "modules/erc20-puppet/tables", + tableIdArgument: true, + }, }, /************************************************************************ * @@ -181,65 +206,72 @@ export default mudConfig({ * ************************************************************************/ ERC721Metadata: { - directory: "modules/erc721-puppet/tables", - keySchema: {}, - valueSchema: { + schema: { name: "string", symbol: "string", baseURI: "string", }, - tableIdArgument: true, + key: [], + codegen: { + outputDirectory: "modules/erc721-puppet/tables", + tableIdArgument: true, + }, }, TokenURI: { - directory: "modules/erc721-puppet/tables", - keySchema: { + schema: { tokenId: "uint256", - }, - valueSchema: { tokenURI: "string", }, - tableIdArgument: true, + key: ["tokenId"], + codegen: { + outputDirectory: "modules/erc721-puppet/tables", + tableIdArgument: true, + }, }, Owners: { - directory: "modules/erc721-puppet/tables", - keySchema: { + schema: { tokenId: "uint256", - }, - valueSchema: { owner: "address", }, - tableIdArgument: true, + key: ["tokenId"], + codegen: { + outputDirectory: "modules/erc721-puppet/tables", + tableIdArgument: true, + }, }, TokenApproval: { - directory: "modules/erc721-puppet/tables", - keySchema: { + schema: { tokenId: "uint256", - }, - valueSchema: { account: "address", }, - tableIdArgument: true, + key: ["tokenId"], + codegen: { + outputDirectory: "modules/erc721-puppet/tables", + tableIdArgument: true, + }, }, OperatorApproval: { - directory: "modules/erc721-puppet/tables", - keySchema: { + schema: { owner: "address", operator: "address", - }, - valueSchema: { approved: "bool", }, - tableIdArgument: true, + key: ["owner", "operator"], + codegen: { + outputDirectory: "modules/erc721-puppet/tables", + tableIdArgument: true, + }, }, ERC721Registry: { - directory: "modules/erc721-puppet/tables", - keySchema: { + schema: { namespaceId: "ResourceId", - }, - valueSchema: { tokenAddress: "address", }, - tableIdArgument: true, + key: ["namespaceId"], + codegen: { + outputDirectory: "modules/erc721-puppet/tables", + tableIdArgument: true, + }, }, }, excludeSystems: ["UniqueEntitySystem", "PuppetFactorySystem", "ERC20System", "ERC721System"], diff --git a/packages/world-modules/ts/scripts/tablegen.ts b/packages/world-modules/ts/scripts/tablegen.ts index 5a91d6d119..e33ecfa8bd 100644 --- a/packages/world-modules/ts/scripts/tablegen.ts +++ b/packages/world-modules/ts/scripts/tablegen.ts @@ -1,11 +1,11 @@ import path from "path"; import { loadConfig } from "@latticexyz/config/node"; import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry"; -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { tablegen } from "@latticexyz/store/codegen"; const config = (await loadConfig()) as StoreConfig; const srcDir = await getSrcDirectory(); const remappings = await getRemappings(); -await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings); +await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings); diff --git a/packages/world-modules/ts/scripts/worldgen.ts b/packages/world-modules/ts/scripts/worldgen.ts index 09b2b09a2e..e16a203f3f 100644 --- a/packages/world-modules/ts/scripts/worldgen.ts +++ b/packages/world-modules/ts/scripts/worldgen.ts @@ -3,9 +3,8 @@ import path, { basename } from "path"; import { rmSync } from "fs"; import { loadConfig } from "@latticexyz/config/node"; import { getSrcDirectory } from "@latticexyz/common/foundry"; -import { WorldConfig } from "@latticexyz/world"; +import { World as WorldConfig } from "@latticexyz/world/config/v2"; import { worldgen } from "@latticexyz/world/node"; -import { StoreConfig } from "@latticexyz/store"; // TODO dedupe this and cli's worldgen command const configPath = undefined; @@ -19,12 +18,14 @@ const existingContracts = glob.sync(`${srcDir}/**/*.sol`).map((path) => ({ })); // Load and resolve the config -const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig; +const mudConfig = (await loadConfig(configPath)) as WorldConfig; -const outputBaseDirectory = path.join(srcDir, mudConfig.codegenDirectory); +const outputBaseDirectory = path.join(srcDir, mudConfig.codegen.outputDirectory); // clear the worldgen directory -if (clean) rmSync(path.join(outputBaseDirectory, mudConfig.worldgenDirectory), { recursive: true, force: true }); +if (clean) { + rmSync(path.join(outputBaseDirectory, mudConfig.codegen.worldgenDirectory), { recursive: true, force: true }); +} // generate new interfaces await worldgen(mudConfig, existingContracts, outputBaseDirectory); diff --git a/packages/world/mud.config.ts b/packages/world/mud.config.ts index dce3430995..882c4599a3 100644 --- a/packages/world/mud.config.ts +++ b/packages/world/mud.config.ts @@ -1,111 +1,108 @@ -import { mudConfig } from "./ts/register"; +import { defineWorld } from "./ts/config/v2/world"; -export default mudConfig({ - worldImportPath: "../../", - worldgenDirectory: "interfaces", - worldInterfaceName: "IBaseWorld", +export default defineWorld({ + codegen: { + worldImportPath: "../../", + worldgenDirectory: "interfaces", + worldInterfaceName: "IBaseWorld", + }, namespace: "world" as const, // NOTE: this namespace is only used for tables, the core system is deployed in the root namespace. userTypes: { - ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", internalType: "bytes32" }, + ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", type: "bytes32" }, }, tables: { NamespaceOwner: { - keySchema: { + schema: { namespaceId: "ResourceId", - }, - valueSchema: { owner: "address", }, + key: ["namespaceId"], }, ResourceAccess: { - keySchema: { + schema: { resourceId: "ResourceId", caller: "address", - }, - valueSchema: { access: "bool", }, + key: ["resourceId", "caller"], }, InstalledModules: { - keySchema: { + schema: { moduleAddress: "address", argumentsHash: "bytes32", // Hash of the params passed to the `install` function - }, - valueSchema: { isInstalled: "bool", }, + key: ["moduleAddress", "argumentsHash"], }, UserDelegationControl: { - keySchema: { + schema: { delegator: "address", delegatee: "address", - }, - valueSchema: { delegationControlId: "ResourceId", }, + key: ["delegator", "delegatee"], }, NamespaceDelegationControl: { - keySchema: { + schema: { namespaceId: "ResourceId", - }, - valueSchema: { delegationControlId: "ResourceId", }, + key: ["namespaceId"], }, Balances: { - keySchema: { + schema: { namespaceId: "ResourceId", - }, - valueSchema: { balance: "uint256", }, + key: ["namespaceId"], }, Systems: { - keySchema: { + schema: { systemId: "ResourceId", - }, - valueSchema: { system: "address", publicAccess: "bool", }, - dataStruct: false, + key: ["systemId"], + codegen: { + dataStruct: false, + }, }, SystemRegistry: { - keySchema: { + schema: { system: "address", - }, - valueSchema: { systemId: "ResourceId", }, + key: ["system"], }, SystemHooks: { - keySchema: { + schema: { systemId: "ResourceId", + value: "bytes21[]", }, - valueSchema: "bytes21[]", + key: ["systemId"], }, FunctionSelectors: { - keySchema: { + schema: { worldFunctionSelector: "bytes4", - }, - valueSchema: { systemId: "ResourceId", systemFunctionSelector: "bytes4", }, - dataStruct: false, + key: ["worldFunctionSelector"], + codegen: { dataStruct: false }, }, FunctionSignatures: { - keySchema: { + type: "offchainTable", + schema: { functionSelector: "bytes4", - }, - valueSchema: { functionSignature: "string", }, - offchainOnly: true, + key: ["functionSelector"], }, InitModuleAddress: { - keySchema: {}, - valueSchema: "address", + schema: { + value: "address", + }, + key: [], }, }, excludeSystems: [ diff --git a/packages/world/ts/config/v2/index.ts b/packages/world/ts/config/v2/index.ts index 2617149780..72e637ef7e 100644 --- a/packages/world/ts/config/v2/index.ts +++ b/packages/world/ts/config/v2/index.ts @@ -1,2 +1,3 @@ export * from "./world"; export * from "./output"; +export * from "./compat"; diff --git a/packages/world/ts/node/render-solidity/worldgen.ts b/packages/world/ts/node/render-solidity/worldgen.ts index af5313ead3..ff704e0db2 100644 --- a/packages/world/ts/node/render-solidity/worldgen.ts +++ b/packages/world/ts/node/render-solidity/worldgen.ts @@ -1,17 +1,18 @@ import { readFileSync } from "fs"; import path from "path"; import { formatAndWriteSolidity, contractToInterface, type RelativeImportDatum } from "@latticexyz/common/codegen"; -import { StoreConfig } from "@latticexyz/store"; import { renderSystemInterface } from "./renderSystemInterface"; import { renderWorldInterface } from "./renderWorldInterface"; import { resolveWorldConfig } from "../../config/resolveWorldConfig"; -import { WorldConfig } from "../../config/types"; +import { World as WorldConfig } from "../../config/v2/output"; +import { worldToV1 } from "../../config/v2/compat"; export async function worldgen( - config: StoreConfig & WorldConfig, + configV2: WorldConfig, existingContracts: { path: string; basename: string }[], outputBaseDirectory: string, ) { + const config = worldToV1(configV2); const resolvedConfig = resolveWorldConfig( config, existingContracts.map(({ basename }) => basename), diff --git a/packages/world/ts/scripts/generate-test-tables.ts b/packages/world/ts/scripts/generate-test-tables.ts index 1ae80c1ede..8c70024133 100644 --- a/packages/world/ts/scripts/generate-test-tables.ts +++ b/packages/world/ts/scripts/generate-test-tables.ts @@ -1,33 +1,40 @@ import path from "path"; import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry"; import { tablegen } from "@latticexyz/store/codegen"; -import { mudConfig } from "../register"; +import { defineWorld } from "../config/v2/world"; -const config = mudConfig({ - codegenDirectory: "../test/codegen", +const config = defineWorld({ + codegen: { + outputDirectory: "../test/codegen", + }, tables: { Bool: { - keySchema: {}, - valueSchema: { + schema: { value: "bool", }, - tableIdArgument: true, + key: [], + codegen: { tableIdArgument: true }, }, TwoFields: { - keySchema: {}, - valueSchema: { + schema: { value1: "bool", value2: "bool", }, - tableIdArgument: true, + key: [], + codegen: { tableIdArgument: true }, }, AddressArray: { - valueSchema: "address[]", - tableIdArgument: true, + schema: { + key: "bytes32", + value: "address[]", + }, + key: ["key"], + codegen: { tableIdArgument: true }, }, }, }); + const srcDir = await getSrcDirectory(); const remappings = await getRemappings(); -await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings); +await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings); diff --git a/packages/world/ts/scripts/list-tables-from-store-and-world-configs.ts b/packages/world/ts/scripts/list-tables-from-store-and-world-configs.ts index 6bbdea2d08..6b0a8e19d7 100644 --- a/packages/world/ts/scripts/list-tables-from-store-and-world-configs.ts +++ b/packages/world/ts/scripts/list-tables-from-store-and-world-configs.ts @@ -1,27 +1,11 @@ -import { type Hex } from "viem"; - -import { type ExpandMUDUserConfig } from "@latticexyz/store/register"; -import { type MUDCoreUserConfig } from "@latticexyz/config/library"; - -import { resourceToHex } from "@latticexyz/common"; - import storeConfig from "@latticexyz/store/mud.config"; import worldConfig from "../../mud.config"; -function configToTables(config: ExpandMUDUserConfig): { name: string; id: Hex }[] { - return ( - Object.entries(config.tables) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .filter(([_, table]) => !table.tableIdArgument) // Skip generic tables - .map(([name, table]) => ({ - name: name, - id: resourceToHex({ - type: table.offchainOnly ? "offchainTable" : "table", - namespace: config.namespace, - name: table.name, - }), - })) - ); -} - -console.log(JSON.stringify([...configToTables(storeConfig), ...configToTables(worldConfig)])); +console.log( + JSON.stringify( + [...Object.values(storeConfig.tables), ...Object.values(worldConfig.tables)] + // Skip generic tables + .filter((table) => !table.codegen.tableIdArgument) + .map((table) => ({ name: table.name, id: table.tableId })), + ), +); diff --git a/packages/world/ts/scripts/tablegen.ts b/packages/world/ts/scripts/tablegen.ts index 5a91d6d119..e33ecfa8bd 100644 --- a/packages/world/ts/scripts/tablegen.ts +++ b/packages/world/ts/scripts/tablegen.ts @@ -1,11 +1,11 @@ import path from "path"; import { loadConfig } from "@latticexyz/config/node"; import { getRemappings, getSrcDirectory } from "@latticexyz/common/foundry"; -import { StoreConfig } from "@latticexyz/store"; +import { Store as StoreConfig } from "@latticexyz/store/config/v2"; import { tablegen } from "@latticexyz/store/codegen"; const config = (await loadConfig()) as StoreConfig; const srcDir = await getSrcDirectory(); const remappings = await getRemappings(); -await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings); +await tablegen(config, path.join(srcDir, config.codegen.outputDirectory), remappings); diff --git a/packages/world/ts/scripts/worldgen.ts b/packages/world/ts/scripts/worldgen.ts index 6eedbc3706..90955971b3 100644 --- a/packages/world/ts/scripts/worldgen.ts +++ b/packages/world/ts/scripts/worldgen.ts @@ -4,8 +4,7 @@ import { rmSync } from "fs"; import { loadConfig } from "@latticexyz/config/node"; import { getSrcDirectory } from "@latticexyz/common/foundry"; import { worldgen } from "../node"; -import { StoreConfig } from "@latticexyz/store"; -import { WorldConfig } from "../config/types"; +import { World as WorldConfig } from "../config/v2/output"; // TODO dedupe this and cli's worldgen command const configPath = undefined; @@ -19,12 +18,14 @@ const existingContracts = glob.sync(`${srcDir}/**/*.sol`).map((path) => ({ })); // Load and resolve the config -const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig; +const mudConfig = (await loadConfig(configPath)) as WorldConfig; -const outputBaseDirectory = path.join(srcDir, mudConfig.codegenDirectory); +const outputBaseDirectory = path.join(srcDir, mudConfig.codegen.outputDirectory); // clear the worldgen directory -if (clean) rmSync(path.join(outputBaseDirectory, mudConfig.worldgenDirectory), { recursive: true, force: true }); +if (clean) { + rmSync(path.join(outputBaseDirectory, mudConfig.codegen.worldgenDirectory), { recursive: true, force: true }); +} // generate new interfaces // override the namespace to be the root namespace for generating the core system interface diff --git a/templates/phaser/packages/contracts/mud.config.ts b/templates/phaser/packages/contracts/mud.config.ts index 70edda1693..1be4a87791 100644 --- a/templates/phaser/packages/contracts/mud.config.ts +++ b/templates/phaser/packages/contracts/mud.config.ts @@ -1,10 +1,12 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ tables: { Counter: { - keySchema: {}, - valueSchema: "uint32", + schema: { + value: "uint32", + }, + key: [], }, }, }); diff --git a/templates/react-ecs/packages/contracts/mud.config.ts b/templates/react-ecs/packages/contracts/mud.config.ts index 70edda1693..1be4a87791 100644 --- a/templates/react-ecs/packages/contracts/mud.config.ts +++ b/templates/react-ecs/packages/contracts/mud.config.ts @@ -1,10 +1,12 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ tables: { Counter: { - keySchema: {}, - valueSchema: "uint32", + schema: { + value: "uint32", + }, + key: [], }, }, }); diff --git a/templates/react/packages/client/src/App.tsx b/templates/react/packages/client/src/App.tsx index 4ac69bc4c7..82c60486a9 100644 --- a/templates/react/packages/client/src/App.tsx +++ b/templates/react/packages/client/src/App.tsx @@ -31,7 +31,7 @@ export const App = () => { checkbox.disabled = true; try { - await toggleTask(task.key.key); + await toggleTask(task.key.id); } finally { checkbox.disabled = false; } @@ -51,7 +51,7 @@ export const App = () => { const button = event.currentTarget; button.disabled = true; try { - await deleteTask(task.key.key); + await deleteTask(task.key.id); } finally { button.disabled = false; } diff --git a/templates/react/packages/client/src/mud/createSystemCalls.ts b/templates/react/packages/client/src/mud/createSystemCalls.ts index d7714ec453..a7447d143c 100644 --- a/templates/react/packages/client/src/mud/createSystemCalls.ts +++ b/templates/react/packages/client/src/mud/createSystemCalls.ts @@ -35,14 +35,14 @@ export function createSystemCalls( await waitForTransaction(tx); }; - const toggleTask = async (key: Hex) => { - const isComplete = (useStore.getState().getValue(tables.Tasks, { key })?.completedAt ?? 0n) > 0n; - const tx = isComplete ? await worldContract.write.resetTask([key]) : await worldContract.write.completeTask([key]); + const toggleTask = async (id: Hex) => { + const isComplete = (useStore.getState().getValue(tables.Tasks, { id })?.completedAt ?? 0n) > 0n; + const tx = isComplete ? await worldContract.write.resetTask([id]) : await worldContract.write.completeTask([id]); await waitForTransaction(tx); }; - const deleteTask = async (key: Hex) => { - const tx = await worldContract.write.deleteTask([key]); + const deleteTask = async (id: Hex) => { + const tx = await worldContract.write.deleteTask([id]); await waitForTransaction(tx); }; diff --git a/templates/react/packages/contracts/mud.config.ts b/templates/react/packages/contracts/mud.config.ts index b10f2d5893..f10a28e3eb 100644 --- a/templates/react/packages/contracts/mud.config.ts +++ b/templates/react/packages/contracts/mud.config.ts @@ -1,13 +1,15 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ tables: { Tasks: { - valueSchema: { + schema: { + id: "bytes32", createdAt: "uint256", completedAt: "uint256", description: "string", }, + key: ["id"], }, }, }); diff --git a/templates/react/packages/contracts/src/codegen/tables/Tasks.sol b/templates/react/packages/contracts/src/codegen/tables/Tasks.sol index f14b49f6a3..454d03032d 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Tasks.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Tasks.sol @@ -40,7 +40,7 @@ library Tasks { */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](1); - keyNames[0] = "key"; + keyNames[0] = "id"; } /** @@ -71,9 +71,9 @@ library Tasks { /** * @notice Get createdAt. */ - function getCreatedAt(bytes32 key) internal view returns (uint256 createdAt) { + function getCreatedAt(bytes32 id) internal view returns (uint256 createdAt) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); @@ -82,9 +82,9 @@ library Tasks { /** * @notice Get createdAt. */ - function _getCreatedAt(bytes32 key) internal view returns (uint256 createdAt) { + function _getCreatedAt(bytes32 id) internal view returns (uint256 createdAt) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (uint256(bytes32(_blob))); @@ -93,9 +93,9 @@ library Tasks { /** * @notice Set createdAt. */ - function setCreatedAt(bytes32 key, uint256 createdAt) internal { + function setCreatedAt(bytes32 id, uint256 createdAt) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((createdAt)), _fieldLayout); } @@ -103,9 +103,9 @@ library Tasks { /** * @notice Set createdAt. */ - function _setCreatedAt(bytes32 key, uint256 createdAt) internal { + function _setCreatedAt(bytes32 id, uint256 createdAt) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((createdAt)), _fieldLayout); } @@ -113,9 +113,9 @@ library Tasks { /** * @notice Get completedAt. */ - function getCompletedAt(bytes32 key) internal view returns (uint256 completedAt) { + function getCompletedAt(bytes32 id) internal view returns (uint256 completedAt) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (uint256(bytes32(_blob))); @@ -124,9 +124,9 @@ library Tasks { /** * @notice Get completedAt. */ - function _getCompletedAt(bytes32 key) internal view returns (uint256 completedAt) { + function _getCompletedAt(bytes32 id) internal view returns (uint256 completedAt) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (uint256(bytes32(_blob))); @@ -135,9 +135,9 @@ library Tasks { /** * @notice Set completedAt. */ - function setCompletedAt(bytes32 key, uint256 completedAt) internal { + function setCompletedAt(bytes32 id, uint256 completedAt) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((completedAt)), _fieldLayout); } @@ -145,9 +145,9 @@ library Tasks { /** * @notice Set completedAt. */ - function _setCompletedAt(bytes32 key, uint256 completedAt) internal { + function _setCompletedAt(bytes32 id, uint256 completedAt) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((completedAt)), _fieldLayout); } @@ -155,9 +155,9 @@ library Tasks { /** * @notice Get description. */ - function getDescription(bytes32 key) internal view returns (string memory description) { + function getDescription(bytes32 id) internal view returns (string memory description) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes memory _blob = StoreSwitch.getDynamicField(_tableId, _keyTuple, 0); return (string(_blob)); @@ -166,9 +166,9 @@ library Tasks { /** * @notice Get description. */ - function _getDescription(bytes32 key) internal view returns (string memory description) { + function _getDescription(bytes32 id) internal view returns (string memory description) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes memory _blob = StoreCore.getDynamicField(_tableId, _keyTuple, 0); return (string(_blob)); @@ -177,9 +177,9 @@ library Tasks { /** * @notice Set description. */ - function setDescription(bytes32 key, string memory description) internal { + function setDescription(bytes32 id, string memory description) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setDynamicField(_tableId, _keyTuple, 0, bytes((description))); } @@ -187,9 +187,9 @@ library Tasks { /** * @notice Set description. */ - function _setDescription(bytes32 key, string memory description) internal { + function _setDescription(bytes32 id, string memory description) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setDynamicField(_tableId, _keyTuple, 0, bytes((description))); } @@ -197,9 +197,9 @@ library Tasks { /** * @notice Get the length of description. */ - function lengthDescription(bytes32 key) internal view returns (uint256) { + function lengthDescription(bytes32 id) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; uint256 _byteLength = StoreSwitch.getDynamicFieldLength(_tableId, _keyTuple, 0); unchecked { @@ -210,9 +210,9 @@ library Tasks { /** * @notice Get the length of description. */ - function _lengthDescription(bytes32 key) internal view returns (uint256) { + function _lengthDescription(bytes32 id) internal view returns (uint256) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; uint256 _byteLength = StoreCore.getDynamicFieldLength(_tableId, _keyTuple, 0); unchecked { @@ -224,9 +224,9 @@ library Tasks { * @notice Get an item of description. * @dev Reverts with Store_IndexOutOfBounds if `_index` is out of bounds for the array. */ - function getItemDescription(bytes32 key, uint256 _index) internal view returns (string memory) { + function getItemDescription(bytes32 id, uint256 _index) internal view returns (string memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; unchecked { bytes memory _blob = StoreSwitch.getDynamicFieldSlice(_tableId, _keyTuple, 0, _index * 1, (_index + 1) * 1); @@ -238,9 +238,9 @@ library Tasks { * @notice Get an item of description. * @dev Reverts with Store_IndexOutOfBounds if `_index` is out of bounds for the array. */ - function _getItemDescription(bytes32 key, uint256 _index) internal view returns (string memory) { + function _getItemDescription(bytes32 id, uint256 _index) internal view returns (string memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; unchecked { bytes memory _blob = StoreCore.getDynamicFieldSlice(_tableId, _keyTuple, 0, _index * 1, (_index + 1) * 1); @@ -251,9 +251,9 @@ library Tasks { /** * @notice Push a slice to description. */ - function pushDescription(bytes32 key, string memory _slice) internal { + function pushDescription(bytes32 id, string memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.pushToDynamicField(_tableId, _keyTuple, 0, bytes((_slice))); } @@ -261,9 +261,9 @@ library Tasks { /** * @notice Push a slice to description. */ - function _pushDescription(bytes32 key, string memory _slice) internal { + function _pushDescription(bytes32 id, string memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.pushToDynamicField(_tableId, _keyTuple, 0, bytes((_slice))); } @@ -271,9 +271,9 @@ library Tasks { /** * @notice Pop a slice from description. */ - function popDescription(bytes32 key) internal { + function popDescription(bytes32 id) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.popFromDynamicField(_tableId, _keyTuple, 0, 1); } @@ -281,9 +281,9 @@ library Tasks { /** * @notice Pop a slice from description. */ - function _popDescription(bytes32 key) internal { + function _popDescription(bytes32 id) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.popFromDynamicField(_tableId, _keyTuple, 0, 1); } @@ -291,9 +291,9 @@ library Tasks { /** * @notice Update a slice of description at `_index`. */ - function updateDescription(bytes32 key, uint256 _index, string memory _slice) internal { + function updateDescription(bytes32 id, uint256 _index, string memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; unchecked { bytes memory _encoded = bytes((_slice)); @@ -304,9 +304,9 @@ library Tasks { /** * @notice Update a slice of description at `_index`. */ - function _updateDescription(bytes32 key, uint256 _index, string memory _slice) internal { + function _updateDescription(bytes32 id, uint256 _index, string memory _slice) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; unchecked { bytes memory _encoded = bytes((_slice)); @@ -317,9 +317,9 @@ library Tasks { /** * @notice Get the full data. */ - function get(bytes32 key) internal view returns (TasksData memory _table) { + function get(bytes32 id) internal view returns (TasksData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( _tableId, @@ -332,9 +332,9 @@ library Tasks { /** * @notice Get the full data. */ - function _get(bytes32 key) internal view returns (TasksData memory _table) { + function _get(bytes32 id) internal view returns (TasksData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( _tableId, @@ -347,14 +347,14 @@ library Tasks { /** * @notice Set the full data using individual values. */ - function set(bytes32 key, uint256 createdAt, uint256 completedAt, string memory description) internal { + function set(bytes32 id, uint256 createdAt, uint256 completedAt, string memory description) internal { bytes memory _staticData = encodeStatic(createdAt, completedAt); PackedCounter _encodedLengths = encodeLengths(description); bytes memory _dynamicData = encodeDynamic(description); bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData); } @@ -362,14 +362,14 @@ library Tasks { /** * @notice Set the full data using individual values. */ - function _set(bytes32 key, uint256 createdAt, uint256 completedAt, string memory description) internal { + function _set(bytes32 id, uint256 createdAt, uint256 completedAt, string memory description) internal { bytes memory _staticData = encodeStatic(createdAt, completedAt); PackedCounter _encodedLengths = encodeLengths(description); bytes memory _dynamicData = encodeDynamic(description); bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } @@ -377,14 +377,14 @@ library Tasks { /** * @notice Set the full data using the data struct. */ - function set(bytes32 key, TasksData memory _table) internal { + function set(bytes32 id, TasksData memory _table) internal { bytes memory _staticData = encodeStatic(_table.createdAt, _table.completedAt); PackedCounter _encodedLengths = encodeLengths(_table.description); bytes memory _dynamicData = encodeDynamic(_table.description); bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData); } @@ -392,14 +392,14 @@ library Tasks { /** * @notice Set the full data using the data struct. */ - function _set(bytes32 key, TasksData memory _table) internal { + function _set(bytes32 id, TasksData memory _table) internal { bytes memory _staticData = encodeStatic(_table.createdAt, _table.completedAt); PackedCounter _encodedLengths = encodeLengths(_table.description); bytes memory _dynamicData = encodeDynamic(_table.description); bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } @@ -447,9 +447,9 @@ library Tasks { /** * @notice Delete all data for given keys. */ - function deleteRecord(bytes32 key) internal { + function deleteRecord(bytes32 id) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.deleteRecord(_tableId, _keyTuple); } @@ -457,9 +457,9 @@ library Tasks { /** * @notice Delete all data for given keys. */ - function _deleteRecord(bytes32 key) internal { + function _deleteRecord(bytes32 id) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } @@ -513,9 +513,9 @@ library Tasks { /** * @notice Encode keys as a bytes32 array using this table's field layout. */ - function encodeKeyTuple(bytes32 key) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 id) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; return _keyTuple; } diff --git a/templates/react/packages/contracts/src/codegen/world/ITasksSystem.sol b/templates/react/packages/contracts/src/codegen/world/ITasksSystem.sol index 4a18791ccf..bfddd5c830 100644 --- a/templates/react/packages/contracts/src/codegen/world/ITasksSystem.sol +++ b/templates/react/packages/contracts/src/codegen/world/ITasksSystem.sol @@ -9,11 +9,11 @@ pragma solidity >=0.8.24; * @dev This interface is automatically generated from the corresponding system contract. Do not edit manually. */ interface ITasksSystem { - function addTask(string memory description) external returns (bytes32 key); + function addTask(string memory description) external returns (bytes32 id); - function completeTask(bytes32 key) external; + function completeTask(bytes32 id) external; - function resetTask(bytes32 key) external; + function resetTask(bytes32 id) external; - function deleteTask(bytes32 key) external; + function deleteTask(bytes32 id) external; } diff --git a/templates/react/packages/contracts/src/systems/TasksSystem.sol b/templates/react/packages/contracts/src/systems/TasksSystem.sol index 9574e202c9..e9a5654f2c 100644 --- a/templates/react/packages/contracts/src/systems/TasksSystem.sol +++ b/templates/react/packages/contracts/src/systems/TasksSystem.sol @@ -5,20 +5,20 @@ import { System } from "@latticexyz/world/src/System.sol"; import { Tasks, TasksData } from "../codegen/index.sol"; contract TasksSystem is System { - function addTask(string memory description) public returns (bytes32 key) { - key = keccak256(abi.encode(block.prevrandao, _msgSender(), description)); - Tasks.set(key, TasksData({ description: description, createdAt: block.timestamp, completedAt: 0 })); + function addTask(string memory description) public returns (bytes32 id) { + id = keccak256(abi.encode(block.prevrandao, _msgSender(), description)); + Tasks.set(id, TasksData({ description: description, createdAt: block.timestamp, completedAt: 0 })); } - function completeTask(bytes32 key) public { - Tasks.setCompletedAt(key, block.timestamp); + function completeTask(bytes32 id) public { + Tasks.setCompletedAt(id, block.timestamp); } - function resetTask(bytes32 key) public { - Tasks.setCompletedAt(key, 0); + function resetTask(bytes32 id) public { + Tasks.setCompletedAt(id, 0); } - function deleteTask(bytes32 key) public { - Tasks.deleteRecord(key); + function deleteTask(bytes32 id) public { + Tasks.deleteRecord(id); } } diff --git a/templates/threejs/packages/contracts/mud.config.ts b/templates/threejs/packages/contracts/mud.config.ts index 6ee5c6a809..e8b8f855d6 100644 --- a/templates/threejs/packages/contracts/mud.config.ts +++ b/templates/threejs/packages/contracts/mud.config.ts @@ -1,13 +1,15 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ tables: { Position: { - valueSchema: { + schema: { + id: "bytes32", x: "int32", y: "int32", z: "int32", }, + key: ["id"], }, }, }); diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index 6f405bf0e3..3a8edfb588 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -40,7 +40,7 @@ library Position { */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](1); - keyNames[0] = "key"; + keyNames[0] = "id"; } /** @@ -71,9 +71,9 @@ library Position { /** * @notice Get x. */ - function getX(bytes32 key) internal view returns (int32 x) { + function getX(bytes32 id) internal view returns (int32 x) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (int32(uint32(bytes4(_blob)))); @@ -82,9 +82,9 @@ library Position { /** * @notice Get x. */ - function _getX(bytes32 key) internal view returns (int32 x) { + function _getX(bytes32 id) internal view returns (int32 x) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 0, _fieldLayout); return (int32(uint32(bytes4(_blob)))); @@ -93,9 +93,9 @@ library Position { /** * @notice Set x. */ - function setX(bytes32 key, int32 x) internal { + function setX(bytes32 id, int32 x) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } @@ -103,9 +103,9 @@ library Position { /** * @notice Set x. */ - function _setX(bytes32 key, int32 x) internal { + function _setX(bytes32 id, int32 x) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setStaticField(_tableId, _keyTuple, 0, abi.encodePacked((x)), _fieldLayout); } @@ -113,9 +113,9 @@ library Position { /** * @notice Get y. */ - function getY(bytes32 key) internal view returns (int32 y) { + function getY(bytes32 id) internal view returns (int32 y) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(bytes4(_blob)))); @@ -124,9 +124,9 @@ library Position { /** * @notice Get y. */ - function _getY(bytes32 key) internal view returns (int32 y) { + function _getY(bytes32 id) internal view returns (int32 y) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 1, _fieldLayout); return (int32(uint32(bytes4(_blob)))); @@ -135,9 +135,9 @@ library Position { /** * @notice Set y. */ - function setY(bytes32 key, int32 y) internal { + function setY(bytes32 id, int32 y) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } @@ -145,9 +145,9 @@ library Position { /** * @notice Set y. */ - function _setY(bytes32 key, int32 y) internal { + function _setY(bytes32 id, int32 y) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setStaticField(_tableId, _keyTuple, 1, abi.encodePacked((y)), _fieldLayout); } @@ -155,9 +155,9 @@ library Position { /** * @notice Get z. */ - function getZ(bytes32 key) internal view returns (int32 z) { + function getZ(bytes32 id) internal view returns (int32 z) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreSwitch.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); return (int32(uint32(bytes4(_blob)))); @@ -166,9 +166,9 @@ library Position { /** * @notice Get z. */ - function _getZ(bytes32 key) internal view returns (int32 z) { + function _getZ(bytes32 id) internal view returns (int32 z) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; bytes32 _blob = StoreCore.getStaticField(_tableId, _keyTuple, 2, _fieldLayout); return (int32(uint32(bytes4(_blob)))); @@ -177,9 +177,9 @@ library Position { /** * @notice Set z. */ - function setZ(bytes32 key, int32 z) internal { + function setZ(bytes32 id, int32 z) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setStaticField(_tableId, _keyTuple, 2, abi.encodePacked((z)), _fieldLayout); } @@ -187,9 +187,9 @@ library Position { /** * @notice Set z. */ - function _setZ(bytes32 key, int32 z) internal { + function _setZ(bytes32 id, int32 z) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setStaticField(_tableId, _keyTuple, 2, abi.encodePacked((z)), _fieldLayout); } @@ -197,9 +197,9 @@ library Position { /** * @notice Get the full data. */ - function get(bytes32 key) internal view returns (PositionData memory _table) { + function get(bytes32 id) internal view returns (PositionData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( _tableId, @@ -212,9 +212,9 @@ library Position { /** * @notice Get the full data. */ - function _get(bytes32 key) internal view returns (PositionData memory _table) { + function _get(bytes32 id) internal view returns (PositionData memory _table) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( _tableId, @@ -227,14 +227,14 @@ library Position { /** * @notice Set the full data using individual values. */ - function set(bytes32 key, int32 x, int32 y, int32 z) internal { + function set(bytes32 id, int32 x, int32 y, int32 z) internal { bytes memory _staticData = encodeStatic(x, y, z); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData); } @@ -242,14 +242,14 @@ library Position { /** * @notice Set the full data using individual values. */ - function _set(bytes32 key, int32 x, int32 y, int32 z) internal { + function _set(bytes32 id, int32 x, int32 y, int32 z) internal { bytes memory _staticData = encodeStatic(x, y, z); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } @@ -257,14 +257,14 @@ library Position { /** * @notice Set the full data using the data struct. */ - function set(bytes32 key, PositionData memory _table) internal { + function set(bytes32 id, PositionData memory _table) internal { bytes memory _staticData = encodeStatic(_table.x, _table.y, _table.z); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData); } @@ -272,14 +272,14 @@ library Position { /** * @notice Set the full data using the data struct. */ - function _set(bytes32 key, PositionData memory _table) internal { + function _set(bytes32 id, PositionData memory _table) internal { bytes memory _staticData = encodeStatic(_table.x, _table.y, _table.z); PackedCounter _encodedLengths; bytes memory _dynamicData; bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } @@ -312,9 +312,9 @@ library Position { /** * @notice Delete all data for given keys. */ - function deleteRecord(bytes32 key) internal { + function deleteRecord(bytes32 id) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreSwitch.deleteRecord(_tableId, _keyTuple); } @@ -322,9 +322,9 @@ library Position { /** * @notice Delete all data for given keys. */ - function _deleteRecord(bytes32 key) internal { + function _deleteRecord(bytes32 id) internal { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; StoreCore.deleteRecord(_tableId, _keyTuple, _fieldLayout); } @@ -355,9 +355,9 @@ library Position { /** * @notice Encode keys as a bytes32 array using this table's field layout. */ - function encodeKeyTuple(bytes32 key) internal pure returns (bytes32[] memory) { + function encodeKeyTuple(bytes32 id) internal pure returns (bytes32[] memory) { bytes32[] memory _keyTuple = new bytes32[](1); - _keyTuple[0] = key; + _keyTuple[0] = id; return _keyTuple; } diff --git a/templates/vanilla/packages/contracts/mud.config.ts b/templates/vanilla/packages/contracts/mud.config.ts index 70edda1693..1be4a87791 100644 --- a/templates/vanilla/packages/contracts/mud.config.ts +++ b/templates/vanilla/packages/contracts/mud.config.ts @@ -1,10 +1,12 @@ -import { mudConfig } from "@latticexyz/world/register"; +import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ +export default defineWorld({ tables: { Counter: { - keySchema: {}, - valueSchema: "uint32", + schema: { + value: "uint32", + }, + key: [], }, }, }); diff --git a/test/mock-game-contracts/mud.config.ts b/test/mock-game-contracts/mud.config.ts index 214f3045a4..c56bca8878 100644 --- a/test/mock-game-contracts/mud.config.ts +++ b/test/mock-game-contracts/mud.config.ts @@ -1,67 +1,6 @@ -import { mudConfig } from "@latticexyz/world/register"; import { defineWorld } from "@latticexyz/world/config/v2"; -export default mudConfig({ - enums: { - TerrainType: ["None", "Ocean", "Grassland", "Desert"], - }, - tables: { - Position: { - keySchema: { - player: "address", - }, - valueSchema: { - x: "int32", - y: "int32", - }, - }, - Health: { - keySchema: { - player: "address", - }, - valueSchema: { - health: "uint256", - }, - }, - Inventory: { - keySchema: { - player: "address", - item: "uint8", - }, - valueSchema: { - amount: "uint32", - }, - }, - Score: { - keySchema: { - player: "address", - game: "uint256", - }, - valueSchema: { - score: "uint256", - }, - }, - Winner: { - keySchema: { - game: "uint256", - }, - valueSchema: { - player: "address", - }, - }, - Terrain: { - keySchema: { - x: "int32", - y: "int32", - }, - valueSchema: { - terrainType: "TerrainType", - }, - }, - }, -}); - -export const configV2 = defineWorld({ +export default defineWorld({ enums: { TerrainType: ["None", "Ocean", "Grassland", "Desert"], },