Skip to content

Commit 6c2b360

Browse files
committed
mirror scaffold
1 parent 1f509ee commit 6c2b360

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

packages/cli/src/commands/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import trace from "./trace";
1515
import devContracts from "./dev-contracts";
1616
import verify from "./verify";
1717
import pull from "./pull";
18+
import mirror from "./mirror";
1819

1920
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
2021
export const commands: CommandModule<any, any>[] = [
@@ -32,4 +33,5 @@ export const commands: CommandModule<any, any>[] = [
3233
abiTs,
3334
verify,
3435
pull,
36+
mirror,
3537
];
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import type { CommandModule, InferredOptionTypes } from "yargs";
2+
import { createClient, getAddress, http } from "viem";
3+
import chalk from "chalk";
4+
import { getChainId } from "viem/actions";
5+
import { defaultChains } from "../defaultChains";
6+
import { mirror } from "../mirror/mirror";
7+
8+
const options = {
9+
rpcBatch: {
10+
type: "boolean",
11+
desc: "Enable batch processing of RPC requests via Viem client (defaults to batch size of 100 and wait of 1s).",
12+
},
13+
kms: {
14+
type: "boolean",
15+
desc: "Deploy the world with an AWS KMS key instead of local private key.",
16+
},
17+
fromWorld: {
18+
type: "string",
19+
desc: "Source world address to mirror from.",
20+
required: true,
21+
},
22+
fromRpc: {
23+
type: "string",
24+
desc: "RPC URL of source chain to mirror from.",
25+
required: true,
26+
},
27+
fromIndexer: {
28+
type: "string",
29+
desc: "MUD indexer URL of source chain to mirror from.",
30+
},
31+
toRpc: {
32+
type: "string",
33+
desc: "RPC URL of target chain to mirror to.",
34+
required: true,
35+
},
36+
} as const;
37+
38+
type Options = InferredOptionTypes<typeof options>;
39+
40+
const commandModule: CommandModule<Options, Options> = {
41+
command: "mirror",
42+
43+
describe: "Mirror an existing world and its data to another chain.",
44+
45+
builder(yargs) {
46+
return yargs.options(options);
47+
},
48+
49+
async handler(opts) {
50+
const fromWorld = getAddress(opts.fromWorld);
51+
const fromClient = createClient({
52+
transport: http(opts.fromRpc, {
53+
batch: opts.rpcBatch ? { batchSize: 100, wait: 1000 } : undefined,
54+
}),
55+
});
56+
const fromChainId = await getChainId(fromClient);
57+
const fromIndexer = opts.fromIndexer ?? defaultChains.find((chain) => chain.id === fromChainId)?.indexerUrl;
58+
59+
const toClient = createClient({
60+
transport: http(opts.toRpc, {
61+
batch: opts.rpcBatch ? { batchSize: 100, wait: 1000 } : undefined,
62+
}),
63+
});
64+
const toChainId = await getChainId(toClient);
65+
66+
console.log(
67+
chalk.bgBlue(
68+
chalk.whiteBright(
69+
`\n Mirroring MUD world at ${opts.fromWorld} from chain ${fromChainId} to chain ${toChainId} \n`,
70+
),
71+
),
72+
);
73+
74+
// TODO: load up account from KMS or private key
75+
76+
await mirror({
77+
from: { world: fromWorld, client: fromClient, indexer: fromIndexer },
78+
to: { client: toClient },
79+
});
80+
},
81+
};
82+
83+
export default commandModule;

packages/cli/src/mirror/mirror.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Address, Client } from "viem";
2+
3+
// TODO: decide if preserving world address is important (chain config has to change anyway)
4+
5+
export async function mirror(opts: {
6+
from: {
7+
world: Address;
8+
client: Client;
9+
indexer?: string;
10+
};
11+
to: {
12+
client: Client;
13+
};
14+
}) {
15+
// TODO: check for world balance, warn
16+
//
17+
// TODO: get world salt, factory, and deployer address
18+
// TODO: prepare world deploy, make sure resulting world addresses will match
19+
// TODO: deploy world
20+
//
21+
// TODO: set up a table to track migrated records? would make this idempotent and enable lazy mirroring
22+
//
23+
// TODO: fetch data from indexer
24+
// TODO: check each system for state/balance, warn
25+
//
26+
// TODO: set records for each table
27+
//
28+
// TODO: deploy each system via original bytecode
29+
// TODO: update system addresses as necessary (should this be done as part of setting records?)
30+
}

0 commit comments

Comments
 (0)