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.
- package/lib/cjs/index.d.ts +2 -1
- package/lib/cjs/index.js +3 -1
- package/lib/cjs/rpc/get-block.test.d.ts +1 -0
- package/lib/cjs/rpc/get-block.test.js +66 -0
- package/lib/cjs/rpc/index.d.ts +6 -0
- package/lib/cjs/rpc/index.js +36 -0
- package/lib/cjs/rpc/utils/clean-block.d.ts +2 -0
- package/lib/cjs/rpc/utils/clean-block.js +38 -0
- package/lib/cjs/rpc/utils/clean-transaction.d.ts +2 -0
- package/lib/cjs/rpc/utils/clean-transaction.js +33 -0
- package/lib/cjs/rpc/utils/fetchers.d.ts +7 -0
- package/lib/cjs/rpc/utils/fetchers.js +26 -0
- package/lib/cjs/rpc/utils/hex-to-decimal.d.ts +1 -0
- package/lib/cjs/rpc/utils/hex-to-decimal.js +7 -0
- package/lib/cjs/shared/tiny-big/tiny-big.d.ts +1 -2
- package/lib/cjs/shared/tiny-big/tiny-big.js +7 -4
- package/lib/cjs/types/block.types.d.ts +47 -0
- package/lib/cjs/types/block.types.js +2 -0
- package/lib/cjs/types/transaction.types.d.ts +34 -0
- package/lib/cjs/types/transaction.types.js +2 -0
- package/lib/esm/index.d.ts +2 -1
- package/lib/esm/index.js +2 -1
- package/lib/esm/rpc/get-block.test.d.ts +1 -0
- package/lib/esm/rpc/get-block.test.js +61 -0
- package/lib/esm/rpc/index.d.ts +6 -0
- package/lib/esm/rpc/index.js +32 -0
- package/lib/esm/rpc/utils/clean-block.d.ts +2 -0
- package/lib/esm/rpc/utils/clean-block.js +34 -0
- package/lib/esm/rpc/utils/clean-transaction.d.ts +2 -0
- package/lib/esm/rpc/utils/clean-transaction.js +29 -0
- package/lib/esm/rpc/utils/fetchers.d.ts +7 -0
- package/lib/esm/rpc/utils/fetchers.js +18 -0
- package/lib/esm/rpc/utils/hex-to-decimal.d.ts +1 -0
- package/lib/esm/rpc/utils/hex-to-decimal.js +3 -0
- package/lib/esm/shared/tiny-big/tiny-big.d.ts +1 -2
- package/lib/esm/shared/tiny-big/tiny-big.js +7 -4
- package/lib/esm/types/block.types.d.ts +47 -0
- package/lib/esm/types/block.types.js +1 -0
- package/lib/esm/types/transaction.types.d.ts +34 -0
- package/lib/esm/types/transaction.types.js +1 -0
- package/package.json +13 -1
- package/readme.md +35 -2
package/lib/cjs/index.d.ts
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, };
|
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,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,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,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;
|
|
@@ -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
|
-
|
|
11
|
+
super(value);
|
|
12
12
|
}
|
|
13
13
|
toNumber() {
|
|
14
|
-
return Number((0, helpers_1.scientificStrToDecimalStr)(
|
|
14
|
+
return Number((0, helpers_1.scientificStrToDecimalStr)(super.toString()));
|
|
15
15
|
}
|
|
16
16
|
toString() {
|
|
17
|
-
|
|
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,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
|
+
}
|
package/lib/esm/index.d.ts
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, };
|
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,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,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,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;
|
|
@@ -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
|
-
|
|
5
|
+
super(value);
|
|
6
6
|
}
|
|
7
7
|
toNumber() {
|
|
8
|
-
return Number(scientificStrToDecimalStr(
|
|
8
|
+
return Number(scientificStrToDecimalStr(super.toString()));
|
|
9
9
|
}
|
|
10
10
|
toString() {
|
|
11
|
-
|
|
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.
|
|
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
|

|
|
27
27
|

|
|
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
|
-
##
|
|
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
|
-
|
|
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)
|