From 217d035d825a2b172de2e382dc3726cbae56294f Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 13:59:38 +0530 Subject: [PATCH 01/10] replace string values with enum --- src/config.ts | 3 ++- src/main.ts | 3 ++- src/tasks/create-first-git-commit.ts | 5 +++-- src/utils/consts.ts | 11 +++++++++++ src/utils/parse-arguments-into-options.ts | 4 ++-- src/utils/render-outro-message.ts | 8 ++++++-- src/utils/system-validation.ts | 1 + 7 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 src/utils/system-validation.ts diff --git a/src/config.ts b/src/config.ts index e886da234..9940f430f 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,5 @@ import { Config, ExternalExtension, typedQuestion } from "./types"; +import { SOLIDITY_FRAMEWORKS } from "./utils/consts"; const config: Config = { questions: [ @@ -6,7 +7,7 @@ const config: Config = { type: "single-select", name: "solidityFramework", message: "What solidity framework do you want to use?", - extensions: ["hardhat", "foundry", null], + extensions: [SOLIDITY_FRAMEWORKS.HARDHAT, SOLIDITY_FRAMEWORKS.FOUNDRY, null], default: "hardhat", }), ], diff --git a/src/main.ts b/src/main.ts index 8c7748564..5b6b556be 100644 --- a/src/main.ts +++ b/src/main.ts @@ -12,6 +12,7 @@ import { Listr } from "listr2"; import path from "path"; import { fileURLToPath } from "url"; import { getArgumentFromExternalExtensionOption } from "./utils/external-extensions"; +import { SOLIDITY_FRAMEWORKS } from "./utils/consts"; export async function createProject(options: Options) { console.log(`\n`); @@ -55,7 +56,7 @@ export async function createProject(options: Options) { }, }, { - title: `📡 Initializing Git repository${options.extensions.includes("foundry") ? " and submodules" : ""}`, + title: `📡 Initializing Git repository${options.extensions.includes(SOLIDITY_FRAMEWORKS.FOUNDRY) ? " and submodules" : ""}`, task: () => createFirstGitCommit(targetDirectory, options), }, ], diff --git a/src/tasks/create-first-git-commit.ts b/src/tasks/create-first-git-commit.ts index 6658a0035..88ffd5e8c 100644 --- a/src/tasks/create-first-git-commit.ts +++ b/src/tasks/create-first-git-commit.ts @@ -1,6 +1,7 @@ import { execa } from "execa"; import { Options } from "../types"; import path from "path"; +import { SOLIDITY_FRAMEWORKS } from "../utils/consts"; // Checkout the latest release tag in a git submodule async function checkoutLatestTag(submodulePath: string): Promise { @@ -24,7 +25,7 @@ async function checkoutLatestTag(submodulePath: string): Promise { export async function createFirstGitCommit(targetDir: string, options: Options) { try { // TODO: Move the logic for adding submodules to tempaltes - if (options.extensions?.includes("foundry")) { + if (options.extensions?.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { const foundryWorkSpacePath = path.resolve(targetDir, "packages", "foundry"); await execa("git", ["submodule", "add", "https://github.com/foundry-rs/forge-std", "lib/forge-std"], { cwd: foundryWorkSpacePath, @@ -61,7 +62,7 @@ export async function createFirstGitCommit(targetDir: string, options: Options) await execa("git", ["commit", "-m", "Initial commit with 🏗️ Scaffold-ETH 2", "--no-verify"], { cwd: targetDir }); // Update the submodule, since we have checked out the latest tag in the previous step of foundry - if (options.extensions?.includes("foundry")) { + if (options.extensions?.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { await execa("git", ["submodule", "update", "--init", "--recursive"], { cwd: path.resolve(targetDir, "packages", "foundry"), }); diff --git a/src/utils/consts.ts b/src/utils/consts.ts index eaafc393e..45465c0f1 100644 --- a/src/utils/consts.ts +++ b/src/utils/consts.ts @@ -1 +1,12 @@ +import { SolidityFramework } from "../types"; + export const baseDir = "base"; + +export const SOLIDITY_FRAMEWORKS = { + HARDHAT: "hardhat", + FOUNDRY: "foundry", +} as const; + +export const isSolidityFramework = (value: string): value is SolidityFramework => { + return Object.values(SOLIDITY_FRAMEWORKS).includes(value as SolidityFramework); +}; diff --git a/src/utils/parse-arguments-into-options.ts b/src/utils/parse-arguments-into-options.ts index 4bf2be80e..fa61166f6 100644 --- a/src/utils/parse-arguments-into-options.ts +++ b/src/utils/parse-arguments-into-options.ts @@ -4,6 +4,7 @@ import * as https from "https"; import { getDataFromExternalExtensionArgument } from "./external-extensions"; import chalk from "chalk"; import { CURATED_EXTENSIONS } from "../config"; +import { SOLIDITY_FRAMEWORKS } from "./consts"; const validateTemplate = async (template: string): Promise<{ repository: string; branch?: string }> => { const { githubUrl, githubBranchUrl, branch } = getDataFromExternalExtensionArgument(template); @@ -86,8 +87,7 @@ export async function parseArgumentsIntoOptions(rawArgs: Args): Promise {}; From c9eada77999ae5935d36d91c7b824efc70eff483 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 14:32:36 +0530 Subject: [PATCH 02/10] add foundryYup validation --- src/cli.ts | 5 +++++ src/utils/parse-arguments-into-options.ts | 5 +++++ src/utils/system-validation.ts | 15 ++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/cli.ts b/src/cli.ts index f44893a9f..931cfda05 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -4,12 +4,17 @@ import { promptForMissingOptions } from "./utils/prompt-for-missing-options"; import { renderIntroMessage } from "./utils/render-intro-message"; import type { Args } from "./types"; import chalk from "chalk"; +import { SOLIDITY_FRAMEWORKS } from "./utils/consts"; +import { validateFoundryYup } from "./utils/system-validation"; export async function cli(args: Args) { try { renderIntroMessage(); const rawOptions = await parseArgumentsIntoOptions(args); const options = await promptForMissingOptions(rawOptions); + if (options.extensions.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { + await validateFoundryYup(); + } await createProject(options); } catch (error: any) { console.error(chalk.red.bold(error.message || "An unknown error occurred.")); diff --git a/src/utils/parse-arguments-into-options.ts b/src/utils/parse-arguments-into-options.ts index fa61166f6..c900aac68 100644 --- a/src/utils/parse-arguments-into-options.ts +++ b/src/utils/parse-arguments-into-options.ts @@ -5,6 +5,7 @@ import { getDataFromExternalExtensionArgument } from "./external-extensions"; import chalk from "chalk"; import { CURATED_EXTENSIONS } from "../config"; import { SOLIDITY_FRAMEWORKS } from "./consts"; +import { validateFoundryYup } from "./system-validation"; const validateTemplate = async (template: string): Promise<{ repository: string; branch?: string }> => { const { githubUrl, githubBranchUrl, branch } = getDataFromExternalExtensionArgument(template); @@ -65,6 +66,10 @@ export async function parseArgumentsIntoOptions(rawArgs: Args): Promise {}; +import chalk from "chalk"; +import { execa } from "execa"; + +export const validateFoundryYup = async () => { + try { + await execa("foundryup", ["-h"]); + } catch (error) { + const message = `${chalk.bold.yellow("NOTE: Foundryup is not installed in your system.")} +${chalk.bold.yellow("To use foundry, please install foundryup")} +${chalk.bold.yellow("Checkout: https://getfoundry.sh")} + `; + throw new Error(message); + } +}; From 744f404359cb0f81432e6a8f4f4b3cc17b2abd40 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 14:34:12 +0530 Subject: [PATCH 03/10] remove validation from outromessage --- src/utils/render-outro-message.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/utils/render-outro-message.ts b/src/utils/render-outro-message.ts index 1295a3b99..b905c61fd 100644 --- a/src/utils/render-outro-message.ts +++ b/src/utils/render-outro-message.ts @@ -1,9 +1,8 @@ import type { Options } from "../types"; import chalk from "chalk"; -import { execa } from "execa"; import { SOLIDITY_FRAMEWORKS } from "./consts"; -export async function renderOutroMessage(options: Options) { +export function renderOutroMessage(options: Options) { let message = ` \n ${chalk.bold.green("Congratulations!")} Your project has been scaffolded! 🎉 @@ -22,17 +21,6 @@ export async function renderOutroMessage(options: Options) { \t${chalk.dim("yarn")} chain `; - if (options.extensions.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { - try { - await execa("foundryup", ["-h"]); - } catch (error) { - message += ` - \t${chalk.bold.yellow("(NOTE: Foundryup is not installed in your system)")} - \t${chalk.dim("Checkout: https://getfoundry.sh")} - `; - } - } - message += ` \t${chalk.bold("In a new terminal window, deploy your contracts")} \t${chalk.dim("yarn")} deploy From 06bcc74207b53c8c590c59bad33a6a9435fc1110 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 14:58:25 +0530 Subject: [PATCH 04/10] use forge to install foundry libraries --- src/tasks/create-first-git-commit.ts | 63 +++------------------------- 1 file changed, 5 insertions(+), 58 deletions(-) diff --git a/src/tasks/create-first-git-commit.ts b/src/tasks/create-first-git-commit.ts index 88ffd5e8c..807e3656c 100644 --- a/src/tasks/create-first-git-commit.ts +++ b/src/tasks/create-first-git-commit.ts @@ -3,73 +3,20 @@ import { Options } from "../types"; import path from "path"; import { SOLIDITY_FRAMEWORKS } from "../utils/consts"; -// Checkout the latest release tag in a git submodule -async function checkoutLatestTag(submodulePath: string): Promise { - try { - const { stdout } = await execa("git", ["tag", "-l", "--sort=-v:refname"], { - cwd: submodulePath, - }); - const tagLines = stdout.split("\n"); - if (tagLines.length > 0) { - const latestTag = tagLines[0]; - await execa("git", ["-C", `${submodulePath}`, "checkout", latestTag]); - } else { - throw new Error(`No tags found in submodule at ${submodulePath}`); - } - } catch (error) { - console.error("Error checking out latest tag:", error); - throw error; - } -} +const foundryLibraries = ["foundry-rs/forge-std", "OpenZeppelin/openzeppelin-contracts", "gnsps/solidity-bytes-utils"]; export async function createFirstGitCommit(targetDir: string, options: Options) { try { - // TODO: Move the logic for adding submodules to tempaltes - if (options.extensions?.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { - const foundryWorkSpacePath = path.resolve(targetDir, "packages", "foundry"); - await execa("git", ["submodule", "add", "https://github.com/foundry-rs/forge-std", "lib/forge-std"], { - cwd: foundryWorkSpacePath, - }); - await execa( - "git", - [ - "submodule", - "add", - "-b", - "release-v5.0", - "https://github.com/OpenZeppelin/openzeppelin-contracts", - "lib/openzeppelin-contracts", - ], - { - cwd: foundryWorkSpacePath, - }, - ); - await execa( - "git", - ["submodule", "add", "https://github.com/gnsps/solidity-bytes-utils", "lib/solidity-bytes-utils"], - { - cwd: foundryWorkSpacePath, - }, - ); - await execa("git", ["submodule", "update", "--init", "--recursive"], { - cwd: foundryWorkSpacePath, - }); - await checkoutLatestTag(path.resolve(foundryWorkSpacePath, "lib", "forge-std")); - await checkoutLatestTag(path.resolve(foundryWorkSpacePath, "lib", "openzeppelin-contracts")); - } - await execa("git", ["add", "-A"], { cwd: targetDir }); await execa("git", ["commit", "-m", "Initial commit with 🏗️ Scaffold-ETH 2", "--no-verify"], { cwd: targetDir }); - // Update the submodule, since we have checked out the latest tag in the previous step of foundry - if (options.extensions?.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { - await execa("git", ["submodule", "update", "--init", "--recursive"], { - cwd: path.resolve(targetDir, "packages", "foundry"), - }); + if (options.extensions.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { + const foundryWorkSpacePath = path.resolve(targetDir, "packages", "foundry"); + // forge install foundry libraries + await execa("forge", ["install", ...foundryLibraries], { cwd: foundryWorkSpacePath }); } } catch (e: any) { // cast error as ExecaError to get stderr - throw new Error("Failed to initialize git repository", { cause: e?.stderr ?? e, }); From 1b595304fdb531cac94a94ce9262b4267dcb110d Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 15:02:11 +0530 Subject: [PATCH 05/10] add changeset --- .changeset/giant-gifts-turn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/giant-gifts-turn.md diff --git a/.changeset/giant-gifts-turn.md b/.changeset/giant-gifts-turn.md new file mode 100644 index 000000000..a99f6427d --- /dev/null +++ b/.changeset/giant-gifts-turn.md @@ -0,0 +1,5 @@ +--- +"create-eth": patch +--- + +foundry: use forge to setup libraries + do early check for foundryup From 0ab5542ccc227568b30176dd4e0ba598f1bd0ef9 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 15:02:28 +0530 Subject: [PATCH 06/10] rename foundryYup => foundryUp --- src/cli.ts | 4 ++-- src/utils/parse-arguments-into-options.ts | 4 ++-- src/utils/system-validation.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 931cfda05..d01d62d2c 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -5,7 +5,7 @@ import { renderIntroMessage } from "./utils/render-intro-message"; import type { Args } from "./types"; import chalk from "chalk"; import { SOLIDITY_FRAMEWORKS } from "./utils/consts"; -import { validateFoundryYup } from "./utils/system-validation"; +import { validateFoundryUp } from "./utils/system-validation"; export async function cli(args: Args) { try { @@ -13,7 +13,7 @@ export async function cli(args: Args) { const rawOptions = await parseArgumentsIntoOptions(args); const options = await promptForMissingOptions(rawOptions); if (options.extensions.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { - await validateFoundryYup(); + await validateFoundryUp(); } await createProject(options); } catch (error: any) { diff --git a/src/utils/parse-arguments-into-options.ts b/src/utils/parse-arguments-into-options.ts index c900aac68..afa0042ab 100644 --- a/src/utils/parse-arguments-into-options.ts +++ b/src/utils/parse-arguments-into-options.ts @@ -5,7 +5,7 @@ import { getDataFromExternalExtensionArgument } from "./external-extensions"; import chalk from "chalk"; import { CURATED_EXTENSIONS } from "../config"; import { SOLIDITY_FRAMEWORKS } from "./consts"; -import { validateFoundryYup } from "./system-validation"; +import { validateFoundryUp } from "./system-validation"; const validateTemplate = async (template: string): Promise<{ repository: string; branch?: string }> => { const { githubUrl, githubBranchUrl, branch } = getDataFromExternalExtensionArgument(template); @@ -67,7 +67,7 @@ export async function parseArgumentsIntoOptions(rawArgs: Args): Promise { +export const validateFoundryUp = async () => { try { await execa("foundryup", ["-h"]); } catch (error) { From 8a7dfa9e0acc3d6bd7fea50942ada64874f15c93 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Thu, 20 Jun 2024 15:09:01 +0530 Subject: [PATCH 07/10] fix lint --- src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index 5b6b556be..bf1986b16 100644 --- a/src/main.ts +++ b/src/main.ts @@ -65,7 +65,7 @@ export async function createProject(options: Options) { try { await tasks.run(); - await renderOutroMessage(options); + renderOutroMessage(options); } catch (error) { console.log("%s Error occurred", chalk.red.bold("ERROR"), error); console.log("%s Exiting...", chalk.red.bold("Uh oh! 😕 Sorry about that!")); From 18e331c34d88a6ba58ca1862b8f98127c6f07b03 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Fri, 21 Jun 2024 12:43:50 +0530 Subject: [PATCH 08/10] remove unused isSolidityFramework func --- src/utils/consts.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/utils/consts.ts b/src/utils/consts.ts index 45465c0f1..af21b61a9 100644 --- a/src/utils/consts.ts +++ b/src/utils/consts.ts @@ -1,12 +1,6 @@ -import { SolidityFramework } from "../types"; - export const baseDir = "base"; export const SOLIDITY_FRAMEWORKS = { HARDHAT: "hardhat", FOUNDRY: "foundry", } as const; - -export const isSolidityFramework = (value: string): value is SolidityFramework => { - return Object.values(SOLIDITY_FRAMEWORKS).includes(value as SolidityFramework); -}; From 4894c790d6eedbcd6627dd4992d9826ac7876c83 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Fri, 21 Jun 2024 12:44:19 +0530 Subject: [PATCH 09/10] replace string literal with value from enum object --- src/config.ts | 2 +- src/tasks/create-first-git-commit.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.ts b/src/config.ts index 9940f430f..283c48edd 100644 --- a/src/config.ts +++ b/src/config.ts @@ -8,7 +8,7 @@ const config: Config = { name: "solidityFramework", message: "What solidity framework do you want to use?", extensions: [SOLIDITY_FRAMEWORKS.HARDHAT, SOLIDITY_FRAMEWORKS.FOUNDRY, null], - default: "hardhat", + default: SOLIDITY_FRAMEWORKS.HARDHAT, }), ], }; diff --git a/src/tasks/create-first-git-commit.ts b/src/tasks/create-first-git-commit.ts index 807e3656c..9565ae194 100644 --- a/src/tasks/create-first-git-commit.ts +++ b/src/tasks/create-first-git-commit.ts @@ -11,7 +11,7 @@ export async function createFirstGitCommit(targetDir: string, options: Options) await execa("git", ["commit", "-m", "Initial commit with 🏗️ Scaffold-ETH 2", "--no-verify"], { cwd: targetDir }); if (options.extensions.includes(SOLIDITY_FRAMEWORKS.FOUNDRY)) { - const foundryWorkSpacePath = path.resolve(targetDir, "packages", "foundry"); + const foundryWorkSpacePath = path.resolve(targetDir, "packages", SOLIDITY_FRAMEWORKS.FOUNDRY); // forge install foundry libraries await execa("forge", ["install", ...foundryLibraries], { cwd: foundryWorkSpacePath }); } From 826ad68d3e62c110cbe7026e4c124bdb54ce4bb5 Mon Sep 17 00:00:00 2001 From: Shiv Bhonde Date: Fri, 21 Jun 2024 12:52:03 +0530 Subject: [PATCH 10/10] NOTE => Attention + align spaces with intro comment --- src/utils/system-validation.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/system-validation.ts b/src/utils/system-validation.ts index e84827b59..a755a93b4 100644 --- a/src/utils/system-validation.ts +++ b/src/utils/system-validation.ts @@ -5,9 +5,9 @@ export const validateFoundryUp = async () => { try { await execa("foundryup", ["-h"]); } catch (error) { - const message = `${chalk.bold.yellow("NOTE: Foundryup is not installed in your system.")} -${chalk.bold.yellow("To use foundry, please install foundryup")} -${chalk.bold.yellow("Checkout: https://getfoundry.sh")} + const message = ` ${chalk.bold.yellow("Attention: Foundryup is not installed in your system.")} + ${chalk.bold.yellow("To use foundry, please install foundryup")} + ${chalk.bold.yellow("Checkout: https://getfoundry.sh")} `; throw new Error(message); }