Development Tools & Workflow
ZK-Kit provides pre-configured development tools for maintaining code quality and streamlining the development process.
Monorepo Structure
ZK-Kit uses Yarn workspaces for minimal monorepo package management. This allows:
- Shared dependencies across packages
- Simplified build and test workflows
- Consistent versioning
Commands
yarn # Install all dependencies
yarn build # Build all packages
yarn docs # Generate documentation for all packages
Code Quality Tools
ESLint
Analyzes code and catches bugs automatically.
yarn lint
ESLint configuration ensures:
- Consistent code style
- Early bug detection
- Best practices enforcement
Features:
- Automatic error detection
- Code style consistency
- TypeScript integration
- Pre-configured rules
Prettier
Code formatting for consistency.
yarn format # Check formatting rules
yarn format:write # Automatically format code
Benefits:
- Consistent code formatting
- No style debates
- Automatic on save (with IDE integration)
- Works with ESLint
Testing Framework
Jest
Test framework for all JavaScript libraries.
yarn test:libraries # Run all tests
yarn test # Run tests for current package
Testing best practices:
- Write tests for all new features
- Maintain high test coverage
- Test edge cases
- Use descriptive test names
Example Test:
import { IMT } from "@zk-kit/imt"
import { poseidon2 } from "poseidon-lite"
describe("IMT", () => {
it("should create a tree and verify proofs", () => {
const tree = new IMT(poseidon2, 16, 0, 2)
tree.insert(BigInt(1))
const proof = tree.createProof(0)
const isValid = tree.verifyProof(proof)
expect(isValid).toBe(true)
})
})
Documentation Generation
Typedocs
Automatically generates documentation from TypeScript code.
yarn docs
Output location: docs/ folder
Features:
- Auto-generated API reference
- Type information
- Function signatures
- Usage examples from JSDoc comments
Writing Documentation Comments:
/**
* Creates a Merkle tree proof for a specific leaf.
* @param index The index of the leaf to prove
* @returns A proof object containing siblings and path
*/
createProof(index: number): MerkleProof {
// implementation
}
Benchmarking
Benny
Simple benchmarking framework for JavaScript/TypeScript.
yarn benchmarks # Run all benchmarks
yarn benchmarks [filename] # Run specific benchmark
Creating benchmarks:
- Create a file in
benchmarks/folder - Export a benchmark function
- Add to
benchmarks/index.ts - Results saved in
benchmarks/results/
Example Benchmark:
import { add, complete, cycle, save, suite } from "benny"
import { IMT } from "@zk-kit/imt"
import { poseidon2 } from "poseidon-lite"
export default function () {
return suite(
"IMT Operations",
add("insert", () => {
const tree = new IMT(poseidon2, 16, 0, 2)
return () => tree.insert(BigInt(1))
}),
add("create proof", () => {
const tree = new IMT(poseidon2, 16, 0, 2)
tree.insert(BigInt(1))
return () => tree.createProof(0)
}),
cycle(),
complete(),
save({ file: "imt", folder: "benchmarks/results" })
)
}
Commit Workflow
Conventional Commits
Structured, human and machine-readable commit messages.
yarn commit
This command:
- Guides you through commit message creation
- Automatically checks ESLint compliance
- Automatically checks Prettier compliance
- Ensures consistent commit format
Commit message format:
type(scope): subject
body
footer
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting)refactor: Code refactoringtest: Adding/updating testschore: Maintenance tasks
Examples:
feat(imt): add batch insertion support
Adds insertMany() method for efficiently inserting multiple leaves at once.
Closes #123
fix(eddsa): correct signature verification edge case
Fixed an issue where signatures with zero values would fail verification.
CI/CD Pipeline
GitHub Actions
Automated workflows for:
- Automatic testing on every push/PR
- Documentation deployment on releases
- Code quality checks (ESLint, Prettier)
- npm publishing when tags are pushed
Workflow triggers:
- Push to main branch
- Pull request creation
- Git tag push (for releases)
Example Workflow:
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: yarn install
- run: yarn build
- run: yarn test
- run: yarn lint
Development Workflow
Standard Development Flow
-
Clone the repository:
git clone https://github.com/privacy-scaling-explorations/zk-kit.git
cd zk-kit -
Install dependencies:
yarn -
Create a branch:
git checkout -b feature/my-feature -
Make changes:
- Write code
- Write tests
- Update documentation
-
Run quality checks:
yarn build # Build packages
yarn test # Run tests
yarn lint # Check linting
yarn format # Check formatting -
Commit changes:
yarn commit # Interactive commit -
Push and create PR:
git push origin feature/my-feature
Package Development
Working on a specific package:
cd packages/imt
yarn test # Run package tests
yarn build # Build package
Testing changes in another project:
# In the zk-kit package directory
yarn link
# In your project
yarn link @zk-kit/imt
Publishing Workflow
Bumping Versions
yarn version:bump <package-name> <version>
# Example:
yarn version:bump utils 2.0.0
This creates:
- A commit with version change
- A git tag
Publishing to npm
Step 1: Bump version (see above)
Step 2: Push to main
git push origin main
Step 3: Push the git tag
git push origin <package-name>-<version>
# Example:
git push origin utils-v2.0.0
Step 4: Automatic deployment
After pushing the tag:
- GitHub Actions workflow triggers automatically
- Package is published to npm
- GitHub release is created with changelogs
IDE Setup
VS Code
Recommended extensions:
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-vscode.vscode-typescript-next"
]
}
Settings:
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"typescript.tsdk": "node_modules/typescript/lib"
}
WebStorm/IntelliJ
- Enable ESLint:
Settings → Languages & Frameworks → JavaScript → Code Quality Tools → ESLint - Enable Prettier:
Settings → Languages & Frameworks → JavaScript → Prettier - Format on save:
Settings → Tools → Actions on Save
Debugging
Node.js Debugging
VS Code launch.json:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest Tests",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"],
"console": "integratedTerminal"
}
]
}
Browser Debugging
Use browser DevTools with source maps:
// Your code here
debugger; // Breakpoint
Performance Monitoring
Memory Profiling
node --inspect-brk node_modules/.bin/jest
# Open chrome://inspect in Chrome
Benchmark Comparison
# Run benchmarks before changes
yarn benchmarks > before.txt
# Make changes
# Run benchmarks after
yarn benchmarks > after.txt
# Compare
diff before.txt after.txt
Troubleshooting
Common Issues
Issue: Tests failing after changes
# Clear Jest cache
yarn test --clearCache
# Rebuild packages
yarn build
Issue: Linting errors
# Auto-fix where possible
yarn lint --fix
# Format code
yarn format:write
Issue: Type errors
# Rebuild TypeScript declarations
yarn build
Best Practices
Code Style
- Use TypeScript for type safety
- Write descriptive variable names
- Keep functions small and focused
- Comment complex logic
- Follow existing patterns
Testing
- Test happy path and edge cases
- Use descriptive test names
- Mock external dependencies
- Aim for 80%+ coverage
- Test public API, not implementation
Documentation
- Document all public APIs
- Include usage examples
- Explain complex algorithms
- Keep README up to date
- Add JSDoc comments
Performance
- Profile before optimizing
- Benchmark critical paths
- Consider memory usage
- Use appropriate data structures
- Avoid premature optimization
Resources
- Yarn Workspaces
- Jest Documentation
- ESLint Rules
- Prettier Options
- Conventional Commits
- GitHub Actions