From 9a36c87de5edee2286c9a75b50e90baea6006193 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 4 Jun 2025 02:17:41 +0900 Subject: [PATCH 1/9] lint --- bun.lockb | Bin 95107 -> 100755 bytes package.json | 27 +-- src/action/deployContracts.ts | 19 +- src/action/findDeployment.ts | 13 +- src/action/verifyContracts.ts | 137 ++++++------ src/clients/createKernelClient.ts | 22 +- src/clients/index.ts | 8 +- src/command/index.ts | 18 +- src/constant.ts | 360 ++++++++++-------------------- src/utils/validate.ts | 66 +++--- test/deployContract.test.ts | 20 +- 11 files changed, 291 insertions(+), 399 deletions(-) diff --git a/bun.lockb b/bun.lockb index 5c3614cfcb985277a3a76defbb97cc92fd7b839d..dd8ac5265962a245a185d58eecc6abdea9b4f335 100755 GIT binary patch delta 23666 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 delta 20754 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 HJ8S-5&*4qS diff --git a/package.json b/package.json index 996003c..ead398f 100644 --- a/package.json +++ b/package.json @@ -43,29 +43,30 @@ ], "license": "MIT", "dependencies": { - "@zerodev/ecdsa-validator": "^5.4.0", - "@zerodev/sdk": "^5.4.3", + "@zerodev/ecdsa-validator": "^5.4.9", + "@zerodev/sdk": "^5.4.36", "chalk": "4.1.2", - "cli-table3": "^0.6.3", + "cli-table3": "^0.6.5", "commander": "^11.1.0", - "dotenv": "^16.3.1", - "figlet": "^1.7.0", - "ora": "^8.0.1", - "tslib": "^2.6.2" + "dotenv": "^16.5.0", + "figlet": "^1.8.1", + "ora": "^8.2.0", + "tslib": "^2.8.1", + "viem": "^2.30.6" }, "devDependencies": { - "@biomejs/biome": "^1.4.1", + "@biomejs/biome": "^1.9.4", "@changesets/changelog-git": "^0.1.14", "@changesets/changelog-github": "^0.4.8", - "@changesets/cli": "^2.27.1", + "@changesets/cli": "^2.29.4", "@size-limit/esbuild-why": "^9.0.0", "@size-limit/preset-small-lib": "^9.0.0", - "@types/figlet": "^1.5.8", - "@types/node": "^18.19.4", + "@types/figlet": "^1.7.0", + "@types/node": "^18.19.110", "@types/ora": "^3.2.0", - "simple-git-hooks": "^2.9.0", + "simple-git-hooks": "^2.13.0", "ts-node": "^10.9.2", - "typescript": "^5.2.2" + "typescript": "^5.8.3" }, "simple-git-hooks": { "pre-commit": "bun run format && bun run lint" diff --git a/src/action/deployContracts.ts b/src/action/deployContracts.ts index cc7ea79..01999de 100644 --- a/src/action/deployContracts.ts +++ b/src/action/deployContracts.ts @@ -3,7 +3,7 @@ import ora from "ora" import type { Address, Hex } from "viem" import { http, createPublicClient, getAddress } from "viem" import { createKernelClient, getZeroDevBundlerRPC } from "../clients/index.js" -import { type Chain, DEPLOYER_CONTRACT_ADDRESS } from "../constant.js" +import { DEPLOYER_CONTRACT_ADDRESS, type ZerodevChain } from "../constant.js" import { ensureHex, writeErrorLogToFile } from "../utils/index.js" import { computeContractAddress } from "./computeAddress.js" import { DeploymentStatus, checkDeploymentOnChain } from "./findDeployment.js" @@ -21,15 +21,17 @@ type DeployResult = [string, string] export const deployToChain = async ( privateKey: Hex, - chain: Chain, + chain: ZerodevChain, bytecode: Hex, salt: Hex, expectedAddress: string | undefined, callGasLimit: bigint | undefined ): Promise => { + console.log("true : ", chain === undefined) + console.log("deploying to chain", chain.name, chain.id) const publicClient = createPublicClient({ - chain: chain.viemChainObject, - transport: http(getZeroDevBundlerRPC(chain.projectId)) + chain: chain, + transport: http() }) const kernelAccountClient = await createKernelClient(privateKey, chain) @@ -86,13 +88,20 @@ export const deployToChain = async ( ]) }) + await kernelAccountClient.waitForUserOperationReceipt({ + hash: opHash + }) + await kernelAccountClient.getUserOperationReceipt({ + hash: opHash + }) + return [getAddress(result.data as Address), opHash] } export const deployContracts = async ( privateKey: Hex, bytecode: Hex, - chains: Chain[], + chains: ZerodevChain[], salt: Hex, expectedAddress: string | undefined, callGasLimit: bigint | undefined diff --git a/src/action/findDeployment.ts b/src/action/findDeployment.ts index bd746fa..963718b 100644 --- a/src/action/findDeployment.ts +++ b/src/action/findDeployment.ts @@ -1,7 +1,7 @@ import type { Address, Hex, PublicClient } from "viem" import { http, createPublicClient } from "viem" import { getZeroDevBundlerRPC } from "../clients/index.js" -import { type Chain, DEPLOYER_CONTRACT_ADDRESS } from "../constant.js" +import { DEPLOYER_CONTRACT_ADDRESS, type ZerodevChain } from "../constant.js" import { computeContractAddress } from "./computeAddress.js" export enum DeploymentStatus { Deployed = 0, @@ -29,12 +29,12 @@ export const checkDeploymentOnChain = async ( export const findDeployment = async ( bytecode: Hex, salt: Hex, - chains: Chain[] + chains: ZerodevChain[] ): Promise<{ address: Address - deployedChains: Chain[] - notDeployedChains: Chain[] - errorChains?: Chain[] + deployedChains: ZerodevChain[] + notDeployedChains: ZerodevChain[] + errorChains?: ZerodevChain[] }> => { const address = computeContractAddress( DEPLOYER_CONTRACT_ADDRESS, @@ -46,7 +46,8 @@ export const findDeployment = async ( chains.map((chain) => { return checkDeploymentOnChain( createPublicClient({ - transport: http(getZeroDevBundlerRPC(chain.projectId)) + chain: chain, + transport: http() }), address ).catch(() => DeploymentStatus.Error) diff --git a/src/action/verifyContracts.ts b/src/action/verifyContracts.ts index 7d3058b..59bc930 100644 --- a/src/action/verifyContracts.ts +++ b/src/action/verifyContracts.ts @@ -3,7 +3,7 @@ import util from "node:util" import chalk from "chalk" import ora from "ora" import type { Address } from "viem" -import type { Chain } from "../constant.js" +import type { ZerodevChain } from "../constant.js" const execPromise = util.promisify(exec) @@ -20,83 +20,80 @@ async function checkForgeAvailability() { async function verifyContract( contractName: string, contractAddress: Address, - chain: Chain + chain: ZerodevChain ): Promise { - if ( - !chain.etherscanApiKey && - chain.name !== "avalanche" && - chain.name !== "avalanche-fuji" && - chain.name !== "opbnb" && - chain.name !== "astar-zkatana" - ) { - throw new Error( - `Etherscan API key is not provided for ${chalk.yellowBright( - chain.name - )}` - ) - } + // if ( + // !chain.etherscanApiKey && + // chain.name !== "avalanche" && + // chain.name !== "avalanche-fuji" && + // chain.name !== "opbnb" && + // chain.name !== "astar-zkatana" + // ) { + // throw new Error( + // `Etherscan API key is not provided for ${chalk.yellowBright( + // chain.name + // )}` + // ) + // } - if (["opbnb", "astar-zkatana"].includes(chain.name)) { - throw new Error( - `Verification is not supported on ${chalk.yellowBright(chain.name)}` - ) - } + // if (["opbnb", "astar-zkatana"].includes(chain.name)) { + // throw new Error( + // `Verification is not supported on ${chalk.yellowBright(chain.name)}` + // ) + // } - const effectiveChainName = - chain.name === "linea-testnet" ? "linea-goerli" : chain.name - const command = `forge verify-contract -c ${effectiveChainName} ${contractAddress} ${contractName} -e ${chain.etherscanApiKey}` + // const effectiveChainName = + // chain.name === "linea-testnet" ? "linea-goerli" : chain.name + // const command = `forge verify-contract -c ${effectiveChainName} ${contractAddress} ${contractName} -e ${chain.etherscanApiKey}` - try { - const { stdout, stderr } = await execPromise(command) - if (stderr) { - return `Error verifying contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( - chain.name - )}: ${stderr}` - } - if (stdout.includes("is already verified")) { - return `Contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( - chain.name - )} is already verified. Skipping verification.` - } - return `Successfully verified contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( - chain.name - )}.` - } catch (error) { - throw new Error(`Error executing ${command}: ${error}`) - } + // try { + // const { stdout, stderr } = await execPromise(command) + // if (stderr) { + // return `Error verifying contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( + // chain.name + // )}: ${stderr}` + // } + // if (stdout.includes("is already verified")) { + // return `Contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( + // chain.name + // )} is already verified. Skipping verification.` + // } + // return `Successfully verified contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( + // chain.name + // )}.` + // } catch (error) { + // throw new Error(`Error executing ${command}: ${error}`) + // } + return "" } export const verifyContracts = async ( contractName: string, contractAddress: Address, - chains: Chain[] + chains: ZerodevChain[] ) => { - await checkForgeAvailability() - - const spinner = ora().start("Verifying contracts...") - - const verificationPromises = chains.map((chain) => - verifyContract(contractName, contractAddress, chain) - .then((message) => { - if (message.includes("is already verified")) { - ora().warn(message).start().stop() - } else { - ora().succeed(message).start().stop() - } - }) - .catch((error) => { - ora() - .fail( - `Verification failed on ${chain.name}: ${error.message}` - ) - .start() - .stop() - }) - ) - - // Wait for all verifications to complete - await Promise.all(verificationPromises) - - spinner.stop() - console.log("✅ All verifications process successfully finished!") + // await checkForgeAvailability() + // const spinner = ora().start("Verifying contracts...") + // const verificationPromises = chains.map((chain) => + // verifyContract(contractName, contractAddress, chain) + // .then((message) => { + // if (message.includes("is already verified")) { + // ora().warn(message).start().stop() + // } else { + // ora().succeed(message).start().stop() + // } + // }) + // .catch((error) => { + // ora() + // .fail( + // `Verification failed on ${chain.name}: ${error.message}` + // ) + // .start() + // .stop() + // }) + // ) + // // Wait for all verifications to complete + // await Promise.all(verificationPromises) + // spinner.stop() + // console.log("✅ All verifications process successfully finished!") } diff --git a/src/clients/createKernelClient.ts b/src/clients/createKernelClient.ts index 340c4ec..c723a2e 100644 --- a/src/clients/createKernelClient.ts +++ b/src/clients/createKernelClient.ts @@ -5,23 +5,26 @@ import { createKernelAccountClient, createZeroDevPaymasterClient } from "@zerodev/sdk" +import { getUserOperationGasPrice } from "@zerodev/sdk" import { KERNEL_V3_1, getEntryPoint } from "@zerodev/sdk/constants" import type { Hex } from "viem" + import { http, createPublicClient } from "viem" import { privateKeyToAccount } from "viem/accounts" -import type { Chain } from "../constant.js" +import type { ZerodevChain } from "../constant.js" import { getZeroDevBundlerRPC, getZeroDevPaymasterRPC } from "./index.js" export const createKernelClient = async ( privateKey: Hex, - chain: Chain + chain: ZerodevChain ): Promise => { - const rpcUrl = getZeroDevBundlerRPC(chain.projectId, "PIMLICO") - const paymasterRpcUrl = getZeroDevPaymasterRPC(chain.projectId, "PIMLICO") + const rpcUrl = getZeroDevBundlerRPC(chain.id, "PIMLICO") + const paymasterRpcUrl = getZeroDevPaymasterRPC(chain.id, "PIMLICO") const entryPoint = getEntryPoint("0.7") + const publicClient = createPublicClient({ - transport: http(rpcUrl), - chain: chain.viemChainObject + chain: chain, + transport: http(chain.rpcUrls.default.http[0]) }) const signer = privateKeyToAccount(privateKey) @@ -41,13 +44,14 @@ export const createKernelClient = async ( }) const zerodevPaymaster = createZeroDevPaymasterClient({ - chain: chain.viemChainObject, + chain: chain, transport: http(paymasterRpcUrl) }) // Construct a Kernel account client const kernelClient = createKernelAccountClient({ - account, - chain: chain.viemChainObject, + account: account, + client: publicClient, + chain: chain, bundlerTransport: http(rpcUrl), paymaster: { getPaymasterData(userOperation) { diff --git a/src/clients/index.ts b/src/clients/index.ts index 8746f8e..a9d8919 100644 --- a/src/clients/index.ts +++ b/src/clients/index.ts @@ -1,18 +1,18 @@ export const getZeroDevBundlerRPC = ( - projectId: string, + chainId: number, provider?: string ): string => { - let rpc = `https://rpc.zerodev.app/api/v2/bundler/${projectId}` + let rpc = `https://rpc.zerodev.app/api/v3/${process.env.ZERODEV_PROJECT_ID}/chain/${chainId}` if (provider) { rpc += `?provider=${provider}` } return rpc } export const getZeroDevPaymasterRPC = ( - projectId: string, + chainId: number, provider?: string ): string => { - let rpc = `https://rpc.zerodev.app/api/v2/paymaster/${projectId}` + let rpc = `https://rpc.zerodev.app/api/v3/${process.env.ZERODEV_PROJECT_ID}/chain/${chainId}` if (provider) { rpc += `?provider=${provider}` } diff --git a/src/command/index.ts b/src/command/index.ts index bfcbecb..2eb70a4 100644 --- a/src/command/index.ts +++ b/src/command/index.ts @@ -55,12 +55,10 @@ program.helpInformation = function () { program .command("chains") .description("Show the list of available chains") - .action(() => { - const chains = getSupportedChains().map((chain) => [ + .action(async () => { + const chains = (await getSupportedChains()).map((chain) => [ chain.name, - chain.type === "mainnet" - ? chalk.blue(chain.type) - : chalk.green(chain.type) + chain.testnet ? chalk.green("testnet") : chalk.blue("mainnet") ]) const table = new Table({ @@ -150,10 +148,11 @@ program const normalizedSalt = normalizeSalt(salt) validateInputs(file, bytecode, normalizedSalt, expectedAddress) - const chainObjects = processAndValidateChains(chains, { + const chainObjects = await processAndValidateChains({ testnetAll, mainnetAll, - allNetworks + allNetworks, + chainOption: chains }) let bytecodeToDeploy = bytecode @@ -216,10 +215,11 @@ program const normalizedSalt = normalizeSalt(salt) validateInputs(file, bytecode, normalizedSalt, undefined) - const chainObjects = processAndValidateChains(chains, { + const chainObjects = await processAndValidateChains({ testnetAll, mainnetAll, - allNetworks + allNetworks, + chainOption: chains }) let bytecodeToDeploy = bytecode diff --git a/src/constant.ts b/src/constant.ts index fbb546f..1b91b39 100644 --- a/src/constant.ts +++ b/src/constant.ts @@ -1,249 +1,137 @@ -import { - type Chain as ViemChain, - arbitrum, - arbitrumNova, - arbitrumSepolia, - astarZkEVM, - astarZkyoto, - avalanche, - avalancheFuji, - base, - baseSepolia, - blast, - blastSepolia, - bsc, - celo, - celoAlfajores, - cyber, - cyberTestnet, - degen, - linea, - lineaTestnet, - mainnet, - opBNB, - optimism, - optimismSepolia, - polygon, - polygonAmoy, - sepolia -} from "viem/chains" +import type { Chain } from "viem/chains" /** @dev deterministic-deployment-proxy contract address */ export const DEPLOYER_CONTRACT_ADDRESS = "0x4e59b44847b379578588920ca78fbf26c0b4956c" -export enum Network { - mainnet = "mainnet", - testnet = "testnet" -} +export type ZerodevChain = { + onlySelfFunded: boolean + rollupProvider: string | null + deprecated: boolean + explorerAPI: string | null +} & Chain -export interface UnvalidatedChain { +interface ZerodevChainResponse { + chainId: number name: string - projectId: string | null - etherscanApiKey?: string - viemChainObject: ViemChain - type: Network + nativeCurrencyName: string + nativeCurrencySymbol: string + nativeCurrencyDecimals: number + rpcUrl: string + explorerUrl: string + testnet: boolean + onlySelfFunded: boolean + rollupProvider: string | null + deprecated: boolean } -export interface Chain { +interface ZerodevProjectResponse { + id: string name: string - projectId: string - etherscanApiKey?: string - viemChainObject: ViemChain - type: Network + teamId: string + chains: { + chain_id: number + name: string + testnet: boolean + }[] } -export const getSupportedChains = (): UnvalidatedChain[] => [ - { - name: "arbitrum", - projectId: process.env.ARBITRUM_PROJECT_ID || null, - etherscanApiKey: process.env.ARBITRUM_ETHERSCAN_API_KEY || undefined, - viemChainObject: arbitrum, - type: Network.mainnet - }, - { - name: "arbitrum-nova", - projectId: process.env.ARBITRUM_NOVA_PROJECT_ID || null, - etherscanApiKey: - process.env.ARBITRUM_NOVA_ETHERSCAN_API_KEY || undefined, - viemChainObject: arbitrumNova, - type: Network.mainnet - }, - { - name: "arbitrum-sepolia", - projectId: process.env.ARBITRUM_SEPOLIA_PROJECT_ID || null, - etherscanApiKey: - process.env.ARBITRUM_SEPOLIA_ETHERSCAN_API_KEY || undefined, - viemChainObject: arbitrumSepolia, - type: Network.testnet - }, - { - name: "astar-zkEVM", - projectId: process.env.ASTAR_ZKEVM_PROJECT_ID || null, - etherscanApiKey: process.env.ASTAR_ZKEVM_ETHERSCAN_API_KEY || undefined, - viemChainObject: astarZkEVM, - type: Network.mainnet - }, - { - name: "astar-zkyoto", - projectId: process.env.ASTAR_ZKYOTO_PROJECT_ID || null, - etherscanApiKey: - process.env.ASTAR_ZKYOTO_ETHERSCAN_API_KEY || undefined, - viemChainObject: astarZkyoto, - type: Network.testnet - }, - { - name: "avalanche", - projectId: process.env.AVALANCHE_PROJECT_ID || null, - etherscanApiKey: process.env.AVALANCHE_ETHERSCAN_API_KEY || undefined, - viemChainObject: avalanche, - type: Network.mainnet - }, - { - name: "avalanche-fuji", - projectId: process.env.AVALANCHE_FUJI_PROJECT_ID || null, - etherscanApiKey: - process.env.AVALANCHE_FUJI_ETHERSCAN_API_KEY || undefined, - viemChainObject: avalancheFuji, - type: Network.testnet - }, - { - name: "base", - projectId: process.env.BASE_PROJECT_ID || null, - etherscanApiKey: process.env.BASE_ETHERSCAN_API_KEY || undefined, - viemChainObject: base, - type: Network.mainnet - }, - { - name: "base-sepolia", - projectId: process.env.BASE_SEPOLIA_PROJECT_ID || null, - etherscanApiKey: - process.env.BASE_SEPOLIA_ETHERSCAN_API_KEY || undefined, - viemChainObject: baseSepolia, - type: Network.testnet - }, - { - name: "blast", - projectId: process.env.BLAST_PROJECT_ID || null, - etherscanApiKey: process.env.BLAST_ETHERSCAN_API_KEY || undefined, - viemChainObject: blast, - type: Network.mainnet - }, - { - name: "blast-sepolia", - projectId: process.env.BLAST_SEPOLIA_PROJECT_ID || null, - etherscanApiKey: process.env.BLAST_ETHERSCAN_API_KEY || undefined, - viemChainObject: blastSepolia, - type: Network.testnet - }, - { - name: "bsc", - projectId: process.env.BSC_PROJECT_ID || null, - etherscanApiKey: process.env.BSC_ETHERSCAN_API_KEY || undefined, - viemChainObject: bsc, - type: Network.mainnet - }, - { - name: "celo", - projectId: process.env.CELO_PROJECT_ID || null, - etherscanApiKey: process.env.CELO_ETHERSCAN_API_KEY || undefined, - viemChainObject: celo, - type: Network.mainnet - }, - { - name: "celo-alfajores", - projectId: process.env.CELO_ALFAJORES_PROJECT_ID || null, - etherscanApiKey: - process.env.CELO_ALFAJORES_ETHERSCAN_API_KEY || undefined, - viemChainObject: celoAlfajores, - type: Network.testnet - }, - { - name: "cyber", - projectId: process.env.CYBER_PROJECT_ID || null, - etherscanApiKey: process.env.CYBER_ETHERSCAN_API_KEY || undefined, - viemChainObject: cyber, - type: Network.mainnet - }, - { - name: "cyber-testnet", - projectId: process.env.CYBER_TESTNET_PROJECT_ID || null, - etherscanApiKey: - process.env.CYBER_TESTNET_ETHERSCAN_API_KEY || undefined, - viemChainObject: cyberTestnet, - type: Network.testnet - }, - { - name: "degen", - projectId: process.env.DEGEN_PROJECT_ID || null, - etherscanApiKey: process.env.DEGEN_ETHERSCAN_API_KEY || undefined, - viemChainObject: degen, - type: Network.mainnet - }, - { - name: Network.mainnet, - projectId: process.env.MAINNET_PROJECT_ID || null, - etherscanApiKey: process.env.MAINNET_ETHERSCAN_API_KEY || undefined, - viemChainObject: mainnet, - type: Network.mainnet - }, - { - name: "sepolia", - projectId: process.env.SEPOILA_PROJECT_ID || null, - etherscanApiKey: process.env.SEPOILA_ETHERSCAN_API_KEY || undefined, - viemChainObject: sepolia, - type: Network.testnet - }, - { - name: "optimism", - projectId: process.env.OPTIMISM_PROJECT_ID || null, - etherscanApiKey: process.env.OPTIMISM_ETHERSCAN_API_KEY || undefined, - viemChainObject: optimism, - type: Network.mainnet - }, - { - name: "optimism-sepolia", - projectId: process.env.OPTIMISM_SEPOLIA_PROJECT_ID || null, - etherscanApiKey: - process.env.OPTIMISM_SEPOLIA_ETHERSCAN_API_KEY || undefined, - viemChainObject: optimismSepolia, - type: Network.testnet - }, - { - name: "opbnb", - projectId: process.env.OPBNB_PROJECT_ID || null, - etherscanApiKey: process.env.OPBNB_ETHERSCAN_API_KEY || undefined, - viemChainObject: opBNB, - type: Network.mainnet - }, - { - name: "polygon", - projectId: process.env.POLYGON_PROJECT_ID || null, - etherscanApiKey: process.env.POLYGON_ETHERSCAN_API_KEY || undefined, - viemChainObject: polygon, - type: Network.mainnet - }, - { - name: "polygon-amoy", - projectId: process.env.POLYGON_AMOY_PROJECT_ID || null, - etherscanApiKey: - process.env.POLYGON_AMOY_ETHERSCAN_API_KEY || undefined, - viemChainObject: polygonAmoy, - type: Network.testnet - }, - { - name: "linea", - projectId: process.env.LINEA_PROJECT_ID || null, - etherscanApiKey: process.env.LINEA_ETHERSCAN_API_KEY || undefined, - viemChainObject: linea, - type: Network.mainnet - }, - { - name: "linea-testnet", - projectId: process.env.LINEA_TESTNET_PROJECT_ID || null, - etherscanApiKey: - process.env.LINEA_TESTNET_ETHERSCAN_API_KEY || undefined, - viemChainObject: lineaTestnet, - type: Network.testnet +/* +curl --request GET \ + --url https://prod-api-us-east.onrender.com/v2/chains \ + --header `X-API-KEY: ${process.env.ZERODEV_API_KEY}` \ + --header 'accept: application/json' + { + "chainId": 1, + "name": "Ethereum", + "nativeCurrencyName": "Ether", + "nativeCurrencySymbol": "ETH", + "nativeCurrencyDecimals": 18, + "rpcUrl": "https://eth.llamarpc.com", + "explorerUrl": "https://etherscan.io", + "testnet": false, + "onlySelfFunded": false, + "rollupProvider": null, + "deprecated": false + }, + +*/ + +export const getSupportedChains = async (): Promise => { + const response = await fetch( + "https://prod-api-us-east.onrender.com/v2/chains", + { + headers: { + "X-API-KEY": process.env.ZERODEV_API_KEY ?? "", + accept: "application/json" + } + } + ) + + if (!response.ok) { + throw new Error(`Failed to fetch chains: ${response.statusText}`) } -] + + const data = (await response.json()) as ZerodevChainResponse[] + + const chains_all = data.reduce( + (acc, chain) => { + const key = `${chain.name}-${chain.chainId}` + acc[key] = { + id: chain.chainId, + name: chain.name, + nativeCurrency: { + name: chain.nativeCurrencyName, + symbol: chain.nativeCurrencySymbol, + decimals: chain.nativeCurrencyDecimals + }, + rpcUrls: { + default: { http: [chain.rpcUrl] } + }, + onlySelfFunded: chain.onlySelfFunded, + rollupProvider: chain.rollupProvider, + deprecated: chain.deprecated, + testnet: chain.testnet, + explorerAPI: chain.explorerUrl || "" + } + return acc + }, + {} as Record + ) + + const response_project = await fetch( + `https://prod-api-us-east.onrender.com/v2/projects/${process.env.ZERODEV_PROJECT_ID}`, + { + headers: { + "X-API-KEY": process.env.ZERODEV_API_KEY ?? "", + accept: "application/json" + } + } + ) + + if (!response_project.ok) { + throw new Error( + `Failed to fetch project chains: ${response_project.statusText}` + ) + } + + const chains_project = + (await response_project.json()) as ZerodevProjectResponse + + const supportedChains = chains_project.chains + .map((chain) => { + const key = `${chain.name}-${chain.chain_id}` + const matchedChain = chains_all[key] + if (!matchedChain) { + return null + } + return matchedChain + }) + .filter((chain): chain is ZerodevChain => chain !== null) + + if (supportedChains.length === 0) { + throw new Error("No supported chains found for the project") + } + + return supportedChains +} diff --git a/src/utils/validate.ts b/src/utils/validate.ts index fe29f6d..442b99f 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -1,9 +1,5 @@ import type { Hex } from "viem" -import { - type Chain, - type UnvalidatedChain, - getSupportedChains -} from "../constant.js" +import { type ZerodevChain, getSupportedChains } from "../constant.js" import { readBytecodeFromFile } from "./file.js" const PRIVATE_KEY_REGEX = /^0x[0-9a-fA-F]{64}$/ @@ -73,16 +69,17 @@ interface CommandOptions { testnetAll?: boolean mainnetAll?: boolean allNetworks?: boolean + chainOption?: string } -export const processAndValidateChains = ( - chainOption: string | undefined, +export const processAndValidateChains = async ( options: CommandOptions -): Chain[] => { - const supportedChains = getSupportedChains() +): Promise => { + const supportedChains = await getSupportedChains() + // Check for mutually exclusive options const exclusiveOptions = [ - chainOption !== undefined, + options.chainOption !== undefined, options.testnetAll, options.mainnetAll, options.allNetworks @@ -103,41 +100,28 @@ export const processAndValidateChains = ( process.exit(1) } - let chains: string[] + let chains: ZerodevChain[] if (options.testnetAll) { - chains = supportedChains - .filter((chain) => chain.type === "testnet") - .map((chain) => chain.name) + chains = supportedChains.filter((chain) => chain.testnet) } else if (options.mainnetAll) { - chains = supportedChains - .filter((chain) => chain.type === "mainnet") - .map((chain) => chain.name) + chains = supportedChains.filter((chain) => !chain.testnet) } else if (options.allNetworks) { - chains = supportedChains.map((chain) => chain.name) - } else { - chains = chainOption ? chainOption.split(",") : [] - } - - const chainObjects: UnvalidatedChain[] = chains.map((chainName: string) => { - const chain = supportedChains.find((c) => c.name === chainName) + chains = supportedChains + } else if (options.chainOption) { + const chain = supportedChains.find( + (chain) => + chain.name.toLowerCase() === options.chainOption?.toLowerCase() + ) if (!chain) { - console.error(`Error: Chain ${chainName} is not supported`) + console.error(`Error: Chain ${options.chainOption} not found`) process.exit(1) } - return chain - }) - - return validateChains(chainObjects) -} - -const validateChains = (chains: UnvalidatedChain[]): Chain[] => { - return chains.map((chain) => { - if (!chain.projectId) { - console.error( - `Error: PROJECT_ID for chain ${chain.name} is not specified` - ) - process.exit(1) - } - return chain as Chain - }) + chains = [chain] + } else { + console.error( + "Error: At least one of -c, -t, -m, -a options must be specified" + ) + process.exit(1) + } + return chains } diff --git a/test/deployContract.test.ts b/test/deployContract.test.ts index 6a202c1..97b0405 100644 --- a/test/deployContract.test.ts +++ b/test/deployContract.test.ts @@ -3,6 +3,7 @@ import { deployToChain,deployContracts } from "../src/action/deployContracts"; import { processAndValidateChains } from "../src/utils"; import {generatePrivateKey,} from "viem/accounts"; import { concat } from 'viem' +import { getSupportedChains } from "../src/constant"; const PRIVATE_KEY = generatePrivateKey(); // this is copied from viem.sh docs, so don't use this in production and no it's not even ours @@ -10,11 +11,12 @@ const PRIVATE_KEY = generatePrivateKey(); // this is copied from viem.sh docs, s test("deployContract", async () => { await deployToChain( PRIVATE_KEY, - processAndValidateChains("sepolia", { + (await processAndValidateChains({ testnetAll : false, mainnetAll : false, - allNetworks : false - })[0], + allNetworks : false, + chainOption : "Sepolia" + }))[0], concat(['0x00', generatePrivateKey()]), generatePrivateKey(), undefined, @@ -26,13 +28,19 @@ test("deployContractTestnet", async () => { await deployContracts( PRIVATE_KEY, concat(['0x00', generatePrivateKey()]), - processAndValidateChains(undefined, { + await processAndValidateChains({ testnetAll : true, mainnetAll : false, - allNetworks : false + allNetworks : false, }), generatePrivateKey(), undefined, undefined ); -}, 30000); \ No newline at end of file +}, 30000); + +test("getSupportedChains", async () => { + const chains = await getSupportedChains(); + console.log(chains.map((chain) => chain.name + " " + chain.id)); + expect(chains).toBeDefined(); +}); \ No newline at end of file From 0371482727301a2825cfdb72a193908a2e3b1b89 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 4 Jun 2025 23:04:24 +0900 Subject: [PATCH 2/9] verification done --- src/action/deployContracts.ts | 11 ++- src/action/verifyContracts.ts | 125 ++++++++++++++++------------------ src/constant.ts | 3 +- 3 files changed, 68 insertions(+), 71 deletions(-) diff --git a/src/action/deployContracts.ts b/src/action/deployContracts.ts index 01999de..0545c1f 100644 --- a/src/action/deployContracts.ts +++ b/src/action/deployContracts.ts @@ -27,8 +27,6 @@ export const deployToChain = async ( expectedAddress: string | undefined, callGasLimit: bigint | undefined ): Promise => { - console.log("true : ", chain === undefined) - console.log("deploying to chain", chain.name, chain.id) const publicClient = createPublicClient({ chain: chain, transport: http() @@ -109,6 +107,7 @@ export const deployContracts = async ( const spinner = ora( `Deploying contract on ${chains.map((chain) => chain.name).join(", ")}` ).start() + let anyError = false const deployments = chains.map(async (chain) => { return deployToChain( privateKey, @@ -139,6 +138,7 @@ export const deployContracts = async ( ) } else { writeErrorLogToFile(chain.name, error) + anyError = true spinner.fail( `Deployment for ${chalk.redBright( chain.name @@ -150,5 +150,10 @@ export const deployContracts = async ( await Promise.allSettled(deployments) spinner.stop() - console.log("✅ All deployments process successfully finished!") + if (anyError) { + console.log("❌ Some deployments failed!") + process.exit(1) + } else { + console.log("✅ All deployments process successfully finished!") + } } diff --git a/src/action/verifyContracts.ts b/src/action/verifyContracts.ts index 59bc930..f60f3af 100644 --- a/src/action/verifyContracts.ts +++ b/src/action/verifyContracts.ts @@ -22,49 +22,35 @@ async function verifyContract( contractAddress: Address, chain: ZerodevChain ): Promise { - // if ( - // !chain.etherscanApiKey && - // chain.name !== "avalanche" && - // chain.name !== "avalanche-fuji" && - // chain.name !== "opbnb" && - // chain.name !== "astar-zkatana" - // ) { - // throw new Error( - // `Etherscan API key is not provided for ${chalk.yellowBright( - // chain.name - // )}` - // ) - // } - - // if (["opbnb", "astar-zkatana"].includes(chain.name)) { - // throw new Error( - // `Verification is not supported on ${chalk.yellowBright(chain.name)}` - // ) - // } - - // const effectiveChainName = - // chain.name === "linea-testnet" ? "linea-goerli" : chain.name - // const command = `forge verify-contract -c ${effectiveChainName} ${contractAddress} ${contractName} -e ${chain.etherscanApiKey}` + if ( + !chain.explorerAPI + ) { + throw new Error( + `Etherscan API key is not provided for ${chalk.yellowBright( + chain.name + )}` + ) + } + const command = `forge verify-contract --chain ${chain.id} --verifier etherscan ${contractAddress} ${contractName} -e ${chain.explorerAPI} -a v2` - // try { - // const { stdout, stderr } = await execPromise(command) - // if (stderr) { - // return `Error verifying contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( - // chain.name - // )}: ${stderr}` - // } - // if (stdout.includes("is already verified")) { - // return `Contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( - // chain.name - // )} is already verified. Skipping verification.` - // } - // return `Successfully verified contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( - // chain.name - // )}.` - // } catch (error) { - // throw new Error(`Error executing ${command}: ${error}`) - // } - return "" + try { + const { stdout, stderr } = await execPromise(command) + if (stderr) { + return `Error verifying contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( + chain.name + )}: ${stderr}` + } + if (stdout.includes("is already verified")) { + return `Contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( + chain.name + )} is already verified. Skipping verification.` + } + return `Successfully verified contract ${contractName} at ${contractAddress} on ${chalk.yellowBright( + chain.name + )}.` + } catch (error) { + throw new Error(`Error executing ${command}: ${error}`) + } } export const verifyContracts = async ( @@ -72,28 +58,35 @@ export const verifyContracts = async ( contractAddress: Address, chains: ZerodevChain[] ) => { - // await checkForgeAvailability() - // const spinner = ora().start("Verifying contracts...") - // const verificationPromises = chains.map((chain) => - // verifyContract(contractName, contractAddress, chain) - // .then((message) => { - // if (message.includes("is already verified")) { - // ora().warn(message).start().stop() - // } else { - // ora().succeed(message).start().stop() - // } - // }) - // .catch((error) => { - // ora() - // .fail( - // `Verification failed on ${chain.name}: ${error.message}` - // ) - // .start() - // .stop() - // }) - // ) - // // Wait for all verifications to complete - // await Promise.all(verificationPromises) - // spinner.stop() - // console.log("✅ All verifications process successfully finished!") + await checkForgeAvailability() + const spinner = ora().start("Verifying contracts...") + let anyError = false + const verificationPromises = chains.map((chain) => + verifyContract(contractName, contractAddress, chain) + .then((message) => { + if (message.includes("is already verified")) { + ora().warn(message).start().stop() + } else { + ora().succeed(message).start().stop() + } + }) + .catch((error) => { + anyError = true + return ora() + .fail( + `Verification failed on ${chain.name}: ${error.message}` + ) + .start() + .stop() + }) + ) + // Wait for all verifications to complete + await Promise.all(verificationPromises) + spinner.stop() + if (anyError) { + console.log("❌ Some verifications failed!") + process.exit(1) + } else { + console.log("✅ All verifications process successfully finished!") + } } diff --git a/src/constant.ts b/src/constant.ts index 1b91b39..7bd1e33 100644 --- a/src/constant.ts +++ b/src/constant.ts @@ -54,7 +54,6 @@ curl --request GET \ "rollupProvider": null, "deprecated": false }, - */ export const getSupportedChains = async (): Promise => { @@ -92,7 +91,7 @@ export const getSupportedChains = async (): Promise => { rollupProvider: chain.rollupProvider, deprecated: chain.deprecated, testnet: chain.testnet, - explorerAPI: chain.explorerUrl || "" + explorerAPI: process.env[`${chain.name.toUpperCase()}_EXPLORER_API_KEY`] ?? process.env.ETHERSCAN_API_KEY ?? "" // try get chain specific api key, if not found, use etherscan api key } return acc }, From a81249cb7826051a836cf66f46086f7037d6dee7 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 4 Jun 2025 23:04:32 +0900 Subject: [PATCH 3/9] verification done --- src/action/verifyContracts.ts | 4 +--- src/constant.ts | 7 ++++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/action/verifyContracts.ts b/src/action/verifyContracts.ts index f60f3af..f2a9f5d 100644 --- a/src/action/verifyContracts.ts +++ b/src/action/verifyContracts.ts @@ -22,9 +22,7 @@ async function verifyContract( contractAddress: Address, chain: ZerodevChain ): Promise { - if ( - !chain.explorerAPI - ) { + if (!chain.explorerAPI) { throw new Error( `Etherscan API key is not provided for ${chalk.yellowBright( chain.name diff --git a/src/constant.ts b/src/constant.ts index 7bd1e33..3264433 100644 --- a/src/constant.ts +++ b/src/constant.ts @@ -91,7 +91,12 @@ export const getSupportedChains = async (): Promise => { rollupProvider: chain.rollupProvider, deprecated: chain.deprecated, testnet: chain.testnet, - explorerAPI: process.env[`${chain.name.toUpperCase()}_EXPLORER_API_KEY`] ?? process.env.ETHERSCAN_API_KEY ?? "" // try get chain specific api key, if not found, use etherscan api key + explorerAPI: + process.env[ + `${chain.name.toUpperCase()}_EXPLORER_API_KEY` + ] ?? + process.env.ETHERSCAN_API_KEY ?? + "" // try get chain specific api key, if not found, use etherscan api key } return acc }, From 5b5569d785f75847e02e857763e1bd654c7078db Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 4 Jun 2025 23:15:54 +0900 Subject: [PATCH 4/9] changed to VERIFICATION_API_KEY --- src/constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constant.ts b/src/constant.ts index 3264433..6ff8851 100644 --- a/src/constant.ts +++ b/src/constant.ts @@ -93,7 +93,7 @@ export const getSupportedChains = async (): Promise => { testnet: chain.testnet, explorerAPI: process.env[ - `${chain.name.toUpperCase()}_EXPLORER_API_KEY` + `${chain.name.toUpperCase()}_VERIFICATION_API_KEY` ] ?? process.env.ETHERSCAN_API_KEY ?? "" // try get chain specific api key, if not found, use etherscan api key From 9d797c00463054b649eef864735eb8b714afb110 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 4 Jun 2025 23:18:48 +0900 Subject: [PATCH 5/9] updated env example --- .env.example | 60 +++------------------------------------------------- 1 file changed, 3 insertions(+), 57 deletions(-) diff --git a/.env.example b/.env.example index 53774dd..d24bc40 100644 --- a/.env.example +++ b/.env.example @@ -2,61 +2,7 @@ PRIVATE_KEY="PRIVATE_KEY" -# Set up zerodev project id for each network you want to deploy on -# Sign up for project IDs here: https://dashboard.zerodev.app/ +ZERODEV_API_KEY="" +ZERODEV_PROJECT_ID="" -ARBITRUM_PROJECT_ID="" -ARBITRUM_NOVA_PROJECT_ID="" -ARBITRUM_SEPOLIA_PROJECT_ID="" -ASTAR_ZKEVM_PROJECT_ID="" -ASTAR_ZKYOTO_PROJECT_ID="" -AVALANCHE_PROJECT_ID="" -AVALANCHE_FUJI_PROJECT_ID="" -BASE_PROJECT_ID="" -BASE_SEPOLIA_PROJECT_ID="" -BLAST_PROJECT_ID="" -BLAST_SEPOLIA_PROJECT_ID="" -BSC_PROJECT_ID="" -CELO_PROJECT_ID="" -CELO_ALFAJORES_PROJECT_ID="" -CYBER_PROJECT_ID="" -CYBER_TESTNET_PROJECT_ID="" -DEGEN_PROJECT_ID="" -MAINNET_PROJECT_ID="" -SEPOILA_PROJECT_ID="" -OPTIMISM_PROJECT_ID="" -OPTIMISM_SEPOLIA_PROJECT_ID="" -OPBNB_PROJECT_ID="" -POLYGON_PROJECT_ID="" -POLYGON_AMOY_PROJECT_ID="" -LINEA_PROJECT_ID="" -LINEA_TESTNET_PROJECT_ID="" - -# Set up etherscan API key for each network you want to verify on - -ARBITRUM_ETHERSCAN_API_KEY="" -ARBITRUM_NOVA_ETHERSCAN_API_KEY="" -ARBITRUM_SEPOLIA_ETHERSCAN_API_KEY="" -ASTAR_ZKEVM_ETHERSCAN_API_KEY="" -ASTAR_ZKYOTO_ETHERSCAN_API_KEY="" -AVALANCHE_ETHERSCAN_API_KEY="" -AVALANCHE_FUJI_ETHERSCAN_API_KEY="" -BASE_ETHERSCAN_API_KEY="" -BASE_SEPOLIA_ETHERSCAN_API_KEY="" -BLAST_ETHERSCAN_API_KEY="" -BLAST_SEPOLIA_ETHERSCAN_API_KEY="" -BSC_ETHERSCAN_API_KEY="" -CELO_ETHERSCAN_API_KEY="" -CELO_ALFAJORES_ETHERSCAN_API_KEY="" -CYBER_ETHERSCAN_API_KEY="" -CYBER_TESTNET_ETHERSCAN_API_KEY="" -DEGEN_ETHERSCAN_API_KEY="" -MAINNET_ETHERSCAN_API_KEY="" -SEPOILA_ETHERSCAN_API_KEY="" -OPTIMISM_ETHERSCAN_API_KEY="" -OPTIMISM_SEPOLIA_ETHERSCAN_API_KEY="" -OPBNB_ETHERSCAN_API_KEY="" -POLYGON_ETHERSCAN_API_KEY="" -POLYGON_AMOY_ETHERSCAN_API_KEY="" -LINEA_ETHERSCAN_API_KEY="" -LINEA_TESTNET_ETHERSCAN_API_KEY="" \ No newline at end of file +ETHERSCAN_API_KEY="" \ No newline at end of file From 7e9c396f399210e317a09bcdf17300e161625854 Mon Sep 17 00:00:00 2001 From: leekt Date: Wed, 4 Jun 2025 23:19:44 +0900 Subject: [PATCH 6/9] updated readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bfef5e9..cb65d71 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Orchestra is a CLI for deterministically deploying contracts to multiple chains, 1. `npm install -g @zerodev/orchestra` 2. Create a `.env` file based on `.env.example` - You can acquire the project IDs from [the ZeroDev dashboard](https://dashboard.zerodev.app/) + - Use [this link](https://dashboard.zerodev.app/account/api-key) to get the API key for the team 3. Test the installation by running `zerodev -h` ## Usage From 225d12b67226ab326837edaba76ac608872443fc Mon Sep 17 00:00:00 2001 From: taek Date: Wed, 4 Jun 2025 23:24:21 +0900 Subject: [PATCH 7/9] Update src/action/verifyContracts.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/action/verifyContracts.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/action/verifyContracts.ts b/src/action/verifyContracts.ts index f2a9f5d..0ea21b9 100644 --- a/src/action/verifyContracts.ts +++ b/src/action/verifyContracts.ts @@ -24,7 +24,7 @@ async function verifyContract( ): Promise { if (!chain.explorerAPI) { throw new Error( - `Etherscan API key is not provided for ${chalk.yellowBright( + `Explorer API key is not provided for ${chalk.yellowBright( chain.name )}` ) From 677572110afe0970a83bd208132c7a2cea64e4e4 Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 5 Jun 2025 01:12:42 +0900 Subject: [PATCH 8/9] fixed chain array --- src/utils/validate.ts | 21 ++++++++++++--------- test/deployContract.test.ts | 2 +- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/utils/validate.ts b/src/utils/validate.ts index 442b99f..b6f56cc 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -108,15 +108,18 @@ export const processAndValidateChains = async ( } else if (options.allNetworks) { chains = supportedChains } else if (options.chainOption) { - const chain = supportedChains.find( - (chain) => - chain.name.toLowerCase() === options.chainOption?.toLowerCase() - ) - if (!chain) { - console.error(`Error: Chain ${options.chainOption} not found`) - process.exit(1) - } - chains = [chain] + const chainNames = options.chainOption + ? options.chainOption.split(",") + : [] + + chains = chainNames + .map((chainName) => + supportedChains.find( + (chain) => + chain.name.toLowerCase() === chainName.toLowerCase() + ) + ) + .filter((chain) => chain !== undefined) } else { console.error( "Error: At least one of -c, -t, -m, -a options must be specified" diff --git a/test/deployContract.test.ts b/test/deployContract.test.ts index 97b0405..b768783 100644 --- a/test/deployContract.test.ts +++ b/test/deployContract.test.ts @@ -15,7 +15,7 @@ test("deployContract", async () => { testnetAll : false, mainnetAll : false, allNetworks : false, - chainOption : "Sepolia" + chainOption : "Sepolia,Base Sepolia" }))[0], concat(['0x00', generatePrivateKey()]), generatePrivateKey(), From de4d004c163f1149de39a58e8ea367ae60ac9fba Mon Sep 17 00:00:00 2001 From: leekt Date: Thu, 5 Jun 2025 01:15:27 +0900 Subject: [PATCH 9/9] released v0.2.0 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f5ebf55 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# @zerodev/orchestra + +## 0.2.0 + +### Minor Changes + +- update to use zerodev v3 api diff --git a/package.json b/package.json index ead398f..be8b800 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zerodev/orchestra", - "version": "0.1.3", + "version": "0.2.0", "description": "", "main": "dist/index.js", "type": "module",