From b01e8809a827b47dd0a61b6e61a57e584f980dfd Mon Sep 17 00:00:00 2001 From: Evan Gray Date: Thu, 19 Dec 2024 11:40:22 -0500 Subject: [PATCH] cli: arbitrary chain registration --- clients/js/src/cmds/generate.ts | 66 +++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 4 deletions(-) diff --git a/clients/js/src/cmds/generate.ts b/clients/js/src/cmds/generate.ts index 0b4682c557..b37c5db2c1 100644 --- a/clients/js/src/cmds/generate.ts +++ b/clients/js/src/cmds/generate.ts @@ -18,6 +18,8 @@ import { import { Chain, chainToPlatform, + Platform, + platforms, toChainId, } from "@wormhole-foundation/sdk-base"; @@ -65,8 +67,21 @@ export const builder = function (y: typeof yargs) { describe: "Chain to register. To see a list of supported chains, run `worm chains`", type: "string", - demandOption: true, + demandOption: false, } as const) + .option("chain-id", { + alias: "i", + describe: + "Chain to register. To see a list of supported chains, run `worm chains`", + type: "number", + demandOption: false, + } as const) + .option("platform", { + alias: "p", + describe: "Platform to encode the address by", + choices: platforms, + demandOption: false, + }) .option("contract-address", { alias: "a", describe: "Contract to register", @@ -80,14 +95,30 @@ export const builder = function (y: typeof yargs) { demandOption: true, } as const), (argv) => { + if (!(argv.chain || (argv["chain-id"] && argv.platform))) { + throw new Error("chain or chain-id and platform are required"); + } const module = argv["module"]; - const chain = chainToChain(argv.chain); + const emitterChain = argv.chain + ? toChainId(chainToChain(argv.chain)) + : argv["chain-id"]; + if (emitterChain === undefined) { + throw new Error("emitterChain is undefined"); + } + let emitterAddress = argv.platform + ? parseAddressByPlatform(argv.platform, argv["contract-address"]) + : argv.chain + ? parseAddress(chainToChain(argv.chain), argv["contract-address"]) + : undefined; + if (emitterAddress === undefined) { + throw new Error("emitterAddress is undefined"); + } const payload: PortalRegisterChain = { module, type: "RegisterChain", chain: 0, - emitterChain: toChainId(chain), - emitterAddress: parseAddress(chain, argv["contract-address"]), + emitterChain, + emitterAddress, }; const vaa = makeVAA( GOVERNANCE_CHAIN, @@ -296,6 +327,33 @@ export const builder = function (y: typeof yargs) { }; export const handler = () => {}; +function parseAddressByPlatform(platform: Platform, address: string): string { + if (platform === "Evm") { + return "0x" + evm_address(address); + } else if (platform === "Cosmwasm") { + return "0x" + toHex(fromBech32(address).data).padStart(64, "0"); + } else if (platform === "Solana") { + return "0x" + toHex(base58.decode(address)).padStart(64, "0"); + } else if (platform === "Algorand") { + // TODO: is there a better native format for algorand? + return "0x" + evm_address(address); + } else if (platform === "Near") { + return "0x" + evm_address(address); + } else if (platform === "Sui") { + return "0x" + evm_address(address); + } else if (platform === "Aptos") { + if (/^(0x)?[0-9a-fA-F]+$/.test(address)) { + return "0x" + evm_address(address); + } + + return sha3_256(Buffer.from(address)); // address is hash of fully qualified type + } else if (platform === "Btc") { + throw Error("btc is not supported yet"); + } else { + throw Error(`Unsupported platform: ${platform}`); + } +} + function parseAddress(chain: Chain, address: string): string { if (chainToPlatform(chain) === "Evm") { return "0x" + evm_address(address);