Skip to content

Commit

Permalink
✨ Feat: Add tevm-run cli (#1346)
Browse files Browse the repository at this point in the history
## Description

_Concise description of proposed changes_

## Testing

Explain the quality checks that have been done on the code changes

## Additional Information

- [ ] I read the [contributing docs](../docs/contributing.md) (if this
is your first contribution)

Your ENS/address:



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced the `tevm-run` command as a lightweight wrapper for
executing scripts using the Bun runtime.
- Added support for automatic loading of the `tevm` compiler and
configuration files.
- Implemented the `tevm-gen` command for generating TypeScript
declaration files from Solidity contracts.
- Added a unit test for the CLI functionality to ensure consistent
command execution.

- **Bug Fixes**
- Removed unnecessary warning messages from the bundler, enhancing user
experience.

- **Documentation**
- Updated documentation to reflect the new `tevm-run` command and its
usage, simplifying instructions for users.
- Provided a comprehensive overview of the `tevm-run` tool in the
README.

- **Chores**
- Added `.gitignore`, `.prettierignore`, and updated `package.json`
files to streamline project management and ignore unnecessary files.
- Modified CI workflow to ensure execution continues even if build tasks
fail.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: William Cory <[email protected]>
  • Loading branch information
roninjin10 and William Cory authored Jul 30, 2024
1 parent a6bda73 commit 2a0c5af
Show file tree
Hide file tree
Showing 59 changed files with 7,164 additions and 503 deletions.
5 changes: 5 additions & 0 deletions .changeset/fast-toys-boil.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tevm/base-bundler": patch
---

Removed warning from tevm bundler
2 changes: 1 addition & 1 deletion .github/workflows/nx.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
uses: ./.github/actions/setup

- name: Initialize the Nx Cloud distributed CI run and stop agents when the build tasks are done
run: bunx nx-cloud start-ci-run --stop-agents-after=build:app
run: bunx nx-cloud start-ci-run --stop-agents-after=build:app --stop-agents-on-failure=false

- name: Run verification
uses: JamesHenry/[email protected]
Expand Down
3 changes: 0 additions & 3 deletions bundler-packages/base-bundler/src/getContractPath.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ export const getContractPath = (basePath) => {
// @ts-expect-error checking for global existence of bun
const isBun = typeof Bun !== 'undefined'
if (isBun) {
console.warn(`Unable to autodetect whether tevm or @tevm/contract is installed because of a known bug in bun. Defaulting to tevm.
You may need to install tevm if it is not already installed for use with bun.
see https://github.com/oven-sh/bun/issues/8974`)
return 'tevm/contract'
}
throw new Error(
Expand Down
50 changes: 50 additions & 0 deletions bundler-packages/tevm-run/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.env

cache
forge-artifacts
broadcast

# compiled output
types
dist
packages/*/dist
tmp
/out-tsc
**/tsconfig.tsbuildinfo

# dependencies
node_modules

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

**/lcov.info

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json

# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
testem.log
/typings

# System Files
.DS_Store
Thumbs.db

# My personal files
.zshrc
1 change: 1 addition & 0 deletions bundler-packages/tevm-run/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
5 changes: 5 additions & 0 deletions bundler-packages/tevm-run/bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
preload = ["./plugins.js"]
[install]
auto = "fallback"
[test]
preload = ["./plugins.js"]
21 changes: 21 additions & 0 deletions bundler-packages/tevm-run/example/SimpleContract.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleContract {
uint256 private value;

event ValueSet(uint256 newValue);

constructor(uint256 initialValue) {
value = initialValue;
}

function get() public view returns (uint256) {
return value;
}

function set(uint256 newValue) public {
value = newValue;
emit ValueSet(newValue);
}
}
22 changes: 22 additions & 0 deletions bundler-packages/tevm-run/example/example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// this is purposefully not installed to test we do install!
import { createMemoryClient } from 'tevm'
// TODO a hard to debug error was thrown if this is not .s.sol. Fix that
import { SimpleContract } from './SimpleContract.s.sol'

const client = createMemoryClient()

const { createdAddress } = await client.tevmDeploy(SimpleContract.deploy(20n))

const contract = SimpleContract.withAddress(createdAddress)

await client.tevmMine()

const value = await client.readContract(contract.read.get())

if (value !== 20n) {
console.error(value)
throw new Error('value should be 20')
}
console.log('success')
console.log('address: ', createdAddress)
console.log('SimpleContract.get(): ', value)
1 change: 1 addition & 0 deletions bundler-packages/tevm-run/example/vanilla.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('success')
52 changes: 52 additions & 0 deletions bundler-packages/tevm-run/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "tevm-run",
"version": "0.0.1",
"license": "MIT",
"type": "module",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./src/index.js",
"default": "./src/index.js"
}
}
},
"main": "src/tevm-run.js",
"module": "src/tevm-run.js",
"types": "src/tevm-run.js",
"bin": {
"tevm-run": "src/tevm-run.js"
},
"files": [
"src",
"bunfig.toml",
"plugin.js"
],
"scripts": {
"all": "bun run lint && bun run format && bun run test:coverage",
"build:dist": "echo 'this package does not have a build'",
"build:types": "echo 'this package does not have a build'",
"dev": "bun run --watch src/tevm-run.js example/example.ts",
"format": "biome format . --write",
"format:check": "biome format .",
"lint": "biome check . --apply-unsafe",
"lint:check": "biome check . --verbose",
"test": "bun test --watch",
"test:coverage": "bun test --coverage",
"test:run": "bun test"
},
"devDependencies": {
"@tevm/tsconfig": "workspace:^"
},
"peerDependencies": {
"@tevm/bun-plugin": "workspace:^",
"bun": "latest",
"bun-types": "latest",
"tevm": "latest"
},
"engines": {
"bun-types": "latest",
"node": ">=16"
}
}
3 changes: 3 additions & 0 deletions bundler-packages/tevm-run/plugins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { bunPluginTevm } from '@tevm/bun-plugin'
import { plugin } from 'bun'
plugin(bunPluginTevm({}))
3 changes: 3 additions & 0 deletions bundler-packages/tevm-run/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## ✨ tevm-run

