Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(world-module-metadata): add metadata module #3026

Merged
merged 24 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"@latticexyz/store": "workspace:*",
"@latticexyz/utils": "workspace:*",
"@latticexyz/world": "workspace:*",
"@latticexyz/world-module-metadata": "workspace:*",
"abitype": "1.0.0",
"asn1.js": "^5.4.1",
"chalk": "^5.0.1",
Expand Down
29 changes: 26 additions & 3 deletions packages/cli/src/deploy/configToModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,37 @@ import { bytesToHex } from "viem";
import { createPrepareDeploy } from "./createPrepareDeploy";
import { World } from "@latticexyz/world";
import { getContractArtifact } from "../utils/getContractArtifact";
import { knownModuleArtifacts } from "../utils/knownModuleArtifacts";
import { importContractArtifact } from "../utils/importContractArtifact";
import { resolveWithContext } from "@latticexyz/world/internal";
import metadataModule from "@latticexyz/world-module-metadata/out/MetadataModule.sol/MetadataModule.json" assert { type: "json" };

/** Please don't add to this list! These are kept for backwards compatibility and assumes the downstream project has this module installed as a dependency. */
const knownModuleArtifacts = {
KeysWithValueModule: "@latticexyz/world-modules/out/KeysWithValueModule.sol/KeysWithValueModule.json",
KeysInTableModule: "@latticexyz/world-modules/out/KeysInTableModule.sol/KeysInTableModule.json",
UniqueEntityModule: "@latticexyz/world-modules/out/UniqueEntityModule.sol/UniqueEntityModule.json",
Unstable_CallWithSignatureModule:
"@latticexyz/world-modules/out/Unstable_CallWithSignatureModule.sol/Unstable_CallWithSignatureModule.json",
};

const metadataModuleArtifact = getContractArtifact(metadataModule);

export async function configToModules<config extends World>(
config: config,
// TODO: remove/replace `forgeOutDir`
forgeOutDir: string,
): Promise<readonly Module[]> {
const defaultModules: Module[] = [
{
name: "MetadataModule",
installAsRoot: false,
installData: "0x",
prepareDeploy: createPrepareDeploy(metadataModuleArtifact.bytecode, metadataModuleArtifact.placeholders),
deployedBytecodeSize: metadataModuleArtifact.deployedBytecodeSize,
abi: metadataModuleArtifact.abi,
},
];

const modules = await Promise.all(
config.modules.map(async (mod): Promise<Module> => {
let artifactPath = mod.artifactPath;
Expand Down Expand Up @@ -46,7 +69,7 @@ export async function configToModules<config extends World>(
}

const name = path.basename(artifactPath, ".json");
const artifact = await getContractArtifact({ artifactPath });
const artifact = await importContractArtifact({ artifactPath });

// TODO: replace args with something more strongly typed
const installArgs = mod.args
Expand All @@ -71,5 +94,5 @@ export async function configToModules<config extends World>(
}),
);

return modules;
return [...defaultModules, ...modules];
}
39 changes: 2 additions & 37 deletions packages/cli/src/utils/getContractArtifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,6 @@ import { LibraryPlaceholder } from "../deploy/common";
import { findPlaceholders } from "./findPlaceholders";
import { z } from "zod";
import { Abi as abiSchema } from "abitype/zod";
import { createRequire } from "node:module";
import { findUp } from "find-up";

export type GetContractArtifactOptions = {
/**
* Path to `package.json` where `artifactPath`s are resolved relative to.
*
* Defaults to nearest `package.json` relative to `process.cwd()`.
*/
packageJsonPath?: string;
/**
* Import path to contract's forge/solc JSON artifact with the contract's compiled bytecode.
*
* This path is resolved using node's module resolution relative to `configPath`, so this supports both
* relative file paths (`../path/to/MyModule.json`) as well as JS import paths (`@latticexyz/world-contracts/out/CallWithSignatureModule.sol/CallWithSignatureModule.json`).
*/
artifactPath: string;
};

export type GetContractArtifactResult = {
bytecode: Hex;
Expand Down Expand Up @@ -49,26 +31,9 @@ const artifactSchema = z.object({
abi: abiSchema,
});

export async function getContractArtifact({
packageJsonPath,
artifactPath,
}: GetContractArtifactOptions): Promise<GetContractArtifactResult> {
let importedArtifact;
try {
const requirePath = packageJsonPath ?? (await findUp("package.json", { cwd: process.cwd() }));
if (!requirePath) throw new Error("Could not find package.json to import relative to.");

const require = createRequire(requirePath);
importedArtifact = require(artifactPath);
} catch (error) {
console.error();
console.error("Could not import contract artifact at", artifactPath);
console.error();
throw error;
}

export function getContractArtifact(artifactJson: unknown): GetContractArtifactResult {
// TODO: improve errors or replace with arktype?
const artifact = artifactSchema.parse(importedArtifact);
const artifact = artifactSchema.parse(artifactJson);
const placeholders = findPlaceholders(artifact.bytecode.linkReferences);

return {
Expand Down
40 changes: 40 additions & 0 deletions packages/cli/src/utils/importContractArtifact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createRequire } from "node:module";
import { findUp } from "find-up";
import { GetContractArtifactResult, getContractArtifact } from "./getContractArtifact";

export type ImportContractArtifactOptions = {
/**
* Path to `package.json` where `artifactPath`s are resolved relative to.
*
* Defaults to nearest `package.json` relative to `process.cwd()`.
*/
packageJsonPath?: string;
/**
* Import path to contract's forge/solc JSON artifact with the contract's compiled bytecode.
*
* This path is resolved using node's module resolution relative to `configPath`, so this supports both
* relative file paths (`../path/to/MyModule.json`) as well as JS import paths (`@latticexyz/world-contracts/out/CallWithSignatureModule.sol/CallWithSignatureModule.json`).
*/
artifactPath: string;
};

export async function importContractArtifact({
packageJsonPath,
artifactPath,
}: ImportContractArtifactOptions): Promise<GetContractArtifactResult> {
let artfactJson;
try {
const requirePath = packageJsonPath ?? (await findUp("package.json", { cwd: process.cwd() }));
if (!requirePath) throw new Error("Could not find package.json to import relative to.");

const require = createRequire(requirePath);
artfactJson = require(artifactPath);
} catch (error) {
console.error();
console.error("Could not import contract artifact at", artifactPath);
console.error();
throw error;
}

return getContractArtifact(artfactJson);
}
8 changes: 0 additions & 8 deletions packages/cli/src/utils/knownModuleArtifacts.ts

This file was deleted.

2 changes: 2 additions & 0 deletions packages/world-module-metadata/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cache
out
8 changes: 8 additions & 0 deletions packages/world-module-metadata/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", ">=0.8.0"],
"avoid-low-level-calls": "off",
"func-visibility": ["warn", { "ignoreConstructors": true }]
}
}
1 change: 1 addition & 0 deletions packages/world-module-metadata/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Metadata world module
15 changes: 15 additions & 0 deletions packages/world-module-metadata/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[profile.default]
solc = "0.8.24"
ffi = false
fuzz_runs = 256
optimizer = true
optimizer_runs = 3000
verbosity = 2
allow_paths = ["../../node_modules", "../"]
src = "src"
out = "out"
bytecode_hash = "none"
extra_output_files = [
"abi",
"evm.bytecode"
]
Loading
Loading