Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: ica submission strategy support in the cli #4980

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
58113ab
feat(sdk): added ICA_FALLBACK_ROUTING variant to the IsmType enum
xeno097 Nov 26, 2024
a48aac0
feat(sdk): updated the ts relayer and IsmReader to support the Ica Is…
xeno097 Nov 26, 2024
c5264a1
feat(sdk): removed the domain field from the ica fallback routing ism…
xeno097 Nov 27, 2024
99d6f26
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Nov 29, 2024
e12e323
test(sdk): added ism test to deploy and read an ICA routing ISM
xeno097 Dec 2, 2024
ad93427
refactor(): renamed OwnableRoutingIsmConfig -> DomainRoutingIsmConfig
xeno097 Dec 2, 2024
d2f6148
refactor(sdk): removed unused params from the deployIcaIsm method
xeno097 Dec 2, 2024
af65d81
docs(changeset): Updated the derivation logic to enable ICA ISM metda…
xeno097 Dec 2, 2024
69991c3
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Dec 2, 2024
54c817c
fix(cli): fixed type compilation issue
xeno097 Dec 2, 2024
106a63f
chore(sdk): updated the routingModuleDelta func to return an empty mo…
xeno097 Dec 2, 2024
bd740c4
refactor(sdk): renamed IsmType.ICA_FALLBACK_ROUTING to IsmType.ICA_RO…
xeno097 Dec 2, 2024
6001d8d
fix(sdk): fixed typing on randomIsmConfig func
xeno097 Dec 2, 2024
05668d2
checkpoint(cli): started working on the ica tx submitter
xeno097 Dec 4, 2024
0c0c7a7
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Dec 4, 2024
45a6e33
feat(sdk): implemented first working version of the EvmIcaSubmitter
xeno097 Dec 5, 2024
fab8017
feat(cli): updated the getSubmitter func to return a EvmIcaSubmitter …
xeno097 Dec 5, 2024
6a318db
feat(cli): added logic to get the interchainAccountRouterAddress if n…
xeno097 Dec 5, 2024
dbfcc00
feat(sdk): updated the EvmIcaTxSubmitter to use the set signer addres…
xeno097 Dec 5, 2024
f527f10
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Dec 5, 2024
a2af040
refactor(sdk): reduced code duplication for types realted to the EvmI…
xeno097 Dec 5, 2024
fae8901
chore(cli): removed transformers from the getSubmitter function
xeno097 Dec 5, 2024
f3fe5a1
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Dec 6, 2024
6967dda
feat(sdk): improved type safety for the getInternalSubmitter func
xeno097 Dec 6, 2024
69c5c80
feat(cli): added self relay support for ica transactions in the cli
xeno097 Dec 10, 2024
6f4a6d3
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Dec 10, 2024
bb50fe6
docs(cli): added examples for the ICA submitter strategy config files
xeno097 Dec 10, 2024
3597d18
test(cli): deduped warp deploy file path var
xeno097 Dec 10, 2024
917a6ab
refactor(cli): implemented the runSelfRelay func
xeno097 Dec 10, 2024
e361777
docs(changeset): Updated ICA transaction support for allowing the CLI…
xeno097 Dec 10, 2024
6aaefb7
Merge branch 'main' of github.com:hyperlane-xyz/hyperlane-monorepo in…
xeno097 Dec 10, 2024
ead2c66
chore: yarn prettier
xeno097 Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/nasty-geckos-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@hyperlane-xyz/cli': major
'@hyperlane-xyz/sdk': major
---

