Skip to content

Commit c150d0d

Browse files
leektCopilot
andauthored
zerodev api v3 support (#15)
* lint * verification done * verification done * changed to VERIFICATION_API_KEY * updated env example * updated readme * Update src/action/verifyContracts.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fixed chain array * released v0.2.0 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4b6c476 commit c150d0d

File tree

14 files changed

+265
-416
lines changed

14 files changed

+265
-416
lines changed

.env.example

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,7 @@
22

33
PRIVATE_KEY="PRIVATE_KEY"
44

5-
# Set up zerodev project id for each network you want to deploy on
6-
# Sign up for project IDs here: https://dashboard.zerodev.app/
5+
ZERODEV_API_KEY=""
6+
ZERODEV_PROJECT_ID=""
77

8-
ARBITRUM_PROJECT_ID=""
9-
ARBITRUM_NOVA_PROJECT_ID=""
10-
ARBITRUM_SEPOLIA_PROJECT_ID=""
11-
ASTAR_ZKEVM_PROJECT_ID=""
12-
ASTAR_ZKYOTO_PROJECT_ID=""
13-
AVALANCHE_PROJECT_ID=""
14-
AVALANCHE_FUJI_PROJECT_ID=""
15-
BASE_PROJECT_ID=""
16-
BASE_SEPOLIA_PROJECT_ID=""
17-
BLAST_PROJECT_ID=""
18-
BLAST_SEPOLIA_PROJECT_ID=""
19-
BSC_PROJECT_ID=""
20-
CELO_PROJECT_ID=""
21-
CELO_ALFAJORES_PROJECT_ID=""
22-
CYBER_PROJECT_ID=""
23-
CYBER_TESTNET_PROJECT_ID=""
24-
DEGEN_PROJECT_ID=""
25-
MAINNET_PROJECT_ID=""
26-
SEPOILA_PROJECT_ID=""
27-
OPTIMISM_PROJECT_ID=""
28-
OPTIMISM_SEPOLIA_PROJECT_ID=""
29-
OPBNB_PROJECT_ID=""
30-
POLYGON_PROJECT_ID=""
31-
POLYGON_AMOY_PROJECT_ID=""
32-
LINEA_PROJECT_ID=""
33-
LINEA_TESTNET_PROJECT_ID=""
34-
35-
# Set up etherscan API key for each network you want to verify on
36-
37-
ARBITRUM_ETHERSCAN_API_KEY=""
38-
ARBITRUM_NOVA_ETHERSCAN_API_KEY=""
39-
ARBITRUM_SEPOLIA_ETHERSCAN_API_KEY=""
40-
ASTAR_ZKEVM_ETHERSCAN_API_KEY=""
41-
ASTAR_ZKYOTO_ETHERSCAN_API_KEY=""
42-
AVALANCHE_ETHERSCAN_API_KEY=""
43-
AVALANCHE_FUJI_ETHERSCAN_API_KEY=""
44-
BASE_ETHERSCAN_API_KEY=""
45-
BASE_SEPOLIA_ETHERSCAN_API_KEY=""
46-
BLAST_ETHERSCAN_API_KEY=""
47-
BLAST_SEPOLIA_ETHERSCAN_API_KEY=""
48-
BSC_ETHERSCAN_API_KEY=""
49-
CELO_ETHERSCAN_API_KEY=""
50-
CELO_ALFAJORES_ETHERSCAN_API_KEY=""
51-
CYBER_ETHERSCAN_API_KEY=""
52-
CYBER_TESTNET_ETHERSCAN_API_KEY=""
53-
DEGEN_ETHERSCAN_API_KEY=""
54-
MAINNET_ETHERSCAN_API_KEY=""
55-
SEPOILA_ETHERSCAN_API_KEY=""
56-
OPTIMISM_ETHERSCAN_API_KEY=""
57-
OPTIMISM_SEPOLIA_ETHERSCAN_API_KEY=""
58-
OPBNB_ETHERSCAN_API_KEY=""
59-
POLYGON_ETHERSCAN_API_KEY=""
60-
POLYGON_AMOY_ETHERSCAN_API_KEY=""
61-
LINEA_ETHERSCAN_API_KEY=""
62-
LINEA_TESTNET_ETHERSCAN_API_KEY=""
8+
ETHERSCAN_API_KEY=""

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# @zerodev/orchestra
2+
3+
## 0.2.0
4+
5+
### Minor Changes
6+
7+
- update to use zerodev v3 api

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Orchestra is a CLI for deterministically deploying contracts to multiple chains,
77
1. `npm install -g @zerodev/orchestra`
88
2. Create a `.env` file based on `.env.example`
99
- You can acquire the project IDs from [the ZeroDev dashboard](https://dashboard.zerodev.app/)
10+
- Use [this link](https://dashboard.zerodev.app/account/api-key) to get the API key for the team
1011
3. Test the installation by running `zerodev -h`
1112

1213
## Usage

bun.lockb

5.52 KB
Binary file not shown.

package.json

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@zerodev/orchestra",
3-
"version": "0.1.3",
3+
"version": "0.2.0",
44
"description": "",
55
"main": "dist/index.js",
66
"type": "module",
@@ -43,29 +43,30 @@
4343
],
4444
"license": "MIT",
4545
"dependencies": {
46-
"@zerodev/ecdsa-validator": "^5.4.0",
47-
"@zerodev/sdk": "^5.4.3",
46+
"@zerodev/ecdsa-validator": "^5.4.9",
47+
"@zerodev/sdk": "^5.4.36",
4848
"chalk": "4.1.2",
49-
"cli-table3": "^0.6.3",
49+
"cli-table3": "^0.6.5",
5050
"commander": "^11.1.0",
51-
"dotenv": "^16.3.1",
52-
"figlet": "^1.7.0",
53-
"ora": "^8.0.1",
54-
"tslib": "^2.6.2"
51+
"dotenv": "^16.5.0",
52+
"figlet": "^1.8.1",
53+
"ora": "^8.2.0",
54+
"tslib": "^2.8.1",
55+
"viem": "^2.30.6"
5556
},
5657
"devDependencies": {
57-
"@biomejs/biome": "^1.4.1",
58+
"@biomejs/biome": "^1.9.4",
5859
"@changesets/changelog-git": "^0.1.14",
5960
"@changesets/changelog-github": "^0.4.8",
60-
"@changesets/cli": "^2.27.1",
61+
"@changesets/cli": "^2.29.4",
6162
"@size-limit/esbuild-why": "^9.0.0",
6263
"@size-limit/preset-small-lib": "^9.0.0",
63-
"@types/figlet": "^1.5.8",
64-
"@types/node": "^18.19.4",
64+
"@types/figlet": "^1.7.0",
65+
"@types/node": "^18.19.110",
6566
"@types/ora": "^3.2.0",
66-
"simple-git-hooks": "^2.9.0",
67+
"simple-git-hooks": "^2.13.0",
6768
"ts-node": "^10.9.2",
68-
"typescript": "^5.2.2"
69+
"typescript": "^5.8.3"
6970
},
7071
"simple-git-hooks": {
7172
"pre-commit": "bun run format && bun run lint"

src/action/deployContracts.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import ora from "ora"
33
import type { Address, Hex } from "viem"
44
import { http, createPublicClient, getAddress } from "viem"
55
import { createKernelClient, getZeroDevBundlerRPC } from "../clients/index.js"
6-
import { type Chain, DEPLOYER_CONTRACT_ADDRESS } from "../constant.js"
6+
import { DEPLOYER_CONTRACT_ADDRESS, type ZerodevChain } from "../constant.js"
77
import { ensureHex, writeErrorLogToFile } from "../utils/index.js"
88
import { computeContractAddress } from "./computeAddress.js"
99
import { DeploymentStatus, checkDeploymentOnChain } from "./findDeployment.js"
@@ -21,15 +21,15 @@ type DeployResult = [string, string]
2121

2222
export const deployToChain = async (
2323
privateKey: Hex,
24-
chain: Chain,
24+
chain: ZerodevChain,
2525
bytecode: Hex,
2626
salt: Hex,
2727
expectedAddress: string | undefined,
2828
callGasLimit: bigint | undefined
2929
): Promise<DeployResult> => {
3030
const publicClient = createPublicClient({
31-
chain: chain.viemChainObject,
32-
transport: http(getZeroDevBundlerRPC(chain.projectId))
31+
chain: chain,
32+
transport: http()
3333
})
3434
const kernelAccountClient = await createKernelClient(privateKey, chain)
3535

@@ -86,20 +86,28 @@ export const deployToChain = async (
8686
])
8787
})
8888

89+
await kernelAccountClient.waitForUserOperationReceipt({
90+
hash: opHash
91+
})
92+
await kernelAccountClient.getUserOperationReceipt({
93+
hash: opHash
94+
})
95+
8996
return [getAddress(result.data as Address), opHash]
9097
}
9198

