From 450e8e0d5531f3fc44f2c1b98195e2743ac5e223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Bayindirli=20=F0=9F=A5=82?= Date: Mon, 22 Apr 2024 13:36:35 -0400 Subject: [PATCH] migrate fork util to SDK (#3625) ### Description * Migrates fork util to SDK ### Drive-by changes * None ### Related issues - Fixes https://github.com/hyperlane-xyz/hyperlane-monorepo/issues/3624 ### Backward compatibility * Yes ### Testing * Manual on core & warp --- .changeset/nice-pianos-tease.md | 6 +++ typescript/cli/src/deploy/dry-run.ts | 13 +++--- typescript/cli/src/deploy/utils.ts | 7 +-- typescript/cli/src/utils/keys.ts | 3 +- typescript/sdk/src/index.ts | 8 ++++ typescript/{cli => sdk}/src/utils/fork.ts | 55 +++++++++++++---------- 6 files changed, 58 insertions(+), 34 deletions(-) create mode 100644 .changeset/nice-pianos-tease.md rename typescript/{cli => sdk}/src/utils/fork.ts (63%) diff --git a/.changeset/nice-pianos-tease.md b/.changeset/nice-pianos-tease.md new file mode 100644 index 0000000000..6c8fafbf1f --- /dev/null +++ b/.changeset/nice-pianos-tease.md @@ -0,0 +1,6 @@ +--- +'@hyperlane-xyz/cli': minor +'@hyperlane-xyz/sdk': minor +--- + +Migrate fork util from CLI to SDK. Anvil IP & Port are now optionally passed into fork util by client. diff --git a/typescript/cli/src/deploy/dry-run.ts b/typescript/cli/src/deploy/dry-run.ts index be2663cde9..6da1d78c66 100644 --- a/typescript/cli/src/deploy/dry-run.ts +++ b/typescript/cli/src/deploy/dry-run.ts @@ -1,13 +1,14 @@ -import { MultiProvider } from '@hyperlane-xyz/sdk'; - -import { Command } from '../commands/deploy.js'; -import { logGray, logGreen, warnYellow } from '../logger.js'; import { ANVIL_RPC_METHODS, + MultiProvider, getLocalProvider, resetFork, setFork, -} from '../utils/fork.js'; +} from '@hyperlane-xyz/sdk'; + +import { Command } from '../commands/deploy.js'; +import { logGray, logGreen, warnYellow } from '../logger.js'; +import { ENV } from '../utils/env.js'; import { toUpperCamelCase } from './utils.js'; @@ -33,7 +34,7 @@ export async function forkNetworkToMultiProvider( export async function verifyAnvil() { logGray('🔎 Verifying anvil node is running...'); - const provider = getLocalProvider(); + const provider = getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT); try { await provider.send(ANVIL_RPC_METHODS.NODE_INFO, []); } catch (error: any) { diff --git a/typescript/cli/src/deploy/utils.ts b/typescript/cli/src/deploy/utils.ts index 0e1a6e2973..5a41a39b0c 100644 --- a/typescript/cli/src/deploy/utils.ts +++ b/typescript/cli/src/deploy/utils.ts @@ -6,6 +6,7 @@ import { IsmConfig, MultiProvider, MultisigConfig, + getLocalProvider, } from '@hyperlane-xyz/sdk'; import { Address, ProtocolType } from '@hyperlane-xyz/utils'; @@ -13,7 +14,7 @@ import { Command } from '../commands/deploy.js'; import { parseIsmConfig } from '../config/ism.js'; import { log, logGreen, logPink } from '../logger.js'; import { assertGasBalances } from '../utils/balances.js'; -import { getLocalProvider } from '../utils/fork.js'; +import { ENV } from '../utils/env.js'; import { assertSigner } from '../utils/keys.js'; import { completeDryRun } from './dry-run.js'; @@ -111,7 +112,7 @@ export async function prepareDeploy( await Promise.all( chains.map(async (chain: ChainName) => { const provider = dryRun - ? getLocalProvider() + ? getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT) : multiProvider.getProvider(chain); const currentBalance = await provider.getBalance(userAddress); initialBalances[chain] = currentBalance; @@ -131,7 +132,7 @@ export async function completeDeploy( if (chains.length > 0) logPink(`⛽️ Gas Usage Statistics`); for (const chain of chains) { const provider = dryRun - ? getLocalProvider() + ? getLocalProvider(ENV.ANVIL_IP_ADDR, ENV.ANVIL_PORT) : multiProvider.getProvider(chain); const currentBalance = await provider.getBalance(userAddress); const balanceDelta = initialBalances[chain].sub(currentBalance); diff --git a/typescript/cli/src/utils/keys.ts b/typescript/cli/src/utils/keys.ts index 37721917ba..7f5b6f6b05 100644 --- a/typescript/cli/src/utils/keys.ts +++ b/typescript/cli/src/utils/keys.ts @@ -1,12 +1,11 @@ import { input } from '@inquirer/prompts'; import { ethers, providers } from 'ethers'; +import { impersonateAccount } from '@hyperlane-xyz/sdk'; import { Address, ensure0x } from '@hyperlane-xyz/utils'; import { ContextSettings, KeyConfig } from '../context.js'; -import { impersonateAccount } from './fork.js'; - const ETHEREUM_ADDRESS_LENGTH = 42; const DEFAULT_KEY_TYPE = 'private key'; const IMPERSONATED_KEY_TYPE = 'address'; diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts index 45b2f9d49e..869b63d5af 100644 --- a/typescript/sdk/src/index.ts +++ b/typescript/sdk/src/index.ts @@ -442,6 +442,14 @@ export { } from './types.js'; export { MultiGeneric } from './utils/MultiGeneric.js'; export { filterByChains } from './utils/filter.js'; +export { + ANVIL_RPC_METHODS, + resetFork, + setFork, + impersonateAccount, + stopImpersonatingAccount, + getLocalProvider, +} from './utils/fork.js'; export { multisigIsmVerificationCost } from './utils/ism.js'; export { SealevelAccountDataWrapper, diff --git a/typescript/cli/src/utils/fork.ts b/typescript/sdk/src/utils/fork.ts similarity index 63% rename from typescript/cli/src/utils/fork.ts rename to typescript/sdk/src/utils/fork.ts index 49979a9114..38660a6c50 100644 --- a/typescript/cli/src/utils/fork.ts +++ b/typescript/sdk/src/utils/fork.ts @@ -1,12 +1,11 @@ import { providers } from 'ethers'; -import { ChainName, MultiProvider } from '@hyperlane-xyz/sdk'; -import { Address, isValidAddressEvm } from '@hyperlane-xyz/utils'; +import { Address, isValidAddressEvm, rootLogger } from '@hyperlane-xyz/utils'; -import { logGray, logGreen } from '../logger.js'; -import { warnYellow } from '../logger.js'; +import { MultiProvider } from '../providers/MultiProvider.js'; +import { ChainName } from '../types.js'; -import { ENV } from './env.js'; +const logger = rootLogger.child({ module: 'fork-utils' }); const ENDPOINT_PREFIX = 'http'; const DEFAULT_ANVIL_ENDPOINT = 'http://127.0.0.1:8545'; @@ -19,12 +18,12 @@ export enum ANVIL_RPC_METHODS { } /** - * Resets the local node to it's original start (anvil [31337] at block zero). + * Resets the local node to it's original state (anvil [31337] at block zero). */ -export const resetFork = async () => { - logGray(`Resetting forked network...`); +export const resetFork = async (anvilIPAddr?: string, anvilPort?: number) => { + logger.info(`Resetting forked network...`); - const provider = getLocalProvider(); + const provider = getLocalProvider(anvilIPAddr, anvilPort); await provider.send(ANVIL_RPC_METHODS.RESET, [ { forking: { @@ -33,7 +32,7 @@ export const resetFork = async () => { }, ]); - logGreen(`✅ Successfully reset forked network`); + logger.info(`✅ Successfully reset forked network`); }; /** @@ -44,10 +43,12 @@ export const resetFork = async () => { export const setFork = async ( multiProvider: MultiProvider, chain: ChainName | number, + anvilIPAddr?: string, + anvilPort?: number, ) => { - logGray(`Forking ${chain} for dry-run...`); + logger.info(`Forking ${chain} for dry-run...`); - const provider = getLocalProvider(); + const provider = getLocalProvider(anvilIPAddr, anvilPort); const currentChainMetadata = multiProvider.metadata[chain]; await provider.send(ANVIL_RPC_METHODS.RESET, [ @@ -60,7 +61,7 @@ export const setFork = async ( multiProvider.setProvider(chain, provider); - logGreen(`✅ Successfully forked ${chain} for dry-run`); + logger.info(`✅ Successfully forked ${chain} for dry-run`); }; /** @@ -70,13 +71,15 @@ export const setFork = async ( */ export const impersonateAccount = async ( address: Address, + anvilIPAddr?: string, + anvilPort?: number, ): Promise => { - logGray(`Impersonating account (${address})...`); + logger.info(`Impersonating account (${address})...`); - const provider = getLocalProvider(); + const provider = getLocalProvider(anvilIPAddr, anvilPort); await provider.send(ANVIL_RPC_METHODS.IMPERSONATE_ACCOUNT, [address]); - logGreen(`✅ Successfully impersonated account (${address})`); + logger.info(`✅ Successfully impersonated account (${address})`); return provider.getSigner(address); }; @@ -85,20 +88,24 @@ export const impersonateAccount = async ( * Stops account impersonation. * @param address the address to stop impersonating */ -export const stopImpersonatingAccount = async (address: Address) => { - logGray(`Stopping account impersonation for address (${address})...`); +export const stopImpersonatingAccount = async ( + address: Address, + anvilIPAddr?: string, + anvilPort?: number, +) => { + logger.info(`Stopping account impersonation for address (${address})...`); if (isValidAddressEvm(address)) throw new Error( `Cannot stop account impersonation: invalid address format: ${address}`, ); - const provider = getLocalProvider(); + const provider = getLocalProvider(anvilIPAddr, anvilPort); await provider.send(ANVIL_RPC_METHODS.STOP_IMPERSONATING_ACCOUNT, [ address.substring(2), ]); - logGreen( + logger.info( `✅ Successfully stopped account impersonation for address (${address})`, ); }; @@ -109,14 +116,16 @@ export const stopImpersonatingAccount = async (address: Address) => { * @returns a local JSON-RPC provider */ export const getLocalProvider = ( + anvilIPAddr?: string, + anvilPort?: number, urlOverride?: string, ): providers.JsonRpcProvider => { let envUrl; - if (ENV.ANVIL_IP_ADDR && ENV.ANVIL_PORT) - envUrl = `${ENDPOINT_PREFIX}${ENV.ANVIL_IP_ADDR}:${ENV.ANVIL_PORT}`; + if (anvilIPAddr && anvilPort) + envUrl = `${ENDPOINT_PREFIX}${anvilIPAddr}:${anvilPort}`; if (urlOverride && !urlOverride.startsWith(ENDPOINT_PREFIX)) { - warnYellow( + logger.warn( `⚠️ Provided URL override (${urlOverride}) does not begin with ${ENDPOINT_PREFIX}. Defaulting to ${ envUrl ?? DEFAULT_ANVIL_ENDPOINT }`,