Skip to content

Commit 77b5839

Browse files
committed
fix arbitrum lazy loading in rebalancer tests
1 parent d79b395 commit 77b5839

6 files changed

Lines changed: 102 additions & 23 deletions

File tree

typescript/rebalancer/src/e2e/harness/MockExternalBridge.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
HypERC20Collateral__factory,
77
HypNative__factory,
88
} from '@hyperlane-xyz/core';
9-
import { HyperlaneRelayer } from '@hyperlane-xyz/relayer';
109
import { HyperlaneCore, type MultiProvider } from '@hyperlane-xyz/sdk';
1110
import { assert, ProtocolType } from '@hyperlane-xyz/utils';
1211

@@ -31,6 +30,19 @@ type MockBridgeRoute = {
3130
tokenType: 'native' | 'erc20';
3231
};
3332

33+
async function loadHyperlaneRelayer(): Promise<
34+
(typeof import('@hyperlane-xyz/relayer'))['HyperlaneRelayer']
35+
> {
36+
const relayerModuleUrl = new URL(
37+
'../../../../relayer/dist/core/HyperlaneRelayer.js',
38+
import.meta.url,
39+
);
40+
const relayerModule = (await import(relayerModuleUrl.href)) as {
41+
HyperlaneRelayer: (typeof import('@hyperlane-xyz/relayer'))['HyperlaneRelayer'];
42+
};
43+
return relayerModule.HyperlaneRelayer;
44+
}
45+
3446
export class MockExternalBridge implements IExternalBridge {
3547
readonly externalBridgeId = 'mock-bridge';
3648
readonly logger: Logger;
@@ -213,6 +225,7 @@ export class MockExternalBridge implements IExternalBridge {
213225
);
214226
const dispatchedMsgId = dispatchedMessages[0].id;
215227

228+
const HyperlaneRelayer = await loadHyperlaneRelayer();
216229
const relayer = new HyperlaneRelayer({ core: this.core });
217230
const receipts = await relayer.relayAll(dispatchTxReceipt);
218231

typescript/rebalancer/src/e2e/harness/TransferHelper.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
HypERC20Collateral__factory,
66
MovableCollateralRouter__factory,
77
} from '@hyperlane-xyz/core';
8-
import { HyperlaneRelayer } from '@hyperlane-xyz/relayer';
98
import {
109
HyperlaneCore,
1110
type MultiProvider,
@@ -14,6 +13,19 @@ import {
1413
} from '@hyperlane-xyz/sdk';
1514
import { addressToBytes32, retryAsync } from '@hyperlane-xyz/utils';
1615

16+
async function loadHyperlaneRelayer(): Promise<
17+
(typeof import('@hyperlane-xyz/relayer'))['HyperlaneRelayer']
18+
> {
19+
const relayerModuleUrl = new URL(
20+
'../../../../relayer/dist/core/HyperlaneRelayer.js',
21+
import.meta.url,
22+
);
23+
const relayerModule = (await import(relayerModuleUrl.href)) as {
24+
HyperlaneRelayer: (typeof import('@hyperlane-xyz/relayer'))['HyperlaneRelayer'];
25+
};
26+
return relayerModule.HyperlaneRelayer;
27+
}
28+
1729
export interface WarpTransferParams {
1830
originChain: string;
1931
destinationChain: string;
@@ -115,6 +127,7 @@ export async function relayMessage(
115127
): Promise<ContractReceipt> {
116128
return retryAsync(
117129
async () => {
130+
const HyperlaneRelayer = await loadHyperlaneRelayer();
118131
const relayer = new HyperlaneRelayer({ core });
119132
const receipts = await relayer.relayAll(transferResult.dispatchTx);
120133
// relayAll keys receipts by domain ID, so look up by domain ID or chain name

typescript/rebalancer/src/factories/RebalancerContextFactory.test.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,19 @@ describe('RebalancerContextFactory', () => {
340340
: ProtocolType.Ethereum,
341341
}));
342342

343-
await expect(
344-
(factory as any).createInventoryRebalancerAndConfig({} as any, {}),
345-
).to.be.rejectedWith(
346-
`Missing inventory signer key for protocol ${ProtocolType.Sealevel}`,
347-
);
343+
let threw = false;
344+
try {
345+
await (factory as any).createInventoryRebalancerAndConfig(
346+
{} as any,
347+
{},
348+
);
349+
} catch (error) {
350+
threw = true;
351+
expect((error as Error).message).to.include(
352+
`Missing inventory signer key for protocol ${ProtocolType.Sealevel}`,
353+
);
354+
}
355+
expect(threw).to.equal(true);
348356
});
349357

350358
it('should accept Tron as a supported inventory protocol', async () => {
@@ -492,11 +500,19 @@ describe('RebalancerContextFactory', () => {
492500
: ProtocolType.Ethereum,
493501
}));
494502

495-
await expect(
496-
(factory as any).createInventoryRebalancerAndConfig({} as any, {}),
497-
).to.be.rejectedWith(
498-
`Inventory rebalancing does not support protocol '${ProtocolType.Cosmos}'`,
499-
);
503+
let threw = false;
504+
try {
505+
await (factory as any).createInventoryRebalancerAndConfig(
506+
{} as any,
507+
{},
508+
);
509+
} catch (error) {
510+
threw = true;
511+
expect((error as Error).message).to.include(
512+
`Inventory rebalancing does not support protocol '${ProtocolType.Cosmos}'`,
513+
);
514+
}
515+
expect(threw).to.equal(true);
500516
});
501517
});
502518
});

