essential-eth 0.1.4 โ†’ 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/lib/cjs/index.d.ts +2 -1
  2. package/lib/cjs/index.js +3 -1
  3. package/lib/cjs/rpc/get-block.test.d.ts +1 -0
  4. package/lib/cjs/rpc/get-block.test.js +66 -0
  5. package/lib/cjs/rpc/index.d.ts +6 -0
  6. package/lib/cjs/rpc/index.js +36 -0
  7. package/lib/cjs/rpc/utils/clean-block.d.ts +2 -0
  8. package/lib/cjs/rpc/utils/clean-block.js +38 -0
  9. package/lib/cjs/rpc/utils/clean-transaction.d.ts +2 -0
  10. package/lib/cjs/rpc/utils/clean-transaction.js +33 -0
  11. package/lib/cjs/rpc/utils/fetchers.d.ts +7 -0
  12. package/lib/cjs/rpc/utils/fetchers.js +26 -0
  13. package/lib/cjs/rpc/utils/hex-to-decimal.d.ts +1 -0
  14. package/lib/cjs/rpc/utils/hex-to-decimal.js +7 -0
  15. package/lib/cjs/shared/tiny-big/tiny-big.d.ts +1 -2
  16. package/lib/cjs/shared/tiny-big/tiny-big.js +7 -4
  17. package/lib/cjs/types/block.types.d.ts +47 -0
  18. package/lib/cjs/types/block.types.js +2 -0
  19. package/lib/cjs/types/transaction.types.d.ts +34 -0
  20. package/lib/cjs/types/transaction.types.js +2 -0
  21. package/lib/esm/index.d.ts +2 -1
  22. package/lib/esm/index.js +2 -1
  23. package/lib/esm/rpc/get-block.test.d.ts +1 -0
  24. package/lib/esm/rpc/get-block.test.js +61 -0
  25. package/lib/esm/rpc/index.d.ts +6 -0
  26. package/lib/esm/rpc/index.js +32 -0
  27. package/lib/esm/rpc/utils/clean-block.d.ts +2 -0
  28. package/lib/esm/rpc/utils/clean-block.js +34 -0
  29. package/lib/esm/rpc/utils/clean-transaction.d.ts +2 -0
  30. package/lib/esm/rpc/utils/clean-transaction.js +29 -0
  31. package/lib/esm/rpc/utils/fetchers.d.ts +7 -0
  32. package/lib/esm/rpc/utils/fetchers.js +18 -0
  33. package/lib/esm/rpc/utils/hex-to-decimal.d.ts +1 -0
  34. package/lib/esm/rpc/utils/hex-to-decimal.js +3 -0
  35. package/lib/esm/shared/tiny-big/tiny-big.d.ts +1 -2
  36. package/lib/esm/shared/tiny-big/tiny-big.js +7 -4
  37. package/lib/esm/types/block.types.d.ts +47 -0
  38. package/lib/esm/types/block.types.js +1 -0
  39. package/lib/esm/types/transaction.types.d.ts +34 -0
  40. package/lib/esm/types/transaction.types.js +1 -0
  41. package/package.json +13 -1
  42. package/readme.md +35 -2
@@ -1,5 +1,6 @@
1
1
  import { etherToWei } from './ether-to-wei';
2
+ import { EssentialEth } from './rpc/index';
2
3
  import { tinyBig, TinyBig } from './shared/tiny-big/tiny-big';
3
4
  import { toChecksumAddress } from './to-checksum-address';
4
5
  import { weiToEther } from './wei-to-ether';
5
- export { toChecksumAddress, etherToWei, weiToEther, tinyBig, TinyBig };
6
+ export { toChecksumAddress, etherToWei, weiToEther, tinyBig, TinyBig, EssentialEth, };
package/lib/cjs/index.js CHANGED
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TinyBig = exports.tinyBig = exports.weiToEther = exports.etherToWei = exports.toChecksumAddress = void 0;
3
+ exports.EssentialEth = exports.TinyBig = exports.tinyBig = exports.weiToEther = exports.etherToWei = exports.toChecksumAddress = void 0;
4
4
  const ether_to_wei_1 = require("./ether-to-wei");
5
5
  Object.defineProperty(exports, "etherToWei", { enumerable: true, get: function () { return ether_to_wei_1.etherToWei; } });
6
+ const index_1 = require("./rpc/index");
7
+ Object.defineProperty(exports, "EssentialEth", { enumerable: true, get: function () { return index_1.EssentialEth; } });
6
8
  const tiny_big_1 = require("./shared/tiny-big/tiny-big");
7
9
  Object.defineProperty(exports, "tinyBig", { enumerable: true, get: function () { return tiny_big_1.tinyBig; } });
