feat(cli): Support creating agent configs from CLI (#3938)

### Description

- Add support for creating agent configs using the CLI
- registry agent-config command with a required --chains option
- This will pick up local registry data

Example usage:

`hyperlane registry agent-config --chains anvil8545`

<!--
What's included in this PR?
-->


### Drive-by changes

<!--
Are there any minor or drive-by changes also included?
-->

### Related issues

<!--
- Fixes #[issue number here]
-->

- Fixes
#[3720](https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3720)

### Backward compatibility

<!--
Are these changes backward compatible? Are there any infrastructure
implications, e.g. changes that would prohibit deploying older commits
using this infra tooling?

Yes/No
-->
Yes

### Testing

Manual

<!--
What kind of testing have these changes undergone?

None/Manual/Unit Tests
-->
pull/3969/head
Mohammed Hussan 5 months ago committed by GitHub
parent 6d30eed2bb
commit 35f8699505
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      .changeset/lovely-boxes-bow.md
  2. 3
      typescript/cli/package.json
  3. 7
      typescript/cli/src/commands/options.ts
  4. 60
      typescript/cli/src/commands/registry.ts
  5. 2
      typescript/cli/src/commands/types.ts
  6. 75
      typescript/cli/src/config/agent.ts
  7. 10
      yarn.lock

@ -0,0 +1,5 @@
---
'@hyperlane-xyz/cli': minor
---
Add command to support creating agent configs

@ -18,7 +18,8 @@
"tsx": "^4.7.1",
"yaml": "^2.4.1",
"yargs": "^17.7.2",
"zod": "^3.21.2"
"zod": "^3.21.2",
"zod-validation-error": "^3.3.0"
},
"devDependencies": {
"@types/mocha": "^10.0.1",

@ -106,6 +106,13 @@ export const agentConfigCommandOption = (
default: defaultPath,
});
export const chainTargetsCommandOption: Options = {
type: 'string',
description: 'Comma-separated list of chain names',
alias: 'c',
demandOption: true,
};
export const outputFileCommandOption = (
defaultPath?: string,
demandOption = false,

@ -1,10 +1,14 @@
import { CommandModule } from 'yargs';
import { CommandModuleWithContext } from '../context/types.js';
import { log, logBlue, logGray, logTable } from '../logger.js';
import { createAgentConfig } from '../config/agent.js';
import { CommandContext, CommandModuleWithContext } from '../context/types.js';
import { log, logBlue, logGray, logRed, logTable } from '../logger.js';
const ChainTypes = ['mainnet', 'testnet'];
type ChainType = (typeof ChainTypes)[number];
import {
chainTargetsCommandOption,
outputFileCommandOption,
} from './options.js';
import { ChainType, ChainTypes } from './types.js';
/**
* Parent command
@ -16,6 +20,7 @@ export const registryCommand: CommandModule = {
yargs
.command(listCommand)
.command(addressesCommand)
.command(createAgentConfigCommand)
.version(false)
.demandCommand(),
handler: () => log('Command required'),
@ -88,3 +93,50 @@ const addressesCommand: CommandModuleWithContext<{ name: string }> = {
}
},
};
/**
* agent-config command
*/
const createAgentConfigCommand: CommandModuleWithContext<{
chains: string;
out: string;
}> = {
command: 'agent-config',
describe: 'Create a new agent config',
builder: {
chains: chainTargetsCommandOption,
out: outputFileCommandOption(
'./configs/agent-config.json',
false,
'The path to output an agent config JSON file.',
),
},
handler: async ({
context,
chains,
out,
}: {
context: CommandContext;
chains: string;
out: string;
}) => {
const { multiProvider } = context;
const chainNames = chains.split(',');
const invalidChainNames = chainNames.filter(
(chainName) => !multiProvider.hasChain(chainName),
);
if (invalidChainNames.length > 0) {
logRed(
`Invalid chain names: ${invalidChainNames
.join(', ')
.replace(/, $/, '')}`,
);
process.exit(1);
}
await createAgentConfig({ context, chains: chainNames, out });
process.exit(0);
},
};

@ -0,0 +1,2 @@
export const ChainTypes = ['mainnet', 'testnet'];
export type ChainType = (typeof ChainTypes)[number];

@ -0,0 +1,75 @@
import { fromError } from 'zod-validation-error';
import {
AgentConfigSchema,
ChainMap,
HyperlaneCore,
HyperlaneDeploymentArtifacts,
buildAgentConfig,
} from '@hyperlane-xyz/sdk';
import { objMap, promiseObjAll } from '@hyperlane-xyz/utils';
import { CommandContext } from '../context/types.js';
import { logBlue, logGreen, logRed } from '../logger.js';
import { writeYamlOrJson } from '../utils/files.js';
export async function createAgentConfig({
context,
chains,
out,
}: {
context: CommandContext;
chains: string[];
out: string;
}) {
logBlue('\nCreating agent config...');
const { registry, multiProvider, chainMetadata } = context;
const addresses = await registry.getAddresses();
const core = HyperlaneCore.fromAddressesMap(addresses, multiProvider);
const startBlocks = await promiseObjAll(
objMap(addresses, async (chain, _) => {
// If the index.from is specified in the chain metadata, use that.
const indexFrom = chainMetadata[chain].index?.from;
if (indexFrom !== undefined) {
return indexFrom;
}
const mailbox = core.getContracts(chain).mailbox;
try {
const deployedBlock = await mailbox.deployedBlock();
return deployedBlock.toNumber();
} catch (err) {
logRed(
`Failed to get deployed block to set an index for ${chain}, this is potentially an issue with rpc provider or a misconfiguration`,
);
process.exit(1);
}
}),
);
// @TODO: consider adding additional config used to pass in gas prices for Cosmos chains
const agentConfig = buildAgentConfig(
chains,
multiProvider,
addresses as ChainMap<HyperlaneDeploymentArtifacts>,
startBlocks,
);
try {
AgentConfigSchema.parse(agentConfig);
} catch (e) {
logRed(
`Agent config is invalid, this is possibly due to required contracts not being deployed. See details below:\n${fromError(
e,
).toString()}`,
);
process.exit(1);
}
logBlue(`Agent config is valid, writing to file ${out}`);
writeYamlOrJson(out, agentConfig, 'json');
logGreen(`✅ Agent config successfully written to ${out}`);
}

@ -5715,6 +5715,7 @@ __metadata:
yaml: "npm:^2.4.1"
yargs: "npm:^17.7.2"
zod: "npm:^3.21.2"
zod-validation-error: "npm:^3.3.0"
bin:
hyperlane: ./dist/cli.js
languageName: unknown
@ -26173,6 +26174,15 @@ __metadata:
languageName: node
linkType: hard
"zod-validation-error@npm:^3.3.0":
version: 3.3.0
resolution: "zod-validation-error@npm:3.3.0"
peerDependencies:
zod: ^3.18.0
checksum: 19574cbc453c7a41105de572546e95191958f459dd93440f541a42c0ff209b56f1cd54e8f8ab1899430dd7c183e11cd16e8cace0bd4fc5d356ef772645210792
languageName: node
linkType: hard
"zod@npm:^3.21.2":
version: 3.21.2
resolution: "zod@npm:3.21.2"

Loading…
Cancel
Save