Skip to content

Commit

Permalink
migrate fork util to SDK (#3625)
Browse files Browse the repository at this point in the history
### Description

* Migrates fork util to SDK

### Drive-by changes

* None

### Related issues

- Fixes #3624

### Backward compatibility

* Yes

### Testing

* Manual on core & warp
  • Loading branch information
nbayindirli authored Apr 22, 2024
1 parent e10735a commit 450e8e0
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 34 deletions.
6 changes: 6 additions & 0 deletions .changeset/nice-pianos-tease.md
Original file line number Diff line number Diff line change
@@ -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.
13 changes: 7 additions & 6 deletions typescript/cli/src/deploy/dry-run.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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) {
Expand Down
7 changes: 4 additions & 3 deletions typescript/cli/src/deploy/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import {
IsmConfig,
MultiProvider,
MultisigConfig,
getLocalProvider,
} from '@hyperlane-xyz/sdk';
import { Address, ProtocolType } from '@hyperlane-xyz/utils';

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';
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions typescript/cli/src/utils/keys.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
8 changes: 8 additions & 0 deletions typescript/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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: {
Expand All @@ -33,7 +32,7 @@ export const resetFork = async () => {
},
]);

logGreen(`✅ Successfully reset forked network`);
logger.info(`✅ Successfully reset forked network`);
};

/**
Expand All @@ -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, [
Expand All @@ -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`);
};

/**
Expand All @@ -70,13 +71,15 @@ export const setFork = async (
*/
export const impersonateAccount = async (
address: Address,
anvilIPAddr?: string,
anvilPort?: number,
): Promise<providers.JsonRpcSigner> => {
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);
};
Expand All @@ -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})`,
);
};
Expand All @@ -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
}`,
Expand Down

0 comments on commit 450e8e0

Please sign in to comment.