8
10
  Object.defineProperty(exports, "TinyBig", { enumerable: true, get: function () { return tiny_big_1.TinyBig; } });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const big_js_1 = __importDefault(require("big.js"));
16
+ const just_omit_1 = __importDefault(require("just-omit"));
17
+ const web3_1 = __importDefault(require("web3"));
18
+ const _1 = require(".");
19
+ const rpcUrl = 'https://free-eth-node.com/api/eth';
20
+ describe('matches web3', () => {
21
+ function testBlockEquality(block1, block2) {
22
+ expect((0, just_omit_1.default)(block1, ['totalDifficulty', 'difficulty'])).toStrictEqual((0, just_omit_1.default)(block2, ['totalDifficulty', 'difficulty']));
23
+ expect((0, big_js_1.default)(block1.difficulty).minus(block2.difficulty).abs().toNumber()).toBeLessThan(3);
24
+ expect((0, big_js_1.default)(block1.totalDifficulty)
25
+ .minus(block2.totalDifficulty)
26
+ .abs()
27
+ .toNumber()).toBeLessThan(4000000);
28
+ }
29
+ it('should allow default eth node to get latest block', () => __awaiter(void 0, void 0, void 0, function* () {
30
+ const essentialEth = new _1.EssentialEth();
31
+ const web3 = new web3_1.default(rpcUrl);
32
+ const [eeLatestBlock, web3LatestBlock] = yield Promise.all([
33
+ essentialEth.getBlock('latest'),
34
+ web3.eth.getBlock('latest'),
35
+ ]);
36
+ testBlockEquality(eeLatestBlock, web3LatestBlock);
37
+ }));
38
+ it('should get latest block', () => __awaiter(void 0, void 0, void 0, function* () {
39
+ const essentialEth = new _1.EssentialEth(rpcUrl);
40
+ const web3 = new web3_1.default(rpcUrl);
41
+ const [eeLatestBlock, web3LatestBlock] = yield Promise.all([
42
+ essentialEth.getBlock('latest'),
43
+ web3.eth.getBlock('latest'),
44
+ ]);
45
+ testBlockEquality(eeLatestBlock, web3LatestBlock);
46
+ }));
47
+ it('should get earliest block', () => __awaiter(void 0, void 0, void 0, function* () {
48
+ const essentialEth = new _1.EssentialEth(rpcUrl);
49
+ const web3 = new web3_1.default(rpcUrl);
50
+ const [eeEarliestBlock, web3EarliestBlock] = yield Promise.all([
51
+ essentialEth.getBlock('earliest'),
52
+ web3.eth.getBlock('earliest'),
53
+ ]);
54
+ testBlockEquality(eeEarliestBlock, web3EarliestBlock);
55
+ }));
56
+ const blockNumber = Math.floor(Math.random() * 13250630);
57
+ it(`should get random block as decimal integer. (block #${blockNumber})`, () => __awaiter(void 0, void 0, void 0, function* () {
58
+ const essentialEth = new _1.EssentialEth(rpcUrl);
59
+ const web3 = new web3_1.default(rpcUrl);
60
+ const [eeRandomBlock, web3RandomBlock] = yield Promise.all([
61
+ essentialEth.getBlock(blockNumber, true),
62
+ web3.eth.getBlock(blockNumber, true),
63
+ ]);
64
+ testBlockEquality(eeRandomBlock, web3RandomBlock);
65
+ }));
66
+ });
@@ -0,0 +1,6 @@
1
+ import { Block } from '../types/block.types';
2
+ export declare class EssentialEth {
3
+ _rpcUrl: string;
4
+ constructor(rpcUrl?: string);
5
+ getBlock(timeFrame: 'latest' | 'earliest' | 'pending' | number, returnTransactionObjects?: boolean): Promise<Block>;
6
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.EssentialEth = void 0;
13
+ const clean_block_1 = require("./utils/clean-block");
14
+ const fetchers_1 = require("./utils/fetchers");
15
+ class EssentialEth {
16
+ constructor(rpcUrl) {
17
+ this._rpcUrl = rpcUrl || 'https://free-eth-node.com/api/eth';
18
+ }
19
+ getBlock(timeFrame, returnTransactionObjects = false) {
20
+ return __awaiter(this, void 0, void 0, function* () {
21
+ let rpcTimeFrame;
22
+ if (typeof timeFrame === 'number') {
23
+ rpcTimeFrame = `0x${timeFrame.toString(16)}`;
24
+ }
25
+ else {
26
+ rpcTimeFrame = timeFrame;
27
+ }
28
+ const nodeResponse = yield (0, fetchers_1.post)(this._rpcUrl, (0, fetchers_1.buildRPCPostBody)('eth_getBlockByNumber', [
29
+ rpcTimeFrame,
30
+ returnTransactionObjects,
31
+ ])).then((data) => data.result);
32
+ return (0, clean_block_1.cleanBlock)(nodeResponse, returnTransactionObjects);
33
+ });
34
+ }
35
+ }
36
+ exports.EssentialEth = EssentialEth;
@@ -0,0 +1,2 @@
1
+ import { Block, RPCBlock } from '../../types/block.types';
2
+ export declare function cleanBlock(block: RPCBlock, returnTransactionObjects: boolean): Block;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanBlock = void 0;
4
+ const __1 = require("../..");
5
+ const clean_transaction_1 = require("./clean-transaction");
6
+ const hex_to_decimal_1 = require("./hex-to-decimal");
7
+ function cleanBlock(block, returnTransactionObjects) {
8
+ const cleanedBlock = Object.assign({}, block);
9
+ Object.keys(block).forEach((key) => {
10
+ if (!block[key])
11
+ return;
12
+ switch (key) {
13
+ case 'gasLimit':
14
+ case 'gasUsed':
15
+ case 'number':
16
+ case 'size':
17
+ case 'timestamp':
18
+ cleanedBlock[key] = Number((0, hex_to_decimal_1.hexToDecimal)(block[key]));
19
+ break;
20
+ case 'difficulty':
21
+ case 'totalDifficulty':
22
+ cleanedBlock[key] = (0, hex_to_decimal_1.hexToDecimal)(block[key]);
23
+ break;
24
+ case 'miner':
25
+ if (block[key]) {
26
+ cleanedBlock[key] = (0, __1.toChecksumAddress)(block[key]);
27
+ }
28
+ break;
29
+ }
30
+ });
31
+ if (returnTransactionObjects) {
32
+ cleanedBlock.transactions.forEach((transaction, index) => {
33
+ cleanedBlock.transactions[index] = (0, clean_transaction_1.cleanTransaction)(transaction);
34
+ });
35
+ }
36
+ return cleanedBlock;
37
+ }
38
+ exports.cleanBlock = cleanBlock;
@@ -0,0 +1,2 @@
1
+ import { RPCTransaction, Transaction } from '../../types/transaction.types';
2
+ export declare function cleanTransaction(transaction: RPCTransaction): Transaction;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanTransaction = void 0;
4
+ const __1 = require("../..");
5
+ const hex_to_decimal_1 = require("./hex-to-decimal");
6
+ function cleanTransaction(transaction) {
7
+ const cleanedTransaction = Object.assign({}, transaction);
8
+ Object.keys(transaction).forEach((key) => {
9
+ if (!transaction[key])
10
+ return;
11
+ switch (key) {
12
+ case 'blockNumber':
13
+ case 'gas':
14
+ case 'nonce':
15
+ case 'transactionIndex':
16
+ case 'type':
17
+ cleanedTransaction[key] = Number((0, hex_to_decimal_1.hexToDecimal)(transaction[key]));
18
+ break;
19
+ case 'gasPrice':
20
+ case 'value':
21
+ cleanedTransaction[key] = (0, hex_to_decimal_1.hexToDecimal)(transaction[key]);
22
+ break;
23
+ case 'from':
24
+ case 'to':
25
+ if (transaction[key]) {
26
+ cleanedTransaction[key] = (0, __1.toChecksumAddress)(transaction[key]);
27
+ }
28
+ break;
29
+ }
30
+ });
31
+ return cleanedTransaction;
32
+ }
33
+ exports.cleanTransaction = cleanTransaction;
@@ -0,0 +1,7 @@
1
+ export declare function post(url: string, body: Record<string, unknown>): Promise<any>;
2
+ export declare function buildRPCPostBody(method: 'eth_getBlockByNumber', params: any[]): {
3
+ jsonrpc: string;
4
+ id: number;
5
+ method: "eth_getBlockByNumber";
6
+ params: any[];
7
+ };
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildRPCPostBody = exports.post = void 0;
7
+ const isomorphic_unfetch_1 = __importDefault(require("isomorphic-unfetch"));
8
+ function post(url, body) {
9
+ return (0, isomorphic_unfetch_1.default)(url, {
10
+ method: 'POST',
11
+ headers: {
12
+ 'Content-Type': 'application/json',
13
+ },
14
+ body: JSON.stringify(body),
15
+ }).then((r) => r.json());
16
+ }
17
+ exports.post = post;
18
+ function buildRPCPostBody(method, params) {
19
+ return {
20
+ jsonrpc: '2.0',
21
+ id: 1,
22
+ method,
23
+ params,
24
+ };
25
+ }
26
+ exports.buildRPCPostBody = buildRPCPostBody;
@@ -0,0 +1 @@
1
+ export declare function hexToDecimal(hex: string): string;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hexToDecimal = void 0;
4
+ function hexToDecimal(hex) {
5
+ return BigInt(hex).toString();
6
+ }
7
+ exports.hexToDecimal = hexToDecimal;
@@ -1,6 +1,5 @@
1
1
  import Big from 'big.js';
2
- export declare class TinyBig {
3
- __value: Big;
2
+ export declare class TinyBig extends Big {
4
3
  constructor(value: number | string);
5
4
  toNumber(): number;
6
5
  toString(): string;
@@ -6,15 +6,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.tinyBig = exports.TinyBig = void 0;
7
7
  const big_js_1 = __importDefault(require("big.js"));
8
8
  const helpers_1 = require("./helpers");
9
- class TinyBig {
9
+ class TinyBig extends big_js_1.default {
10
10
  constructor(value) {
11
- this.__value = (0, big_js_1.default)(value);
11
+ super(value);
12
12
  }
13
13
  toNumber() {
14
- return Number((0, helpers_1.scientificStrToDecimalStr)(this.__value.toString()));
14
+ return Number((0, helpers_1.scientificStrToDecimalStr)(super.toString()));
15
15
  }
16
16
  toString() {
17
- return (0, helpers_1.scientificStrToDecimalStr)(this.__value.toString());
17
+ if (this.toNumber() === 0) {
18
+ return '0';
19
+ }
20
+ return (0, helpers_1.scientificStrToDecimalStr)(super.toString());
18
21
  }
19
22
  }
20
23
  exports.TinyBig = TinyBig;
@@ -0,0 +1,47 @@
1
+ import { RPCTransaction, Transaction } from './transaction.types';
2
+ export interface Block {
3
+ baseFeePerGas: string;
4
+ difficulty: number;
5
+ extraData: string;
6
+ gasLimit: number;
7
+ gasUsed: number;
8
+ hash: string;
9
+ logsBloom: string;
10
+ miner: string;
11
+ mixHash: string;
12
+ nonce: string;
13
+ number: number;
14
+ parentHash: string;
15
+ receiptsRoot: string;
16
+ sha3Uncles: string;
17
+ size: number;
18
+ stateRoot: string;
19
+ timestamp: number;
20
+ totalDifficulty: number;
21
+ transactions: string[] | Transaction[];
22
+ transactionsRoot: string;
23
+ uncles: unknown[];
24
+ }
25
+ export interface RPCBlock {
26
+ baseFeePerGas: string;
27
+ difficulty: string;
28
+ extraData: string;
29
+ gasLimit: string;
30
+ gasUsed: string;
31
+ hash: string;
32
+ logsBloom: string;
33
+ miner: string;
34
+ mixHash: string;
35
+ nonce: string;
36
+ number: string;
37
+ parentHash: string;
38
+ receiptsRoot: string;
39
+ sha3Uncles: string;
40
+ size: string;
41
+ stateRoot: string;
42
+ timestamp: string;
43
+ totalDifficulty: string;
44
+ transactions: Array<string> | Array<RPCTransaction>;
45
+ transactionsRoot: string;
46
+ uncles: unknown[];
47
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,34 @@
1
+ export interface Transaction {
2
+ blockHash: string;
3
+ blockNumber: number;
4
+ from: string;
5
+ gas: number;
6
+ gasPrice: string;
7
+ hash: string;
8
+ input: string;
9
+ nonce: number;
10
+ r: string;
11
+ s: string;
12
+ to: string;
13
+ transactionIndex: number;
14
+ type: number;
15
+ v: string;
16
+ value: string;
17
+ }
18
+ export interface RPCTransaction {
19
+ blockHash: string;
20
+ blockNumber: string;
21
+ from: string;
22
+ gas: string;
23
+ gasPrice: string;
24
+ hash: string;
25
+ input: string;
26
+ nonce: string;
27
+ r: string;
28
+ s: string;
29
+ to: string;
30
+ transactionIndex: string;
31
+ type: string;
32
+ v: string;
33
+ value: string;
34
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,5 +1,6 @@
1
1
  import { etherToWei } from './ether-to-wei';
2
+ import { EssentialEth } from './rpc/index';
2
3
  import { tinyBig, TinyBig } from './shared/tiny-big/tiny-big';
3
4
  import { toChecksumAddress } from './to-checksum-address';
4
5
  import { weiToEther } from './wei-to-ether';
5
- export { toChecksumAddress, etherToWei, weiToEther, tinyBig, TinyBig };
6
+ export { toChecksumAddress, etherToWei, weiToEther, tinyBig, TinyBig, EssentialEth, };
package/lib/esm/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { etherToWei } from './ether-to-wei';
2
+ import { EssentialEth } from './rpc/index';
2
3
  import { tinyBig, TinyBig } from './shared/tiny-big/tiny-big';
3
4
  import { toChecksumAddress } from './to-checksum-address';
4
5
  import { weiToEther } from './wei-to-ether';
5
- export { toChecksumAddress, etherToWei, weiToEther, tinyBig, TinyBig };
6
+ export { toChecksumAddress, etherToWei, weiToEther, tinyBig, TinyBig, EssentialEth, };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,61 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import Big from 'big.js';
11
+ import omit from 'just-omit';
12
+ import Web3 from 'web3';
13
+ import { EssentialEth } from '.';
14
+ const rpcUrl = 'https://free-eth-node.com/api/eth';
15
+ describe('matches web3', () => {
16
+ function testBlockEquality(block1, block2) {
17
+ expect(omit(block1, ['totalDifficulty', 'difficulty'])).toStrictEqual(omit(block2, ['totalDifficulty', 'difficulty']));
18
+ expect(Big(block1.difficulty).minus(block2.difficulty).abs().toNumber()).toBeLessThan(3);
19
+ expect(Big(block1.totalDifficulty)
20
+ .minus(block2.totalDifficulty)
21
+ .abs()
22
+ .toNumber()).toBeLessThan(4000000);
23
+ }
24
+ it('should allow default eth node to get latest block', () => __awaiter(void 0, void 0, void 0, function* () {
25
+ const essentialEth = new EssentialEth();
26
+ const web3 = new Web3(rpcUrl);
27
+ const [eeLatestBlock, web3LatestBlock] = yield Promise.all([
28
+ essentialEth.getBlock('latest'),
29
+ web3.eth.getBlock('latest'),
30
+ ]);
31
+ testBlockEquality(eeLatestBlock, web3LatestBlock);
32
+ }));
33
+ it('should get latest block', () => __awaiter(void 0, void 0, void 0, function* () {
34
+ const essentialEth = new EssentialEth(rpcUrl);
35
+ const web3 = new Web3(rpcUrl);
36
+ const [eeLatestBlock, web3LatestBlock] = yield Promise.all([
37
+ essentialEth.getBlock('latest'),
38
+ web3.eth.getBlock('latest'),
39
+ ]);
40
+ testBlockEquality(eeLatestBlock, web3LatestBlock);
41
+ }));
42
+ it('should get earliest block', () => __awaiter(void 0, void 0, void 0, function* () {
43
+ const essentialEth = new EssentialEth(rpcUrl);
44
+ const web3 = new Web3(rpcUrl);
45
+ const [eeEarliestBlock, web3EarliestBlock] = yield Promise.all([
46
+ essentialEth.getBlock('earliest'),
47
+ web3.eth.getBlock('earliest'),
48
+ ]);
49
+ testBlockEquality(eeEarliestBlock, web3EarliestBlock);
50
+ }));
51
+ const blockNumber = Math.floor(Math.random() * 13250630);
52
+ it(`should get random block as decimal integer. (block #${blockNumber})`, () => __awaiter(void 0, void 0, void 0, function* () {
53
+ const essentialEth = new EssentialEth(rpcUrl);
54
+ const web3 = new Web3(rpcUrl);
55
+ const [eeRandomBlock, web3RandomBlock] = yield Promise.all([
56
+ essentialEth.getBlock(blockNumber, true),
57
+ web3.eth.getBlock(blockNumber, true),
58
+ ]);
59
+ testBlockEquality(eeRandomBlock, web3RandomBlock);
60
+ }));
61
+ });
@@ -0,0 +1,6 @@
1
+ import { Block } from '../types/block.types';
2
+ export declare class EssentialEth {
3
+ _rpcUrl: string;
4
+ constructor(rpcUrl?: string);
5
+ getBlock(timeFrame: 'latest' | 'earliest' | 'pending' | number, returnTransactionObjects?: boolean): Promise<Block>;
6
+ }
@@ -0,0 +1,32 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { cleanBlock } from './utils/clean-block';
11
+ import { buildRPCPostBody, post } from './utils/fetchers';
12
+ export class EssentialEth {
13
+ constructor(rpcUrl) {
14
+ this._rpcUrl = rpcUrl || 'https://free-eth-node.com/api/eth';
15
+ }
16
+ getBlock(timeFrame, returnTransactionObjects = false) {
17
+ return __awaiter(this, void 0, void 0, function* () {
18
+ let rpcTimeFrame;
19
+ if (typeof timeFrame === 'number') {
20
+ rpcTimeFrame = `0x${timeFrame.toString(16)}`;
21
+ }
22
+ else {
23
+ rpcTimeFrame = timeFrame;
24
+ }
25
+ const nodeResponse = yield post(this._rpcUrl, buildRPCPostBody('eth_getBlockByNumber', [
26
+ rpcTimeFrame,
27
+ returnTransactionObjects,
28
+ ])).then((data) => data.result);
29
+ return cleanBlock(nodeResponse, returnTransactionObjects);
30
+ });
31
+ }
32
+ }
@@ -0,0 +1,2 @@
1
+ import { Block, RPCBlock } from '../../types/block.types';
2
+ export declare function cleanBlock(block: RPCBlock, returnTransactionObjects: boolean): Block;
@@ -0,0 +1,34 @@
1
+ import { toChecksumAddress } from '../..';
2
+ import { cleanTransaction } from './clean-transaction';
3
+ import { hexToDecimal } from './hex-to-decimal';
4
+ export function cleanBlock(block, returnTransactionObjects) {
5
+ const cleanedBlock = Object.assign({}, block);
6
+ Object.keys(block).forEach((key) => {
7
+ if (!block[key])
8
+ return;
9
+ switch (key) {
10
+ case 'gasLimit':
11
+ case 'gasUsed':
12
+ case 'number':
13
+ case 'size':
14
+ case 'timestamp':
15
+ cleanedBlock[key] = Number(hexToDecimal(block[key]));
16
+ break;
17
+ case 'difficulty':
18
+ case 'totalDifficulty':
19
+ cleanedBlock[key] = hexToDecimal(block[key]);
20
+ break;
21
+ case 'miner':
22
+ if (block[key]) {
23
+ cleanedBlock[key] = toChecksumAddress(block[key]);
24
+ }
25
+ break;
26
+ }
27
+ });
28
+ if (returnTransactionObjects) {
29
+ cleanedBlock.transactions.forEach((transaction, index) => {
30
+ cleanedBlock.transactions[index] = cleanTransaction(transaction);
31
+ });
32
+ }
33
+ return cleanedBlock;
34
+ }
@@ -0,0 +1,2 @@
1
+ import { RPCTransaction, Transaction } from '../../types/transaction.types';
2
+ export declare function cleanTransaction(transaction: RPCTransaction): Transaction;
@@ -0,0 +1,29 @@
1
+ import { toChecksumAddress } from '../..';
2
+ import { hexToDecimal } from './hex-to-decimal';
3
+ export function cleanTransaction(transaction) {
4
+ const cleanedTransaction = Object.assign({}, transaction);
5
+ Object.keys(transaction).forEach((key) => {
6
+ if (!transaction[key])
7
+ return;
8
+ switch (key) {
9
+ case 'blockNumber':
10
+ case 'gas':
11
+ case 'nonce':
12
+ case 'transactionIndex':
13
+ case 'type':
14
+ cleanedTransaction[key] = Number(hexToDecimal(transaction[key]));
15
+ break;
16
+ case 'gasPrice':
17
+ case 'value':
18
+ cleanedTransaction[key] = hexToDecimal(transaction[key]);
19
+ break;
20
+ case 'from':
21
+ case 'to':
22
+ if (transaction[key]) {
23
+ cleanedTransaction[key] = toChecksumAddress(transaction[key]);
24
+ }
25
+ break;
26
+ }
27
+ });
28
+ return cleanedTransaction;
29
+ }
@@ -0,0 +1,7 @@
1
+ export declare function post(url: string, body: Record<string, unknown>): Promise<any>;
2
+ export declare function buildRPCPostBody(method: 'eth_getBlockByNumber', params: any[]): {
3
+ jsonrpc: string;
4
+ id: number;
5
+ method: "eth_getBlockByNumber";
6
+ params: any[];
7
+ };
@@ -0,0 +1,18 @@
1
+ import unfetch from 'isomorphic-unfetch';
2
+ export function post(url, body) {
3
+ return unfetch(url, {
4
+ method: 'POST',
5
+ headers: {
6
+ 'Content-Type': 'application/json',
7
+ },
8
+ body: JSON.stringify(body),
9
+ }).then((r) => r.json());
10
+ }
11
+ export function buildRPCPostBody(method, params) {
12
+ return {
13
+ jsonrpc: '2.0',
14
+ id: 1,
15
+ method,
16
+ params,
17
+ };
18
+ }
@@ -0,0 +1 @@
1
+ export declare function hexToDecimal(hex: string): string;
@@ -0,0 +1,3 @@
1
+ export function hexToDecimal(hex) {
2
+ return BigInt(hex).toString();
3
+ }
@@ -1,6 +1,5 @@
1
1
  import Big from 'big.js';
2
- export declare class TinyBig {
3
- __value: Big;
2
+ export declare class TinyBig extends Big {
4
3
  constructor(value: number | string);
5
4
  toNumber(): number;
6
5
  toString(): string;
@@ -1,14 +1,17 @@
1
1
  import Big from 'big.js';
2
2
  import { scientificStrToDecimalStr } from './helpers';
3
- export class TinyBig {
3
+ export class TinyBig extends Big {
4
4
  constructor(value) {
5
- this.__value = Big(value);
5
+ super(value);
6
6
  }
7
7
  toNumber() {
8
- return Number(scientificStrToDecimalStr(this.__value.toString()));
8
+ return Number(scientificStrToDecimalStr(super.toString()));
9
9
  }
10
10
  toString() {
11
- return scientificStrToDecimalStr(this.__value.toString());
11
+ if (this.toNumber() === 0) {
12
+ return '0';
13
+ }
14
+ return scientificStrToDecimalStr(super.toString());
12
15
  }
13
16
  }
14
17
  export function tinyBig(value) {
@@ -0,0 +1,47 @@
1
+ import { RPCTransaction, Transaction } from './transaction.types';
2
+ export interface Block {
3
+ baseFeePerGas: string;
4
+ difficulty: number;
5
+ extraData: string;
6
+ gasLimit: number;
7
+ gasUsed: number;
8
+ hash: string;
9
+ logsBloom: string;
10
+ miner: string;
11
+ mixHash: string;
12
+ nonce: string;
13
+ number: number;
14
+ parentHash: string;
15
+ receiptsRoot: string;
16
+ sha3Uncles: string;
17
+ size: number;
18
+ stateRoot: string;
19
+ timestamp: number;
20
+ totalDifficulty: number;
21
+ transactions: string[] | Transaction[];
22
+ transactionsRoot: string;
23
+ uncles: unknown[];
24
+ }
25
+ export interface RPCBlock {
26
+ baseFeePerGas: string;
27
+ difficulty: string;
28
+ extraData: string;
29
+ gasLimit: string;
30
+ gasUsed: string;
31
+ hash: string;
32
+ logsBloom: string;
33
+ miner: string;
34
+ mixHash: string;
35
+ nonce: string;
36
+ number: string;
37
+ parentHash: string;
38
+ receiptsRoot: string;
39
+ sha3Uncles: string;
40
+ size: string;
41
+ stateRoot: string;
42
+ timestamp: string;
43
+ totalDifficulty: string;
44
+ transactions: Array<string> | Array<RPCTransaction>;
45
+ transactionsRoot: string;
46
+ uncles: unknown[];
47
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,34 @@
1
+ export interface Transaction {
2
+ blockHash: string;
3
+ blockNumber: number;
4
+ from: string;
5
+ gas: number;
6
+ gasPrice: string;
7
+ hash: string;
8
+ input: string;
9
+ nonce: number;
10
+ r: string;
11
+ s: string;
12
+ to: string;
13
+ transactionIndex: number;
14
+ type: number;
15
+ v: string;
16
+ value: string;
17
+ }
18
+ export interface RPCTransaction {
19
+ blockHash: string;
20
+ blockNumber: string;
21
+ from: string;
22
+ gas: string;
23
+ gasPrice: string;
24
+ hash: string;
25
+ input: string;
26
+ nonce: string;
27
+ r: string;
28
+ s: string;
29
+ to: string;
30
+ transactionIndex: string;
31
+ type: string;
32
+ v: string;
33
+ value: string;
34
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "essential-eth",
3
3
  "description": "Ultralight JS library for Ethereum utilities",
4
- "version": "0.1.4",
4
+ "version": "0.2.0",
5
5
  "license": "MIT",
6
6
  "sideEffects": false,
7
7
  "main": "./lib/cjs/index.js",
@@ -29,19 +29,30 @@
29
29
  "devDependencies": {
30
30
  "@ethersproject/keccak256": "^5.4.0",
31
31
  "@types/big.js": "^6.1.2",
32
+ "@types/body-parser": "^1.19.1",
33
+ "@types/eslint": "^7.28.0",
34
+ "@types/express": "^4.17.13",
32
35
  "@types/jest": "^27.0.1",
36
+ "@types/jest-dev-server": "^5.0.0",
33
37
  "@types/node": "^16.9.2",
38
+ "@types/prettier": "^2.3.2",
39
+ "@types/supertest": "^2.0.11",
34
40
  "@typescript-eslint/eslint-plugin": "^4.31.1",
35
41
  "@typescript-eslint/parser": "^4.31.1",
42
+ "body-parser": "^1.19.0",
36
43
  "eslint": "^7.32.0",
37
44
  "eslint-plugin-jest": "^24.4.2",
38
45
  "ethers": "^5.4.7",
46
+ "express": "^4.17.1",
39
47
  "husky": "^4.3.0",
40
48
  "jest": "^27.2.0",
49
+ "jest-dev-server": "^5.0.3",
50
+ "just-omit": "^1.2.0",
41
51
  "lint-staged": "^11.1.2",
42
52
  "npm-run-all": "^4.1.5",
43
53
  "prettier": "^2.4.1",
44
54
  "prettier-plugin-organize-imports": "^2.3.3",
55
+ "supertest": "^6.1.6",
45
56
  "ts-jest": "^27.0.5",
46
57
  "ts-node": "^10.2.1",
47
58
  "typedoc": "^0.22.3",
@@ -50,6 +61,7 @@
50
61
  },
51
62
  "dependencies": {
52
63
  "big.js": "^6.1.1",
64
+ "isomorphic-unfetch": "^3.1.0",
53
65
  "sha3": "^2.1.4"
54
66
  },
55
67
  "husky": {
package/readme.md CHANGED
@@ -26,12 +26,15 @@
26
26
  ![](https://badgen.net/bundlephobia/min/essential-eth)
27
27
  ![](https://badgen.net/bundlephobia/dependency-count/essential-eth)
28
28
 
29
+ ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป Breaking changes will exist between minor versions until `1.0.0` (Versions go `major.minor.patch`)
30
+
29
31
  ## Features
30
32
 
31
33
  - โšก๏ธ A replacement for the utils in web3.js and ethers.js
32
34
  - ๐ŸŽ [The TINIEST code size possible](https://bundlephobia.com/package/essential-eth)
33
35
  - สฆ Fully typed with TypeScript (also works with JavaScript)
34
36
  - ๐ŸŒฒ Tree-shaking and no side-effects
37
+ - ๐Ÿงช Tested heavily to match both web3 and ethers.js
35
38
  - ๐Ÿ‘ฉโ€โš–๏ธ MIT License
36
39
 
37
40
  ## Install
@@ -43,7 +46,7 @@ npm install --save essential-eth # TypeScript types load automatically
43
46
  yarn add essential-eth # TypeScript types load automatically
44
47
  ```
45
48
 
46
- ## Require
49
+ ## Utils (do not require connecting to an Eth node)
47
50
 
48
51
  ```typescript
49
52
  import { etherToWei } from 'essential-eth';
@@ -52,18 +55,48 @@ import { etherToWei } from 'essential-eth';
52
55
  const { etherToWei } = require('essential-eth');
53
56
  ```
54
57
 
55
- ## Functions
58
+ #### `etherToWei`
56
59
 
57
60
  ```typescript
58
61
  // convert ether to wei
59
62
  etherToWei(etherQuantity: string | number): TinyBig
63
+ ```
64
+
65
+ #### `weiToEther`
60
66
 
67
+ ```typescript
61
68
  // convert wei to ether
62
69
  weiToEther(weiQuantity: string | number): TinyBig
70
+ ```
63
71
 
72
+ #### `toChecksumAddress`
73
+
74
+ ```typescript
64
75
  // return proper mixed-case address
65
76
  toChecksumAddress(address: string): string
66
77
  ```
67
78
 
79
+ ## RPC
80
+
81
+ ```typescript
82
+ import { EssentialEth } from 'essential-eth';
83
+ const essentialEth = new EssentialEth('RPC URL HERE' /* Try POKT or Infura */);
84
+ // OR for very quick testing (limited to 500 requests)
85
+ const essentialEth = new EssentialEth();
86
+ ```
87
+
88
+ #### `getBlock`
89
+
90
+ Returns a [Block](src/types/block.types.ts)
91
+
92
+ ```typescript
93
+ // Same API as web3.eth.getBlock
94
+ getBlock(timeFrame: number | "latest" | "earliest" | "pending", returnTransactionObjects?: boolean): Promise<Block>
95
+ ```
96
+
97
+ <br/>
98
+ <br/>
99
+
68
100
  - [๐Ÿ““ View full docs](https://essential-eth.vercel.app)
101
+ - [๐Ÿ““ View changelog (by looking at releases diff)](https://github.com/dawsbot/essential-eth/releases)
69
102
  - [๐Ÿ““ View docs for an older version](https://essential-eth.vercel.app/versions)