typescript/relayer/src/metadata/builder.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ArbL2ToL1IsmConfig,
23
ArbL2ToL1HookConfig,
34
HookType,
45
HyperlaneCore,
@@ -14,7 +15,6 @@ import {
1415
} from '@hyperlane-xyz/utils';
1516

1617
import { AggregationMetadataBuilder } from './aggregation.js';
17-
import { ArbL2ToL1MetadataBuilder } from './arbL2ToL1.js';
1818
import { OffchainLookupMetadataBuilder } from './ccipread.js';
1919
import { decodeIsmMetadata } from './decode.js';
2020
import { MultisigMetadataBuilder } from './multisig.js';
@@ -27,23 +27,33 @@ import type {
2727
StructuredMetadata,
2828
} from './types.js';
2929

30+
type ArbL2ToL1MetadataBuilderLike = {
31+
build(
32+
context: MetadataContext<
33+
WithAddress<ArbL2ToL1IsmConfig>,
34+
WithAddress<ArbL2ToL1HookConfig>
35+
>,
36+
): Promise<MetadataBuildResult>;
37+
};
38+
3039
export class BaseMetadataBuilder implements MetadataBuilder {
3140
public nullMetadataBuilder: NullMetadataBuilder;
3241
public multisigMetadataBuilder: MultisigMetadataBuilder;
3342
public aggregationMetadataBuilder: AggregationMetadataBuilder;
3443
public routingMetadataBuilder: DynamicRoutingMetadataBuilder;
35-
public arbL2ToL1MetadataBuilder: ArbL2ToL1MetadataBuilder;
44+
public arbL2ToL1MetadataBuilder?: ArbL2ToL1MetadataBuilderLike;
3645
public ccipReadMetadataBuilder: OffchainLookupMetadataBuilder;
3746

3847
public multiProvider: MultiProvider;
3948
protected logger = rootLogger.child({ module: 'BaseMetadataBuilder' });
49+
protected core: HyperlaneCore;
4050

4151
constructor(core: HyperlaneCore) {
52+
this.core = core;
4253
this.multisigMetadataBuilder = new MultisigMetadataBuilder(core);
4354
this.aggregationMetadataBuilder = new AggregationMetadataBuilder(this);
4455
this.routingMetadataBuilder = new DynamicRoutingMetadataBuilder(this);
4556
this.nullMetadataBuilder = new NullMetadataBuilder(core.multiProvider);
46-
this.arbL2ToL1MetadataBuilder = new ArbL2ToL1MetadataBuilder(core);
4757
this.ccipReadMetadataBuilder = new OffchainLookupMetadataBuilder(core);
4858
this.multiProvider = core.multiProvider;
4959
}
@@ -108,7 +118,9 @@ export class BaseMetadataBuilder implements MetadataBuilder {
108118

109119
case IsmType.ARB_L2_TO_L1: {
110120
const hookConfig = hook as WithAddress<ArbL2ToL1HookConfig>;
111-
return this.arbL2ToL1MetadataBuilder.build({
121+
const arbL2ToL1MetadataBuilder =
122+
await this.getArbL2ToL1MetadataBuilder();
123+
return arbL2ToL1MetadataBuilder.build({
112124
...context,
113125
ism,
114126
hook: hookConfig,
@@ -132,4 +144,12 @@ export class BaseMetadataBuilder implements MetadataBuilder {
132144
): StructuredMetadata {
133145
return decodeIsmMetadata(metadata, context);
134146
}
147+
148+
protected async getArbL2ToL1MetadataBuilder(): Promise<ArbL2ToL1MetadataBuilderLike> {
149+
if (!this.arbL2ToL1MetadataBuilder) {
150+
const { ArbL2ToL1MetadataBuilder } = await import('./arbL2ToL1.js');
151+
this.arbL2ToL1MetadataBuilder = new ArbL2ToL1MetadataBuilder(this.core);
152+
}
153+
return this.arbL2ToL1MetadataBuilder;
154+
}
135155
}

typescript/relayer/src/metadata/decode.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { IsmType } from '@hyperlane-xyz/sdk';
2+
import { IOutbox__factory } from '@hyperlane-xyz/core';
3+
import { utils } from 'ethers';
24

35
import { AggregationMetadataBuilder } from './aggregation.js';
4-
import { ArbL2ToL1MetadataBuilder } from './arbL2ToL1.js';
56
import { MultisigMetadataBuilder } from './multisig.js';
67
import { NullMetadataBuilder } from './null.js';
78
import { DynamicRoutingMetadataBuilder } from './routing.js';
9+
import type { ArbL2ToL1Metadata } from './arbL2ToL1.js';
810
import { MetadataContext, StructuredMetadata } from './types.js';
911

1012
export function decodeIsmMetadata(
@@ -33,12 +35,26 @@ export function decodeIsmMetadata(
3335
});
3436

3537
case IsmType.ARB_L2_TO_L1:
36-
return ArbL2ToL1MetadataBuilder.decode(metadata, {
37-
...context,
38-
ism,
39-
});
38+
return decodeArbL2ToL1Metadata(metadata);
4039

4140
default:
4241
throw new Error(`Unsupported ISM type: ${ism.type}`);
4342
}
4443
}
44+
45+
function decodeArbL2ToL1Metadata(metadata: string): ArbL2ToL1Metadata {
46+
const abiCoder = new utils.AbiCoder();
47+
const outboxInterface = IOutbox__factory.createInterface();
48+
const executeTransactionInputs =
49+
outboxInterface.functions[
50+
'executeTransaction(bytes32[],uint256,address,address,uint256,uint256,uint256,uint256,bytes)'
51+
].inputs;
52+
const executeTransactionTypes = executeTransactionInputs
53+
.map((input) => input.type)
54+
.filter((_, index, array) => index !== array.length - 2);
55+
const decoded = abiCoder.decode(executeTransactionTypes, metadata);
56+
57+
return Object.fromEntries(
58+
Object.keys({} as ArbL2ToL1Metadata).map((key, i) => [key, decoded[i]]),
59+
) as ArbL2ToL1Metadata;
60+
}

typescript/sdk/src/hook/EvmHookModule.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { getArbitrumNetwork } from '@arbitrum/sdk';
21
import { BigNumber, ethers } from 'ethers';
32

43
import {
@@ -896,7 +895,9 @@ export class EvmHookModule extends HyperlaneModule<
896895
}
897896

898897
const bridge =
899-
config.bridge ?? getArbitrumNetwork(destinationChainId).ethBridge.bridge;
898+
config.bridge ??
899+
(await import('@arbitrum/sdk')).getArbitrumNetwork(destinationChainId)
900+
.ethBridge.bridge;
900901

901902
const ismConfig: ArbL2ToL1IsmConfig = {
902903
type: IsmType.ARB_L2_TO_L1,

0 commit comments

Comments
 (0)