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

refactor(cli): refactor to esm #417

Merged
merged 13 commits into from
Feb 22, 2023
Merged
14 changes: 9 additions & 5 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
"name": "@latticexyz/cli",
"version": "1.37.1",
"description": "Command line interface for mud",
"main": "src/index.ts",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "module",
"license": "MIT",
"bin": {
"mud": "./dist/index.js"
"mud": "./dist/mud.js"
},
"repository": {
"type": "git",
Expand All @@ -14,9 +16,11 @@
},
"scripts": {
"prepare": "yarn build && chmod u+x git-install.sh",
"build": "rimraf dist && esbuild ./src/index.ts ./src/commands/* --bundle --platform=node --outdir=dist --external:fsevents && chmod u+x dist/index.js",
"lint": "eslint . --ext .ts",
"build": "tsup",
"link": "yarn link",
"test": "tsc && echo 'todo: add tests'",
"test": "tsc --noEmit && echo 'todo: add tests'",
"test:next": "tsc --noEmit --moduleResolution nodenext",
"git:install": "bash git-install.sh",
"release": "npm publish || echo 'version already published'"
},
Expand All @@ -34,6 +38,7 @@
"pkg": "^5.7.0",
"rimraf": "^3.0.2",
"ts-node": "^10.7.0",
"tsup": "^6.6.3",
"typescript": "^4.6.4"
},
"dependencies": {
Expand All @@ -42,7 +47,6 @@
"@latticexyz/services": "^1.37.1",
"@latticexyz/solecs": "^1.37.1",
"@latticexyz/std-contracts": "^1.37.1",
"@latticexyz/utils": "^1.37.1",
"@typechain/ethers-v5": "^10.1.1",
"chalk": "^5.0.1",
"chokidar": "^3.5.3",
Expand Down
76 changes: 41 additions & 35 deletions packages/cli/src/commands/bulkupload.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,50 @@
import { Arguments, CommandBuilder } from "yargs";
import { execa } from "execa";
import path from "path";
import type { CommandModule } from "yargs";

const importExeca = eval('import("execa")') as Promise<typeof import("execa")>;
const contractsDirectory = new URL("../src/contracts", import.meta.url).pathname;

type Options = {
statePath: string;
worldAddress: string;
rpc: string;
};

export const command = "bulkupload";
export const desc = "Uploads the provided ECS state to the provided World";

export const builder: CommandBuilder<Options, Options> = (yargs) =>
yargs.options({
statePath: { type: "string", demandOption: true, desc: "Path to the ECS state to upload" },
worldAddress: { type: "string", demandOption: true, desc: "Contract address of the World to upload to" },
rpc: { type: "string", demandOption: true, desc: "JSON RPC endpoint" },
});

export const handler = async (argv: Arguments<Options>): Promise<void> => {
const { execa } = await importExeca;
const { statePath, worldAddress, rpc } = argv;
console.log("Uploading state at ", statePath, "to", worldAddress, "on", rpc);
const url = __dirname + "/../../src/contracts/BulkUpload.sol";
console.log("Using BulkUpload script from", url);

try {
await execa("forge", [
"script",
"--sig",
'"run(string, address)"',
"--rpc-url",
rpc,
`${url}:BulkUpload`,
statePath,
worldAddress,
]);
} catch (e) {
console.error(e);
}

process.exit(0);
const commandModule: CommandModule<Options, Options> = {
command: "bulkupload",

describe: "Uploads the provided ECS state to the provided World",

builder(yargs) {
return yargs.options({
statePath: { type: "string", demandOption: true, desc: "Path to the ECS state to upload" },
worldAddress: { type: "string", demandOption: true, desc: "Contract address of the World to upload to" },
rpc: { type: "string", demandOption: true, desc: "JSON RPC endpoint" },
});
},

async handler({ statePath, worldAddress, rpc }) {
console.log("Uploading state at ", statePath, "to", worldAddress, "on", rpc);
const url = path.join(contractsDirectory, "BulkUpload.sol");
console.log("Using BulkUpload script from", url);

try {
await execa("forge", [
"script",
"--sig",
'"run(string, address)"',
"--rpc-url",
rpc,
`${url}:BulkUpload`,
statePath,
worldAddress,
]);
} catch (e) {
console.error(e);
}

process.exit(0);
},
};

export default commandModule;
98 changes: 51 additions & 47 deletions packages/cli/src/commands/call-system.ts
Original file line number Diff line number Diff line change
@@ -1,66 +1,70 @@
import { defaultAbiCoder as abi } from "ethers/lib/utils";
import { defaultAbiCoder as abi } from "ethers/lib/utils.js";
import path from "path";
import { Arguments, CommandBuilder } from "yargs";
import { execLog } from "../utils";
import { getTestDirectory } from "../utils/forgeConfig";
import type { CommandModule } from "yargs";
import { execLog } from "../utils/index.js";
import { getTestDirectory } from "../utils/forgeConfig.js";

type Options = {
rpc?: string;
caller?: string;
world: string;
systemId?: string;
systemAddress?: string;
argTypes?: any[];
args?: any[];
argTypes?: string[];
args?: (string | number)[];
calldata?: string;
broadcast?: boolean;
callerPrivateKey?: string;
debug?: boolean;
};

export const command = "call-system";
export const desc = "Execute a mud system";
const commandModule: CommandModule<Options, Options> = {
command: "call-system",

export const builder: CommandBuilder<Options, Options> = (yargs) =>
yargs.options({
rpc: { type: "string", description: "json rpc endpoint, defaults to http://localhost:8545" },
caller: { type: "string", description: "caller address" },
world: { type: "string", required: true, description: "world contract address" },
systemId: { type: "string", description: "system id preimage (eg mud.system.Move)" },
systemAddress: { type: "string", description: "system address (alternative to system id)" },
argTypes: { type: "array", description: "system argument types for abi encoding" },
args: { type: "array", description: "system arguments" },
calldata: { type: "string", description: "abi encoded system arguments (instead of args/argTypes)" },
broadcast: { type: "boolean", description: "send txs to the chain" },
callerPrivateKey: {
type: "string",
description: "must be set if broadcast is set, must correspond to caller address",
},
debug: { type: "boolean", description: "open debugger" },
});
describe: "Execute a mud system",

export const handler = async (argv: Arguments<Options>): Promise<void> => {
const { rpc, caller, world, systemId, argTypes, args, calldata, broadcast, callerPrivateKey, debug } = argv;
const encodedArgs = calldata ?? (argTypes && args && abi.encode(argTypes, args)) ?? "";
const testDir = await getTestDirectory();
builder(yargs) {
return yargs.options({
rpc: { type: "string", description: "json rpc endpoint, defaults to http://localhost:8545" },
caller: { type: "string", description: "caller address" },
world: { type: "string", required: true, description: "world contract address" },
systemId: { type: "string", description: "system id preimage (eg mud.system.Move)" },
systemAddress: { type: "string", description: "system address (alternative to system id)" },
argTypes: { type: "array", string: true, description: "system argument types for abi encoding" },
args: { type: "array", description: "system arguments" },
calldata: { type: "string", description: "abi encoded system arguments (instead of args/argTypes)" },
broadcast: { type: "boolean", description: "send txs to the chain" },
callerPrivateKey: {
type: "string",
description: "must be set if broadcast is set, must correspond to caller address",
},
debug: { type: "boolean", description: "open debugger" },
});
},

await execLog("forge", [
"script",
"--fork-url",
rpc ?? "http://localhost:8545", // default anvil rpc
"--sig",
"debug(address,address,string,bytes,bool)",
path.join(testDir, "utils/Debug.sol"), // the cli expects the Debug.sol file at this path
caller ?? "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", // default anvil deployer
world,
systemId || "",
encodedArgs,
broadcast ? "true" : "false",
"-vvvvv",
broadcast ? "--broadcast" : "",
callerPrivateKey ? `--private-key ${callerPrivateKey}` : "",
debug ? "--debug" : "",
]);
async handler({ rpc, caller, world, systemId, argTypes, args, calldata, broadcast, callerPrivateKey, debug }) {
const encodedArgs = calldata ?? (argTypes && args && abi.encode(argTypes, args)) ?? "";
const testDir = await getTestDirectory();
await execLog("forge", [
"script",
"--fork-url",
rpc ?? "http://localhost:8545", // default anvil rpc
"--sig",
"debug(address,address,string,bytes,bool)",
path.join(testDir, "utils/Debug.sol"), // the cli expects the Debug.sol file at this path
caller ?? "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", // default anvil deployer
world,
systemId || "",
encodedArgs,
broadcast ? "true" : "false",
"-vvvvv",
broadcast ? "--broadcast" : "",
callerPrivateKey ? `--private-key ${callerPrivateKey}` : "",
debug ? "--debug" : "",
]);

process.exit(0);
process.exit(0);
},
};

export default commandModule;
33 changes: 19 additions & 14 deletions packages/cli/src/commands/codegen-libdeploy.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import type { Arguments, CommandBuilder } from "yargs";
import { generateLibDeploy } from "../utils";
import type { CommandModule } from "yargs";
import { generateLibDeploy } from "../utils/index.js";

type Options = {
config: string;
out: string;
systems?: string;
};

export const command = "codegen-libdeploy";
export const desc = "Generate LibDeploy.sol from given deploy config";
const commandModule: CommandModule<Options, Options> = {
command: "codegen-libdeploy",

export const builder: CommandBuilder<Options, Options> = (yargs) =>
yargs.options({
config: { type: "string", default: "./deploy.json", desc: "Component and system deployment configuration" },
out: { type: "string", default: ".", desc: "Output directory for LibDeploy.sol" },
systems: { type: "string", desc: "Only generate deploy code for the given systems" },
});
describe: "Generate LibDeploy.sol from given deploy config",

export const handler = async (args: Arguments<Options>): Promise<void> => {
const { config, out, systems } = args;
await generateLibDeploy(config, out, systems);
process.exit(0);
builder(yargs) {
return yargs.options({
config: { type: "string", default: "./deploy.json", desc: "Component and system deployment configuration" },
out: { type: "string", default: ".", desc: "Output directory for LibDeploy.sol" },
systems: { type: "string", desc: "Only generate deploy code for the given systems" },
});
},

async handler({ config, out, systems }) {
await generateLibDeploy(config, out, systems);
process.exit(0);
},
};

export default commandModule;
30 changes: 0 additions & 30 deletions packages/cli/src/commands/create.ts

This file was deleted.

Loading