-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
409 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Run Localnet | ||
|
||
on: | ||
pull_request: | ||
branches: [main] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
start: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout Repository | ||
uses: actions/checkout@v3 | ||
|
||
- name: Setup Node.js | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: "21" | ||
registry-url: "https://registry.npmjs.org" | ||
|
||
- name: Install Foundry | ||
uses: foundry-rs/foundry-toolchain@v1 | ||
|
||
- name: Install Dependencies | ||
run: yarn | ||
|
||
- name: Start Localnet | ||
run: yarn hardhat localnet --stop-after-init |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { localnetTask } from "./localnet"; | ||
export { localnetStopTask } from "./stop"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,165 @@ | ||
import { task, types } from "hardhat/config"; | ||
import { initLocalnet } from "../../localnet/src"; | ||
import { exec } from "child_process"; | ||
import { exec, execSync } from "child_process"; | ||
import waitOn from "wait-on"; | ||
import ansis from "ansis"; | ||
import fs from "fs"; | ||
import { confirm } from "@inquirer/prompts"; | ||
|
||
const main = async (args: any) => { | ||
const port = args.port || 8545; | ||
const anvilArgs = args.anvil ? `${args.anvil}` : ""; | ||
const LOCALNET_PID_FILE = "./localnet.pid"; | ||
|
||
console.log(`Starting anvil on port ${port} with args: ${anvilArgs}`); | ||
const killProcessOnPort = async (port: number, forceKill: boolean) => { | ||
try { | ||
const output = execSync(`lsof -ti tcp:${port}`).toString().trim(); | ||
if (output) { | ||
console.log( | ||
ansis.yellow(`Port ${port} is already in use by process ${output}.`) | ||
); | ||
|
||
if (forceKill) { | ||
execSync(`kill -9 ${output}`); | ||
console.log( | ||
ansis.green(`Successfully killed process ${output} on port ${port}.`) | ||
); | ||
} else { | ||
const answer = await confirm({ | ||
message: `Do you want to kill the process running on port ${port}?`, | ||
default: true, | ||
}); | ||
|
||
if (answer) { | ||
execSync(`kill -9 ${output}`); | ||
console.log( | ||
ansis.green( | ||
`Successfully killed process ${output} on port ${port}.` | ||
) | ||
); | ||
} else { | ||
console.log(ansis.red("Process not killed. Exiting...")); | ||
process.exit(1); | ||
} | ||
} | ||
} | ||
} catch (error) { | ||
// Silently continue if no process is found or killing fails | ||
} | ||
}; | ||
|
||
const localnet = async (args: any) => { | ||
try { | ||
execSync("which anvil"); | ||
} catch (error) { | ||
console.error( | ||
ansis.red( | ||
"Error: 'anvil' not found. Please install Foundry: https://getfoundry.sh" | ||
) | ||
); | ||
process.exit(1); | ||
} | ||
|
||
await killProcessOnPort(args.port, args.forceKill); | ||
|
||
if (args.anvil !== "") | ||
console.log(`Starting anvil on port ${args.port} with args: ${args.anvil}`); | ||
|
||
const anvilProcess = exec( | ||
`anvil --auto-impersonate --port ${port} ${anvilArgs}` | ||
`anvil --auto-impersonate --port ${args.port} ${args.anvil}` | ||
); | ||
|
||
if (anvilProcess.stdout && anvilProcess.stderr) { | ||
anvilProcess.stdout.pipe(process.stdout); | ||
anvilProcess.stderr.pipe(process.stderr); | ||
} | ||
|
||
await waitOn({ resources: [`tcp:127.0.0.1:${port}`] }); | ||
await waitOn({ resources: [`tcp:127.0.0.1:${args.port}`] }); | ||
|
||
const addr = await initLocalnet(port); | ||
const cleanup = () => { | ||
console.log("\nShutting down anvil and cleaning up..."); | ||
if (anvilProcess) { | ||
anvilProcess.kill(); | ||
} | ||
if (fs.existsSync(LOCALNET_PID_FILE)) { | ||
fs.unlinkSync(LOCALNET_PID_FILE); | ||
} | ||
}; | ||
|
||
console.log(ansis.cyan` | ||
EVM Contract Addresses | ||
====================== | ||
try { | ||
const addr = await initLocalnet(args.port); | ||
|
||
Gateway EVM: ${addr.gatewayEVM} | ||
ERC-20 custody: ${addr.custodyEVM} | ||
TSS: ${addr.tssEVM} | ||
ZETA: ${addr.zetaEVM}`); | ||
// EVM Contract Addresses | ||
const evmHeader = "\nEVM Contract Addresses"; | ||
console.log(ansis.cyan(`${evmHeader}\n${"=".repeat(evmHeader.length)}`)); | ||
|
||
addr.foreignCoins | ||
.filter((coin: any) => coin.asset !== "") | ||
.forEach((coin: any) => { | ||
console.log(ansis.cyan`ERC-20 ${coin.symbol}: ${coin.asset}`); | ||
}); | ||
const evmAddresses = { | ||
"Gateway EVM": addr.gatewayEVM, | ||
"ERC-20 Custody": addr.custodyEVM, | ||
TSS: addr.tssEVM, | ||
ZETA: addr.zetaEVM, | ||
...addr.foreignCoins | ||
.filter((coin: any) => coin.asset !== "") | ||
.reduce((acc: any, coin: any) => { | ||
acc[`ERC-20 ${coin.symbol}`] = coin.asset; | ||
return acc; | ||
}, {}), | ||
}; | ||
|
||
console.log(ansis.green` | ||
ZetaChain Contract Addresses | ||
============================ | ||
console.table(evmAddresses); | ||
|
||
Gateway ZetaChain: ${addr.gatewayZetaChain} | ||
ZETA: ${addr.zetaZetaChain} | ||
Fungible module: ${addr.fungibleModuleZetaChain} | ||
System contract: ${addr.sytemContractZetaChain}`); | ||
const zetaHeader = "\nZetaChain Contract Addresses"; | ||
console.log(ansis.green(`${zetaHeader}\n${"=".repeat(zetaHeader.length)}`)); | ||
|
||
addr.foreignCoins.forEach((coin: any) => { | ||
console.log( | ||
ansis.green`ZRC-20 ${coin.symbol}: ${coin.zrc20_contract_address}` | ||
); | ||
}); | ||
const zetaAddresses = { | ||
"Gateway ZetaChain": addr.gatewayZetaChain, | ||
ZETA: addr.zetaZetaChain, | ||
"Fungible Module": addr.fungibleModuleZetaChain, | ||
"System Contract": addr.sytemContractZetaChain, | ||
...addr.foreignCoins.reduce((acc: any, coin: any) => { | ||
acc[`ZRC-20 ${coin.symbol}`] = coin.zrc20_contract_address; | ||
return acc; | ||
}, {}), | ||
}; | ||
|
||
console.table(zetaAddresses); | ||
|
||
fs.writeFileSync(LOCALNET_PID_FILE, process.pid.toString(), "utf-8"); | ||
} catch (error: any) { | ||
console.error(ansis.red`Error initializing localnet: ${error}`); | ||
cleanup(); | ||
process.exit(1); | ||
} | ||
|
||
process.on("SIGINT", () => { | ||
console.log("\nReceived Ctrl-C, shutting down anvil..."); | ||
anvilProcess.kill(); | ||
const handleExit = (signal: string) => { | ||
console.log(`\nReceived ${signal}, shutting down...`); | ||
cleanup(); | ||
process.exit(); | ||
}; | ||
|
||
process.on("SIGINT", () => handleExit("SIGINT")); | ||
process.on("SIGTERM", () => handleExit("SIGTERM")); | ||
|
||
process.on("exit", () => { | ||
console.log("Process exiting..."); | ||
}); | ||
|
||
if (args.stopAfterInit) { | ||
console.log(ansis.green("Localnet successfully initialized. Stopping...")); | ||
cleanup(); | ||
process.exit(0); | ||
} | ||
|
||
await new Promise(() => {}); | ||
}; | ||
|
||
export const localnetTask = task("localnet", "Start localnet", main) | ||
export const localnetTask = task("localnet", "Start localnet", localnet) | ||
.addOptionalParam("port", "Port to run anvil on", 8545, types.int) | ||
.addOptionalParam( | ||
"anvil", | ||
"Additional arguments to pass to anvil", | ||
"", | ||
types.string | ||
) | ||
.addFlag("forceKill", "Force kill any process on the port without prompting") | ||
.addFlag( | ||
"stopAfterInit", | ||
"Stop the localnet after successful initialization" | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { task } from "hardhat/config"; | ||
import fs from "fs"; | ||
import ansis from "ansis"; | ||
|
||
const LOCALNET_PID_FILE = "./localnet.pid"; | ||
|
||
const localnetStop = async (args: any) => { | ||
if (!fs.existsSync(LOCALNET_PID_FILE)) { | ||
console.log(ansis.red("Localnet is not running or PID file is missing.")); | ||
return; | ||
} | ||
|
||
const pid = fs.readFileSync(LOCALNET_PID_FILE, "utf-8").trim(); | ||
try { | ||
process.kill(Number(pid)); | ||
console.log(ansis.green(`Successfully stopped localnet (PID: ${pid})`)); | ||
fs.unlinkSync(LOCALNET_PID_FILE); | ||
console.log(ansis.green(`PID file ${LOCALNET_PID_FILE} removed.`)); | ||
} catch (err) { | ||
console.error(ansis.red(`Failed to stop localnet: ${err}`)); | ||
} | ||
}; | ||
|
||
export const localnetStopTask = task( | ||
"localnet-stop", | ||
"Stop localnet", | ||
localnetStop | ||
); |
Oops, something went wrong.