Skip to content

Commit

Permalink
refactor(cli): remove last ethers usage (#2952)
Browse files Browse the repository at this point in the history
  • Loading branch information
holic authored Jul 17, 2024
1 parent 5ff9f2a commit 609de11
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 532 deletions.
5 changes: 5 additions & 0 deletions .changeset/selfish-readers-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/cli": patch
---

Refactored `mud trace` command to use Viem instead of Ethers and removed Ethers dependencies from the package.
3 changes: 0 additions & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@
},
"dependencies": {
"@aws-sdk/client-kms": "^3.556.0",
"@ethersproject/abi": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@latticexyz/abi-ts": "workspace:*",
"@latticexyz/common": "workspace:*",
"@latticexyz/config": "workspace:*",
Expand All @@ -57,7 +55,6 @@
"chokidar": "^3.5.3",
"debug": "^4.3.4",
"dotenv": "^16.0.3",
"ethers": "^5.7.2",
"execa": "^7.0.0",
"find-up": "^6.3.0",
"glob": "^10.4.2",
Expand Down
71 changes: 31 additions & 40 deletions packages/cli/src/commands/trace.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import path from "node:path";
import { existsSync, readFileSync } from "node:fs";
import fs from "node:fs";
import type { CommandModule } from "yargs";
import { ethers } from "ethers";
import { loadConfig, resolveConfigPath } from "@latticexyz/config/node";
import { MUDError } from "@latticexyz/common/errors";
import { cast, getRpcUrl } from "@latticexyz/common/foundry";
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 { createClient, http } from "viem";
import { getChainId } from "viem/actions";
import { Hex, createClient, http } from "viem";
import { getChainId, readContract } from "viem/actions";
import { World as WorldConfig } from "@latticexyz/world";
import { resolveSystems } from "@latticexyz/world/node";
import { worldAbi } from "../deploy/common";

const systemsTableId = worldConfig.tables.world__Systems.tableId;

function getWorldAddress(worldsFile: string, chainId: number): Hex {
if (!fs.existsSync(worldsFile)) {
throw new MUDError(`Missing expected worlds.json file at "${worldsFile}"`);
}

const deploys = JSON.parse(fs.readFileSync(worldsFile, "utf-8"));

if (!deploys[chainId]) {
throw new MUDError(`Missing chain ID ${chainId} in "${worldsFile}"`);
}

return deploys[chainId].address as Hex;
}

type Options = {
tx: string;
worldAddress?: string;
Expand Down Expand Up @@ -48,37 +60,31 @@ const commandModule: CommandModule<Options, Options> = {
const profile = args.profile ?? process.env.FOUNDRY_PROFILE;
const rpc = args.rpc ?? (await getRpcUrl(profile));

// Load the config
const config = (await loadConfig(configPath)) as WorldConfig;

// Get worldAddress either from args or from worldsFile
const worldAddress = args.worldAddress ?? (await getWorldAddress(config.deploy.worldsFile, rpc));

// Create World contract instance from deployed address
const provider = new ethers.providers.StaticJsonRpcProvider(rpc);
const WorldContract = new ethers.Contract(worldAddress, IBaseWorldAbi, provider);
const client = createClient({ transport: http(rpc) });
const chainId = await getChainId(client);
const worldAddress = (args.worldAddress ?? getWorldAddress(config.deploy.worldsFile, chainId)) as Hex;

// TODO: replace with system.namespace
const namespace = config.namespace;
const systems = await resolveSystems({ rootDir, config });

// Fetch system table field layout from chain
const systemTableFieldLayout = await WorldContract.getFieldLayout(systemsTableId);
const labels = await Promise.all(
systems.map(async (system) => {
// TODO: replace with system.systemId
const systemId = resourceToHex({ type: "system", namespace, name: system.name });
// Get the first field of `Systems` table (the table maps system name to its address and other data)
const address = await WorldContract.getField(systemsTableId, [systemId], 0, systemTableFieldLayout);
return { name: system.name, address };
}),
systems.map(async (system) => ({
label: system.label,
address: await readContract(client, {
abi: worldAbi,
address: worldAddress,
functionName: "getField",
args: [systemsTableId, [system.systemId], 0],
}),
})),
);

const result = await cast([
"run",
"--label",
`${worldAddress}:World`,
...labels.map(({ name, address }) => ["--label", `${address}:${name}`]).flat(),
...labels.map(({ label, address }) => ["--label", `${address}:${label}`]).flat(),
`${args.tx}`,
]);
console.log(result);
Expand All @@ -88,18 +94,3 @@ const commandModule: CommandModule<Options, Options> = {
};

export default commandModule;

async function getWorldAddress(worldsFile: string, rpc: string) {
if (existsSync(worldsFile)) {
const client = createClient({ transport: http(rpc) });
const chainId = await getChainId(client);
const deploys = JSON.parse(readFileSync(worldsFile, "utf-8"));

if (!deploys[chainId]) {
throw new MUDError(`chainId ${chainId} is missing in worldsFile "${worldsFile}"`);
}
return deploys[chainId].address as string;
} else {
throw new MUDError("worldAddress is not specified and worldsFile is missing");
}
}
18 changes: 4 additions & 14 deletions packages/cli/src/deploy/resolveConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import path from "path";
import { resolveSystems } from "@latticexyz/world/node";
import { Library, System, WorldFunction } from "./common";
import { resourceToHex } from "@latticexyz/common";
import { Hex, isHex, toFunctionSelector, toFunctionSignature } from "viem";
import { getContractData } from "../utils/getContractData";
import { groupBy } from "@latticexyz/common/utils";
Expand Down Expand Up @@ -43,12 +42,6 @@ export async function resolveConfig({
const configSystems = await resolveSystems({ rootDir, config });

const systems = configSystems.map((system): System => {
// TODO: replace with system.namespace
const namespace = config.namespace;
const name = system.name;
// TODO: replace with system.systemId
const systemId = resourceToHex({ type: "system", namespace, name });
// TODO: replace system.name with system.label
const contractData = getContractData(`${system.label}.sol`, system.label, forgeOutDir);

const systemFunctions = contractData.abi
Expand All @@ -57,11 +50,11 @@ export async function resolveConfig({
.filter((sig) => !baseSystemFunctions.includes(sig))
.map((sig): WorldFunction => {
// TODO: figure out how to not duplicate contract behavior (https://github.com/latticexyz/mud/issues/1708)
const worldSignature = namespace === "" ? sig : `${namespace}__${sig}`;
const worldSignature = system.namespace === "" ? sig : `${system.namespace}__${sig}`;
return {
signature: worldSignature,
selector: toFunctionSelector(worldSignature),
systemId,
systemId: system.systemId,
systemFunctionSignature: sig,
systemFunctionSelector: toFunctionSelector(sig),
};
Expand All @@ -73,14 +66,11 @@ export async function resolveConfig({
.filter((target) => !isHex(target))
.map((label) => {
const system = configSystems.find((s) => s.label === label)!;
// TODO: replace with system.systemId
return resourceToHex({ type: "system", namespace, name: system.name });
return system.systemId;
});

return {
namespace,
name,
systemId,
...system,
allowAll: system.openAccess,
allowedAddresses,
allowedSystemIds,
Expand Down
2 changes: 1 addition & 1 deletion packages/world/ts/node/render-solidity/worldgen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export async function worldgen({
const systemInterfaceName = `I${system.label}`;
const output = renderSystemInterface({
name: systemInterfaceName,
functionPrefix: config.namespace === "" ? "" : `${config.namespace}__`,
functionPrefix: system.namespace === "" ? "" : `${system.namespace}__`,
functions,
errors,
imports,
Expand Down
11 changes: 9 additions & 2 deletions packages/world/ts/node/resolveSystems.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { isHex } from "viem";
import { Hex, isHex } from "viem";
import { getSystemContracts } from ".";
import { System, World } from "../config/v2";
import { SYSTEM_DEFAULTS } from "../config/v2/defaults";
import { resourceToHex } from "@latticexyz/common";

export type ResolvedSystem = System & {
// TODO: move label into System config output
// TODO: move label, namespace, systemId into System config output
readonly label: string;
readonly namespace: string;
readonly systemId: Hex;
readonly sourcePath: string;
};

Expand All @@ -32,6 +35,10 @@ export async function resolveSystems({
return {
...systemConfig,
label: contract.name,
// TODO: remove once system ID is resolved by config
// TODO: replace config.namespace with system.namespace once available
systemId: resourceToHex({ type: "system", namespace: config.namespace, name: contract.name }),
namespace: config.namespace,
sourcePath: contract.sourcePath,
};
})
Expand Down
Loading

0 comments on commit 609de11

Please sign in to comment.