diff --git a/.github/workflows/multichain-e2e-template.yml b/.github/workflows/multichain-e2e-template.yml new file mode 100644 index 00000000000..9c3f7a63370 --- /dev/null +++ b/.github/workflows/multichain-e2e-template.yml @@ -0,0 +1,121 @@ +name: Multichain E2E Workflow Template + +on: + workflow_call: + inputs: + config: + required: true + type: string + test_command: + required: true + type: string + description: 'Test command to run (e.g., "test:main" or "test:fast-usdc")' + +jobs: + multichain-e2e: + runs-on: ubuntu-latest-16core + + steps: + - uses: actions/checkout@v4 + with: + submodules: 'true' + path: ./agoric-sdk + + - uses: ./agoric-sdk/.github/actions/restore-node + with: + node-version: 18.x + path: ./agoric-sdk + + # Extract chain and relayer information + - name: Extract config information + id: extract-config + run: | + # Create logs directory + mkdir -p ./agoric-sdk/multichain-testing/logs + + # Extract namespace name + NAMESPACE=$(yq e '.name' ./agoric-sdk/multichain-testing/${{ inputs.config }}) + echo "NAMESPACE=${NAMESPACE}" >> $GITHUB_ENV + + # Build validator pod names (chainid-genesis-0) + VALIDATOR_PODS=$(yq e '.chains[] | .id + "-genesis-0"' ./agoric-sdk/multichain-testing/${{ inputs.config }} | tr '\n' ' ') + echo "VALIDATOR_PODS=${VALIDATOR_PODS}" >> $GITHUB_ENV + + # Build relayer pod names (type-name-0) + RELAYER_PODS=$(yq e '.relayers[] | .type + "-" + .name + "-0"' ./agoric-sdk/multichain-testing/${{ inputs.config }} | tr '\n' ' ') + echo "RELAYER_PODS=${RELAYER_PODS}" >> $GITHUB_ENV + + # For debugging + echo "Namespace: ${NAMESPACE}" + echo "Validator pods: ${VALIDATOR_PODS}" + echo "Relayer pods: ${RELAYER_PODS}" + + - name: yarn link + run: | + yarn link-cli ~/bin/agoric + echo "/home/runner/bin" >> $GITHUB_PATH + working-directory: ./agoric-sdk + + - name: Enable Corepack + run: corepack enable + working-directory: ./agoric-sdk/multichain-testing + + - name: Install @agoric/multichain-testing deps + run: yarn install + working-directory: ./agoric-sdk/multichain-testing + + - name: Lint @agoric/multichain-testing + run: yarn lint + working-directory: ./agoric-sdk/multichain-testing + + - name: Setup Starship Infrastructure + id: starship-infra + uses: cosmology-tech/starship-action@0.3.0 + with: + values: ./agoric-sdk/multichain-testing/${{ inputs.config }} + port-forward: true + version: 0.2.20 + timeout: 30m + namespace: ${{ env.NAMESPACE }} + + - name: Fund Provision Pool + run: | + kubectl config set-context --current --namespace=${NAMESPACE} + kubectl get pods + make fund-provision-pool + working-directory: ./agoric-sdk/multichain-testing + + - name: Override Chain Registry + run: make override-chain-registry + working-directory: ./agoric-sdk/multichain-testing + + - name: Run @agoric/multichain-testing E2E Tests + run: yarn ${{ inputs.test_command }} + working-directory: ./agoric-sdk/multichain-testing + env: + FILE: ${{ inputs.config }} + + - name: Capture validator logs + if: always() + run: | + for pod in ${VALIDATOR_PODS}; do + echo "Capturing validator logs for ${pod}" + kubectl logs ${pod} --container=validator > ./agoric-sdk/multichain-testing/logs/${pod}.log 2>&1 || true + done + working-directory: ./agoric-sdk + + - name: Capture relayer logs + if: always() + run: | + for pod in ${RELAYER_PODS}; do + echo "Capturing relayer logs for ${pod}" + kubectl logs ${pod} --container=relayer > ./agoric-sdk/multichain-testing/logs/${pod}.log 2>&1 || true + done + working-directory: ./agoric-sdk + + - name: Upload test logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: multichain-e2e-logs-${NAMESPACE} + path: ./agoric-sdk/multichain-testing/logs/ diff --git a/.github/workflows/multichain-e2e.yml b/.github/workflows/multichain-e2e.yml index 718e9d2974d..bb86c2d7ffc 100644 --- a/.github/workflows/multichain-e2e.yml +++ b/.github/workflows/multichain-e2e.yml @@ -5,81 +5,16 @@ on: workflow_call: jobs: - multichain-e2e: - runs-on: ubuntu-latest-16core - - steps: - - uses: actions/checkout@v4 - with: - submodules: 'true' - path: ./agoric-sdk - - uses: ./agoric-sdk/.github/actions/restore-node - with: - node-version: 18.x - path: ./agoric-sdk - - - name: yarn link - run: | - yarn link-cli ~/bin/agoric - echo "/home/runner/bin" >> $GITHUB_PATH - working-directory: ./agoric-sdk - - - name: Enable Corepack - run: corepack enable - working-directory: ./agoric-sdk/multichain-testing - - - name: Install @agoric/multichain-testing deps - run: yarn install - working-directory: ./agoric-sdk/multichain-testing - - - name: Lint @agoric/multichain-testing - run: yarn lint - working-directory: ./agoric-sdk/multichain-testing - - - name: Setup Starship Infrastructure - id: starship-infra - uses: cosmology-tech/starship-action@0.3.0 - with: - # uses ghcr.io/agoric/agoric-sdk:dev image (latest master) - values: ./agoric-sdk/multichain-testing/config.yaml - port-forward: true - version: 0.2.10 - timeout: 30m - namespace: agoric-multichain - - - name: Fund Provision Pool - run: | - kubectl config set-context --current --namespace=agoric-multichain - kubectl get pods - make fund-provision-pool - working-directory: ./agoric-sdk/multichain-testing - - - name: Ensure ports are forwarded - run: | - curl --fail --retry 3 --retry-delay 10 http://localhost:26657/status || (echo "agoriclocal node is available") - curl --fail --retry 3 --retry-delay 10 http://localhost:8081/chains/agoriclocal || (echo "agoriclocal URL check failed") - curl --fail --retry 3 --retry-delay 10 http://localhost:8081/chains/osmosislocal || (echo "osmosislocal URL check failed") - curl --fail --retry 3 --retry-delay 10 http://localhost:8081/chains/gaialocal || (echo "gaialocal URL check failed") - - - name: Override Chain Registry - run: make override-chain-registry - working-directory: ./agoric-sdk/multichain-testing - - - name: Run @agoric/multichain-testing E2E Tests - run: yarn test - working-directory: ./agoric-sdk/multichain-testing - - - name: Capture and print agoric validator logs - if: always() - run: kubectl logs agoriclocal-genesis-0 --container=validator || true - working-directory: ./agoric-sdk/multichain-testing - - - name: Capture and print agoric-osmosis relayer logs - if: always() - run: kubectl logs hermes-agoric-osmosis-0 --container=relayer || true - working-directory: ./agoric-sdk/multichain-testing - - - name: Capture and print agoric-cosmos relayer logs - if: always() - run: kubectl logs hermes-agoric-gaia-0 --container=relayer || true - working-directory: ./agoric-sdk/multichain-testing + orchestration-api-test: + name: Multichain E2E (Orchestration API) + uses: ./.github/workflows/multichain-e2e-template.yml + with: + config: config.yaml + test_command: test:main + + fast-usdc-test: + name: Multichain E2E (Fast USDC) + uses: ./.github/workflows/multichain-e2e-template.yml + with: + config: config.fusdc.yaml + test_command: test:fast-usdc diff --git a/multichain-testing/Makefile b/multichain-testing/Makefile index 3fe90607fed..9fd5b926b18 100644 --- a/multichain-testing/Makefile +++ b/multichain-testing/Makefile @@ -5,7 +5,7 @@ FILE = config.yaml HELM_REPO = starship HELM_CHART = devnet -HELM_VERSION = v0.2.10 +HELM_VERSION = v0.2.20 ############################################################################### ### All commands ### diff --git a/multichain-testing/ava.fusdc.config.js b/multichain-testing/ava.fusdc.config.js new file mode 100644 index 00000000000..2e76acc2d19 --- /dev/null +++ b/multichain-testing/ava.fusdc.config.js @@ -0,0 +1,11 @@ +export default { + extensions: { + ts: 'module', + }, + require: ['@endo/init/debug.js'], + nodeArguments: ['--import=tsimp/import'], + files: ['test/fast-usdc/**/*.test.ts'], + concurrency: 1, + serial: true, + timeout: '125s', +}; diff --git a/multichain-testing/ava.main.config.js b/multichain-testing/ava.main.config.js new file mode 100644 index 00000000000..b3719a2569e --- /dev/null +++ b/multichain-testing/ava.main.config.js @@ -0,0 +1,11 @@ +export default { + extensions: { + ts: 'module', + }, + require: ['@endo/init/debug.js'], + nodeArguments: ['--import=tsimp/import'], + files: ['test/**/*.test.ts', '!test/fast-usdc/**/*.test.ts'], + concurrency: 1, + serial: true, + timeout: '125s', +}; diff --git a/multichain-testing/config.fusdc.yaml b/multichain-testing/config.fusdc.yaml new file mode 100644 index 00000000000..c542d208386 --- /dev/null +++ b/multichain-testing/config.fusdc.yaml @@ -0,0 +1,110 @@ +name: agoric-multichain-testing-fusdc +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: false + ports: + rest: 1317 + rpc: 26657 + exposer: 38087 + grpc: 9090 + 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: hermes + replicas: 1 + chains: + - osmosislocal + - noblelocal + - name: agoric-osmosis + type: hermes + replicas: 1 + chains: + - agoriclocal + - osmosislocal + - name: agoric-noble + type: hermes + replicas: 1 + chains: + - agoriclocal + - noblelocal + +explorer: + enabled: false + +registry: + enabled: true + ports: + rest: 8081 diff --git a/multichain-testing/config.yaml b/multichain-testing/config.yaml index 8bb75beeeb4..b16d3daf89c 100644 --- a/multichain-testing/config.yaml +++ b/multichain-testing/config.yaml @@ -1,3 +1,6 @@ +name: agoric-multichain-testing +version: 0.2.20 + chains: - id: agoriclocal name: agoric diff --git a/multichain-testing/package.json b/multichain-testing/package.json index 4da3c745934..f666fd07867 100644 --- a/multichain-testing/package.json +++ b/multichain-testing/package.json @@ -8,7 +8,9 @@ "lint:eslint": "eslint .", "lint:types": "tsc --noEmit", "lint-fix": "yarn lint:eslint --fix", - "test": "ava", + "test": "echo 'Run specific test suites:\nyarn test:main (needs `make start`)\nyarn test:fast-usdc (needs `make start FILE=config.fusdc.yaml`)'", + "test:main": "ava --config ava.main.config.js", + "test:fast-usdc": "FILE=config.fusdc.yaml ava --config ava.fusdc.config.js", "starship:setup": "make setup-deps setup-kind", "starship:install": "make install", "starship:port-forward": "make port-forward", @@ -44,23 +46,6 @@ "resolutions": { "axios": "1.6.7" }, - "ava": { - "extensions": { - "ts": "module" - }, - "require": [ - "@endo/init/debug.js" - ], - "nodeArguments": [ - "--import=tsimp/import" - ], - "files": [ - "**/*.test.ts" - ], - "concurrency": 1, - "serial": true, - "timeout": "125s" - }, "eslintConfig": { "root": true, "env": { diff --git a/multichain-testing/scripts/install.sh b/multichain-testing/scripts/install.sh index 930212af9e4..2f1181aeaca 100644 --- a/multichain-testing/scripts/install.sh +++ b/multichain-testing/scripts/install.sh @@ -24,7 +24,7 @@ NAMESPACE="" HELM_REPO="starship" HELM_CHART="starship/devnet" HELM_REPO_URL="https://cosmology-tech.github.io/starship/" -HELM_CHART_VERSION="0.2.8" +HELM_CHART_VERSION="0.2.20" HELM_NAME="agoric-multichain-testing" # check_helm function verifies the helm binary is installed diff --git a/multichain-testing/test/auto-stake-it.test.ts b/multichain-testing/test/auto-stake-it.test.ts index 5aee9d6fa15..f7b3ff9ba7c 100644 --- a/multichain-testing/test/auto-stake-it.test.ts +++ b/multichain-testing/test/auto-stake-it.test.ts @@ -1,7 +1,6 @@ import type { CosmosChainInfo } from '@agoric/orchestration'; import anyTest from '@endo/ses-ava/prepare-endo.js'; import type { ExecutionContext, TestFn } from 'ava'; -import { useChain } from 'starshipjs'; import chainInfo from '../starship-chain-info.js'; import { makeDoOffer } from '../tools/e2e-tools.js'; import { @@ -36,7 +35,7 @@ test.after(async t => { }); const makeFundAndTransfer = (t: ExecutionContext) => { - const { retryUntilCondition } = t.context; + const { retryUntilCondition, useChain } = t.context; return async (chainName: string, agoricAddr: string, amount = 100n) => { const { staking } = useChain(chainName).chainInfo.chain; const denom = staking?.staking_tokens?.[0].denom; @@ -45,6 +44,7 @@ const makeFundAndTransfer = (t: ExecutionContext) => { const { client, address, wallet } = await createFundedWalletAndClient( t, chainName, + useChain, ); const balancesResult = await retryUntilCondition( () => client.getAllBalances(address), @@ -59,6 +59,7 @@ const makeFundAndTransfer = (t: ExecutionContext) => { { address: agoricAddr, chainName: 'agoric' }, { address: address, chainName }, Date.now(), + useChain, ); console.log('Transfer Args:', transferArgs); // TODO #9200 `sendIbcTokens` does not support `memo` @@ -89,6 +90,7 @@ const autoStakeItScenario = test.macro({ vstorageClient, provisionSmartWallet, retryUntilCondition, + useChain, } = t.context; const fundAndTransfer = makeFundAndTransfer(t); diff --git a/multichain-testing/test/fast-usdc/README.md b/multichain-testing/test/fast-usdc/README.md new file mode 100644 index 00000000000..c63d3635d97 --- /dev/null +++ b/multichain-testing/test/fast-usdc/README.md @@ -0,0 +1,20 @@ +## Start Chains + +Runs agoric, noble, and osmosis with hermes relayers. + +```sh +# start starship with fusdc configuration +make start FILE=config.fusdc.yaml +``` + +## Run Tests + +```sh +yarn test:fast-usdc +``` + +## Stop Chains + +```sh +make stop +``` diff --git a/multichain-testing/test/fast-usdc/noble-forwarding.test.ts b/multichain-testing/test/fast-usdc/noble-forwarding.test.ts new file mode 100644 index 00000000000..84ce4f3ae95 --- /dev/null +++ b/multichain-testing/test/fast-usdc/noble-forwarding.test.ts @@ -0,0 +1,88 @@ +import anyTest from '@endo/ses-ava/prepare-endo.js'; +import type { TestFn } from 'ava'; +import { commonSetup, type SetupContext } from '../support.js'; +import { createWallet } from '../../tools/wallet.js'; +import type { IBCConnectionInfo } from '@agoric/orchestration'; +import { makeQueryClient } from '../../tools/query.js'; + +const test = anyTest as TestFn; + +test('noble forwarding', async t => { + const { nobleTools, retryUntilCondition, useChain, vstorageClient } = + await commonSetup(t); + + const agoricWallet = await createWallet('agoric'); + const agoricAddr = (await agoricWallet.getAccounts())[0].address; + t.log('Made agoric wallet:', agoricAddr); + + const agoricChainId = useChain('agoric').chain.chain_id; + const nobleChainId = useChain('noble').chain.chain_id; + + const connInfoPath = `published.agoricNames.chainConnection.${agoricChainId}_${nobleChainId}`; + const { + transferChannel: { counterPartyChannelId, channelId }, + }: IBCConnectionInfo = await vstorageClient.queryData(connInfoPath); + + t.regex( + counterPartyChannelId, + /^channel-/, + 'counterPartyChannelId retrieved from vstorage', + ); + t.log(`Found noble->agoric channelId in vstorage: ${counterPartyChannelId}`); + + t.log( + `Registering forwarding account for ${counterPartyChannelId} ${agoricAddr}...`, + ); + const registerFwdAcctTx = nobleTools.registerForwardingAcct( + counterPartyChannelId, + agoricAddr, + ); + t.is(registerFwdAcctTx?.code, 0, 'registered forwarding account'); + t.log('Register forwarding account tx:', { + code: registerFwdAcctTx?.code, + height: registerFwdAcctTx?.height, + txhash: registerFwdAcctTx?.txhash, + }); + + const { address: nobleForwardingAddr, exists } = + nobleTools.queryForwardingAddress(counterPartyChannelId, agoricAddr); + t.regex(nobleForwardingAddr, /^noble1/, 'noble forwarding address'); + t.true(exists, 'forwarding address exists'); + t.log(`Got forwarding address: ${nobleForwardingAddr}`); + + const qty = 10_000_000n; + t.log( + `Initiating mock cctp mint for ${qty} uusdc to ${nobleForwardingAddr}...`, + ); + const cctpMintTx = nobleTools.mockCctpMint(qty, nobleForwardingAddr); + t.is(cctpMintTx?.code, 0, 'mocked cctp mint'); + t.log('Mocked CCTP Mint tx:', { + code: cctpMintTx?.code, + height: cctpMintTx?.height, + txhash: cctpMintTx?.txhash, + }); + + const apiUrl = await useChain('agoric').getRestEndpoint(); + const queryClient = makeQueryClient(apiUrl); + + const { balances } = await retryUntilCondition( + () => queryClient.queryBalances(agoricAddr), + ({ balances }) => !!balances.length, + `${agoricAddr} received forwarded funds from noble`, + ); + t.is(BigInt(balances[0]?.amount), qty, 'got tokens'); + t.log('Received forwarded funds from noble:', balances); + + const { hash: expectedHash } = await queryClient.queryDenom( + `transfer/${channelId}`, + 'uusdc', + ); + t.log('Expected denom hash:', expectedHash); + + t.regex(balances[0]?.denom, /^ibc/); + t.is( + balances[0]?.denom.split('ibc/')[1], + expectedHash, + 'got expected ibc denom hash', + ); +}); diff --git a/multichain-testing/test/support.ts b/multichain-testing/test/support.ts index 2267b813436..9c2a297296e 100644 --- a/multichain-testing/test/support.ts +++ b/multichain-testing/test/support.ts @@ -5,11 +5,16 @@ import fse from 'fs-extra'; import childProcess from 'node:child_process'; import { makeAgdTools } from '../tools/agd-tools.js'; import { type E2ETools } from '../tools/e2e-tools.js'; -import { makeGetFile, makeSetupRegistry } from '../tools/registry.js'; +import { + makeGetFile, + makeSetupRegistry, + type MultichainRegistry, +} from '../tools/registry.js'; 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 { makeNobleTools } from '../tools/noble-tools.js'; export const FAUCET_POUR = 10_000n * 1_000_000n; @@ -54,7 +59,16 @@ const makeKeyring = async ( }; export const commonSetup = async (t: ExecutionContext) => { - const { useChain } = await setupRegistry(); + let useChain: MultichainRegistry['useChain']; + try { + const registry = await setupRegistry({ + config: `../${process.env.FILE || 'config.yaml'}`, + }); + useChain = registry.useChain; + } catch (e) { + console.error('setupRegistry failed', e); + throw e; + } const tools = await makeAgdTools(t.log, childProcess); const keyring = await makeKeyring(tools); const deployBuilder = makeDeployBuilder(tools, fse.readJSON, execa); @@ -63,6 +77,7 @@ export const commonSetup = async (t: ExecutionContext) => { setTimeout: globalThis.setTimeout, }); const hermes = makeHermes(childProcess); + const nobleTools = makeNobleTools(childProcess); /** * Starts a contract if instance not found. Takes care of installing @@ -98,6 +113,7 @@ export const commonSetup = async (t: ExecutionContext) => { retryUntilCondition, deployBuilder, hermes, + nobleTools, startContract, }; }; diff --git a/multichain-testing/tools/ibc-transfer.ts b/multichain-testing/tools/ibc-transfer.ts index bdabf473b3e..41db593cff2 100644 --- a/multichain-testing/tools/ibc-transfer.ts +++ b/multichain-testing/tools/ibc-transfer.ts @@ -2,7 +2,6 @@ import type { ExecutionContext } from 'ava'; import type { StdFee } from '@cosmjs/amino'; import { coins } from '@cosmjs/proto-signing'; import { SigningStargateClient } from '@cosmjs/stargate'; -import { useChain } from 'starshipjs'; import type { CosmosChainInfo, DenomAmount, @@ -16,6 +15,7 @@ import { import { MsgTransfer } from '@agoric/cosmic-proto/ibc/applications/transfer/v1/tx.js'; import { createWallet } from './wallet.js'; import chainInfo from '../starship-chain-info.js'; +import type { MultichainRegistry } from './registry.js'; interface MakeFeeObjectArgs { denom?: string; @@ -61,6 +61,7 @@ export const makeIBCTransferMsg = ( destination: SimpleChainAddress, sender: SimpleChainAddress, currentTime: number, + useChain: MultichainRegistry['useChain'], opts: IBCMsgTransferOptions = {}, ) => { const { timeoutHeight, timeoutTimestamp, memo = '' } = opts; @@ -119,6 +120,7 @@ export const makeIBCTransferMsg = ( export const createFundedWalletAndClient = async ( t: ExecutionContext, chainName: string, + useChain: MultichainRegistry['useChain'], ) => { const { chain, creditFromFaucet, getRpcEndpoint } = useChain(chainName); const wallet = await createWallet(chain.bech32_prefix); diff --git a/multichain-testing/tools/noble-tools.ts b/multichain-testing/tools/noble-tools.ts new file mode 100644 index 00000000000..0ece8dfd8b8 --- /dev/null +++ b/multichain-testing/tools/noble-tools.ts @@ -0,0 +1,100 @@ +import type { IBCChannelID } from '@agoric/vats'; +import type { ExecSync } from './agd-lib.js'; +import type { ChainAddress } from '@agoric/orchestration'; + +const kubectlBinary = 'kubectl'; +const noblePod = 'noblelocal-genesis-0'; +const nobleBinary = 'nobled'; + +const makeKubeArgs = () => { + return [ + 'exec', + '-i', + noblePod, + '-c', + 'validator', + '--tty=false', + '--', + nobleBinary, + ]; +}; + +export const makeNobleTools = ({ + execFileSync, +}: { + execFileSync: ExecSync; +}) => { + const exec = ( + args: string[], + opts = { encoding: 'utf-8' as const, stdio: ['ignore', 'pipe', 'ignore'] }, + ) => execFileSync(kubectlBinary, [...makeKubeArgs(), ...args], opts); + + const checkEnv = () => { + if (process.env.FILE !== 'config.fusdc.yaml') { + console.error('Warning: Noble chain must be running for this to work'); + } + }; + + const registerForwardingAcct = ( + channelId: IBCChannelID, + address: ChainAddress['value'], + ) => { + checkEnv(); + return JSON.parse( + exec([ + 'tx', + 'forwarding', + 'register-account', + channelId, + address, + '--from=genesis', + '-y', + '-b', + 'block', + ]), + ); + }; + + const mockCctpMint = (amount: bigint, destination: ChainAddress['value']) => { + checkEnv(); + return JSON.parse( + exec([ + 'tx', + 'bank', + 'send', + 'faucet', + destination, + `${Number(amount)}uusdc`, + '--from=faucet', + '-y', + '-b', + 'block', + ]), + ); + }; + + const queryForwardingAddress = ( + channelId: IBCChannelID, + address: ChainAddress['value'], + ) => { + checkEnv(); + return JSON.parse( + exec([ + 'query', + 'forwarding', + 'address', + channelId, + address, + '--output=json', + ]), + ); + }; + + return { + mockCctpMint, + queryForwardingAddress, + registerForwardingAcct, + }; +}; + +export type NobleTools = ReturnType; diff --git a/multichain-testing/tools/registry.ts b/multichain-testing/tools/registry.ts index d4b15c5b8b7..b61fd2fee72 100644 --- a/multichain-testing/tools/registry.ts +++ b/multichain-testing/tools/registry.ts @@ -7,6 +7,10 @@ export const makeGetFile = type GetFilePathFn = ReturnType; +export type MultichainRegistry = Awaited< + ReturnType> +>; + export const makeSetupRegistry = (getFile: GetFilePathFn) => { let initialized = false; /**