UNPKG

cosmic-interchain-cli

Version:

A command-line utility for Cosmic Wire's interchain messaging protocol

112 lines 5.07 kB
import { confirm } from '@inquirer/prompts'; import { ethers } from 'ethers'; import { getLocalProvider, } from '@hyperlane-xyz/sdk'; import { ProtocolType } from '@hyperlane-xyz/utils'; import { parseIsmConfig } from '../config/ism.js'; import { log, logBlue, logGray, logGreen, logPink, logTable, } from '../logger.js'; import { nativeBalancesAreSufficient } from '../utils/balances.js'; import { ENV } from '../utils/env.js'; import { assertSigner } from '../utils/keys.js'; import { completeDryRun } from './dry-run.js'; export async function runPreflightChecksForChains({ context, chains, minGas, chainsToGasCheck, }) { log('Running pre-flight checks for chains...'); const { signer, multiProvider } = context; if (!chains?.length) throw new Error('Empty chain selection'); for (const chain of chains) { const metadata = multiProvider.tryGetChainMetadata(chain); if (!metadata) throw new Error(`No chain config found for ${chain}`); if (metadata.protocol !== ProtocolType.Ethereum) throw new Error('Only Ethereum chains are supported for now'); } logGreen('✅ Chains are valid'); assertSigner(signer); logGreen('✅ Signer is valid'); await nativeBalancesAreSufficient(multiProvider, signer, chainsToGasCheck ?? chains, minGas); } export async function runDeployPlanStep({ context, chain, }) { const { signer, chainMetadata: chainMetadataMap, skipConfirmation } = context; const address = await signer.getAddress(); logBlue('\nDeployment plan'); logGray('==============='); log(`Transaction signer and owner of new contracts: ${address}`); log(`Deploying core contracts to network: ${chain}`); const transformedChainMetadata = transformChainMetadataForDisplay(chainMetadataMap[chain]); logTable(transformedChainMetadata); log(`Note: There are several contracts required for each chain, but contracts in your provided registries will be skipped.`); if (skipConfirmation) return; await confirmExistingMailbox(context, chain); const isConfirmed = await confirm({ message: 'Is this deployment plan correct?', }); if (!isConfirmed) throw new Error('Deployment cancelled'); } async function confirmExistingMailbox(context, chain) { const addresses = await context.registry.getChainAddresses(chain); if (addresses?.mailbox) { const isConfirmed = await confirm({ message: `Mailbox already exists at ${addresses.mailbox}. Are you sure you want to deploy a new mailbox and overwrite existing registry artifacts?`, default: false, }); if (!isConfirmed) { throw Error('Deployment cancelled'); } } } // from parsed types export function isISMConfig(config) { return Object.values(config).some((c) => 'type' in c); } // directly from filepath export function isZODISMConfig(filepath) { return parseIsmConfig(filepath).success; } export async function prepareDeploy(context, userAddress, chains) { const { multiProvider, isDryRun } = context; const initialBalances = {}; await Promise.all(chains.map(async (chain) => { const provider = isDryRun ? getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT) : multiProvider.getProvider(chain); const currentBalance = await provider.getBalance(userAddress); initialBalances[chain] = currentBalance; })); return initialBalances; } export async function completeDeploy(context, command, initialBalances, userAddress, chains) { const { multiProvider, isDryRun } = context; if (chains.length > 0) logPink(`⛽️ Gas Usage Statistics`); for (const chain of chains) { const provider = isDryRun ? getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT) : multiProvider.getProvider(chain); const currentBalance = await provider.getBalance(userAddress); const balanceDelta = initialBalances[chain].sub(currentBalance); if (isDryRun && balanceDelta.lt(0)) break; logPink(`\t- Gas required for ${command} ${isDryRun ? 'dry-run' : 'deploy'} on ${chain}: ${ethers.utils.formatEther(balanceDelta)} ${multiProvider.getChainMetadata(chain).nativeToken?.symbol ?? 'ETH'}`); } if (isDryRun) await completeDryRun(command); } export function toUpperCamelCase(string) { return string.charAt(0).toUpperCase() + string.slice(1); } function transformChainMetadataForDisplay(chainMetadata) { return { Name: chainMetadata.name, 'Display Name': chainMetadata.displayName, 'Chain ID': chainMetadata.chainId, 'Domain ID': chainMetadata.domainId, Protocol: chainMetadata.protocol, 'JSON RPC URL': chainMetadata.rpcUrls[0].http, 'Native Token: Symbol': chainMetadata.nativeToken?.symbol, 'Native Token: Name': chainMetadata.nativeToken?.name, 'Native Token: Decimals': chainMetadata.nativeToken?.decimals, }; } //# sourceMappingURL=utils.js.map