A simple cli wrapper around bun for easily run tevm scripts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`should run a cli 1`] = `
"[tevm-run] bun run --bun --config=/bunfig.toml --install=fallback ./example/example.ts
success
address: 0x5FbDB2315678afecb367f032d93F642f64180aa3
SimpleContract.get(): 20n
"
`;
5 changes: 5 additions & 0 deletions bundler-packages/tevm-run/src/argsSchema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const argsSchema = {
options: {},
strict: true,
allowPositionals: true,
}
3 changes: 3 additions & 0 deletions bundler-packages/tevm-run/src/configPath.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { join } from 'node:path'

export const configPath = join(__dirname, '..', 'bunfig.toml')
7 changes: 7 additions & 0 deletions bundler-packages/tevm-run/src/configPath.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { expect, test } from 'bun:test'
import { join } from 'node:path'
import { configPath } from './configPath.js'

test('should return config path', () => {
expect(configPath).toBe(join(__dirname, '..', 'bunfig.toml'))
})
4 changes: 4 additions & 0 deletions bundler-packages/tevm-run/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './argsSchema.js'
export * from './configPath.js'
export * from './parseArgs.js'
export * from './run.js'
20 changes: 20 additions & 0 deletions bundler-packages/tevm-run/src/parseArgs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { parseArgs as nodeParseArgs } from 'node:util'
import { argsSchema } from './argsSchema.js'

/**
* @param {string[]} rawArgs
*/
export const parseArgs = (rawArgs) => {
const args = nodeParseArgs({
...argsSchema,
args: rawArgs,
})
const tevmRunIndex = rawArgs.findIndex((arg) => arg.endsWith('tevm-run') || arg.endsWith('tevm-run.js'))
// remove the bun arg and the tevm-run.js arg
args.positionals = args.positionals.slice(tevmRunIndex + 1)
if (args.positionals.length === 0) {
console.error('Usage: tevm-run <scriptPath> [positionals...]')
throw new Error('No script path provided.')
}
return args
}
15 changes: 15 additions & 0 deletions bundler-packages/tevm-run/src/parseArgs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, it } from 'bun:test'
import { parseArgs } from './parseArgs.js'

describe(parseArgs.name, () => {
it('should parse the arguments', async () => {
expect(await parseArgs(['bunx', 'tevm-run', './example/example.ts'])).toEqual({
values: {},
positionals: ['./example/example.ts'],
})
})

it('should throw if no positional argument is provided', () => {
expect(() => parseArgs(['bunx', 'tevm-run'])).toThrow()
})
})
25 changes: 25 additions & 0 deletions bundler-packages/tevm-run/src/run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { $ } from 'bun'
import { configPath } from './configPath.js'
import { parseArgs } from './parseArgs.js'

/**
* Executes the provided script using Bun with the specified configuration.
* @param {string} scriptPath - The path to the script to execute.
* @param {...string} positionals - The positional arguments to pass to the script.
* @returns {Promise<void>}
*/
export const run = async ([scriptPath, ...positionals] = parseArgs(process.argv).positionals) => {
try {
const command = `[tevm-run] bun run --bun --config=${configPath} --install=fallback ${scriptPath} ${positionals.join(' ')}`
console.log(command)
return $`bun run --config=${configPath} --install=fallback ${scriptPath} ${positionals.join(' ')}`
} catch (error) {
console.log('error')
console.log(err.stdout.toString())
console.error(`Failed with code ${err.exitCode}`)
console.error(err.stderr.toString())
throw new Error(`Error executing the script: ${error instanceof Error ? error.message : err.stderr.toString()}`, {
cause: error,
})
}
}
8 changes: 8 additions & 0 deletions bundler-packages/tevm-run/src/run.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { describe, expect, it } from 'bun:test'
import { run } from './run.js'

describe(run.name, () => {
it('should run the `tevm run` command to run a script', async () => {
expect((await run(['./example/vanilla.ts'])).text()).toBe('success\n')
})
})
10 changes: 10 additions & 0 deletions bundler-packages/tevm-run/src/tevm-run.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bun

import('./run.js')
.then(({ run }) => {
return run()
})
.catch((e) => {
console.error('An error occurred:', e)
process.exit(1)
})
15 changes: 15 additions & 0 deletions bundler-packages/tevm-run/src/tevm-run.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { expect, it } from 'bun:test'
import { $ } from 'bun'

it('should run a cli', async () => {
const result = (await $`./src/tevm-run.js ./example/example.ts`)
.text()
.split('\n')
.map((line) => line.replace(process.cwd(), '').trim())
.join('\n')
expect(result).toInclude('[tevm-run] bun run --bun --config=/bunfig.toml --install=fallback ./example/example.ts')
expect(result).toInclude('success')
expect(result).toInclude('address: 0x5FbDB2315678afecb367f032d93F642f64180aa3')
expect(result).toInclude('SimpleContract.get()')
expect(result).toInclude('20n')
})
13 changes: 13 additions & 0 deletions bundler-packages/tevm-run/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"compilerOptions": {
"paths": {
"react": ["./node_modules/@types/react"]
},
"plugins": [
{
"name": "@tevm/ts-plugin"
}
],
"types": ["bun-types"]
}
}
Loading

0 comments on commit 2a0c5af

Please sign in to comment.