Skip to content

Commit

Permalink
feat: cli warp route checker (#4667)
Browse files Browse the repository at this point in the history
### Description

This PR implements the `warp check` command to compare on-chain warp
deployments with provided configuration files

### Drive-by changes

- updated the `inputFileCommandOption` to be a function for defining cli
input file args
- defined the `DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH` to avoid
hardcoding the `./configs/warp-route-deployment.yaml` file path
- implemented the `logCommandHeader` function to format the command
header and avoid always having to manually log the `---` separator in
command outputs
- implements the `getWarpCoreConfigOrExit` to get the warp core
configuration from either the registry or a user-defined path and exit
early if no input value is provided
- Updated the `IsmConfigSchema`s to include the `BaseIsmConfigSchema`
because when parsing config files the address field was not included in
the parsed object as it wasn't defined on the type

Example output

![image](https://github.com/user-attachments/assets/07821a13-d2e2-4b73-b493-9a2c2829a7b3)


![image](https://github.com/user-attachments/assets/768d724f-c96e-4ff5-9c4d-332560c57626)


![image](https://github.com/user-attachments/assets/f92df7c5-acac-4ff7-974b-0334e4a221ab)

### Related issues

- Fixes #4666

### Backward compatibility

- Yes

### Testing

- Manual
  • Loading branch information
xeno097 authored Oct 21, 2024
1 parent 7bfc7ec commit 32d0a67
Show file tree
Hide file tree
Showing 13 changed files with 596 additions and 124 deletions.
6 changes: 6 additions & 0 deletions .changeset/grumpy-ears-relate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hyperlane-xyz/cli': minor
'@hyperlane-xyz/sdk': minor
---

Adds the warp check command to compare warp routes config files with on chain warp route deployments
41 changes: 41 additions & 0 deletions typescript/cli/src/check/warp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { stringify as yamlStringify } from 'yaml';

import { WarpRouteDeployConfig, normalizeConfig } from '@hyperlane-xyz/sdk';
import { ObjectDiff, diffObjMerge } from '@hyperlane-xyz/utils';

import { log, logGreen } from '../logger.js';
import '../utils/output.js';
import { formatYamlViolationsOutput } from '../utils/output.js';

export async function runWarpRouteCheck({
warpRouteConfig,
onChainWarpConfig,
}: {
warpRouteConfig: WarpRouteDeployConfig;
onChainWarpConfig: WarpRouteDeployConfig;
}): Promise<void> {
// Go through each chain and only add to the output the chains that have mismatches
const [violations, isInvalid] = Object.keys(warpRouteConfig).reduce(
(acc, chain) => {
const { mergedObject, isInvalid } = diffObjMerge(
normalizeConfig(onChainWarpConfig[chain]),
normalizeConfig(warpRouteConfig[chain]),
);

if (isInvalid) {
acc[0][chain] = mergedObject;
acc[1] ||= isInvalid;
}

return acc;
},
[{}, false] as [{ [index: string]: ObjectDiff }, boolean],
);

if (isInvalid) {
log(formatYamlViolationsOutput(yamlStringify(violations, null, 2)));
process.exit(1);
}

logGreen(`No violations found`);
}
8 changes: 4 additions & 4 deletions typescript/cli/src/commands/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const validateChainCommand: CommandModuleWithContext<{ path: string }> = {
command: 'chain',
describe: 'Validate a chain config file',
builder: {
path: inputFileCommandOption,
path: inputFileCommandOption(),
},
handler: async ({ path }) => {
readChainConfigs(path);
Expand All @@ -54,7 +54,7 @@ const validateIsmCommand: CommandModuleWithContext<{ path: string }> = {
command: 'ism',
describe: 'Validate the basic ISM config file',
builder: {
path: inputFileCommandOption,
path: inputFileCommandOption(),
},
handler: async ({ path }) => {
readMultisigConfig(path);
Expand All @@ -67,7 +67,7 @@ const validateIsmAdvancedCommand: CommandModuleWithContext<{ path: string }> = {
command: 'ism-advanced',
describe: 'Validate the advanced ISM config file',
builder: {
path: inputFileCommandOption,
path: inputFileCommandOption(),
},
handler: async ({ path }) => {
readIsmConfig(path);
Expand All @@ -80,7 +80,7 @@ const validateWarpCommand: CommandModuleWithContext<{ path: string }> = {
command: 'warp',
describe: 'Validate a Warp Route deployment config file',
builder: {
path: inputFileCommandOption,
path: inputFileCommandOption(),
},
handler: async ({ path }) => {
await readWarpRouteDeployConfig(path);
Expand Down
26 changes: 20 additions & 6 deletions typescript/cli/src/commands/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,14 @@ export const hookCommandOption: Options = {
'A path to a JSON or YAML file with Hook configs (for every chain)',
};

export const DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH =
'./configs/warp-route-deployment.yaml';

export const warpDeploymentConfigCommandOption: Options = {
type: 'string',
description:
'A path to a JSON or YAML file with a warp route deployment config.',
default: './configs/warp-route-deployment.yaml',
default: DEFAULT_WARP_ROUTE_DEPLOYMENT_CONFIG_PATH,
alias: 'wd',
};

Expand Down Expand Up @@ -134,12 +137,23 @@ export const outputFileCommandOption = (
demandOption,
});

export const inputFileCommandOption: Options = {
interface InputFileCommandOptionConfig
extends Pick<Options, 'demandOption' | 'alias' | 'description'> {
defaultPath?: string;
}

export const inputFileCommandOption = ({
defaultPath,
demandOption = true,
description = 'Input file path',
alias = 'i',
}: InputFileCommandOptionConfig = {}): Options => ({
type: 'string',
description: 'Input file path',
alias: 'i',
demandOption: true,
};
description,
default: defaultPath,
alias,
demandOption,
});

export const fromAddressCommandOption: Options = {
type: 'string',
Expand Down
Loading

0 comments on commit 32d0a67

Please sign in to comment.