9299
export const deployContracts = async (
93100
privateKey: Hex,
94101
bytecode: Hex,
95-
chains: Chain[],
102+
chains: ZerodevChain[],
96103
salt: Hex,
97104
expectedAddress: string | undefined,
98105
callGasLimit: bigint | undefined
99106
) => {
100107
const spinner = ora(
101108
`Deploying contract on ${chains.map((chain) => chain.name).join(", ")}`
102109
).start()
110+
let anyError = false
103111
const deployments = chains.map(async (chain) => {
104112
return deployToChain(
105113
privateKey,
@@ -130,6 +138,7 @@ export const deployContracts = async (
130138
)
131139
} else {
132140
writeErrorLogToFile(chain.name, error)
141+
anyError = true
133142
spinner.fail(
134143
`Deployment for ${chalk.redBright(
135144
chain.name
@@ -141,5 +150,10 @@ export const deployContracts = async (
141150

142151
await Promise.allSettled(deployments)
143152
spinner.stop()
144-
console.log("✅ All deployments process successfully finished!")
153+
if (anyError) {
154+
console.log("❌ Some deployments failed!")
155+
process.exit(1)
156+
} else {
157+
console.log("✅ All deployments process successfully finished!")
158+
}
145159
}

src/action/findDeployment.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { Address, Hex, PublicClient } from "viem"
22
import { http, createPublicClient } from "viem"
33
import { getZeroDevBundlerRPC } from "../clients/index.js"
4-
import { type Chain, DEPLOYER_CONTRACT_ADDRESS } from "../constant.js"
4+
import { DEPLOYER_CONTRACT_ADDRESS, type ZerodevChain } from "../constant.js"
55
import { computeContractAddress } from "./computeAddress.js"
66
export enum DeploymentStatus {
77
Deployed = 0,
@@ -29,12 +29,12 @@ export const checkDeploymentOnChain = async (
2929
export const findDeployment = async (
3030
bytecode: Hex,
3131
salt: Hex,
32-
chains: Chain[]
32+
chains: ZerodevChain[]
3333
): Promise<{
3434
address: Address
35-
deployedChains: Chain[]
36-
notDeployedChains: Chain[]
37-
errorChains?: Chain[]
35+
deployedChains: ZerodevChain[]
36+
notDeployedChains: ZerodevChain[]
37+
errorChains?: ZerodevChain[]
3838
}> => {
3939
const address = computeContractAddress(
4040
DEPLOYER_CONTRACT_ADDRESS,
@@ -46,7 +46,8 @@ export const findDeployment = async (
4646
chains.map((chain) => {
4747
return checkDeploymentOnChain(
4848
createPublicClient({
49-
transport: http(getZeroDevBundlerRPC(chain.projectId))
49+
chain: chain,
50+
transport: http()
5051
}),
5152
address
5253
).catch(() => DeploymentStatus.Error)

src/action/verifyContracts.ts

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import util from "node:util"
33
import chalk from "chalk"
44
import ora from "ora"
55
import type { Address } from "viem"
6-
import type { Chain } from "../constant.js"
6+
import type { ZerodevChain } from "../constant.js"
77

88
const execPromise = util.promisify(exec)
99

@@ -20,31 +20,16 @@ async function checkForgeAvailability() {
2020
async function verifyContract(
2121
contractName: string,
2222
contractAddress: Address,
23-
chain: Chain
23+
chain: ZerodevChain
2424
): Promise<string> {
25-
if (
26-
!chain.etherscanApiKey &&
27-
chain.name !== "avalanche" &&
28-
chain.name !== "avalanche-fuji" &&
29-
chain.name !== "opbnb" &&
30-
chain.name !== "astar-zkatana"
31-
) {
25+
if (!chain.explorerAPI) {
3226
throw new Error(
33-
`Etherscan API key is not provided for ${chalk.yellowBright(
27+
`Explorer API key is not provided for ${chalk.yellowBright(
3428
chain.name
3529
)}`
3630
)
3731
}
38-
39-
if (["opbnb", "astar-zkatana"].includes(chain.name)) {
40-
throw new Error(
41-
`Verification is not supported on ${chalk.yellowBright(chain.name)}`
42-
)
43-
}
44-
45-
const effectiveChainName =
46-
chain.name === "linea-testnet" ? "linea-goerli" : chain.name
47-
const command = `forge verify-contract -c ${effectiveChainName} ${contractAddress} ${contractName} -e ${chain.etherscanApiKey}`
32+
const command = `forge verify-contract --chain ${chain.id} --verifier etherscan ${contractAddress} ${contractName} -e ${chain.explorerAPI} -a v2`
4833

4934
try {
5035
const { stdout, stderr } = await execPromise(command)
@@ -69,12 +54,11 @@ async function verifyContract(
6954
export const verifyContracts = async (
7055
contractName: string,
7156
contractAddress: Address,
72-
chains: Chain[]
57+
chains: ZerodevChain[]
7358
) => {
7459
await checkForgeAvailability()
75-
7660
const spinner = ora().start("Verifying contracts...")
77-
61+
let anyError = false
7862
const verificationPromises = chains.map((chain) =>
7963
verifyContract(contractName, contractAddress, chain)
8064
.then((message) => {
@@ -85,18 +69,22 @@ export const verifyContracts = async (
8569
}
8670
})
8771
.catch((error) => {
88-
ora()
72+
anyError = true
73+
return ora()
8974
.fail(
9075
`Verification failed on ${chain.name}: ${error.message}`
9176
)
9277
.start()
9378
.stop()
9479
})
9580
)
96-
9781
// Wait for all verifications to complete
9882
await Promise.all(verificationPromises)
99-
10083
spinner.stop()
101-
console.log("✅ All verifications process successfully finished!")
84+
if (anyError) {
85+
console.log("❌ Some verifications failed!")
86+
process.exit(1)
87+
} else {
88+
console.log("✅ All verifications process successfully finished!")
89+
}
10290
}

src/clients/createKernelClient.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,26 @@ import {
55
createKernelAccountClient,
66
createZeroDevPaymasterClient
77
} from "@zerodev/sdk"
8+
import { getUserOperationGasPrice } from "@zerodev/sdk"
89
import { KERNEL_V3_1, getEntryPoint } from "@zerodev/sdk/constants"
910
import type { Hex } from "viem"
11+
1012
import { http, createPublicClient } from "viem"
1113
import { privateKeyToAccount } from "viem/accounts"
12-
import type { Chain } from "../constant.js"
14+
import type { ZerodevChain } from "../constant.js"
1315
import { getZeroDevBundlerRPC, getZeroDevPaymasterRPC } from "./index.js"
1416

1517
export const createKernelClient = async (
1618
privateKey: Hex,
17-
chain: Chain
19+
chain: ZerodevChain
1820
): Promise<KernelAccountClient> => {
19-
const rpcUrl = getZeroDevBundlerRPC(chain.projectId, "PIMLICO")
20-
const paymasterRpcUrl = getZeroDevPaymasterRPC(chain.projectId, "PIMLICO")
21+
const rpcUrl = getZeroDevBundlerRPC(chain.id, "PIMLICO")
22+
const paymasterRpcUrl = getZeroDevPaymasterRPC(chain.id, "PIMLICO")
2123
const entryPoint = getEntryPoint("0.7")
24+
2225
const publicClient = createPublicClient({
23-
transport: http(rpcUrl),
24-
chain: chain.viemChainObject
26+
chain: chain,
27+
transport: http(chain.rpcUrls.default.http[0])
2528
})
2629
const signer = privateKeyToAccount(privateKey)
2730

@@ -41,13 +44,14 @@ export const createKernelClient = async (
4144
})
4245

4346
const zerodevPaymaster = createZeroDevPaymasterClient({
44-
chain: chain.viemChainObject,
47+
chain: chain,
4548
transport: http(paymasterRpcUrl)
4649
})
4750
// Construct a Kernel account client
4851
const kernelClient = createKernelAccountClient({
49-
account,
50-
chain: chain.viemChainObject,
52+
account: account,
53+
client: publicClient,
54+
chain: chain,
5155
bundlerTransport: http(rpcUrl),
5256
paymaster: {
5357
getPaymasterData(userOperation) {

0 commit comments

Comments
 (0)