LogoLogo
  • ⏩Introduction
    • Hyperlane Introduction
    • Getting started
    • Why Should You Use Hyperlane?
  • Permissionless Interoperability
    • Overview
    • Deploy Hyperlane
    • Warp Routes
      • Deploy a Warp Route
      • Deploy a UI for your Warp Route
    • Modular Rollup Interoperability
  • Build With Hyperlane
    • Quickstarts
      • Messaging
      • Accounts
      • Queries
      • hyperlane-quickstart repo
    • Guides
      • Finding my messages
      • Automatically pay for interchain gas
      • Manually pay for interchain gas
      • Choosing an interchain gas paymaster contract
      • Unit testing
      • Specifying an ISM
      • V2 migration guide
    • Explorer
      • Debugging messages
      • Configuring PI Chains
      • REST API
      • GraphQL API
    • Troubleshooting/Developer FAQ
    • Example apps
  • APIs and SDKs
    • Messaging API
      • Send
      • Receive
    • Accounts API
    • Queries API
    • Warp Route API
    • Interchain gas paymaster API
    • Hyperlane App Framework
      • Example usage
        • HelloWorld
        • Interchain Token
      • Solidity SDK
        • HyperlaneConnectionClient
        • Router
      • NodeJS SDK
        • RPC Providers
        • Deployment
        • Interchain testing
        • Quoting gas payments
        • App Abstraction
    • Hooks API
      • Contract addresses
  • Protocol
    • Overview
    • Mailbox
    • Interchain security modules
      • Interface
      • Multisig ISM
      • Routing ISM
      • Aggregation ISM
      • Optimistic ISM
      • Wormhole ISM
      • Hook ISM
      • CCIP-Read ISM
    • Interchain gas payments
    • Staking and slashing
    • Agents
      • Validators
      • Relayers
      • Watchtowers
    • Warp Routes
    • Implementation Guide
  • Operators
    • Validators
      • Guide
      • AWS setup
      • Monitoring and alerting
    • Relayers
      • Guide
      • Message filtering
    • Agent keys
      • Hexadecimal keys
      • AWS KMS keys
    • Agent configuration
      • Configuration reference
    • Running with docker compose
  • Resources
    • FAQ
    • Glossary
    • Contract addresses
      • Permissionless Deployment Contract Addresses
    • Domain identifiers
      • Permissionless Domain Identifiers
    • Default ISM settings
    • Coming Soon: Hyperlane v3
    • Token sources & faucets
    • Latencies
    • Github
    • Discord
    • Website
Powered by GitBook
On this page
  1. APIs and SDKs
  2. Hyperlane App Framework
  3. NodeJS SDK

Interchain testing

Testing contracts locally using SDK test utilities

PreviousDeploymentNextQuoting gas payments

Last updated 2 years ago

Once you're done writing your contracts, it's time to test them! You can use the Hyperlane TestCoreApp and TestCoreDeployer to create an instance of Hyperlane for testing purposes and simulate interchain messaging.

Example Usage

In the example below, we simulate message passing between two chains. For more in depth examples see the tests in the .

import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { expect } from 'chai';
import { ethers } from 'hardhat';

import {
  ChainMap,
  ChainNameToDomainId,
  MultiProvider,
  TestChainNames,
  TestCoreApp,
  TestCoreDeployer,
  getChainToOwnerMap,
  getTestMultiProvider,
  testChainConnectionConfigs,
} from '@hyperlane-xyz/sdk';

import { HelloWorldConfig } from '../deploy/config';
import { HelloWorldDeployer } from '../deploy/deploy';
import { HelloWorld } from '../types';

describe('HelloWorld', async () => {
  const localChain = 'test1';
  const remoteChain = 'test2';
  const localDomain = ChainNameToDomainId[localChain];
  const remoteDomain = ChainNameToDomainId[remoteChain];

  let signer: SignerWithAddress;
  let local: HelloWorld;
  let remote: HelloWorld;
  let multiProvider: MultiProvider<TestChainNames>;
  let coreApp: TestCoreApp;
  let config: ChainMap<TestChainNames, HelloWorldConfig>;

  before(async () => {
    [signer] = await ethers.getSigners();

    multiProvider = getTestMultiProvider(signer);

    const coreDeployer = new TestCoreDeployer(multiProvider);
    const coreContractsMaps = await coreDeployer.deploy();
    coreApp = new TestCoreApp(coreContractsMaps, multiProvider);
    config = coreApp.extendWithConnectionClientConfig(
      getChainToOwnerMap(testChainConnectionConfigs, signer.address),
    );
  });

  beforeEach(async () => {
    const helloWorld = new HelloWorldDeployer(multiProvider, config, coreApp);
    const contracts = await helloWorld.deploy();

    local = contracts[localChain].router;
    remote = contracts[remoteChain].router;

    // The all counts start empty
    expect(await local.sent()).to.equal(0);
    expect(await local.received()).to.equal(0);
    expect(await remote.sent()).to.equal(0);
    expect(await remote.received()).to.equal(0);
  });

  it('sends a message', async () => {
    await expect(local.sendHelloWorld(remoteDomain, 'Hello')).to.emit(
      local,
      'SentHelloWorld',
    );
    // The sent counts are correct
    expect(await local.sent()).to.equal(1);
    expect(await local.sentTo(remoteDomain)).to.equal(1);
    // The received counts are correct
    expect(await local.received()).to.equal(0);
  });

  it('handles a message', async () => {
    await local.sendHelloWorld(remoteDomain, 'World');
    // Mock processing of the message by Hyperlane
    await coreApp.processOutboundMessages(localChain);
    // The initial message has been dispatched.
    expect(await local.sent()).to.equal(1);
    // The initial message has been processed.
    expect(await remote.received()).to.equal(1);
    expect(await remote.receivedFrom(localDomain)).to.equal(1);
  });
Hyperlane template application