Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ lib/solidity-bytes-utils/
lib/v3-core/
lib/v3-periphery/

# Exclude most of lib/evvm except contracts
lib/evvm/testnet/broadcast/
lib/evvm/testnet/cache/
lib/evvm/testnet/out/
lib/evvm/testnet/test/
lib/evvm/testnet/script/
lib/evvm/testnet/lib/

# Input configuration files
input/

Expand All @@ -54,5 +62,7 @@ wake.toml
# TypeScript example
package-ts.json.example

# Source directory (since we copy from src/ to root during packaging)
src/
# Executables and wrapper scripts
.executables/
evvm
evvm.bat
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ Before deploying with the CLI, ensure you have the following installed:

## Quick start (2 min)

### Option A: Using bunx/npx (No clone required)

Run the CLI directly without cloning the repository:

```bash
# Using Bun (recommended)
bunx @evvm/cli deploy

# Using npm/npx
npx @evvm/cli deploy
```

**Note:** You still need Foundry and Git installed on your system.

### Option B: Clone & install (For development)

1. Clone & install

```bash
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "@evvm/cli",
"version": "3.1.2",
"version": "1.0.0",
"type": "module",
"description": "EVVM CLI - Command-line tool for deploying and managing EVVM instances on testnets",
"description": "EVVM CLI - Command-line tool for deploying and managing EVVM instances",
"keywords": [
"evvm",
"ethereum",
Expand All @@ -24,10 +24,10 @@
"bugs": {
"url": "https://github.com/EVVM-org/evvm-cli/issues"
},
"bin": {
"evvm": "src/index.ts"
},
"scripts": {
"build": "bun run copy-files",
"copy-files": "cp -r lib/evvm/testnet/src/contracts . && cp -r lib/evvm/testnet/src/interfaces . && cp -r lib/evvm/testnet/src/library .",
"clean": "rm -rf contracts interfaces library",
"evvm": "bun run src/index.ts",
"buildCli": "bun build src/index.ts --compile --outfile evvm",
"build-all": "bun run build-linux && bun run build-windows && bun run build-macos",
Expand Down
11 changes: 11 additions & 0 deletions src/commands/deploy/deployCross.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
showAllCrossChainDeployedContracts,
forgeScript,
} from "../../utils/foundry";
import { areContractsInstalled } from "../../utils/git";
import { installDependencies } from "../developer";
import {
configurationBasic,
configurationCrossChain,
Expand Down Expand Up @@ -85,6 +87,15 @@ export async function deployCross(args: string[], options: any) {
walletNameExternal,
]);

const contractsInstalled = await areContractsInstalled();
if (!contractsInstalled) {
warning(
"EVVM contracts not found",
`${colors.darkGray}Installing contracts automatically...${colors.reset}`
);
await installDependencies();
}

if (skipInputConfig) {
warning(
`Skipping input configuration`,
Expand Down
11 changes: 11 additions & 0 deletions src/commands/deploy/deploySingle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
showDeployContractsAndFindEvvm,
verifyFoundryInstalledAndAccountSetup,
} from "../../utils/foundry";
import { areContractsInstalled } from "../../utils/git";
import { installDependencies } from "../developer";
import {
chainIdNotSupported,
confirmation,
Expand Down Expand Up @@ -68,6 +70,15 @@ export async function deploySingle(args: string[], options: any) {

await verifyFoundryInstalledAndAccountSetup([walletName]);

const contractsInstalled = await areContractsInstalled();
if (!contractsInstalled) {
warning(
"EVVM contracts not found",
`${colors.darkGray}Installing contracts automatically...${colors.reset}`
);
await installDependencies();
}

if (skipInputConfig) {
warning(
`Skipping input configuration`,
Expand Down
66 changes: 58 additions & 8 deletions src/commands/developer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
import { $ } from "bun";
import { colors } from "../constants";
import { contractInterfacesGenerator, contractTesting } from "../utils/foundry";
import { promptSelect } from "../utils/prompts";
import { confirmation, seccionTitle, sectionSubtitle } from "../utils/outputMesages";
import { verifyGitInstalled, updateSubmodules, isGitRepository, areContractsInstalled, cloneContractsRepo } from "../utils/git";
import { promptSelect, promptYesNo } from "../utils/prompts";
import { confirmation, seccionTitle, sectionSubtitle, warning } from "../utils/outputMesages";

/**
* Developer utilities command handler
Expand Down Expand Up @@ -68,15 +69,64 @@ export async function developer(_args: string[], options: any) {


export async function installDependencies() {
sectionSubtitle("Cloning EVVM Testnet Contracts");
await $`git submodule update --init --recursive --depth 1 --jobs 4`;
await $`git submodule update --remote --merge`;
await verifyGitInstalled();

const contractsInstalled = await areContractsInstalled();

if (contractsInstalled) {
const reinstall = await promptYesNo(
"EVVM contracts are already installed. Do you want to reinstall them?",
false
);

if (!reinstall) {
warning("Skipping contract installation");
sectionSubtitle("Installing EVVM CLI Dependencies");
await $`bun install`;
sectionSubtitle("Installing EVVM Contracts Dependencies");
await $`bun install`.cwd("lib/evvm/testnet");
sectionSubtitle("Installing EVVM Foundry Dependencies");
await $`forge install`.cwd("lib/evvm/testnet");
console.log();
confirmation(`All dependencies installed successfully`);
return;
}
}

const isGitRepo = await isGitRepository();

if (isGitRepo) {
await updateSubmodules();
} else {
await cloneContractsRepo();
}

sectionSubtitle("Installing EVVM CLI Dependencies");
await $`bun install`;
const bunInstallCli = Bun.spawn(["bun", "install"], {
stderr: "inherit",
stdout: "inherit",
});
await bunInstallCli.exited;
if (bunInstallCli.exitCode !== 0) throw new Error("bun install failed");

sectionSubtitle("Installing EVVM Contracts Dependencies");
await $`bun install`.cwd("lib/evvm/testnet");
const bunInstallContracts = Bun.spawn(["bun", "install"], {
cwd: "lib/evvm/testnet",
stderr: "inherit",
stdout: "inherit",
});
await bunInstallContracts.exited;
if (bunInstallContracts.exitCode !== 0) throw new Error("bun install in lib/evvm/testnet failed");

sectionSubtitle("Installing EVVM Foundry Dependencies");
await $`forge install`.cwd("lib/evvm/testnet");
const forgeInstall = Bun.spawn(["forge", "install"], {
cwd: "lib/evvm/testnet",
stderr: "inherit",
stdout: "inherit",
});
await forgeInstall.exited;
if (forgeInstall.exitCode !== 0) throw new Error("forge install failed");

console.log();
confirmation(`All dependencies installed successfully`);
}
Empty file modified src/index.ts
100644 → 100755
Empty file.
108 changes: 108 additions & 0 deletions src/utils/git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* Git Integration Utilities
*
* Provides functions for interacting with Git including:
* - Git installation validation
* - Submodule management
* - Repository detection
* - Direct contract cloning
*
* @module cli/utils/git
*/

import { $ } from "bun";
import { colors } from "../constants";
import { criticalErrorCustom, sectionSubtitle } from "./outputMesages";

/**
* Checks if Git is installed
*
* @returns {Promise<boolean>} True if Git is installed and accessible
*/
export async function gitIsInstalled(): Promise<boolean> {
try {
await $`git --version`.quiet();
} catch (error) {
return false;
}
return true;
}

/**
* Verifies that Git is installed and shows error if not
*
* @returns {Promise<void>}
*/
export async function verifyGitInstalled(): Promise<void> {
if (!(await gitIsInstalled()))
criticalErrorCustom(
"Git installation not detected.",
"Visit https://git-scm.com/downloads for installation instructions."
);
}

/**
* Updates Git submodules with initialization
*
* @returns {Promise<void>}
*/
export async function updateSubmodules(): Promise<void> {
sectionSubtitle("Cloning EVVM Testnet Contracts");
const init = Bun.spawn(["git", "submodule", "update", "--init", "--recursive", "--depth", "1", "--jobs", "4"], {
stderr: "inherit",
stdout: "inherit",
});
await init.exited;
if (init.exitCode !== 0) throw new Error("git submodule update failed");

const merge = Bun.spawn(["git", "submodule", "update", "--remote", "--merge"], {
stderr: "inherit",
stdout: "inherit",
});
await merge.exited;
if (merge.exitCode !== 0) throw new Error("git submodule update --remote failed");
}

/**
* Checks if current directory is a Git repository
*
* @returns {Promise<boolean>} True if current directory is a Git repository
*/
export async function isGitRepository(): Promise<boolean> {
try {
await $`git rev-parse --is-inside-work-tree`.quiet();
return true;
} catch (error) {
return false;
}
}

/**
* Checks if EVVM contracts are already installed
*
* @returns {Promise<boolean>} True if lib/evvm/testnet directory exists
*/
export async function areContractsInstalled(): Promise<boolean> {
try {
const stat = await $`test -d lib/evvm/testnet`.quiet();
return stat.exitCode === 0;
} catch (error) {
return false;
}
}

/**
* Clones EVVM testnet contracts repository directly
* Used when not in a Git repository (e.g., bunx/npx installation)
*
* @returns {Promise<void>}
*/
export async function cloneContractsRepo(): Promise<void> {
sectionSubtitle("Cloning EVVM Testnet Contracts");
const proc = Bun.spawn(["git", "clone", "https://github.com/EVVM-org/testnet-Contracts", "lib/evvm/testnet"], {
stderr: "inherit",
stdout: "inherit",
});
await proc.exited;
if (proc.exitCode !== 0) throw new Error("git clone failed");
}
Loading