Skip to content

Commit

Permalink
test: noble forwarding tools
Browse files Browse the repository at this point in the history
  • Loading branch information
0xpatrickdev committed Nov 1, 2024
1 parent a868412 commit f27ebfe
Show file tree
Hide file tree
Showing 3 changed files with 198 additions and 1 deletion.
90 changes: 90 additions & 0 deletions multichain-testing/test/fast-usdc/noble-forwarding.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
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<SetupContext>;

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;
// TODO registry 'name' doesn't work with `type: custom`?
// const nobleChainId = useChain('noble').chain.chain_id;
const nobleChainId = 'noblelocal';

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.is(exists, true, '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',
);
});
9 changes: 8 additions & 1 deletion multichain-testing/test/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, type UseChainFn } from '../tools/registry.js';
import {
makeGetFile,
makeSetupRegistry,
type UseChainFn,
} 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;

Expand Down Expand Up @@ -72,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
Expand Down Expand Up @@ -107,6 +113,7 @@ export const commonSetup = async (t: ExecutionContext) => {
retryUntilCondition,
deployBuilder,
hermes,
nobleTools,
startContract,
};
};
Expand Down
100 changes: 100 additions & 0 deletions multichain-testing/tools/noble-tools.ts
Original file line number Diff line number Diff line change
@@ -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<typeof makeNobleTools>;

0 comments on commit f27ebfe

Please sign in to comment.