🪶 Essential Eth 🪶
An alternative 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
computeAddress
computePublicKey
concat
etherToGwei
etherToWei
gweiToEther
hashMessage
hexConcat
hexDataLength
hexDataSlice
hexStripZeros
hexValue
hexZeroPad
hexlify
isAddress
isBytes
isBytesLike
isHexString
jsonRpcProvider
keccak256
pack
solidityKeccak256
splitSignature
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 ]
computeAddress(key: string): string
computePublicKey(privKey: BytesLike): string
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'
splitSignature(signature: SignatureLike): Signature
View Example
import { splitSignature } from 'essential-eth';
// or in a require environment
const { splitSignature } = require('essential-eth');
const signature = '0x60bc4ed91f2021aefe7045f3f77bd12f87eb733aee24bd1965343b3c27b3971647252185b7d2abb411b01b5d1ac4ab41ea486df1e9b396758c1aec6c1b6eee331b';
splitSignature(signature);
{
r: "0x60bc4ed91f2021aefe7045f3f77bd12f87eb733aee24bd1965343b3c27b39716",
s: "0x47252185b7d2abb411b01b5d1ac4ab41ea486df1e9b396758c1aec6c1b6eee33",
_vs: "0x47252185b7d2abb411b01b5d1ac4ab41ea486df1e9b396758c1aec6c1b6eee33",
recoveryParam: 0,
v: 27,
yParityAndS: "0x47252185b7d2abb411b01b5d1ac4ab41ea486df1e9b396758c1aec6c1b6eee33",
compact: "0x60bc4ed91f2021aefe7045f3f77bd12f87eb733aee24bd1965343b3c27b3971647252185b7d2abb411b01b5d1ac4ab41ea486df1e9b396758c1aec6c1b6eee33"
}
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
)