Contributing to essential-eth
essential-eth is a minimal, tree-shakeable Ethereum utility library (~43 kB) that serves as a lightweight alternative to ethers.js and web3.js. It uses native bigint instead of BigNumber classes.
Project Structure
code
src/ ├── classes/ # Contract and BaseContract ├── providers/ # JsonRpcProvider, FallthroughProvider, AlchemyProvider │ └── BaseProvider.ts # Abstract base with all RPC methods ├── utils/ # One file per utility function │ └── tests/ # Colocated test files ├── conversions/ # Lightweight conversion-only entry point ├── types/ # TypeScript type definitions (Hex, Address, Hash, etc.) └── index.ts # Barrel exports
Adding a New Utility Function
- •Create
src/utils/<function-name>.tswith a single exported function - •Add JSDoc with
@param,@returns, and@exampletags - •Create
src/utils/tests/<function-name>.test.ts - •Export from
src/index.ts(andsrc/utils/index-utils.tsif appropriate)
Example utility file
typescript
import type { BytesLike } from './bytes';
/**
* Brief description of what the function does.
*
* @param input description of parameter
* @returns description of return value
* @example
* ```javascript
* myFunction('0x1234');
* // '0xabcd...'
* ```
*/
export function myFunction(input: BytesLike): string {
// implementation
}
Example test file
typescript
import { describe, expect, it } from 'vitest';
import { myFunction } from './../my-function';
describe('myFunction', () => {
it('should handle hex strings', () => {
expect(myFunction('0x1234')).toBe('expected-output');
});
});
Coding Conventions
- •One function per file in
src/utils/, named with kebab-case - •Use
interfacenottypefor object shapes (@typescript-eslint/consistent-type-definitions) - •Use
import typefor type-only imports (@typescript-eslint/consistent-type-imports) - •No
console.log--no-consoleis set to error - •JSDoc required on all non-test source files with
@exampleblocks - •Branded types -- use
Hex,Address,Hashfromsrc/types/Primitives.types.ts - •Native
bigint-- never use BigNumber libraries - •No side effects -- all utility functions must be pure
Testing
- •Framework: Vitest with globals enabled
- •Tests live in
src/utils/tests/orsrc/<module>/test/ - •Timeout: 15 seconds
- •Run tests:
npm run test(runs vitest + build + eslint) - •Run just vitest:
npx vitest run
Build
- •tsup builds three entry points:
index,utils,conversions - •Output: ESM (with splitting) and CJS
- •Run:
npm run build - •Bundle size matters -- prefer
@noble/hashesover heavier crypto libraries
Provider Methods
When adding provider methods, add them to src/providers/BaseProvider.ts. Each method should include JSDoc with comparison lines to ethers.js and web3.js equivalents.
Key Dependencies
- •
@noble/hashes-- cryptographic hashing (keccak256, sha3) - •
@noble/secp256k1-- elliptic curve operations - •
isomorphic-unfetch-- universal fetch for RPC calls