Skip to content

Commit 70354d6

Browse files
authored
fix(cli): restore foreignDeployment behaviour during deployment + add cross chain tests for the cli (#7156)
1 parent 97b1e76 commit 70354d6

29 files changed

Lines changed: 1824 additions & 85 deletions

File tree

.changeset/long-adults-repeat.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@hyperlane-xyz/cli": patch
3+
"@hyperlane-xyz/sdk": patch
4+
---
5+
6+
Restore foreignDeployment field behaviour to allow enrollment of unsupported chains during deployment

.github/workflows/test.yml

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,9 +393,43 @@ jobs:
393393
env:
394394
CLI_E2E_TEST: ${{ matrix.test }}
395395

396+
cli-cross-chain-e2e-matrix:
397+
runs-on: depot-ubuntu-latest
398+
needs: [rust-only]
399+
if: needs.rust-only.outputs.only_rust == 'false'
400+
strategy:
401+
fail-fast: false
402+
matrix:
403+
test:
404+
# Warp Commands
405+
- warp-apply
406+
- warp-deploy
407+
steps:
408+
- uses: actions/checkout@v4
409+
with:
410+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
411+
submodules: recursive
412+
fetch-depth: 0
413+
414+
- name: install-hyperlane-cli
415+
id: install-hyperlane-cli
416+
uses: ./.github/actions/install-cli
417+
with:
418+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
419+
cache-provider: github
420+
421+
- name: Checkout registry
422+
uses: ./.github/actions/checkout-registry
423+
424+
- name: CLI cross chain e2e tests (${{ matrix.test }})
425+
run: yarn --cwd typescript/cli test:cross-chain:e2e
426+
env:
427+
CLI_E2E_TEST: ${{ matrix.test }}
428+
396429
cli-e2e:
397430
runs-on: ubuntu-latest
398-
needs: [cli-evm-e2e-matrix, cli-cosmos-e2e-matrix]
431+
needs:
432+
[cli-evm-e2e-matrix, cli-cosmos-e2e-matrix, cli-cross-chain-e2e-matrix]
399433
if: always()
400434
steps:
401435
- uses: actions/checkout@v4
@@ -409,6 +443,11 @@ jobs:
409443
with:
410444
job_name: 'CLI CosmosNative E2E'
411445
result: ${{ needs.cli-cosmos-e2e-matrix.result }}
446+
- name: Check CLI Cross Chain E2E status
447+
uses: ./.github/actions/check-job-status
448+
with:
449+
job_name: 'CLI Cross Chain E2E'
450+
result: ${{ needs.cli-cross-chain-e2e-matrix.result }}
412451

413452
cosmos-sdk-e2e-run:
414453
runs-on: depot-ubuntu-latest

typescript/cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"prettier": "^3.5.3",
4444
"prom-client": "^14.0.1",
4545
"terminal-link": "^3.0.0",
46+
"testcontainers": "11.7.0",
4647
"tsx": "^4.19.1",
4748
"typescript": "5.3.3",
4849
"yaml": "2.4.5",
@@ -62,6 +63,7 @@
6263
"prettier": "prettier --write ./src ./examples",
6364
"test:ci": "yarn mocha --config .mocharc.json",
6465
"test:ethereum:e2e": "./src/tests/ethereum/run-e2e-test.sh",
66+
"test:cross-chain:e2e": "./src/tests/cross-chain/run-e2e-test.sh",
6567
"test:cosmosnative:e2e": "./src/tests/cosmosnative/run-e2e-test.sh",
6668
"version:update": "echo \"export const VERSION = '$npm_package_version';\" > src/version.ts",
6769
"prepack": "yarn bundle"

typescript/cli/src/deploy/warp.ts

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ export async function runWarpRouteApply(
373373
params: WarpApplyParams,
374374
): Promise<void> {
375375
const { warpDeployConfig, warpCoreConfig, context } = params;
376-
const { chainMetadata, skipConfirmation } = context;
376+
const { chainMetadata, skipConfirmation, multiProvider } = context;
377377

378378
WarpRouteDeployConfigSchema.parse(warpDeployConfig);
379379
WarpCoreConfigSchema.parse(warpCoreConfig);
@@ -394,10 +394,18 @@ export async function runWarpRouteApply(
394394
// temporarily configure deployer as owner so that warp update after extension
395395
// can leverage JSON RPC submitter on new chains
396396
const intermediateOwnerConfig = await promiseObjAll(
397-
objMap(params.warpDeployConfig, async (chain, config) => ({
398-
...config,
399-
owner: await multiProtocolSigner.getSignerAddress(chain),
400-
})),
397+
objMap(params.warpDeployConfig, async (chain, config) => {
398+
const protocolType = multiProvider.getProtocol(chain);
399+
400+
if (!COMPATIBLE_PROTOCOLS.includes(protocolType)) {
401+
return config;
402+
}
403+
404+
return {
405+
...config,
406+
owner: await multiProtocolSigner.getSignerAddress(chain),
407+
};
408+
}),
401409
);
402410

403411
// Extend the warp route and get the updated configs
@@ -636,14 +644,20 @@ async function updateExistingWarpRoute(
636644
await promiseObjAll(
637645
objMap(expandedWarpDeployConfig, async (chain, config) => {
638646
await retryAsync(async () => {
647+
const protocolType = multiProvider.getProtocol(chain);
648+
if (!COMPATIBLE_PROTOCOLS.includes(protocolType)) {
649+
logBlue(`Skipping non-compatible chain ${chain}`);
650+
return;
651+
}
652+
639653
const deployedTokenRoute = deployedRoutersAddresses[chain];
640654
assert(deployedTokenRoute, `Missing artifacts for ${chain}.`);
641655
const configWithMailbox = {
642656
...config,
643657
mailbox: registryAddresses[chain].mailbox,
644658
};
645659

646-
switch (multiProvider.getProtocol(chain)) {
660+
switch (protocolType) {
647661
case ProtocolType.Ethereum: {
648662
const evmERC20WarpModule = new EvmERC20WarpModule(
649663
multiProvider,
@@ -683,10 +697,6 @@ async function updateExistingWarpRoute(
683697
updateTransactions[chain] = transactions;
684698
break;
685699
}
686-
default: {
687-
logBlue(`Skipping non-compatible chain ${chain}`);
688-
return;
689-
}
690700
}
691701
});
692702
}),

typescript/cli/src/read/warp.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ import {
2020
import {
2121
Address,
2222
ProtocolType,
23+
objFilter,
2324
objMap,
2425
promiseObjAll,
2526
} from '@hyperlane-xyz/utils';
2627

28+
import { COMPATIBLE_PROTOCOLS } from '../config/protocols.js';
2729
import { CommandContext } from '../context/types.js';
2830
import { logGray, logRed, logTable, warnYellow } from '../logger.js';
2931
import { getWarpCoreConfigOrExit } from '../utils/warp.js';
@@ -66,7 +68,21 @@ export async function runWarpRouteRead({
6668
);
6769
}
6870

69-
return deriveWarpRouteConfigs(context, addresses, warpCoreConfig);
71+
// Remove any unsupported chain to avoid crashing
72+
const filteredAddresses = objFilter(
73+
addresses,
74+
(chain, _address): _address is string =>
75+
COMPATIBLE_PROTOCOLS.includes(context.multiProvider.getProtocol(chain)),
76+
);
77+
if (warpCoreConfig) {
78+
warpCoreConfig.tokens = warpCoreConfig.tokens.filter((config) =>
79+
COMPATIBLE_PROTOCOLS.includes(
80+
context.multiProvider.getProtocol(config.chainName),
81+
),
82+
);
83+
}
84+
85+
return deriveWarpRouteConfigs(context, filteredAddresses, warpCoreConfig);
7086
}
7187

7288
export async function getWarpRouteConfigsByCore({

typescript/cli/src/tests/commands/core.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { readYamlOrJson } from '../../utils/files.js';
99

1010
import { localTestRunCmdPrefix } from './helpers.js';
1111

12+
$.verbose = true;
13+
1214
export class HyperlaneE2ECoreTestCommands {
1315
protected cmdPrefix: string[];
1416

typescript/cli/src/tests/commands/warp.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,15 @@ export class HyperlaneE2EWarpTestCommands {
118118
skipConfirmationPrompts,
119119
privateKey,
120120
warpRouteId,
121+
extraArgs,
121122
}: {
122123
warpCorePath?: string;
123124
warpDeployPath?: string;
124125
hypKey?: string;
125126
skipConfirmationPrompts?: boolean;
126127
privateKey?: string;
127128
warpRouteId?: string;
129+
extraArgs?: string[];
128130
}): ProcessPromise {
129131
return $`${
130132
hypKey ? [`${this.hypKeyEnvName}=${hypKey}`] : []
@@ -135,7 +137,9 @@ export class HyperlaneE2EWarpTestCommands {
135137
${privateKey ? [this.privateKeyFlag, privateKey] : []} \
136138
--verbosity debug \
137139
${warpRouteId ? ['--warpRouteId', warpRouteId] : []} \
138-
${skipConfirmationPrompts ? ['--yes'] : []}`;
140+
${skipConfirmationPrompts ? ['--yes'] : []} \
141+
${extraArgs ? extraArgs : []}
142+
`;
139143
}
140144

141145
/**
@@ -153,4 +157,41 @@ export class HyperlaneE2EWarpTestCommands {
153157
warpRouteId,
154158
});
155159
}
160+
161+
public applyRaw({
162+
warpDeployPath,
163+
warpCorePath,
164+
strategyUrl,
165+
warpRouteId,
166+
privateKey,
167+
relay,
168+
hypKey,
169+
extraArgs,
170+
skipConfirmationPrompts,
171+
}: {
172+
warpDeployPath?: string;
173+
warpCorePath?: string;
174+
strategyUrl?: string;
175+
warpRouteId?: string;
176+
privateKey?: string;
177+
hypKey?: string;
178+
relay?: boolean;
179+
skipConfirmationPrompts?: boolean;
180+
extraArgs?: string[];
181+
}): ProcessPromise {
182+
return $` ${
183+
hypKey ? [`${this.hypKeyEnvName}=${hypKey}`] : []
184+
} ${localTestRunCmdPrefix()} hyperlane warp apply \
185+
--registry ${this.registryPath} \
186+
${warpDeployPath ? ['--config', warpDeployPath] : []} \
187+
${warpCorePath ? ['--warp', warpCorePath] : []} \
188+
${strategyUrl ? ['--strategy', strategyUrl] : []} \
189+
${warpRouteId ? ['--warpRouteId', warpRouteId] : []} \
190+
${privateKey ? [this.privateKeyFlag, privateKey] : []} \
191+
--verbosity debug \
192+
${relay ? ['--relay'] : []} \
193+
${skipConfirmationPrompts ? ['--yes'] : []} \
194+
${extraArgs ? extraArgs : []}
195+
`;
196+
}
156197
}

0 commit comments

Comments
 (0)