@hyperlane-xyz/cli
Version:
A command-line utility for common Hyperlane operations
140 lines • 6.63 kB
JavaScript
import { JsonRpcProvider } from '@ethersproject/providers';
import { Wallet } from 'ethers';
import { parseUnits } from 'ethers/lib/utils.js';
import { readYamlOrJson, writeYamlOrJson } from '../../utils/files.js';
import { ANVIL_KEY, CHAIN_2_METADATA_PATH, CHAIN_3_METADATA_PATH, CHAIN_NAME_2, CHAIN_NAME_3, CORE_CONFIG_PATH, WARP_DEPLOY_OUTPUT_PATH, deploy4626Vault, deployOrUseExistingCore, deployToken, getCombinedWarpRoutePath, sendWarpRouteMessageRoundTrip, } from '../commands/helpers.js';
import { generateWarpConfigs, hyperlaneWarpDeploy } from '../commands/warp.js';
export const TOTAL_PARTS = 2;
export async function runWarpBridgeTests(config, warpConfigTestCases) {
for (let i = 0; i < warpConfigTestCases.length; i++) {
const warpConfig = warpConfigTestCases[i];
console.log(`[${i + 1} of ${warpConfigTestCases.length}] Should deploy and be able to bridge in a ${warpConfig[CHAIN_NAME_2].type} -> ${warpConfig[CHAIN_NAME_3].type} warp route ...`);
writeYamlOrJson(WARP_DEPLOY_OUTPUT_PATH, warpConfig);
await hyperlaneWarpDeploy(WARP_DEPLOY_OUTPUT_PATH);
let startChain, targetChain;
if (!warpConfig[CHAIN_NAME_2].type.match(/.*synthetic.*/i)) {
startChain = CHAIN_NAME_2;
targetChain = CHAIN_NAME_3;
}
else {
startChain = CHAIN_NAME_3;
targetChain = CHAIN_NAME_2;
}
const symbol = getTokenSymbolFromDeployment(warpConfig, config.tokenVaultChain2Symbol, config.tokenChain2Symbol, config.tokenVaultChain3Symbol, config.tokenChain3Symbol);
const routeConfigPath = getCombinedWarpRoutePath(symbol, [
CHAIN_NAME_2,
CHAIN_NAME_3,
]);
await collateralizeWarpTokens(routeConfigPath, warpConfig, {
[CHAIN_NAME_2]: {
wallet: config.walletChain2,
collateral: config.tokenChain2,
},
[CHAIN_NAME_3]: {
wallet: config.walletChain3,
collateral: config.tokenChain3,
},
});
await sendWarpRouteMessageRoundTrip(startChain, targetChain, routeConfigPath);
console.log(`Should deploy and be able to bridge in a ${warpConfig[CHAIN_NAME_2].type} -> ${warpConfig[CHAIN_NAME_3].type} warp route ✅`);
}
}
export async function setupChains() {
const chain2Metadata = readYamlOrJson(CHAIN_2_METADATA_PATH);
const chain3Metadata = readYamlOrJson(CHAIN_3_METADATA_PATH);
const providerChain2 = new JsonRpcProvider(chain2Metadata.rpcUrls[0].http);
const providerChain3 = new JsonRpcProvider(chain3Metadata.rpcUrls[0].http);
const walletChain2 = new Wallet(ANVIL_KEY).connect(providerChain2);
const walletChain3 = new Wallet(ANVIL_KEY).connect(providerChain3);
const ownerAddress = walletChain2.address;
const [chain2Addresses, chain3Addresses] = await Promise.all([
deployOrUseExistingCore(CHAIN_NAME_2, CORE_CONFIG_PATH, ANVIL_KEY),
deployOrUseExistingCore(CHAIN_NAME_3, CORE_CONFIG_PATH, ANVIL_KEY),
]);
const tokenChain2 = await deployToken(ANVIL_KEY, CHAIN_NAME_2);
const vaultChain2 = await deploy4626Vault(ANVIL_KEY, CHAIN_NAME_2, tokenChain2.address);
const [tokenChain2Symbol, tokenVaultChain2Symbol] = await Promise.all([
tokenChain2.symbol(),
vaultChain2.symbol(),
]);
const tokenChain3 = await deployToken(ANVIL_KEY, CHAIN_NAME_3);
const vaultChain3 = await deploy4626Vault(ANVIL_KEY, CHAIN_NAME_3, tokenChain3.address);
const [tokenChain3Symbol, tokenVaultChain3Symbol] = await Promise.all([
tokenChain3.symbol(),
vaultChain3.symbol(),
]);
return {
chain2Addresses,
chain3Addresses,
ownerAddress,
walletChain2,
walletChain3,
tokenChain2,
tokenChain2Symbol,
vaultChain2,
tokenVaultChain2Symbol,
tokenChain3,
tokenChain3Symbol,
vaultChain3,
tokenVaultChain3Symbol,
};
}
export function generateTestCases(config, divideBy, index) {
const warpConfigTestCases = generateWarpConfigs({
chainName: CHAIN_NAME_2,
mailbox: config.chain2Addresses.mailbox,
owner: config.ownerAddress,
token: config.tokenChain2.address,
vault: config.vaultChain2.address,
}, {
chainName: CHAIN_NAME_3,
mailbox: config.chain3Addresses.mailbox,
owner: config.ownerAddress,
token: config.tokenChain3.address,
vault: config.vaultChain3.address,
});
const chunkSize = Math.ceil(warpConfigTestCases.length / divideBy);
const start = index * chunkSize;
const end = Math.min(start + chunkSize, warpConfigTestCases.length);
return warpConfigTestCases.slice(start, end);
}
export function getTokenSymbolFromDeployment(warpConfig, tokenVaultChain2Symbol, tokenChain2Symbol, tokenVaultChain3Symbol, tokenChain3Symbol) {
let symbol;
if (warpConfig[CHAIN_NAME_2].type.match(/.*vault.*/i)) {
symbol = tokenVaultChain2Symbol;
}
else if (warpConfig[CHAIN_NAME_2].type.match(/.*collateral.*/i)) {
symbol = tokenChain2Symbol;
}
else if (warpConfig[CHAIN_NAME_3].type.match(/.*vault.*/i)) {
symbol = tokenVaultChain3Symbol;
}
else if (warpConfig[CHAIN_NAME_3].type.match(/.*collateral.*/i)) {
symbol = tokenChain3Symbol;
}
else {
symbol = 'ETH';
}
return symbol;
}
export async function collateralizeWarpTokens(routeConfigPath, warpDeployConfig, walletAndCollateralByChain) {
const config = readYamlOrJson(routeConfigPath).tokens.reduce((acc, curr) => ({ ...acc, [curr.chainName]: curr }), {});
await Promise.all([CHAIN_NAME_2, CHAIN_NAME_3]
.filter((chainName) => walletAndCollateralByChain[chainName])
.map(async (chainName) => {
if (warpDeployConfig[chainName].type.match(/.*native/i)) {
const tx = await walletAndCollateralByChain[chainName].wallet.sendTransaction({
to: config[chainName].addressOrDenom,
value: 1000000000,
});
await tx.wait();
}
if (!warpDeployConfig[chainName].type.match(/.*synthetic/i) &&
warpDeployConfig[chainName].type.match(/.*collateral/i)) {
const decimals = await walletAndCollateralByChain[chainName].collateral.decimals();
const tx = await walletAndCollateralByChain[chainName].collateral.transfer(config[chainName].addressOrDenom, parseUnits('1', decimals));
await tx.wait();
}
}));
}
//# sourceMappingURL=warp-bridge-utils.js.map