diff --git a/.github/workflows/multichain-e2e-template.yml b/.github/workflows/multichain-e2e-template.yml index 32cc3f6594a..eac801343c2 100644 --- a/.github/workflows/multichain-e2e-template.yml +++ b/.github/workflows/multichain-e2e-template.yml @@ -97,7 +97,7 @@ jobs: working-directory: ./agoric-sdk/multichain-testing - name: Run @agoric/multichain-testing E2E Tests - run: yarn ${{ inputs.test_command }} + run: ${{ inputs.test_command }} working-directory: ./agoric-sdk/multichain-testing env: FILE: ${{ inputs.config }} diff --git a/.github/workflows/multichain-e2e.yml b/.github/workflows/multichain-e2e.yml index bb86c2d7ffc..2e06f82f67c 100644 --- a/.github/workflows/multichain-e2e.yml +++ b/.github/workflows/multichain-e2e.yml @@ -2,19 +2,55 @@ name: Multichain E2E Tests on: workflow_dispatch: + inputs: + test_type: + description: 'Select which test to run' + type: choice + required: true + options: + - orchestration-api-hermes + - fast-usdc-hermes + - orchestration-api-go-relayer + - fast-usdc-go-relayer workflow_call: jobs: - orchestration-api-test: - name: Multichain E2E (Orchestration API) + orchestration-api-hermes: + name: Multichain E2E (Orchestration API - Hermes) + if: | + github.event_name == 'workflow_call' || + github.event_name == 'pull_request' || + (github.event_name == 'workflow_dispatch' && inputs.test_type == 'orchestration-api-hermes') uses: ./.github/workflows/multichain-e2e-template.yml with: config: config.yaml - test_command: test:main + test_command: yarn test:main - fast-usdc-test: - name: Multichain E2E (Fast USDC) + fast-usdc-hermes: + name: Multichain E2E (Fast USDC - Hermes) + if: | + github.event_name == 'workflow_call' || + github.event_name == 'pull_request' || + (github.event_name == 'workflow_dispatch' && inputs.test_type == 'fast-usdc-hermes') uses: ./.github/workflows/multichain-e2e-template.yml with: config: config.fusdc.yaml - test_command: test:fast-usdc + test_command: yarn test:fast-usdc + + orchestration-api-go-relayer: + name: Multichain E2E (Orchestration API - Go Relayer) + # run on dispatch only + if: github.event_name == 'workflow_dispatch' && inputs.test_type == 'orchestration-api-go-relayer' + uses: ./.github/workflows/multichain-e2e-template.yml + with: + config: config.go-relayer.yaml + test_command: RELAYER_TYPE=go-relayer yarn test:main + + fast-usdc-go-relayer: + name: Multichain E2E (Fast USDC - Go Relayer) + # run on dispatch only + if: github.event_name == 'workflow_dispatch' && inputs.test_type == 'fast-usdc-go-relayer' + uses: ./.github/workflows/multichain-e2e-template.yml + with: + config: config.fusdc.go-relayer.yaml + test_command: RELAYER_TYPE=go-relayer yarn test:fast-usdc diff --git a/multichain-testing/README.md b/multichain-testing/README.md index 949b1aeab8d..b2fd0ba8bcc 100644 --- a/multichain-testing/README.md +++ b/multichain-testing/README.md @@ -88,8 +88,17 @@ make tail-slog kubectl logs agoriclocal-genesis-0 --container=validator --follow # relayer logs -kubectl logs hermes-agoric-gaia-0 --container=relayer --follow -kubectl logs hermes-osmosis-gaia-0 --container=relayer --follow +kubectl logs hermes-agoric-cosmoshub-0 --container=relayer --follow +kubectl logs hermes-osmosis-cosmoshub-0 --container=relayer --follow +``` + +## Running with Go Relayer + +```sh +# run tests with go-relayer configuration +make start FILE=config.go-relayer.yaml + +RELAYER_TYPE=go-relayer yarn test ``` ## Agoric Smart Wallet @@ -116,6 +125,6 @@ These only work if you've done `make port-forward`. - http://localhost:8081/chains/agoriclocal - http://localhost:8081/chains/osmosislocal -- http://localhost:8081/chains/gaialocal +- http://localhost:8081/chains/cosmoshublocal - http://localhost:8081/chains/agoriclocal/keys - http://localhost:8081/ibc diff --git a/multichain-testing/config.fusdc.go-relayer.yaml b/multichain-testing/config.fusdc.go-relayer.yaml new file mode 100644 index 00000000000..e69d6a55ba2 --- /dev/null +++ b/multichain-testing/config.fusdc.go-relayer.yaml @@ -0,0 +1,112 @@ +name: agoric-multichain-testing-fusdc-go-relayer +version: 0.2.20 + +chains: + - id: agoriclocal + name: agoric + image: ghcr.io/agoric/agoric-sdk:dev + numValidators: 1 + env: + - name: DEBUG + value: SwingSet:vat,SwingSet:ls + genesis: + app_state: + staking: + params: + unbonding_time: '2m' + swingset: + params: + bootstrap_vat_config: '@agoric/vm-config/decentral-itest-orchestration-config.json' + scripts: + updateConfig: + file: scripts/update-config.sh + faucet: + enabled: true + type: starship + ports: + rest: 1317 + rpc: 26657 + exposer: 38087 + grpc: 9090 + faucet: 8082 + resources: + cpu: 1 + memory: 4Gi + - id: osmosislocal + name: osmosis + numValidators: 1 + genesis: + app_state: + staking: + params: + unbonding_time: '2m' + interchain_accounts: + host_genesis_state: + params: + host_enabled: true + allow_messages: ['*'] + interchainquery: + host_port: 'icqhost' + params: + host_enabled: true + allow_queries: + - /cosmos.bank.v1beta1.Query/Balance + - /cosmos.bank.v1beta1.Query/AllBalances + faucet: + enabled: true + type: starship + ports: + rest: 1315 + rpc: 26655 + grpc: 9093 + faucet: 8084 + resources: + cpu: 1 + memory: 1Gi + - id: noblelocal + name: noble + numValidators: 1 + genesis: + app_state: + staking: + params: + unbonding_time: '2m' + faucet: + enabled: true + type: starship + ports: + rest: 1314 + rpc: 26654 + grpc: 9092 + faucet: 8083 + resources: + cpu: 1 + memory: 1Gi + +relayers: + - name: osmosis-noble + type: go-relayer + replicas: 1 + chains: + - osmosislocal + - noblelocal + - name: agoric-osmosis + type: go-relayer + replicas: 1 + chains: + - agoriclocal + - osmosislocal + - name: agoric-noble + type: go-relayer + replicas: 1 + chains: + - agoriclocal + - noblelocal + +explorer: + enabled: false + +registry: + enabled: true + ports: + rest: 8081 diff --git a/multichain-testing/config.fusdc.yaml b/multichain-testing/config.fusdc.yaml index c542d208386..aeca4b59785 100644 --- a/multichain-testing/config.fusdc.yaml +++ b/multichain-testing/config.fusdc.yaml @@ -21,12 +21,14 @@ chains: updateConfig: file: scripts/update-config.sh faucet: - enabled: false + enabled: true + type: starship ports: rest: 1317 rpc: 26657 exposer: 38087 grpc: 9090 + faucet: 8082 resources: cpu: 1 memory: 4Gi diff --git a/multichain-testing/config.go-relayer.yaml b/multichain-testing/config.go-relayer.yaml new file mode 100644 index 00000000000..1ac6ecde64d --- /dev/null +++ b/multichain-testing/config.go-relayer.yaml @@ -0,0 +1,117 @@ +name: agoric-multichain-testing-go-relayer +version: 0.2.20 + +chains: + - id: agoriclocal + name: agoric + image: ghcr.io/agoric/agoric-sdk:dev + numValidators: 1 + env: + - name: DEBUG + value: SwingSet:vat,SwingSet:ls + genesis: + app_state: + staking: + params: + unbonding_time: '2m' + swingset: + params: + bootstrap_vat_config: '@agoric/vm-config/decentral-itest-orchestration-config.json' + scripts: + updateConfig: + file: scripts/update-config.sh + faucet: + enabled: true + type: starship + ports: + rest: 1317 + rpc: 26657 + exposer: 38087 + grpc: 9090 + faucet: 8082 + resources: + cpu: 1 + memory: 4Gi + - id: osmosislocal + name: osmosis + numValidators: 1 + genesis: + app_state: + staking: + params: + unbonding_time: '2m' + interchain_accounts: + host_genesis_state: + params: + host_enabled: true + allow_messages: ['*'] + interchainquery: + host_port: 'icqhost' + params: + host_enabled: true + allow_queries: + - /cosmos.bank.v1beta1.Query/Balance + - /cosmos.bank.v1beta1.Query/AllBalances + faucet: + enabled: true + type: starship + ports: + rest: 1315 + rpc: 26655 + grpc: 9093 + faucet: 8084 + resources: + cpu: 1 + memory: 1Gi + - id: cosmoshublocal + name: cosmoshub + numValidators: 1 + genesis: + app_state: + staking: + params: + unbonding_time: '2m' + interchain_accounts: + host_genesis_state: + params: + host_enabled: true + allow_messages: ['*'] + faucet: + enabled: true + type: starship + ports: + rest: 1314 + rpc: 26654 + grpc: 9092 + faucet: 8083 + resources: + cpu: 1 + memory: 1Gi + +relayers: + - name: osmosis-cosmoshub + type: go-relayer + replicas: 1 + chains: + - osmosislocal + - cosmoshublocal + - name: agoric-osmosis + type: go-relayer + replicas: 1 + chains: + - agoriclocal + - osmosislocal + - name: agoric-cosmoshub + type: go-relayer + replicas: 1 + chains: + - agoriclocal + - cosmoshublocal + +explorer: + enabled: false + +registry: + enabled: true + ports: + rest: 8081 diff --git a/multichain-testing/config.yaml b/multichain-testing/config.yaml index b16d3daf89c..eb97ac10cf5 100644 --- a/multichain-testing/config.yaml +++ b/multichain-testing/config.yaml @@ -21,12 +21,14 @@ chains: updateConfig: file: scripts/update-config.sh faucet: - enabled: false + enabled: true + type: starship ports: rest: 1317 rpc: 26657 exposer: 38087 grpc: 9090 + faucet: 8082 resources: cpu: 1 memory: 4Gi @@ -61,7 +63,7 @@ chains: resources: cpu: 1 memory: 1Gi - - id: gaialocal + - id: cosmoshublocal name: cosmoshub numValidators: 1 genesis: @@ -87,24 +89,24 @@ chains: memory: 1Gi relayers: - - name: osmosis-gaia + - name: osmosis-cosmoshub type: hermes replicas: 1 chains: - osmosislocal - - gaialocal + - cosmoshublocal - name: agoric-osmosis type: hermes replicas: 1 chains: - agoriclocal - osmosislocal - - name: agoric-gaia + - name: agoric-cosmoshub type: hermes replicas: 1 chains: - agoriclocal - - gaialocal + - cosmoshublocal explorer: enabled: false diff --git a/multichain-testing/test/config.ts b/multichain-testing/test/config.ts index 975c0d25e34..f0bf2f93422 100644 --- a/multichain-testing/test/config.ts +++ b/multichain-testing/test/config.ts @@ -41,3 +41,8 @@ export const MAKE_ACCOUNT_AND_QUERY_BALANCE_TIMEOUT: RetryOptions = { retryIntervalMs: 5000, maxRetries: 24, }; + +export const ICA_CHANNEL_CLOSE_TIMEOUT: RetryOptions = { + retryIntervalMs: 5000, + maxRetries: 24, +}; diff --git a/multichain-testing/test/fast-usdc/fast-usdc.test.ts b/multichain-testing/test/fast-usdc/fast-usdc.test.ts index 81de8db9128..f166e9879d9 100644 --- a/multichain-testing/test/fast-usdc/fast-usdc.test.ts +++ b/multichain-testing/test/fast-usdc/fast-usdc.test.ts @@ -23,6 +23,8 @@ import { createWallet } from '../../tools/wallet.js'; import { commonSetup, type SetupContextWithWallets } from '../support.js'; import { makeFeedPolicyPartial, oracleMnemonics } from './config.js'; +const { RELAYER_TYPE } = process.env; + const log = makeTracer('MCFU'); const { keys, values, fromEntries } = Object; @@ -50,7 +52,7 @@ const LP_DEPOSIT_AMOUNT = 8_000n * 10n ** 6n; test.before(async t => { const { setupTestKeys, ...common } = await commonSetup(t, { - config: '../config.fusdc.yaml', + config: `../config.fusdc${RELAYER_TYPE ? '.' + RELAYER_TYPE : ''}.yaml`, }); const { chainInfo, diff --git a/multichain-testing/test/ica-channel-close.test.ts b/multichain-testing/test/ica-channel-close.test.ts index 6ee59dc825f..13ad3ee2264 100644 --- a/multichain-testing/test/ica-channel-close.test.ts +++ b/multichain-testing/test/ica-channel-close.test.ts @@ -12,6 +12,8 @@ import { import { makeQueryClient } from '../tools/query.js'; import { parseLocalAddress, parseRemoteAddress } from '../tools/address.js'; import chainInfo from '../starship-chain-info.js'; +import { ICA_CHANNEL_CLOSE_TIMEOUT } from './config.js'; +import { sleep } from '../tools/sleep.js'; const test = anyTest as TestFn; @@ -182,6 +184,7 @@ const intentionalCloseAccountScenario = test.macro({ () => remoteQueryClient.queryChannels(), ({ channels }) => !!findNewChannel(channels, { rPortID, lPortID }), `ICA channel is reopened on ${chainName} Host`, + ICA_CHANNEL_CLOSE_TIMEOUT, ); const newChannel = findNewChannel(channels, { rPortID, lPortID }); t.log('New Channel after Reactivate', newChannel); @@ -217,7 +220,7 @@ const channelCloseInitScenario = test.macro({ vstorageClient, retryUntilCondition, useChain, - hermes, + relayer, } = t.context; // make an account so there's an ICA channel we can attempt to close @@ -280,17 +283,21 @@ const channelCloseInitScenario = test.macro({ console.log( `Initiating channelCloseInit for dst: ${JSON.stringify(dst)} src: ${JSON.stringify(src)}`, ); - t.throws( - () => hermes.channelCloseInit(chainName, dst, src), - { message: /Command failed/ }, - 'hermes channelCloseInit failed from agoric side for ICA', - ); - t.throws( - () => hermes.channelCloseInit(chainName, src, dst), - { message: /Command failed/ }, - `hermes channelCloseInit failed from ${chainName} side for ICA`, - ); - + try { + t.log('relayer channelCloseInit failed from agoric side for ICA'); + relayer.channelCloseInit(chainName, dst, src); + } catch (e) { + t.log(e); // hermes relayer throws, but go-relayer does not + } + try { + t.log(`relayer channelCloseInit failed from ${chainName} side for ICA`); + relayer.channelCloseInit(chainName, src, dst); + } catch (e) { + t.log(e); // hermes relayer throws, but go-relayer does not + } + t.log('Sleeping 10 seconds for potential channel closure to propagate'); + // approx 3-4 blocks time to propagate + await sleep(10 * 1_000); const remoteQueryClient = makeQueryClient( await useChain(chainName).getRestEndpoint(), ); @@ -298,7 +305,7 @@ const channelCloseInitScenario = test.macro({ () => remoteQueryClient.queryChannel(rPortID, rChannelID), // @ts-expect-error ChannelSDKType.state is a string not a number ({ channel }) => channel?.state === 'STATE_OPEN', - 'Hermes closeChannelInit failed so ICA channel is still open', + 'relayer closeChannelInit failed so ICA channel is still open', ); t.log(channel); t.is( @@ -328,26 +335,31 @@ const channelCloseInitScenario = test.macro({ portID: 'transfer', connectionID: rConnectionID, }; - t.throws( - () => - hermes.channelCloseInit( - chainName, - dstTransferChannel, - srcTransferChannel, - ), - { message: /Command failed/ }, - 'hermes channelCloseInit failed from agoric side for transfer', - ); - t.throws( - () => - hermes.channelCloseInit( - chainName, - srcTransferChannel, - dstTransferChannel, - ), - { message: /Command failed/ }, - `hermes channelCloseInit failed from ${chainName} side for transfer`, - ); + try { + t.log('relayer channelCloseInit failed from agoric side for transfer'); + relayer.channelCloseInit( + chainName, + dstTransferChannel, + srcTransferChannel, + ); + } catch (e) { + t.log(e); // hermes relayer throws, but go-relayer does not + } + try { + t.log( + `relayer channelCloseInit failed from ${chainName} side for transfer`, + ); + relayer.channelCloseInit( + chainName, + srcTransferChannel, + dstTransferChannel, + ); + } catch (e) { + t.log(e); // hermes relayer throws, but go-relayer does not + } + t.log('Sleeping 10 seconds for potential channel closure to propagate'); + // approx 3-4 blocks time to propagate + await sleep(10 * 1_000); const { channel } = await retryUntilCondition( () => @@ -357,7 +369,7 @@ const channelCloseInitScenario = test.macro({ ), // @ts-expect-error ChannelSDKType.state is a string not a number ({ channel }) => channel?.state === 'STATE_OPEN', - 'Hermes closeChannelInit failed so transfer channel is still open', + 'relayer closeChannelInit failed so transfer channel is still open', ); t.log(channel); t.is( diff --git a/multichain-testing/test/stake-ica.test.ts b/multichain-testing/test/stake-ica.test.ts index 7ef65ad33eb..c0d118734b7 100644 --- a/multichain-testing/test/stake-ica.test.ts +++ b/multichain-testing/test/stake-ica.test.ts @@ -258,7 +258,7 @@ const stakeScenario = test.macro(async (t, scenario: StakeIcaScenario) => { test.serial('send wallet offers stakeAtom contract', stakeScenario, { chain: 'cosmoshub', - chainId: 'gaialocal', + chainId: 'cosmoshublocal', contractName: 'stakeAtom', denom: 'uatom', expectedAddressPrefix: 'cosmos', diff --git a/multichain-testing/test/support.ts b/multichain-testing/test/support.ts index 0f3dd42c14f..a728c3851fd 100644 --- a/multichain-testing/test/support.ts +++ b/multichain-testing/test/support.ts @@ -14,7 +14,7 @@ import { import { generateMnemonic } from '../tools/wallet.js'; import { makeRetryUntilCondition } from '../tools/sleep.js'; import { makeDeployBuilder } from '../tools/deploy.js'; -import { makeHermes } from '../tools/hermes-tools.js'; +import { makeRelayer } from '../tools/relayer-tools.js'; import { makeNobleTools } from '../tools/noble-tools.js'; import { makeAssetInfo } from '../tools/asset-info.js'; import starshipChainInfo from '../starship-chain-info.js'; @@ -70,7 +70,10 @@ const makeKeyring = async ( export const commonSetup = async ( t: ExecutionContext, - { config = '../config.yaml' } = {}, + { + relayerType = process.env.RELAYER_TYPE, + config = `../config${relayerType ? '.' + relayerType : ''}.yaml`, + } = {}, ) => { let useChain: MultichainRegistry['useChain']; try { @@ -89,7 +92,7 @@ export const commonSetup = async ( log: t.log, setTimeout: globalThis.setTimeout, }); - const hermes = makeHermes(childProcess); + const relayer = makeRelayer(childProcess); const nobleTools = makeNobleTools(childProcess); const assetInfo = makeAssetInfo(starshipChainInfo); const chainInfo = withChainCapabilities(starshipChainInfo); @@ -138,7 +141,7 @@ export const commonSetup = async ( ...keyring, retryUntilCondition, deployBuilder, - hermes, + relayer, nobleTools, startContract, assetInfo, diff --git a/multichain-testing/test/tools/asset-info.test.ts b/multichain-testing/test/tools/asset-info.test.ts index 1806a3c4e26..a314173d606 100644 --- a/multichain-testing/test/tools/asset-info.test.ts +++ b/multichain-testing/test/tools/asset-info.test.ts @@ -6,7 +6,7 @@ const minChainInfo = { agoric: { chainId: 'agoriclocal', connections: { - gaialocal: { + cosmoshublocal: { transferChannel: { channelId: 'channel-1', }, @@ -19,7 +19,7 @@ const minChainInfo = { }, }, cosmoshub: { - chainId: 'gaialocal', + chainId: 'cosmoshublocal', connections: { agoriclocal: { transferChannel: { @@ -41,7 +41,7 @@ const minChainInfo = { channelId: 'channel-1', }, }, - gaialocal: { + cosmoshublocal: { transferChannel: { channelId: 'channel-0', }, diff --git a/multichain-testing/test/tools/wallet.test.ts b/multichain-testing/test/tools/wallet.test.ts index bc76ab8b993..34308259a24 100644 --- a/multichain-testing/test/tools/wallet.test.ts +++ b/multichain-testing/test/tools/wallet.test.ts @@ -6,44 +6,51 @@ import { commonSetup } from '../support.js'; const test = anyTest as TestFn>; -const walletScenario = test.macro(async (t, scenario: string) => { - const { useChain, retryUntilCondition } = await commonSetup(t); - - const prefix = useChain(scenario).chain.bech32_prefix; - const wallet = await createWallet(prefix); - const addr = (await wallet.getAccounts())[0].address; - t.regex(addr, new RegExp(`^${prefix}1`)); - t.log('Made temp wallet:', addr); - - const apiUrl = await useChain(scenario).getRestEndpoint(); - const queryClient = makeQueryClient(apiUrl); - t.log('Made query client'); - - const { balances } = await queryClient.queryBalances(addr); - t.log('Beginning balances:', balances); - t.deepEqual(balances, []); - - const { creditFromFaucet } = useChain(scenario); - t.log('Requesting faucet funds'); - - await creditFromFaucet(addr); - // XXX needed to avoid race condition between faucet POST and LCD Query - // see https://github.com/cosmology-tech/starship/issues/417 - const { balances: updatedBalances } = await retryUntilCondition( - () => queryClient.queryBalances(addr), - ({ balances }) => !!balances.length, - `${scenario} balance available from faucet`, - ); - - const expectedDenom = scenario === 'osmosis' ? 'uosmo' : 'uatom'; - t.like(updatedBalances, [{ denom: expectedDenom, amount: '10000000000' }]); - t.log('Updated balances:', updatedBalances); - - const bondDenom = useChain(scenario).chain.staking?.staking_tokens?.[0].denom; - t.truthy(bondDenom, 'bond denom found'); - const { balance } = await queryClient.queryBalance(addr, bondDenom!); - t.deepEqual(balance, { denom: bondDenom, amount: '10000000000' }); +const walletScenario = test.macro({ + title: (_, chainName: string) => + `create a wallet and get tokens on ${chainName}`, + exec: async (t, chainName: string) => { + const { useChain, retryUntilCondition } = await commonSetup(t); + + const { bech32_prefix, staking } = useChain(chainName).chain; + const wallet = await createWallet(bech32_prefix); + const addr = (await wallet.getAccounts())[0].address; + t.regex(addr, new RegExp(`^${bech32_prefix}1`)); + t.log('Made temp wallet:', addr); + + const apiUrl = await useChain(chainName).getRestEndpoint(); + const queryClient = makeQueryClient(apiUrl); + t.log('Made query client'); + + const { balances } = await queryClient.queryBalances(addr); + t.log('Beginning balances:', balances); + t.deepEqual(balances, []); + + const { creditFromFaucet } = useChain(chainName); + t.log('Requesting faucet funds'); + + await creditFromFaucet(addr); + // XXX needed to avoid race condition between faucet POST and LCD Query + // see https://github.com/cosmology-tech/starship/issues/417 + const { balances: updatedBalances } = await retryUntilCondition( + () => queryClient.queryBalances(addr), + ({ balances }) => !!balances.length, + `${chainName} balance available from faucet`, + ); + + const expectedDenom = staking?.staking_tokens?.[0]?.denom; + t.assert(expectedDenom, 'expected denom found in registry'); + t.like(updatedBalances, [{ denom: expectedDenom, amount: '10000000000' }]); + t.log('Updated balances:', updatedBalances); + + const bondDenom = + useChain(chainName).chain.staking?.staking_tokens?.[0].denom; + t.truthy(bondDenom, 'bond denom found'); + const { balance } = await queryClient.queryBalance(addr, bondDenom!); + t.deepEqual(balance, { denom: bondDenom, amount: '10000000000' }); + }, }); -test('create a wallet and get tokens (osmosis)', walletScenario, 'osmosis'); -test('create a wallet and get tokens (cosmoshub)', walletScenario, 'cosmoshub'); +test(walletScenario, 'osmosis'); +test(walletScenario, 'cosmoshub'); +test(walletScenario, 'agoric'); diff --git a/multichain-testing/tools/hermes-tools.ts b/multichain-testing/tools/hermes-tools.ts deleted file mode 100644 index 4868fdd3f88..00000000000 --- a/multichain-testing/tools/hermes-tools.ts +++ /dev/null @@ -1,70 +0,0 @@ -import type { IBCChannelID, IBCConnectionID, IBCPortID } from '@agoric/vats'; -import type { ExecSync } from './agd-lib.js'; - -const kubectlBinary = 'kubectl'; - -// based on config.yaml -const relayerMap: { [key: string]: string } = { - osmosis: 'hermes-agoric-osmosis-0', - cosmoshub: 'hermes-agoric-gaia-0', -}; - -const makeKubeArgs = (chainName: string) => { - if (!relayerMap[chainName]) throw Error('Unsupported chain: ' + chainName); - return [ - 'exec', - '-i', - relayerMap[chainName], - '-c', - 'relayer', - '--tty=false', - '--', - 'hermes', - ]; -}; - -type ChannelCloseParams = { - dst: { - chainId: string; - portID: IBCPortID; - channelID: IBCChannelID; - connectionID: IBCConnectionID; - }; - src: { - chainId: string; - portID: IBCPortID; - channelID: IBCChannelID; - }; -}; - -export const makeHermes = ({ execFileSync }: { execFileSync: ExecSync }) => { - const exec = ( - chainName: string, - args: string[], - opts = { encoding: 'utf-8' as const, stdio: ['ignore', 'pipe', 'ignore'] }, - ) => execFileSync(kubectlBinary, [...makeKubeArgs(chainName), ...args], opts); - - /** Submit MsgChannelCloseInit to the src chain */ - const channelCloseInit = ( - chainName: string, - dst: ChannelCloseParams['dst'], - src: ChannelCloseParams['src'], - ) => { - return exec(chainName, [ - 'tx', - 'chan-close-init', - `--dst-chain=${dst.chainId}`, - `--src-chain=${src.chainId}`, - `--dst-connection=${dst.connectionID}`, - `--dst-port=${dst.portID}`, - `--src-port=${src.portID}`, - `--dst-channel=${dst.channelID}`, - `--src-channel=${src.channelID}`, - ]); - }; - - return { - exec, - channelCloseInit, - }; -}; diff --git a/multichain-testing/tools/relayer-tools.ts b/multichain-testing/tools/relayer-tools.ts new file mode 100644 index 00000000000..6ffd9408510 --- /dev/null +++ b/multichain-testing/tools/relayer-tools.ts @@ -0,0 +1,100 @@ +import type { IBCChannelID, IBCConnectionID, IBCPortID } from '@agoric/vats'; +import type { ExecSync } from './agd-lib.js'; + +const kubectlBinary = 'kubectl'; + +type RelayerType = 'hermes' | 'go-relayer'; + +const getRelayerBinary = (relayer: RelayerType) => { + switch (relayer) { + case 'hermes': + return 'hermes'; + case 'go-relayer': + return 'rly'; + default: + throw new Error(`Unsupported relayer type: ${relayer}`); + } +}; + +const makeKubeArgs = (chainName: string, relayerType: RelayerType) => { + return [ + 'exec', + '-i', + `${relayerType}-agoric-${chainName}-0`, + '-c', + 'relayer', + '--tty=false', + '--', + getRelayerBinary(relayerType), + ]; +}; + +type ChannelCloseParams = { + dst: { + chainId: string; + portID: IBCPortID; + channelID: IBCChannelID; + connectionID: IBCConnectionID; + }; + src: { + chainId: string; + portID: IBCPortID; + channelID: IBCChannelID; + }; +}; + +const getPathname = (srcChainId: string, dstChainId: string) => + [srcChainId, dstChainId].sort().join('-'); + +export const makeRelayer = ({ execFileSync }: { execFileSync: ExecSync }) => { + const relayerType = (process.env.RELAYER_TYPE || 'hermes') as RelayerType; + + const exec = ( + chainName: string, + args: string[], + opts = { encoding: 'utf-8' as const, stdio: ['ignore', 'pipe', 'ignore'] }, + ) => + execFileSync( + kubectlBinary, + [...makeKubeArgs(chainName, relayerType), ...args], + opts, + ); + + /** Submit MsgChannelCloseInit to the src chain */ + const channelCloseInit = ( + chainName: string, + dst: ChannelCloseParams['dst'], + src: ChannelCloseParams['src'], + ) => { + let args: string[]; + if (relayerType === 'hermes') { + args = [ + 'tx', + 'chan-close-init', + `--dst-chain=${dst.chainId}`, + `--src-chain=${src.chainId}`, + `--dst-connection=${dst.connectionID}`, + `--dst-port=${dst.portID}`, + `--src-port=${src.portID}`, + `--dst-channel=${dst.channelID}`, + `--src-channel=${src.channelID}`, + ]; + } else if (relayerType === 'go-relayer') { + args = [ + 'tx', + 'channel-close', + getPathname(src.chainId, dst.chainId), + src.channelID, + src.portID, + ]; + } else { + throw new Error(`Unsupported relayer type: ${relayerType}`); + } + return exec(chainName, args); + }; + + return { + exec, + channelCloseInit, + }; +};