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(cli): generate system ABI's from World address #2849

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5d50595
feat(cli): generate system interface from FunctionSignatures
yonadaaa May 21, 2024
a1f03ec
f to func
yonadaaa May 21, 2024
5fcf8d4
refactor: system function sig
yonadaaa May 21, 2024
d3b44ad
fix: parse with regex
yonadaaa May 21, 2024
f2b425e
wip: codegen struct names
yonadaaa May 21, 2024
0032e7b
feat: abigen
yonadaaa May 21, 2024
8aa75a7
fix: reorganise, types
yonadaaa May 21, 2024
b0d0313
refactor: simplify types
yonadaaa May 21, 2024
a4ff4cd
refactor: rename
yonadaaa May 21, 2024
6844e86
refactor: use parseAbiItem
yonadaaa May 22, 2024
b28b723
feat: write abis to file
yonadaaa May 22, 2024
d8fca7e
feat: resourceToLabel
yonadaaa May 22, 2024
b9d2796
feat: world abi
yonadaaa May 22, 2024
f41cfb5
refactor: worldRegisteredFunctions
yonadaaa May 22, 2024
216ff7d
refactor: describe
yonadaaa May 22, 2024
3fe68e1
refactor: move util
yonadaaa May 22, 2024
1b9c25b
refactor: systemToAbi
yonadaaa May 22, 2024
98f34b4
refactor: rename to generate-abi
yonadaaa May 22, 2024
0cbccff
chore: changeset
yonadaaa May 22, 2024
3c59a73
refactor: add helper
yonadaaa May 22, 2024
069f96b
fix: world ABI uses correct signature
yonadaaa May 22, 2024
0f7419f
fix: abi.json
yonadaaa May 22, 2024
b2722bf
feat: abis directory
yonadaaa May 22, 2024
7ba1f43
chore: do not generate system abis
yonadaaa May 22, 2024
a3d4d1d
refactor: constants
yonadaaa May 23, 2024
812c752
refactor: getWorldAbi helper
yonadaaa May 23, 2024
56fa764
fix: use await
yonadaaa Jun 3, 2024
a142476
export getWorldAbi + getWorldDeploy
karooolis Aug 5, 2024
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
50 changes: 50 additions & 0 deletions packages/cli/src/commands/abigen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { CommandModule, InferredOptionTypes } from "yargs";
import { Hex, createWalletClient, http } from "viem";
import { getSystems } from "../deploy/getSystems";
import { getWorldDeploy } from "../deploy/getWorldDeploy";
import { systemFunctionSignaturesToAbi } from "@latticexyz/world/node";
import { getRpcUrl } from "@latticexyz/common/foundry";

const abigenOptions = {
worldAddress: { type: "string", required: true, desc: "Verify an existing World at the given address" },
profile: { type: "string", desc: "The foundry profile to use" },
rpc: {
type: "string",
desc: "The RPC URL to use. Defaults to the RPC url from the local foundry.toml",
},
} as const;

type Options = InferredOptionTypes<typeof abigenOptions>;

const commandModule: CommandModule<Options, Options> = {
command: "abigen",

describe: "Autogenerate interfaces for Systems and World based on RPC",

builder(yargs) {
return yargs.options(abigenOptions);
},

async handler(args) {
await abigenHandler(args);
process.exit(0);
},
};

export async function abigenHandler(opts: Options) {
const worldAddress = opts.worldAddress as Hex;
const profile = opts.profile ?? process.env.FOUNDRY_PROFILE;
const rpc = opts.rpc ?? (await getRpcUrl(profile));

const client = createWalletClient({
transport: http(rpc),
});

const worldDeploy = await getWorldDeploy(client, worldAddress);

const systems = await getSystems({ client, worldDeploy });

systems.map((system) => systemFunctionSignaturesToAbi(system.functions.map((func) => func.systemFunctionSignature)));
}

export default commandModule;
2 changes: 2 additions & 0 deletions packages/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import test from "./test";
import trace from "./trace";
import devContracts from "./dev-contracts";
import verify from "./verify";
import abigen from "./abigen";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a huge fan of continuing the tablegen, worldgen, etc. naming pattern

I could see us eventually combining all of these features under a codegen command, maybe with sub commands like codegen tables), but in the meantime, something like "codegen abi" or "generate abi" for the CLI command and "world to abi" for the helper methods?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I like this line of thinking, lemme marinate on it

It's interesting that abigen and worldgen have different inputs but basically the same output

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command is now generate-abi and the helper is just systemToAbi


// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
export const commands: CommandModule<any, any>[] = [
Expand All @@ -30,4 +31,5 @@ export const commands: CommandModule<any, any>[] = [
devContracts,
abiTs,
verify,
abigen,
];
1 change: 1 addition & 0 deletions packages/world/ts/node/render-solidity/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./renderSystemInterface";
export * from "./renderWorldInterface";
export * from "./types";
export * from "./worldgen";
export * from "./systemFunctionSignaturesToAbi";
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Abi } from "viem";

export function systemFunctionSignaturesToAbi(systemFunctionSignatures: readonly string[]): Abi {
const abi = systemFunctionSignatures.map((systemFunctionSignature) => {
const match = systemFunctionSignature.match(/^([a-zA-Z_]\w*)\((.*)\)$/);
if (!match) {
throw new Error("Invalid signature");
}

const name = match[1];
const argsString = match[2];

const args = argsString.split(",");

const item = {
type: "function" as const,
name,
inputs: args.map((type, i) => {
const isTuple = type[0] === "(";
if (!isTuple) {
return {
name: "",
type,
internalType: type,
};
} else {
return {
name: "",
type: "tuple[]",
internalType: `${name}${i}Struct[]`,
components: type
.replace("(", "")
.replace(")", "")
.split(",")
.map((member, j) => ({
name: `value${j}`,
type: member,
internalType: member,
})),
};
}
}),
outputs: [],
stateMutability: "nonpayable" as const,
};

console.log(argsString, item);

return item;
});

return abi;
}
Loading