🪶 Essential Eth 🪶
A replacement for ethers & web3 that's 20x smaller
- 🏆️ smallest code size possible
- ʦ Fully typed with TypeScript (also works with JavaScript)
- 🧪 Tested to match both
web3
andethers
-
- ⚡️ Near-identical API to
ethers
- ⚡️ Near-identical API to
- 🌲 Tree-shaking and no side-effects
- 🙌 Supports multiple JS versions (CommonJS and ESM)
- ✅ Node 18, 16, 14, & 12
- ✅ Web
Click to expand
- Why you should replace Ethers.js and web3
- Install
- 🛠 Utils
arrayify
concat
etherToGwei
etherToWei
gweiToEther
hashMessage
hexConcat
hexDataLength
hexDataSlice
hexStripZeros
hexValue
hexZeroPad
hexlify
isAddress
isBytes
isBytesLike
isHexString
jsonRpcProvider
keccak256
pack
solidityKeccak256
stripZeros
tinyBig
toChecksumAddress
toUtf8Bytes
weiToEther
zeroPad
- RPC
- Contract
- More Info
npm install --save essential-eth # TypeScript types load automatically
# or yarn
yarn add essential-eth # TypeScript types load automatically
import { etherToWei } from 'essential-eth';
// or in a non-import environment
const { etherToWei } = require('essential-eth');
arrayify(value: number | BytesLike | Hexable, options: DataOptions): Uint8Array
View Example
import { arrayify } from 'essential-eth';
// or in a require environment
const { arrayify } = require('essential-eth');
arrayify(1);
// Uint8Array(1) [ 1 ]
arrayify(0x1234);
// Uint8Array(2) [ 18, 52 ]
arrayify('0x1', { hexPad: 'right' });
// Uint8Array(1) [ 16 ]
concat(arrayOfBytesLike: Array<BytesLikeWithNumber>): Uint8Array
View Example
import { concat } from 'essential-eth';
// or in a require environment
const { concat } = require('essential-eth');
concat([0, 1]);
// Uint8Array(2) [ 0, 1 ]
etherToGwei(etherQuantity: string | number | TinyBig | Big): TinyBig
View Example
import { etherToGwei } from 'essential-eth';
// or in a require environment
const { etherToGwei } = require('essential-eth');
etherToGwei('1000').toString();
// '1000000000000'
etherToGwei(1000).toString();
// '1000000000000'
etherToGwei('1000').toNumber();
// 1000000000000
etherToGwei(1000).toNumber();
// 1000000000000
etherToWei(etherQuantity: string | number | TinyBig | Big): TinyBig
View Example
import { etherToWei } from 'essential-eth';
// or in a require environment
const { etherToWei } = require('essential-eth');
etherToWei('1000').toString();
// '1000000000000000000000'
etherToWei(1000).toString();
// '1000000000000000000000'
etherToWei('1000').toNumber();
// 1000000000000000000000
etherToWei(1000).toNumber();
// 1000000000000000000000
gweiToEther(gweiQuantity: string | number | TinyBig | Big): TinyBig
View Example
import { gweiToEther } from 'essential-eth';
// or in a require environment
const { gweiToEther } = require('essential-eth');
gweiToEther('1000000000000').toString();
// '1000'
gweiToEther(1000000000000).toString();
// '1000'
gweiToEther('1000000000000').toNumber();
// 1000
gweiToEther(1000000000000).toNumber();
// 1000
hashMessage(message: string | Bytes): string
View Example
import { hashMessage } from 'essential-eth';
// or in a require environment
const { hashMessage } = require('essential-eth');
hashMessage('Hello World');
// '0xa1de988600a42c4b4ab089b619297c17d53cffae5d5120d82d8a92d0bb3b78f2'
hexConcat(items: Array<BytesLike>): string
hexDataLength(data: BytesLike): null | number
hexDataSlice(data: BytesLikeWithNumber, offset: number, endOffset: number): string
hexStripZeros(value: BytesLike): string
hexValue(value: number | bigint | BytesLike | Hexable): string
hexZeroPad(value: BytesLikeWithNumber, length: number): string
View Example
import { hexZeroPad } from 'essential-eth';
// or in a require environment
const { hexZeroPad } = require('essential-eth');
hexZeroPad('0x60', 2);
// '0x0060'
hexZeroPad(0x60, 3);
// '0x000060'
hexZeroPad('12345', 1);
// Throws
hexlify(value: number | bigint | BytesLike | Hexable, options: DataOptions): string
View Example
import { hexlify } from 'essential-eth';
// or in a require environment
const { hexlify } = require('essential-eth');
hexlify(4);
// '0x04'
hexlify(14);
// '0x0e'
isAddress(address: string): boolean
View Example
import { isAddress } from 'essential-eth';
// or in a require environment
const { isAddress } = require('essential-eth');
isAddress('0xc0deaf6bd3f0c6574a6a625ef2f22f62a5150eab');
// true
isAddress('bad');
// false
// Does NOT support ENS.
isAddress('vitalik.eth');
// false
isBytes(value: any): value
View Example
import { isBytes } from 'essential-eth';
// or in a require environment
const { isBytes } = require('essential-eth');
isBytes([1, 2, 3]);
// true
isBytes(false);
// false
isBytes(new Uint8Array(1));
// true
isBytesLike(value: any): value
View Example
import { isBytesLike } from 'essential-eth';
// or in a require environment
const { isBytesLike } = require('essential-eth');
isBytesLike([1, 2, 3]);
// true
isBytesLike(false);
// false
isBytesLike(new Uint8Array(1));
// true
isHexString(value: any, length: number): boolean
jsonRpcProvider(rpcUrl: string): JsonRpcProvider
View Example
import { jsonRpcProvider } from 'essential-eth';
// or in a require environment
const { jsonRpcProvider } = require('essential-eth');
jsonRpcProvider()
.getBlock('latest')
.then((block) => {
console.log(block.number);
});
// 14530496
keccak256(data: BytesLike): string
pack(types: Array<string>, values: Array<any>): string
solidityKeccak256(types: Array<string>, values: Array<any>): string
View Example
import { solidityKeccak256 } from 'essential-eth';
// or in a require environment
const { solidityKeccak256 } = require('essential-eth');
const types = ['string', 'bool', 'uint32'];
const values = ['essential-eth is great', true, 14];
solidityKeccak256(types, values);
// '0xe4d4c8e809faac09d58f468f0aeab9474fe8965d554c6c0f868c433c3fd6acab'
const types = ['bytes4', 'uint32[5]'];
const values = [
[116, 101, 115, 116],
[5, 3, 4, 9, 18],
];
solidityKeccak256(types, values);
// '0x038707a887f09355dc545412b058e7ba8f3c74047050c7c5e5e52eec608053d9'
stripZeros(value: BytesLike): Uint8Array
tinyBig(value: string | number | TinyBig | Big): TinyBig
View Example
import { tinyBig } from 'essential-eth';
// or in a require environment
const { tinyBig } = require('essential-eth');
tinyBig(10).times(3).toNumber();
// 30
toChecksumAddress(address: string): string
View Example
import { toChecksumAddress } from 'essential-eth';
// or in a require environment
const { toChecksumAddress } = require('essential-eth');
toChecksumAddress('0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359');
// '0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359'
Similar to "getAddress" in ethers.js
Similar to "toChecksumAddress" in web3.js
toUtf8Bytes(data: string): Uint8Array
weiToEther(weiQuantity: string | number | TinyBig | Big): TinyBig
View Example
import { weiToEther } from 'essential-eth';
// or in a require environment
const { weiToEther } = require('essential-eth');
weiToEther('1000000000000000000000').toString();
// '1000'
weiToEther(1000000000000000000000).toString();
// '1000'
weiToEther('1000000000000000000000').toNumber();
// 1000
weiToEther(1000000000000000000000).toNumber();
// 1000
zeroPad(value: BytesLike, length: number): Uint8Array
- The return-type
TinyBig
is justBig
but expands scientific notation ontoNumber()
andtoString()
import { JsonRpcProvider } from 'essential-eth';
const essentialEth = new JsonRpcProvider(
'RPC URL HERE' /* Try POKT or Infura */,
);
// OR for very quick testing (limited to 10,000 requests)
const essentialEth = new JsonRpcProvider();
Want a redundant provider that handles outages?
import { FallthroughProvider } from 'essential-eth';
// The FallthroughProvider handles falling through to the next valid URL.
// It's dynamic to never trust one URL again when it fails * until it has tried all other provided URLs
// The default timeout for a request is 8 seconds after which it moves to the next URL
const provider = new FallthroughProvider([
'https://bad.com',
'https://free-eth-node.com/api/eth',
]);
provider.getGasPrice().toNumber();
/*
39695942769
*/
Returns the current gas price in gwei
// Same as ethers.providers.getGasPrice
getGasPrice(): Promise<TinyBig>
View Example
import { JsonRpcProvider } from 'essential-eth';
const provider = new JsonRpcProvider('https://free-eth-node.com/api/eth');
provider.getGasPrice().toNumber();
/*
39695942769
*/
Returns the balance of an address at a given block
// Same API as ethers.providers.getBalance
// Same API as web3.eth.getBalance
getBalance(address: string, blockTag?: BlockTag): Promise<TinyBig>
View Example
import { JsonRpcProvider } from 'essential-eth';
const provider = new JsonRpcProvider();
await provider
.getBalance('0x7cB57B5A97eAbe94205C07890BE4c1aD31E486A8')
.then((balance) => console.log(balance.toString()));
// "28798127851528138"
Returns a Network
// Same API as ethers.providers.getNetwork
getNetwork(): Promise<Network>
View Example
import { JsonRpcProvider } from 'essential-eth';
const maticProvider = new JsonRpcProvider(
'https://free-eth-node.com/api/matic',
);
maticProvider.getNetwork();
/*
{ chainId: 137, name: 'MATIC', ensAddress: null }
*/
const xdaiProvider = new JsonRpcProvider('https://free-eth-node.com/api/xdai');
xdaiProvider.getNetwork();
/*
{ chainId: 100, name: 'xdai', ensAddress: null } }
*/
Returns a Block
// Same API as web3.eth.getBlock
getBlock(timeFrame: number | "latest" | "earliest" | "pending", returnTransactionObjects?: boolean): Promise<Block>
View Example
import { JsonRpcProvider } from 'essential-eth';
const essentialEth = new JsonRpcProvider();
essentialEth.getBlock('latest');
/*
{
number: 4232826,
hash: '0x93211a1cd17e154b183565ec685254a03f844a8e34824a46ce1bdd6753dcb669',
parentHash: '0x1b32bfcba1bb2a57f56e166a3bb06875a1978992999dfc8828397b4c1526f472',
sha3Uncles: '0x0fb399c67bb5a071ec8a22549223215ab76b7d4009941c9c37aa3c3936010463',
logsBloom: '0x00000000000000000000101000000000020000000000000000000000000000000000400000010000000000000000000000000000010000000008800000000800000000200000000000000000000000000000000000000000000002000000000000000000000000000040000000000040000000000000000000000000000000000000000000000001000000000004000000000010000000000000000020000000000000000200100020000000000000000080000000000080001000000000000000000001040000000000000000008000000020010100000000200000100000000000000000000000002000000080000000020400000000002000200000000000',
transactionsRoot: '0xc43b3f13e1fe810e34d3a26ffe465b72c7063a5c70a02de2c78e91e4d10bd9fb',
stateRoot: '0x04d7bc816537ea7ef3a16e76c9879d29f34f99d4154273c2e98e012a31bad745',
receiptsRoot: '0x89c6f781ceac0bd49c4d9aa9115df4a5d4dd0e0220ff7668012f15bc04222c6b',
miner: '0x31fe561eb2c628cD32Ec52573D7c4b7E4C278Bfa',
difficulty: '1300907486001755331049',
totalDifficulty: '5989929395521171616186006183',
extraData: '0xce018c495249532d62613031656132',
size: 5416,
gasLimit: 6800000,
gasUsed: 202955,
timestamp: 1649884910,
transactions: [
'0x6b34a59c7b9aead24fa6dad782f8a3ad84ed4a23ee09bcbf0bcf880840fbbe20',
'0x9a3851ca24d5336c6a0d48aba2c4b4769d7a672c9b01729c5eb9924efd1b19a7',
'0xc3ed3d198b62f2f3427ebfa3bbd0fcada4e3c0c189e4464e7eeceb403c75981e'
],
uncles: [
'0x0c567c054e98153f10d651fbbc018891c1dd9d62a9ffd998e87678803e95b6ed',
'0xb7d69389dbfb057c6fcb4bc0582d46a2ba01170703f0dadf8cd1462b83e88753',
'0xd5f74ccd0ad4c58b3161e8c2c507c264231e5f28925061b809c02e5e4bb6db28'
],
minimumGasPrice: '0x387ee40',
bitcoinMergedMiningHeader: '0x04000020e8567ed3d2480e15a1dd1b4335e4732ae343c037e4fd03000000000000000000ed10a8340d163d3e813bdd430f902f4e5a56828dc62313b2e23797c0be6b8516eb3e576297d8091735884f42',
bitcoinMergedMiningCoinbaseTransaction: '0x0000000000000140e910128fda7bac502dc5e0573bbaf12de8e2524f70c22f7bd160dedcb19a2521002b6a2952534b424c4f434b3ae493303f597fa368c0ccc4f8aceabf1c315bb7c9a07605c073a89f260040967aace6a7d9',
bitcoinMergedMiningMerkleProof: '0xdf63a3d7eb6fbcfb301311faa46e9a15b0408bb1a04e284daee86c273c1dfd65ede23f3170f806e9e0f4cef7ba6b56aa37470d9c23f96ec8e43d08b58645919c5e10bcb892897a731f8f9ce79c72dc0e390896bcd6c67bb38c0bdb72982b6cf05519968d76673572c3f3ef3a08b0ddb464863f1788f7cdbaad3fe44a8a8af576d430ac282fe28852c16df198ca96cc5f71a50695912efe1a836e8442be69e31b6d6f973da2818bce9a3a1c2d9be0671aee9a7776e398d6a03d1e178e20d84646004a3d03c0501334e629d9146aa6a01316dcbaa289df6e6c5e3090cadaddff22699cfc7ff09512fc0d65c5062f17c98561ce3c9510de210d9d654cf99f8d756ff37c9fa21e7122ee8cadb923341690845d572921425f2bd7e044558b7e07983ac4df28928028b0c13c3624dc7a965af8091b0cecc845bf7da5308c03b2c97d607f6706a599f802025894435f1d76ea4e67cc2fc4e1559f1206f559a24633de0f',
hashForMergedMining: '0xe493303f597fa368c0ccc4f8aceabf1c315bb7c9a07605c073a89f260040967a',
paidFees: '0xc0744dcb7a0',
cumulativeDifficulty: '0x1190930db285269e582'
}
*/
Returns the Transaction associated with a given hash
// Similar to ethers.provider.getTransaction, formatting may differ
getTransaction(hash: string): Promise<Transaction>
View Example
import { JsonRpcProvider } from 'essential-eth';
const essentialEth = new JsonRpcProvider();
await provider.getTransaction(
'0x9014ae6ef92464338355a79e5150e542ff9a83e2323318b21f40d6a3e65b4789',
);
/*
{
accessList: [],
blockHash: '0x876810a013dbcd140f6fd6048c1dc33abbb901f1f96b394c2fa63aef3cb40b5d',
blockNumber: 14578286,
chainId: 1,
from: '0xdfD9dE5f6FA60BD70636c0900752E93a6144AEd4',
gas: Big {
s: 1,
e: 5,
c: [ 1, 1, 2, 1, 6, 3 ],
constructor: <ref *1> [Function: Big] {
DP: 20,
RM: 1,
NE: -7,
PE: 21,
strict: false,
roundDown: 0,
roundHalfUp: 1,
roundHalfEven: 2,
roundUp: 3,
Big: [Circular *1],
default: [Circular *1]
}
},
gasPrice: Big {
s: 1,
e: 10,
c: [
4, 8, 5, 9, 2,
4, 2, 6, 8, 5,
8
],
constructor: <ref *1> [Function: Big] {
DP: 20,
RM: 1,
NE: -7,
PE: 21,
strict: false,
roundDown: 0,
roundHalfUp: 1,
roundHalfEven: 2,
roundUp: 3,
Big: [Circular *1],
default: [Circular *1]
}
},
hash: '0x9014ae6ef92464338355a79e5150e542ff9a83e2323318b21f40d6a3e65b4789',
input: '0x83259f170000000000000000000000000000000000000000000000000000000000000080000000000000000000000000dfd9de5f6fa60bd70636c0900752e93a6144aed400000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000009e99ad11a214fd016b19dc3648678c5944859ae292b21c24ca94f857836c4596f1950c82dd0c23dd621af4763edc2f66466e63c5df9de0c1107b1cd16bf460fe93e43fd308e3444bc79c3d88a4cb961dc8367ab6ad048867afc76d193bca99cf3a068864ed4a7df1dbf1d4c52238eced3e5e05644b4040fc2b3ccb8557b0e99fff6131305a0ea2b8061b90bd418db5bbdd2e92129f52d93f90531465e309c4caec5b85285822b6196398d36f16f511811b61bbda6461e80e29210cd303118bdcee8df6fa0505ffbe8642094fd2ba4dd458496fe3b459ac880bbf71877c713e969ccf5ed7efab8a84ebc07e3939901371ca427e1192e455a8f35a6a1d7ad09e1475dd1758b36fa631dab5d70e99316b23c4c43094188d360cd9c3457355904e07c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000162074a7047f',
maxFeePerGas: Big {
s: 1,
e: 10,
c: [
6, 7, 6, 8, 1,
2, 6, 1, 6, 1,
8
],
constructor: <ref *1> [Function: Big] {
DP: 20,
RM: 1,
NE: -7,
PE: 21,
strict: false,
roundDown: 0,
roundHalfUp: 1,
roundHalfEven: 2,
roundUp: 3,
Big: [Circular *1],
default: [Circular *1]
}
},
maxPriorityFeePerGas: Big {
s: 1,
e: 9,
c: [ 1, 5 ],
constructor: <ref *1> [Function: Big] {
DP: 20,
RM: 1,
NE: -7,
PE: 21,
strict: false,
roundDown: 0,
roundHalfUp: 1,
roundHalfEven: 2,
roundUp: 3,
Big: [Circular *1],
default: [Circular *1]
}
},
nonce: 129,
r: '0x59a7c15b12c18cd68d6c440963d959bff3e73831ffc938e75ecad07f7ee43fbc',
s: '0x1ebaf05f0d9273b16c2a7748b150a79d22533a8cd74552611cbe620fee3dcf1c',
to: '0x39B72d136ba3e4ceF35F48CD09587ffaB754DD8B',
transactionIndex: 29,
type: 2,
v: 0,
value: Big {
s: 1,
e: 0,
c: [ 0 ],
constructor: <ref *1> [Function: Big] {
DP: 20,
RM: 1,
NE: -7,
PE: 21,
strict: false,
roundDown: 0,
roundHalfUp: 1,
roundHalfEven: 2,
roundUp: 3,
Big: [Circular *1],
default: [Circular *1]
}
},
confirmations: 1210
}
*/
- 🧪
Contract
support is experimental, do not use this in production yet. (even though earni.fi does)
Encoding support:
bool
bytes
address
Decoding support:
bool
address
uint256
bytes32
uint8
Assume all types outside the above types will break for now
import { Contract, jsonRpcProvider, JSONABI } from 'essential-eth';
// UNI airdrop contract
const contractAddress = '0x090D4613473dEE047c3f2706764f49E0821D256e';
const provider = jsonRpcProvider(/* RPC URL optional */);
const abi: JSONABI = [
{
inputs: [
{
internalType: 'uint256',
name: 'index',
type: 'uint256',
},
],
name: 'isClaimed',
outputs: [
{
internalType: 'bool',
name: '',
type: 'bool',
},
],
stateMutability: 'view',
type: 'function',
},
];
const contract = new Contract(contractAddress, abi, provider);
(async () => {
// prints boolean as to whether index 0 has claimed airdrop or not
console.log(await contract.isClaimed(0));
})();
Any function on a contract. Returns are the same as ethers.js
, except that instead of BigNumber, essential-eth
always returns a TinyBig
🧪 This repo is under active development. The API is less-fully featured than web3
and ethers
. More functions added often!
👨🏻💻 Breaking changes will exist between minor versions until 1.0.0
(Versions go major.minor.patch
)