diff --git a/src/commands/create/groups/quickstart.ts b/src/commands/create/groups/quickstart.ts new file mode 100644 index 0000000..b2de324 --- /dev/null +++ b/src/commands/create/groups/quickstart.ts @@ -0,0 +1,115 @@ +import chalk from "chalk"; +import inquirer from "inquirer"; + +import Logger from "../../../utils/logger.js"; +import { packageManagers } from "../../../utils/packageManager.js"; +import { isPrivateKey } from "../../../utils/validators.js"; +import { askForTemplate, setupTemplate, askForPackageManager, successfulMessage, getUniqueValues } from "../utils.js"; + +import type { GenericTemplate } from "../index.js"; + +type Template = GenericTemplate & { + framework: "Hardhat"; + ethereumFramework: "Ethers v5" | "Ethers v6"; + language: "Solidity" | "Vyper"; +}; + +export const templates: Template[] = [ + { + name: "Quickstart - Hardhat + Solidity", + value: "qs-hello-zksync", + framework: "Hardhat", + ethereumFramework: "Ethers v6", + language: "Solidity", + path: "templates/hello-zksync", + git: "https://github.com/dutterbutter/zksync-quickstart-guide", + }, + { + name: "Quickstart - Hardhat + Solidity", + value: "qs-factories", + framework: "Hardhat", + ethereumFramework: "Ethers v6", + language: "Solidity", + path: "templates/factories", + git: "https://github.com/dutterbutter/zksync-quickstart-guide", + }, + { + name: "Quickstart - Hardhat + Solidity", + value: "qs-testing", + framework: "Hardhat", + ethereumFramework: "Ethers v6", + language: "Solidity", + path: "templates/testing", + git: "https://github.com/dutterbutter/zksync-quickstart-guide", + }, + { + name: "Quickstart - Hardhat + Solidity", + value: "qs-upgrade", + framework: "Hardhat", + ethereumFramework: "Ethers v6", + language: "Solidity", + path: "templates/upgradability", + git: "https://github.com/dutterbutter/zksync-quickstart-guide", + }, + { + name: "Quickstart - Hardhat + Solidity", + value: "qs-paymaster", + framework: "Hardhat", + ethereumFramework: "Ethers v6", + language: "Solidity", + path: "templates/paymaster", + git: "https://github.com/dutterbutter/zksync-quickstart-guide", + }, +]; + +export default async (folderLocation: string, folderRelativePath: string, templateKey?: string) => { + let env: Record = {}; + let template: Template; + if (!templateKey) { + const { ethereumFramework }: { ethereumFramework: Template["ethereumFramework"] } = await inquirer.prompt([ + { + message: "Ethereum framework", + name: "ethereumFramework", + type: "list", + choices: getUniqueValues(templates.map((template) => template.ethereumFramework)), + required: true, + }, + ]); + template = await askForTemplate(templates.filter((template) => template.ethereumFramework === ethereumFramework)); + } else { + template = templates.find((e) => e.value === templateKey)!; + Logger.info(`Using ${chalk.magentaBright(template.name)} template`); + } + const { privateKey }: { privateKey: string } = await inquirer.prompt([ + { + message: "Private key of the wallet responsible for deploying contracts", + name: "privateKey", + suffix: chalk.gray(" (optional)"), + type: "input", + validate: (input: string) => { + if (!input) return true; // since it's optional + return isPrivateKey(input); + }, + transformer: (input: string) => { + return input.replace(/./g, "*"); + }, + }, + ]); + env = { + ...env, + WALLET_PRIVATE_KEY: privateKey, + }; + const packageManager = await askForPackageManager(); + await setupTemplate(template, folderLocation, env, packageManager); + + successfulMessage.start(folderRelativePath); + Logger.info(`${chalk.magentaBright("Directory Overview:")} + - Contracts: /contracts + - Deployment Scripts: /deploy + +${chalk.magentaBright("Commands:")} + - Compile your contracts: ${chalk.blueBright(packageManagers[packageManager].run("compile"))} + - Deploy your contract: ${chalk.blueBright(packageManagers[packageManager].run("deploy"))} + - Tip: You can use the ${chalk.blueBright("--network")} option to specify the network to deploy to.`); + successfulMessage.end(folderRelativePath); +}; diff --git a/src/commands/create/index.ts b/src/commands/create/index.ts index 695c7c7..d0cf738 100644 --- a/src/commands/create/index.ts +++ b/src/commands/create/index.ts @@ -5,6 +5,7 @@ import path from "path"; import useContractTemplates, { templates as contractTemplates } from "./groups/contracts.js"; import useFrontendTemplates, { templates as frontendTemplates } from "./groups/frontend.js"; +import useQuickstartTemplates, { templates as quickstartTemplates } from "./groups/quickstart.js"; import useScriptingTemplates, { templates as scriptingTemplates } from "./groups/scripting.js"; import { zeekOption } from "../../common/options.js"; import Program from "../../program.js"; @@ -20,10 +21,12 @@ export type GenericTemplate = { git: string; path?: string; }; -type ProjectType = "frontend" | "contracts" | "scripting"; +type ProjectType = "frontend" | "contracts" | "scripting" | "quickstart"; const templateOption = new Option("--template ", "Project template to use").choices( - [...contractTemplates, ...frontendTemplates, ...scriptingTemplates].map((template) => template.value) + [...contractTemplates, ...frontendTemplates, ...scriptingTemplates, ...quickstartTemplates].map( + (template) => template.value + ) ); const projectTypeOption = new Option("--project ", "Project type to select templates from").choices([ "contracts", @@ -75,6 +78,7 @@ export const handler = async (predefinedFolderName: string | undefined, options: } = { contracts: useContractTemplates, frontend: useFrontendTemplates, + quickstart: useQuickstartTemplates, scripting: useScriptingTemplates, }; @@ -115,6 +119,8 @@ export const handler = async (predefinedFolderName: string | undefined, options: projectType = "frontend"; } else if (scriptingTemplates.some((template) => template.value === options.template)) { projectType = "scripting"; + } else if (quickstartTemplates.some((template) => template.value === options.template)) { + projectType = "quickstart"; } if (!projectType) throw new Error(`Could not find project type for template ${options.template}`);