mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 01:38:32 +00:00
## Summary - **Add `--environment` option to `contracts upgrade` command**, aligning it with `deploy`, `verify`, and other contracts subcommands. Deployment file lookups now use `buildNetworkId(chain, environment)` (e.g. `stagenet-hoodi.json`). - **Fix ProxyAdmin address written as `address(0)` in deployment JSON for live deployments.** `_createServiceManagerProxy` now returns the actual ProxyAdmin so it propagates to `_outputDeployedAddresses`. - **Fix ProxyAdmin ownership transfer using wrong address in `DeployLive`.** `transferOwnership` now uses `params.avsOwner` (from `AVS_OWNER_ADDRESS`) instead of `_avsOwner` (from `AVS_OWNER_PRIVATE_KEY` with Anvil default fallback). - **Add ProxyAdmin to the `contracts verify` list** so it is verified on block explorers. - **Log AVS owner address** before the proxy upgrade transaction for signer verification. - **Handle forge receipt-fetch failures gracefully** during proxy upgrades — downgrade to a warning with the tx hash instead of a hard error when the RPC returns null for a receipt. ## Stagenet upgrade to v0.20.0 AVS contracts were upgraded to version v0.20.0 on Stagenet (Hoodi). Updated contract addresses: | Contract | Address | |---|---| | ServiceManager (Proxy) | `0xED73cCaF067cebC706B2B3a6cf2b9af2c696c6d3` | | ServiceManagerImplementation | `0x0Af4a129D0F3d57B5bD51CAB323EA114C28c064a` | | ProxyAdmin | `0xeb1a705e1aa96e6a6329d8a8eb0f5ec38eb7b69d` | | BeefyClient | `0xE65dc4eCA2Fd428361076e1f204731224CeB4292` | | AgentExecutor | `0x35d3FdCB19A246a1763421168dF69dA3dE207063` | | Gateway | `0xE9352f1488F12bFEd722c133C129ca5F467463d1` | | RewardsAgent | `0x2E039a88838241d1Ac738cf2e3C5763ba12571e7` | | DelegationManager | `0x867837a9722C512e0862d8c2E15b8bE220E8b87d` | | StrategyManager | `0xeE45e76ddbEDdA2918b8C7E3035cd37Eab3b5D41` | | AVSDirectory | `0xD58f6844f79eB1fbd9f7091d05f7cb30d3363926` | | RewardsCoordinator | `0x29e8572678e0c272350aa0b4B8f304E47EBcd5e7` | | AllocationManager | `0x95a7431400F362F3647a69535C5666cA0133CAA0` | | PermissionController | `0xdcCF401fD121d8C542E96BC1d0078884422aFAD2` | Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
487 lines
20 KiB
TypeScript
487 lines
20 KiB
TypeScript
#!/usr/bin/env bun
|
|
import { Command, InvalidArgumentError } from "@commander-js/extra-typings";
|
|
import type { DeployEnvironment } from "utils";
|
|
import { logger, printHeader } from "utils";
|
|
import {
|
|
contractsCheck,
|
|
contractsChecks,
|
|
contractsDeploy,
|
|
contractsPreActionHook,
|
|
contractsUpdateBeefyCheckpoint,
|
|
contractsUpdateRewardsOrigin,
|
|
contractsUpgrade,
|
|
contractsVerify,
|
|
deploy,
|
|
deployPreActionHook,
|
|
launch,
|
|
launchPreActionHook,
|
|
stop,
|
|
stopPreActionHook,
|
|
updateAVSMetadataURI,
|
|
versioningPostChecks
|
|
} from "./handlers";
|
|
|
|
// Function to parse integer
|
|
function parseIntValue(value: string): number {
|
|
const parsedValue = Number.parseInt(value, 10);
|
|
if (Number.isNaN(parsedValue)) {
|
|
throw new InvalidArgumentError("Not a number.");
|
|
}
|
|
return parsedValue;
|
|
}
|
|
|
|
// Function to parse and validate DeployEnvironment
|
|
function parseDeployEnvironment(value: string): DeployEnvironment {
|
|
if (value === "local" || value === "stagenet" || value === "testnet" || value === "mainnet") {
|
|
return value;
|
|
}
|
|
throw new InvalidArgumentError(
|
|
"Invalid environment. Must be one of 'local', 'stagenet', 'testnet', or 'mainnet'."
|
|
);
|
|
}
|
|
|
|
// ===== Program =====
|
|
const program = new Command()
|
|
.version("0.2.0")
|
|
.name("bun cli")
|
|
.summary("🫎 DataHaven CLI: Network Toolbox")
|
|
.usage("[options]");
|
|
|
|
// ===== Deploy ======
|
|
program
|
|
.command("deploy")
|
|
.addHelpText(
|
|
"before",
|
|
`🫎 DataHaven: Network Deployer CLI for deploying a full DataHaven network stack to a Kubernetes cluster
|
|
It will deploy:
|
|
- DataHaven solochain validators (all envs),
|
|
- StorageHub components: MSP, BSP, Indexer, Fisherman nodes and databases (local & stagenet envs),
|
|
- Kurtosis Ethereum private network (stagenet env),
|
|
- Snowbridge Relayers (all envs)
|
|
`
|
|
)
|
|
.description("Deploy a full DataHaven network stack to a Kubernetes cluster")
|
|
.option("--e, --environment <value>", "Environment to deploy to", parseDeployEnvironment, "local")
|
|
.option(
|
|
"--k, --kube-namespace <value>",
|
|
"Kubernetes namespace to deploy to. In 'stagenet' this parameter is ignored and the Kurtosis namespace is used instead. Default will be `datahaven-<environment>`."
|
|
)
|
|
.option(
|
|
"--ke, --kurtosis-enclave-name <value>",
|
|
"Name of the Kurtosis enclave",
|
|
"datahaven-local"
|
|
)
|
|
.option("--st, --slot-time <number>", "Set slot time in seconds", parseIntValue, 12)
|
|
.option("--kn, --kurtosis-network-args <value>", "CustomKurtosis network args")
|
|
.option("--v, --verified", "Verify smart contracts with Blockscout")
|
|
.option("--b, --blockscout", "Enable Blockscout")
|
|
.option(
|
|
"--dit, --datahaven-image-tag <value>",
|
|
"Tag of the datahaven image to use",
|
|
"datahavenxyz/datahaven:main"
|
|
)
|
|
.option(
|
|
"--el-rpc-url <value>",
|
|
"URL of the Ethereum Execution Layer (EL) RPC endpoint to use. In local & stagenet environments (private networks), the Kurtosis Ethereum network will be used. In testnet and mainnet environments (public networks), this parameter is required."
|
|
)
|
|
.option(
|
|
"--cl-endpoint <value>",
|
|
"URL of the Ethereum Consensus Layer (CL) endpoint to use. In local & stagenet environments (private networks), the Kurtosis Ethereum network will be used. In testnet and mainnet environments (public networks), this parameter is required."
|
|
)
|
|
.option(
|
|
"--rit, --relayer-image-tag <value>",
|
|
"Tag of the relayer image to use",
|
|
"datahavenxyz/snowbridge-relay:latest"
|
|
)
|
|
.option("--docker-username <value>", "Docker Hub username")
|
|
.option("--docker-password <value>", "Docker Hub password")
|
|
.option("--docker-email <value>", "Docker Hub email")
|
|
.option("--chainspec <value>", "Absolute path to custom chainspec file")
|
|
.option("--skip-cleanup", "Skip cleaning up the network", false)
|
|
.option("--skip-kurtosis", "Skip deploying Kurtosis Ethereum private network", false)
|
|
.option("--skip-datahaven-solochain", "Skip deploying DataHaven solochain validators", false)
|
|
.option("--skip-contracts", "Skip deploying smart contracts", false)
|
|
.option("--skip-validator-operations", "Skip performing validator operations", false)
|
|
.option("--skip-set-parameters", "Skip setting DataHaven runtime parameters", false)
|
|
.option("--skip-relayers", "Skip deploying Snowbridge Relayers", false)
|
|
.option(
|
|
"--skip-storage-hub",
|
|
"Skip deploying StorageHub components (MSP, BSP, Indexer, Fisherman, databases)",
|
|
false
|
|
)
|
|
.hook("preAction", deployPreActionHook)
|
|
.action(deploy);
|
|
|
|
// ===== Launch ======
|
|
program
|
|
.command("launch")
|
|
.addHelpText(
|
|
"before",
|
|
`🫎 DataHaven: Network Launcher CLI for launching a full DataHaven network.
|
|
Complete with:
|
|
- Solo-chain validators,
|
|
- StorageHub components: MSP, BSP, Indexer, Fisherman nodes and databases,
|
|
- Ethereum Private network,
|
|
- Snowbridge Relayers
|
|
`
|
|
)
|
|
.description("Launch a full E2E DataHaven & Ethereum network and more")
|
|
.option("--A, --all", "Launch all components without prompting")
|
|
.option("--d, --datahaven", "(Re)Launch DataHaven network")
|
|
.option("--nd, --no-datahaven", "Skip launching DataHaven network")
|
|
.option("--bd, --build-datahaven", "Build DataHaven node local Docker image")
|
|
.option("--nbd, --no-build-datahaven", "Skip building DataHaven node local Docker image")
|
|
.option("--lk, --launch-kurtosis", "Launch Kurtosis Ethereum network with EL and CL clients")
|
|
.option("--nlk, --no-launch-kurtosis", "Skip launching Kurtosis Ethereum network")
|
|
.option("--dc, --deploy-contracts", "Deploy smart contracts")
|
|
.option("--ndc, --no-deploy-contracts", "Skip deploying smart contracts")
|
|
.option("--fv, --fund-validators", "Fund validators")
|
|
.option("--nfv, --no-fund-validators", "Skip funding validators")
|
|
.option("--sv, --setup-validators", "Setup validators")
|
|
.option("--nsv, --no-setup-validators", "Skip setup validators")
|
|
.option("--uv, --update-validator-set", "Update validator set")
|
|
.option("--nuv, --no-update-validator-set", "Skip update validator set")
|
|
.option("--sp, --set-parameters", "Set DataHaven runtime parameters")
|
|
.option("--nsp, --no-set-parameters", "Skip setting DataHaven runtime parameters")
|
|
.option("--r, --relayer", "Launch Snowbridge Relayers")
|
|
.option("--nr, --no-relayer", "Skip Snowbridge Relayers")
|
|
.option("--sh, --storagehub", "Launch StorageHub components")
|
|
.option("--nsh, --no-storagehub", "Skip launching StorageHub components")
|
|
.option("--b, --blockscout", "Enable Blockscout")
|
|
.option("--slot-time <number>", "Set slot time in seconds", parseIntValue)
|
|
.option("--cn, --clean-network", "Always clean Kurtosis enclave and Docker containers")
|
|
.option(
|
|
"--ic, --inject-contracts",
|
|
"Inject pre-deployed contracts from state-diff.json into Kurtosis network",
|
|
true
|
|
)
|
|
.option(
|
|
"--nic, --no-inject-contracts",
|
|
"Deploy contracts instead of injecting from state-diff.json"
|
|
)
|
|
.option(
|
|
"--datahaven-build-extra-args <value>",
|
|
"Extra args for DataHaven node Cargo build (the plain command is `cargo build --release` for linux, `cargo zigbuild --target x86_64-unknown-linux-gnu --release` for mac)",
|
|
"--features=fast-runtime"
|
|
)
|
|
.option(
|
|
"--e --kurtosis-enclave-name <value>",
|
|
"Name of the Kurtosis Enclave",
|
|
"datahaven-ethereum"
|
|
)
|
|
.option("--kurtosis-network-args <value>", "CustomKurtosis network args")
|
|
.option("--verified", "Verify smart contracts with Blockscout")
|
|
.option(
|
|
"--dit, --datahaven-image-tag <value>",
|
|
"Tag of the datahaven image to use",
|
|
"datahavenxyz/datahaven:local"
|
|
)
|
|
.option(
|
|
"--rit, --relayer-image-tag <value>",
|
|
"Tag of the relayer",
|
|
"datahavenxyz/snowbridge-relay:latest"
|
|
)
|
|
.hook("preAction", launchPreActionHook)
|
|
.action(launch);
|
|
|
|
// ===== Stop ======
|
|
program
|
|
.command("stop")
|
|
.description("Stop any launched running network components")
|
|
.option("--A --all", "Stop all components associated with project")
|
|
.option("--d, --datahaven", "Stop DataHaven network")
|
|
.option("--nd, --no-datahaven", "Skip stopping DataHaven network")
|
|
.option("--e, --enclave", "Stop Ethereum Kurtosis enclave")
|
|
.option("--ne, --no-enclave", "Skip stopping Ethereum Kurtosis enclave")
|
|
.option("--kurtosis-engine", "Stop Kurtosis engine", false)
|
|
.option("--r, --relayer", "Stop Snowbridge Relayers")
|
|
.option("--nr, --no-relayer", "Skip stopping Snowbridge Relayers")
|
|
.hook("preAction", stopPreActionHook)
|
|
.action(stop);
|
|
|
|
// ===== Contracts ======
|
|
const contractsCommand = program
|
|
.command("contracts")
|
|
.addHelpText(
|
|
"before",
|
|
`🫎 DataHaven: Contracts Deployment CLI for deploying DataHaven AVS contracts to supported chains
|
|
|
|
Commands:
|
|
- status: Show deployment plan, configuration, and status (default)
|
|
- deploy: Deploy contracts to specified chain
|
|
- upgrade: Upgrade contracts by deploying new implementations
|
|
- verify: Verify deployed contracts on block explorer
|
|
- update-beefy-checkpoint: Fetch BEEFY authorities from a live chain and update config
|
|
- update-rewards-origin: Fetch or compute the AgentOrigin and update config
|
|
- update-metadata: Update the metadata URI of an existing AVS contract
|
|
|
|
Common options:
|
|
--chain: Target chain (required: hoodi, ethereum, anvil)
|
|
--environment: Deployment environment (stagenet, testnet, mainnet)
|
|
When specified, config files are read from {environment}-{chain}.json
|
|
and deployments are written to {environment}-{chain}.json
|
|
--rpc-url: Chain RPC URL (optional, defaults based on chain)
|
|
--private-key: Private key for deployment
|
|
--skip-verification: Skip contract verification
|
|
|
|
Versioning:
|
|
- contracts/VERSION is the single source of truth for the code version and must be updated in source control.
|
|
- bun cli contracts upgrade --target X.Y.Z upgrades on-chain to that version WITHOUT writing to contracts/VERSION.
|
|
- Omit --target to use the current contracts/VERSION value (the common case after bumping the file in a commit).
|
|
|
|
Upgrade dry-run (production default):
|
|
- bun cli contracts upgrade --chain hoodi --target X.Y.Z
|
|
Deploys the new implementation, then prints the ProxyAdmin.upgradeAndCall calldata
|
|
for the multisig team to execute manually. No AVS owner key required.
|
|
- bun cli contracts upgrade --chain hoodi --target X.Y.Z --execute
|
|
Full on-chain upgrade: deploys the implementation AND broadcasts the proxy upgrade
|
|
+ version update transaction. Requires AVS_OWNER_PRIVATE_KEY.
|
|
`
|
|
)
|
|
.description("Deploy and manage DataHaven AVS contracts on supported chains");
|
|
|
|
// Contracts Check (default)
|
|
contractsCommand
|
|
.command("status")
|
|
.description("Show deployment plan, configuration, and status")
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.option(
|
|
"--private-key <value>",
|
|
"Private key for deployment",
|
|
process.env.DEPLOYER_PRIVATE_KEY || ""
|
|
)
|
|
.option("--skip-verification", "Skip contract verification", false)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(contractsCheck);
|
|
|
|
// Contracts Deploy
|
|
contractsCommand
|
|
.command("deploy")
|
|
.description("Deploy DataHaven AVS contracts to specified chain")
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.option(
|
|
"--private-key <value>",
|
|
"Private key for deployment",
|
|
process.env.DEPLOYER_PRIVATE_KEY || ""
|
|
)
|
|
.option("--avs-owner-address <value>", "Address to set as AVS owner (required for non-local)")
|
|
.option("--avs-owner-key <value>", "Private key for the AVS owner (hex string)")
|
|
.option(
|
|
"--execute-owner-transactions",
|
|
"Execute AVS owner transactions immediately (tx execution on)"
|
|
)
|
|
.option("--skip-verification", "Skip contract verification", false)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(contractsDeploy);
|
|
|
|
// Contracts Upgrade
|
|
contractsCommand
|
|
.command("upgrade")
|
|
.description("Upgrade DataHaven AVS contracts by deploying new implementations")
|
|
.option("--chain <value>", "Target chain (hoodi, mainnet, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.option("--private-key-file <value>", "Path to file containing private key for deployment")
|
|
.option("--verify", "Verify upgraded contracts on block explorer", false)
|
|
.option(
|
|
"--target <value>",
|
|
"Version to upgrade to (X.Y.Z). Omit to use the current contracts/VERSION value. Does NOT write to contracts/VERSION — update that file in source control separately."
|
|
)
|
|
.option(
|
|
"--execute",
|
|
"Execute the proxy upgrade transaction on-chain. Without this flag the command outputs the calldata for manual multisig execution (dry-run mode).",
|
|
false
|
|
)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(async (options: any, command: any) => {
|
|
// Try to get chain and environment from options or parent command
|
|
let chain = options.chain;
|
|
if (!chain && command.parent) {
|
|
chain = command.parent.getOptionValue("chain");
|
|
}
|
|
if (!chain) {
|
|
chain = command.getOptionValue("chain");
|
|
}
|
|
|
|
let environment = options.environment;
|
|
if (!environment && command.parent) {
|
|
environment = command.parent.getOptionValue("environment");
|
|
}
|
|
|
|
const displayName = environment ? `${environment}-${chain}` : chain;
|
|
printHeader(`Upgrading DataHaven Contracts on ${displayName}`);
|
|
|
|
try {
|
|
await contractsUpgrade({
|
|
chain: chain,
|
|
environment: environment,
|
|
rpcUrl: options.rpcUrl,
|
|
privateKeyFile: options.privateKeyFile,
|
|
verify: options.verify,
|
|
version: options.target,
|
|
execute: options.execute
|
|
});
|
|
|
|
if (options.execute) {
|
|
await versioningPostChecks({
|
|
chain,
|
|
rpcUrl: options.rpcUrl
|
|
});
|
|
}
|
|
} catch (error) {
|
|
logger.error(`❌ Upgrade failed: ${error}`);
|
|
}
|
|
});
|
|
|
|
// Contracts Version Check
|
|
contractsCommand
|
|
.command("version-check")
|
|
.description("Run contract version checks")
|
|
.option("--chain <value>", "Target chain (hoodi, mainnet, anvil)")
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(contractsChecks);
|
|
|
|
// Contracts Verify
|
|
contractsCommand
|
|
.command("verify")
|
|
.description("Verify deployed contracts on block explorer")
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.option("--skip-verification", "Skip contract verification", false)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(contractsVerify);
|
|
|
|
// Contracts Update BEEFY Checkpoint
|
|
contractsCommand
|
|
.command("update-beefy-checkpoint")
|
|
.description(
|
|
"Fetch BEEFY authorities from a live DataHaven chain and update the config file with validator hashes"
|
|
)
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option(
|
|
"--rpc-url <value>",
|
|
"WebSocket RPC URL of the DataHaven chain to fetch BEEFY authorities from"
|
|
)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(async (_options: any, command: any) => {
|
|
// Options are captured by parent command due to shared option names
|
|
// Use optsWithGlobals() to get all options including inherited ones
|
|
const opts = command.optsWithGlobals();
|
|
await contractsUpdateBeefyCheckpoint(opts, command);
|
|
});
|
|
|
|
// Contracts Update Rewards Origin
|
|
contractsCommand
|
|
.command("update-rewards-origin")
|
|
.description(
|
|
"Fetch or compute the AgentOrigin and update the config file with the rewards message origin"
|
|
)
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--rpc-url <value>", "WebSocket RPC URL of the DataHaven chain to fetch AgentOrigin from")
|
|
.option(
|
|
"--genesis-hash <value>",
|
|
"Chain genesis hash (32 bytes hex). If not provided, will be fetched from the chain."
|
|
)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(async (_options: any, command: any) => {
|
|
const opts = command.optsWithGlobals();
|
|
await contractsUpdateRewardsOrigin(opts, command);
|
|
});
|
|
|
|
// Contracts Update Metadata
|
|
contractsCommand
|
|
.command("update-metadata")
|
|
.description("Update AVS metadata URI for the DataHaven Service Manager")
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--uri <value>", "New metadata URI (required)")
|
|
.option("--reset", "Use if you want to reset the metadata URI")
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.option("--avs-owner-key <value>", "Private key for the AVS owner (hex string)")
|
|
.option("--execute", "Execute transaction immediately instead of emitting calldata", false)
|
|
.action(async (options: any, command: any) => {
|
|
// Try to get chain from options or command
|
|
let chain = options.chain;
|
|
if (!chain && command.parent) {
|
|
chain = command.parent.getOptionValue("chain");
|
|
}
|
|
if (!chain) {
|
|
chain = command.getOptionValue("chain");
|
|
}
|
|
if (!options.uri && !options.reset) {
|
|
throw new Error("--uri parameter is required");
|
|
}
|
|
if (options.reset) {
|
|
options.uri = "";
|
|
}
|
|
if (!chain) {
|
|
throw new Error("--chain parameter is required");
|
|
}
|
|
let environment = options.environment;
|
|
if (!environment && command.parent) {
|
|
environment = command.parent.getOptionValue("environment");
|
|
}
|
|
await updateAVSMetadataURI(chain, options.uri, {
|
|
execute: options.execute,
|
|
avsOwnerKey: options.avsOwnerKey,
|
|
environment
|
|
});
|
|
});
|
|
|
|
// Default Contracts command (runs check when no subcommand is specified)
|
|
// preAction hook on subcommands handles validation before the action runs
|
|
contractsCommand
|
|
.description("Show deployment plan, configuration, and status")
|
|
.option("--chain <value>", "Target chain (hoodi, ethereum, anvil)")
|
|
.option(
|
|
"--environment <value>",
|
|
"Deployment environment (stagenet, testnet, mainnet). Config and deployment files will be prefixed with this value."
|
|
)
|
|
.option("--rpc-url <value>", "Chain RPC URL (optional, defaults based on chain)")
|
|
.option(
|
|
"--private-key <value>",
|
|
"Private key for deployment",
|
|
process.env.DEPLOYER_PRIVATE_KEY || ""
|
|
)
|
|
.option("--skip-verification", "Skip contract verification", false)
|
|
.hook("preAction", contractsPreActionHook)
|
|
.action(async (options: any, command: any) => {
|
|
await contractsCheck(options, command);
|
|
});
|
|
|
|
// ===== Exec ======
|
|
// Disabled until need arises
|
|
// program
|
|
// .command("exec <action> [args]")
|
|
// .description("Execute a standalone function against an running running network");
|
|
|
|
program.parseAsync(Bun.argv);
|