Updated ICA transaction support for allowing the CLI to send them when provided with the appropriate strategy config

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
polygonamoy:
submitter:
type: interchainAccount
# The origin chain for the ICA transactions
chain: basesepolia
# The destination chain for the transactions
destinationChain: polygonamoy
# The owner of the remote ICA account
owner: '0x32e02dDB233958834fcB5E93b11E254F8D1EAd1b'
internalSubmitter:
type: gnosisSafeTxBuilder
# The Gnosis Safe address. It must be equal to the owner field as
# the Safe is the owner of ICA account on the remote chain
safeAddress: '0x32e02dDB233958834fcB5E93b11E254F8D1EAd1b'
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
anvil3:
submitter:
type: interchainAccount
# The origin chain for the ICA transactions
chain: anvil2
# The destination chain for the transactions
destinationChain: anvil3
# Specifies how the ICA transactions will be sent to the destination chain. If omitted it
# will default to use a JSON RPC submitter
internalSubmitter:
type: jsonRpc
9 changes: 9 additions & 0 deletions typescript/cli/src/commands/warp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export const apply: CommandModuleWithWriteContext<{
warp: string;
strategy?: string;
receiptsDir: string;
relay?: boolean;
}> = {
command: 'apply',
describe: 'Update Warp Route contracts',
Expand All @@ -89,6 +90,12 @@ export const apply: CommandModuleWithWriteContext<{
default: './generated/transactions',
coerce: (dir) => removeEndingSlash(dir),
},
relay: {
type: 'boolean',
description:
'Handle self-relay of ICA transactions when using a JSON RPC submitter',
default: false,
},
},
handler: async ({
context,
Expand All @@ -97,6 +104,7 @@ export const apply: CommandModuleWithWriteContext<{
warp,
strategy: strategyUrl,
receiptsDir,
relay,
}) => {
logCommandHeader('Hyperlane Warp Apply');

Expand All @@ -116,6 +124,7 @@ export const apply: CommandModuleWithWriteContext<{
warpCoreConfig,
strategyUrl,
receiptsDir,
selfRelay: relay,
});
process.exit(0);
},
Expand Down
1 change: 1 addition & 0 deletions typescript/cli/src/config/submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export async function runSubmit({
const submitterBuilder = await getSubmitterBuilder<ProtocolType>({
submissionStrategy,
multiProvider,
registry: context.registry,
});

try {
Expand Down
44 changes: 35 additions & 9 deletions typescript/cli/src/deploy/warp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
RemoteRouters,
RoutingIsmConfig,
SubmissionStrategy,
SubmissionStrategySchema,
TOKEN_TYPE_TO_STANDARD,
TokenFactories,
TrustedRelayerIsmConfig,
Expand Down Expand Up @@ -69,6 +70,7 @@ import { MINIMUM_WARP_DEPLOY_GAS } from '../consts.js';
import { requestAndSaveApiKeys } from '../context/context.js';
import { WriteCommandContext } from '../context/types.js';
import { log, logBlue, logGray, logGreen, logTable } from '../logger.js';
import { WarpSendLogs } from '../send/transfer.js';
import { getSubmitterBuilder } from '../submit/submit.js';
import {
indentYamlOrJson,
Expand All @@ -77,6 +79,7 @@ import {
runFileSelectionStep,
writeYamlOrJson,
} from '../utils/files.js';
import { canSelfRelay, runSelfRelay } from '../utils/relay.js';

import {
completeDeploy,
Expand All @@ -93,6 +96,7 @@ interface WarpApplyParams extends DeployParams {
warpCoreConfig: WarpCoreConfig;
strategyUrl?: string;
receiptsDir: string;
selfRelay?: boolean;
}

export async function runWarpRouteDeploy({
Expand Down Expand Up @@ -1011,13 +1015,14 @@ async function submitWarpApplyTransactions(
await retryAsync(
async () => {
const chain = chainIdToName[chainId];
const submitter: TxSubmitterBuilder<ProtocolType> =
await getWarpApplySubmitter({
const { submitter, config } =
await getWarpApplySubmitter<ProtocolType.Ethereum>({
chain,
context: params.context,
strategyUrl: params.strategyUrl,
});
const transactionReceipts = await submitter.submit(...transactions);

if (transactionReceipts) {
const receiptPath = `${params.receiptsDir}/${chain}-${
submitter.txSubmitterType
Expand All @@ -1027,6 +1032,20 @@ async function submitWarpApplyTransactions(
`Transactions receipts successfully written to ${receiptPath}`,
);
}

const canRelay = canSelfRelay(
params.selfRelay ?? false,
config,
transactionReceipts,
);
if (canRelay.relay) {
await runSelfRelay({
txReceipt: canRelay.txReceipt,
multiProvider: params.context.multiProvider,
registry: params.context.registry,
successMessage: WarpSendLogs.SUCCESS,
});
}
},
5, // attempts
100, // baseRetryMs
Expand All @@ -1040,16 +1059,19 @@ async function submitWarpApplyTransactions(
*
* @returns the warp apply submitter
*/
async function getWarpApplySubmitter({
async function getWarpApplySubmitter<T extends ProtocolType>({
chain,
context,
strategyUrl,
}: {
chain: ChainName;
context: WriteCommandContext;
strategyUrl?: string;
}): Promise<TxSubmitterBuilder<ProtocolType>> {
const { multiProvider } = context;
}): Promise<{
submitter: TxSubmitterBuilder<T>;
config: SubmissionStrategy;
}> {
const { multiProvider, registry } = context;

const submissionStrategy: SubmissionStrategy = strategyUrl
? readChainSubmissionStrategy(strategyUrl)[chain]
Expand All @@ -1060,8 +1082,12 @@ async function getWarpApplySubmitter({
},
};

return getSubmitterBuilder<ProtocolType>({
submissionStrategy,
multiProvider,
});
return {
submitter: await getSubmitterBuilder<T>({
submissionStrategy: SubmissionStrategySchema.parse(submissionStrategy),
multiProvider,
registry,
}),
config: submissionStrategy,
};
}
19 changes: 7 additions & 12 deletions typescript/cli/src/send/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
ChainName,
DispatchedMessage,
HyperlaneCore,
HyperlaneRelayer,
MultiProtocolProvider,
ProviderType,
Token,
Expand All @@ -20,7 +19,7 @@ import { runPreflightChecksForChains } from '../deploy/utils.js';
import { log, logBlue, logGreen, logRed } from '../logger.js';
import { runSingleChainSelectionStep } from '../utils/chains.js';
import { indentYamlOrJson } from '../utils/files.js';
import { stubMerkleTreeConfig } from '../utils/relay.js';
import { runSelfRelay } from '../utils/relay.js';
import { runTokenSelectionStep } from '../utils/tokens.js';

export const WarpSendLogs = {
Expand Down Expand Up @@ -183,16 +182,12 @@ async function executeDelivery({
log(`Body:\n${indentYamlOrJson(yamlStringify(parsed, null, 2), 4)}`);

if (selfRelay) {
const relayer = new HyperlaneRelayer({ core });

const hookAddress = await core.getSenderHookAddress(message);
const merkleAddress = chainAddresses[origin].merkleTreeHook;
stubMerkleTreeConfig(relayer, origin, hookAddress, merkleAddress);

log('Attempting self-relay of transfer...');
await relayer.relayMessage(transferTxReceipt, messageIndex, message);
logGreen(WarpSendLogs.SUCCESS);
return;
return runSelfRelay({
txReceipt: transferTxReceipt,
multiProvider: multiProvider,
registry: registry,
successMessage: WarpSendLogs.SUCCESS,
});
}

if (skipWaitForDelivery) return;
Expand Down
65 changes: 30 additions & 35 deletions typescript/cli/src/submit/submit.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
import { IRegistry } from '@hyperlane-xyz/registry';
import {
EV5GnosisSafeTxBuilder,
EV5GnosisSafeTxSubmitter,
EV5ImpersonatedAccountTxSubmitter,
EV5InterchainAccountTxTransformer,
EV5JsonRpcTxSubmitter,
EvmIcaTxSubmitter,
MultiProvider,
SubmitterMetadata,
TransformerMetadata,
TxSubmitterBuilder,
TxSubmitterInterface,
TxSubmitterType,
TxTransformerInterface,
TxTransformerType,
} from '@hyperlane-xyz/sdk';
import { ProtocolType } from '@hyperlane-xyz/utils';
import { Address, ProtocolType } from '@hyperlane-xyz/utils';

import { SubmitterBuilderSettings } from './types.js';

export async function getSubmitterBuilder<TProtocol extends ProtocolType>({
submissionStrategy,
multiProvider,
registry,
}: SubmitterBuilderSettings): Promise<TxSubmitterBuilder<TProtocol>> {
const submitter = await getSubmitter<TProtocol>(
multiProvider,
submissionStrategy.submitter,
);
const transformers = await getTransformers<TProtocol>(
multiProvider,
submissionStrategy.transforms ?? [],
registry,
);

return new TxSubmitterBuilder<TProtocol>(submitter, transformers);
return new TxSubmitterBuilder<TProtocol>(submitter, []);
}

async function getSubmitter<TProtocol extends ProtocolType>(
multiProvider: MultiProvider,
submitterMetadata: SubmitterMetadata,
registry: IRegistry,
): Promise<TxSubmitterInterface<TProtocol>> {
let interchainAccountRouterAddress: Address | undefined;
if (submitterMetadata.type === TxSubmitterType.INTERCHAIN_ACCOUNT) {
const metadata = await registry.getChainAddresses(submitterMetadata.chain);

interchainAccountRouterAddress =
submitterMetadata.originInterchainAccountRouter ??
metadata?.interchainAccountRouter;
}

switch (submitterMetadata.type) {
case TxSubmitterType.JSON_RPC:
return new EV5JsonRpcTxSubmitter(multiProvider, {
Expand All @@ -54,32 +60,21 @@ async function getSubmitter<TProtocol extends ProtocolType>(
return EV5GnosisSafeTxBuilder.create(multiProvider, {
...submitterMetadata,
});
default:
throw new Error(`Invalid TxSubmitterType.`);
}
}

async function getTransformers<TProtocol extends ProtocolType>(
multiProvider: MultiProvider,
transformersMetadata: TransformerMetadata[],
): Promise<TxTransformerInterface<TProtocol>[]> {
return Promise.all(
transformersMetadata.map((transformerMetadata) =>
getTransformer<TProtocol>(multiProvider, transformerMetadata),
),
);
}
case TxSubmitterType.INTERCHAIN_ACCOUNT:
if (!interchainAccountRouterAddress) {
throw new Error(
`Origin chain InterchainAccountRouter address not supplied and none found in the registry metadata for chain ${submitterMetadata.chain}`,
);
}

async function getTransformer<TProtocol extends ProtocolType>(
multiProvider: MultiProvider,
transformerMetadata: TransformerMetadata,
): Promise<TxTransformerInterface<TProtocol>> {
switch (transformerMetadata.type) {
case TxTransformerType.INTERCHAIN_ACCOUNT:
return new EV5InterchainAccountTxTransformer(multiProvider, {
...transformerMetadata,
});
return EvmIcaTxSubmitter.fromConfig(
{
...submitterMetadata,
originInterchainAccountRouter: interchainAccountRouterAddress,
},
multiProvider,
);
default:
throw new Error('Invalid TxTransformerType.');
throw new Error(`Invalid TxSubmitterType.`);
}
}
2 changes: 2 additions & 0 deletions typescript/cli/src/submit/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { IRegistry } from '@hyperlane-xyz/registry';
import type { MultiProvider, SubmissionStrategy } from '@hyperlane-xyz/sdk';

export type SubmitterBuilderSettings = {
submissionStrategy: SubmissionStrategy;
multiProvider: MultiProvider;
registry: IRegistry;
};
6 changes: 6 additions & 0 deletions typescript/cli/src/tests/commands/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@ export const CHAIN_NAME_3 = 'anvil3';
export const EXAMPLES_PATH = './examples';
export const CORE_CONFIG_PATH = `${EXAMPLES_PATH}/core-config.yaml`;
export const CORE_READ_CONFIG_PATH_2 = `${TEMP_PATH}/${CHAIN_NAME_2}/core-config-read.yaml`;
export const CORE_READ_CONFIG_PATH_3 = `${TEMP_PATH}/${CHAIN_NAME_3}/core-config-read.yaml`;
export const CHAIN_2_METADATA_PATH = `${REGISTRY_PATH}/chains/${CHAIN_NAME_2}/metadata.yaml`;
export const CHAIN_3_METADATA_PATH = `${REGISTRY_PATH}/chains/${CHAIN_NAME_3}/metadata.yaml`;

export const WARP_CONFIG_PATH_EXAMPLE = `${EXAMPLES_PATH}/warp-route-deployment.yaml`;
export const WARP_CONFIG_PATH_2 = `${TEMP_PATH}/${CHAIN_NAME_2}/warp-route-deployment-anvil2.yaml`;
export const WARP_CORE_CONFIG_PATH_2 = `${REGISTRY_PATH}/deployments/warp_routes/ETH/anvil2-config.yaml`;

export const WARP_DEPLOY_CONFIG_CHAIN_2 = `${TEMP_PATH}/warp-route-deployment-2.yaml`;
export const WARP_DEPLOY_CONFIG_CHAIN_3 = `${TEMP_PATH}/warp-route-deployment-3.yaml`;

export const JSON_RPC_ICA_STRATEGY_CONFIG_PATH = `${EXAMPLES_PATH}/submit/strategy/json-rpc-ica-strategy.yaml`;

export const DEFAULT_E2E_TEST_TIMEOUT = 100_000; // Long timeout since these tests can take a while

/**
Expand Down
2 changes: 2 additions & 0 deletions typescript/cli/src/tests/commands/warp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export async function hyperlaneWarpApply(
warpDeployPath: string,
warpCorePath: string,
strategyUrl = '',
relay = false,
) {
return $`yarn workspace @hyperlane-xyz/cli run hyperlane warp apply \
--registry ${REGISTRY_PATH} \
Expand All @@ -38,6 +39,7 @@ export async function hyperlaneWarpApply(
--key ${ANVIL_KEY} \
--verbosity debug \
--strategy ${strategyUrl} \
${relay ? '--relay' : ''} \
--yes`;
}

Expand Down
Loading
Loading