essential-eth 0.5.0 → 0.5.4
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/classes/Contract.d.ts +3 -2
- package/lib/cjs/classes/Contract.js +3 -2
- package/lib/cjs/classes/utils/clean-transaction-receipt.d.ts +5 -0
- package/lib/cjs/classes/utils/clean-transaction-receipt.js +55 -0
- package/lib/cjs/classes/utils/encode-decode-transaction.d.ts +1 -0
- package/lib/cjs/classes/utils/encode-decode-transaction.js +4 -4
- package/lib/cjs/classes/utils/fetchers.d.ts +1 -1
- package/lib/cjs/index.d.ts +7 -2
- package/lib/cjs/index.js +24 -3
- package/lib/cjs/logger/logger.d.ts +11 -0
- package/lib/cjs/logger/logger.js +36 -0
- package/lib/cjs/logger/package-version.d.ts +1 -0
- package/lib/cjs/logger/package-version.js +5 -0
- package/lib/cjs/providers/BaseProvider.d.ts +270 -0
- package/lib/cjs/providers/BaseProvider.js +361 -0
- package/lib/cjs/providers/FallthroughProvider.d.ts +25 -0
- package/lib/cjs/providers/FallthroughProvider.js +65 -0
- package/lib/cjs/providers/JsonRpcProvider.d.ts +4 -200
- package/lib/cjs/providers/JsonRpcProvider.js +11 -263
- package/lib/cjs/providers/test/rpc-urls.d.ts +1 -0
- package/lib/cjs/providers/test/rpc-urls.js +1 -0
- package/lib/cjs/providers/utils/chains-info.d.ts +8 -0
- package/lib/cjs/providers/utils/chains-info.js +24 -0
- package/lib/cjs/shared/tiny-big/tiny-big.d.ts +9 -2
- package/lib/cjs/shared/tiny-big/tiny-big.js +27 -9
- package/lib/cjs/types/Transaction.types.d.ts +53 -0
- package/lib/cjs/utils/bytes.d.ts +172 -0
- package/lib/cjs/utils/bytes.js +564 -0
- package/lib/cjs/utils/hash-message.d.ts +12 -0
- package/lib/cjs/utils/hash-message.js +26 -0
- package/lib/cjs/utils/keccak256.d.ts +2 -0
- package/lib/cjs/utils/keccak256.js +17 -0
- package/lib/cjs/utils/solidity-keccak256.d.ts +29 -0
- package/lib/cjs/utils/solidity-keccak256.js +118 -0
- package/lib/cjs/utils/to-utf8-bytes.d.ts +1 -0
- package/lib/cjs/utils/to-utf8-bytes.js +7 -0
- package/lib/esm/classes/Contract.js +1 -1
- package/lib/esm/classes/utils/clean-transaction-receipt.d.ts +2 -0
- package/lib/esm/classes/utils/clean-transaction-receipt.js +48 -0
- package/lib/esm/classes/utils/encode-decode-transaction.d.ts +1 -0
- package/lib/esm/classes/utils/encode-decode-transaction.js +2 -2
- package/lib/esm/classes/utils/fetchers.d.ts +1 -1
- package/lib/esm/index.d.ts +7 -2
- package/lib/esm/index.js +7 -2
- package/lib/esm/logger/logger.d.ts +11 -0
- package/lib/esm/logger/logger.js +33 -0
- package/lib/esm/logger/package-version.d.ts +1 -0
- package/lib/esm/logger/package-version.js +1 -0
- package/lib/esm/providers/BaseProvider.d.ts +18 -0
- package/lib/esm/providers/BaseProvider.js +101 -0
- package/lib/esm/providers/FallthroughProvider.d.ts +12 -0
- package/lib/esm/providers/FallthroughProvider.js +41 -0
- package/lib/esm/providers/JsonRpcProvider.d.ts +4 -12
- package/lib/esm/providers/JsonRpcProvider.js +8 -69
- package/lib/esm/providers/test/rpc-urls.d.ts +1 -0
- package/lib/esm/providers/test/rpc-urls.js +1 -0
- package/lib/esm/providers/utils/chains-info.d.ts +8 -0
- package/lib/esm/providers/utils/chains-info.js +24 -0
- package/lib/esm/shared/tiny-big/tiny-big.d.ts +2 -0
- package/lib/esm/shared/tiny-big/tiny-big.js +20 -7
- package/lib/esm/types/Transaction.types.d.ts +45 -0
- package/lib/esm/utils/bytes.d.ts +40 -0
- package/lib/esm/utils/bytes.js +245 -0
- package/lib/esm/utils/hash-message.d.ts +2 -0
- package/lib/esm/utils/hash-message.js +12 -0
- package/lib/esm/utils/keccak256.d.ts +2 -0
- package/lib/esm/utils/keccak256.js +13 -0
- package/lib/esm/utils/solidity-keccak256.d.ts +2 -0
- package/lib/esm/utils/solidity-keccak256.js +85 -0
- package/lib/esm/utils/to-utf8-bytes.d.ts +1 -0
- package/lib/esm/utils/to-utf8-bytes.js +3 -0
- package/package.json +19 -19
- package/readme.md +36 -5
- package/lib/cjs/utils/hex-zero-pad.d.ts +0 -32
- package/lib/cjs/utils/hex-zero-pad.js +0 -52
- package/lib/esm/utils/hex-zero-pad.d.ts +0 -1
- package/lib/esm/utils/hex-zero-pad.js +0 -17
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.solidityKeccak256 = exports.pack = void 0;
|
|
4
|
+
const buffer_1 = require("buffer");
|
|
5
|
+
const encode_decode_transaction_1 = require("../classes/utils/encode-decode-transaction");
|
|
6
|
+
const logger_1 = require("../logger/logger");
|
|
7
|
+
const tiny_big_1 = require("../shared/tiny-big/tiny-big");
|
|
8
|
+
const bytes_1 = require("./bytes");
|
|
9
|
+
const keccak256_1 = require("./keccak256");
|
|
10
|
+
const regexBytes = new RegExp('^bytes([0-9]+)$');
|
|
11
|
+
const regexNumber = new RegExp('^(u?int)([0-9]*)$');
|
|
12
|
+
const regexArray = new RegExp('^(.*)\\[([0-9]*)\\]$');
|
|
13
|
+
function _pack(type, value, isArray) {
|
|
14
|
+
switch (type) {
|
|
15
|
+
case 'address':
|
|
16
|
+
if (isArray) {
|
|
17
|
+
return (0, bytes_1.zeroPad)(value, 32);
|
|
18
|
+
}
|
|
19
|
+
return (0, bytes_1.arrayify)(value);
|
|
20
|
+
case 'string':
|
|
21
|
+
return buffer_1.Buffer.from(value);
|
|
22
|
+
case 'bytes':
|
|
23
|
+
return (0, bytes_1.arrayify)(value);
|
|
24
|
+
case 'bool':
|
|
25
|
+
value = value ? '0x01' : '0x00';
|
|
26
|
+
if (isArray) {
|
|
27
|
+
return (0, bytes_1.zeroPad)(value, 32);
|
|
28
|
+
}
|
|
29
|
+
return (0, bytes_1.arrayify)(value);
|
|
30
|
+
}
|
|
31
|
+
let match = type.match(regexNumber);
|
|
32
|
+
if (match) {
|
|
33
|
+
//let signed = (match[1] === "int")
|
|
34
|
+
let size = parseInt(match[2] || '256');
|
|
35
|
+
if ((match[2] && String(size) !== match[2]) ||
|
|
36
|
+
size % 8 !== 0 ||
|
|
37
|
+
size === 0 ||
|
|
38
|
+
size > 256) {
|
|
39
|
+
logger_1.logger.throwArgumentError('invalid number type', 'type', type);
|
|
40
|
+
}
|
|
41
|
+
if (isArray) {
|
|
42
|
+
size = 256;
|
|
43
|
+
}
|
|
44
|
+
value = (0, tiny_big_1.tinyBig)(value).toTwos(size).toNumber();
|
|
45
|
+
const hexValue = (0, bytes_1.hexlify)(value);
|
|
46
|
+
return (0, bytes_1.zeroPad)(hexValue, size / 8);
|
|
47
|
+
}
|
|
48
|
+
match = type.match(regexBytes);
|
|
49
|
+
if (match) {
|
|
50
|
+
const size = parseInt(match[1]);
|
|
51
|
+
if (String(size) !== match[1] || size === 0 || size > 32) {
|
|
52
|
+
logger_1.logger.throwArgumentError('invalid bytes type', 'type', type);
|
|
53
|
+
}
|
|
54
|
+
if ((0, bytes_1.arrayify)(value).byteLength !== size) {
|
|
55
|
+
logger_1.logger.throwArgumentError(`invalid value for ${type}`, 'value', value);
|
|
56
|
+
}
|
|
57
|
+
if (isArray) {
|
|
58
|
+
return (0, bytes_1.arrayify)((value + encode_decode_transaction_1.hexFalse).substring(0, 66));
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
match = type.match(regexArray);
|
|
63
|
+
if (match && Array.isArray(value)) {
|
|
64
|
+
const baseType = match[1];
|
|
65
|
+
const count = parseInt(match[2] || String(value.length));
|
|
66
|
+
if (count != value.length) {
|
|
67
|
+
logger_1.logger.throwArgumentError(`invalid array length for ${type}`, 'value', value);
|
|
68
|
+
}
|
|
69
|
+
const result = [];
|
|
70
|
+
value.forEach(function (value) {
|
|
71
|
+
result.push(_pack(baseType, value, true));
|
|
72
|
+
});
|
|
73
|
+
return (0, bytes_1.concat)(result);
|
|
74
|
+
}
|
|
75
|
+
return logger_1.logger.throwArgumentError('invalid type', 'type', type);
|
|
76
|
+
}
|
|
77
|
+
function pack(types, values) {
|
|
78
|
+
if (types.length != values.length) {
|
|
79
|
+
logger_1.logger.throwArgumentError('wrong number of values; expected ${ types.length }', 'values', values);
|
|
80
|
+
}
|
|
81
|
+
const tight = [];
|
|
82
|
+
types.forEach(function (type, index) {
|
|
83
|
+
tight.push(_pack(type, values[index]));
|
|
84
|
+
});
|
|
85
|
+
return (0, bytes_1.hexlify)((0, bytes_1.concat)(tight));
|
|
86
|
+
}
|
|
87
|
+
exports.pack = pack;
|
|
88
|
+
/**
|
|
89
|
+
* Hashes data from Solidity using the Keccak256 algorithm.
|
|
90
|
+
*
|
|
91
|
+
* Similar to ["solidityKeccak256" in ethers.js](https://docs.ethers.io/v5/api/utils/hashing/#utils-solidityKeccak256)
|
|
92
|
+
*
|
|
93
|
+
* @param types - Each [Solidity type](https://docs.soliditylang.org/en/v0.8.13/types.html) corresponding to the values passed in. Helps the function parse and pack data properly.
|
|
94
|
+
*
|
|
95
|
+
* @param values - Data to be concatenated (combined) and then hashed.
|
|
96
|
+
*
|
|
97
|
+
* @returns - A Keccak256 hash (hex string) based on the values provided
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```javascript
|
|
101
|
+
* const types = ['string', 'bool', 'uint32'];
|
|
102
|
+
* const values = ['essential-eth is great', true, 14];
|
|
103
|
+
* solidityKeccak256(types, values);
|
|
104
|
+
* // '0xe4d4c8e809faac09d58f468f0aeab9474fe8965d554c6c0f868c433c3fd6acab'
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```javascript
|
|
109
|
+
* const types = ['bytes4', 'uint32[5]'];
|
|
110
|
+
* const values = [[116, 101, 115, 116], [5, 3, 4, 9, 18]];
|
|
111
|
+
* solidityKeccak256(types, values);
|
|
112
|
+
* // '0x038707a887f09355dc545412b058e7ba8f3c74047050c7c5e5e52eec608053d9'
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
function solidityKeccak256(types, values) {
|
|
116
|
+
return (0, keccak256_1.keccak256)(pack(types, values));
|
|
117
|
+
}
|
|
118
|
+
exports.solidityKeccak256 = solidityKeccak256;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function toUtf8Bytes(data: string): Uint8Array;
|
|
@@ -40,7 +40,7 @@ export class BaseContract {
|
|
|
40
40
|
? estimateGas(data)
|
|
41
41
|
: null;
|
|
42
42
|
const req = () => __awaiter(this, void 0, void 0, function* () {
|
|
43
|
-
return yield post(this._provider.
|
|
43
|
+
return yield post(this._provider.selectRpcUrl(), buildRPCPostBody('eth_call', [
|
|
44
44
|
Object.assign({ to: this._address.toLowerCase(), data }, (decimalGas
|
|
45
45
|
? { gas: `0x${decimalGas.toString(16)}` }
|
|
46
46
|
: {})),
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { tinyBig, toChecksumAddress } from '../..';
|
|
2
|
+
import { cleanTransaction } from './clean-transaction';
|
|
3
|
+
import { hexToDecimal } from './hex-to-decimal';
|
|
4
|
+
export function cleanTransactionReceipt(transactionReceipt) {
|
|
5
|
+
const cleanedTransaction = cleanTransaction(transactionReceipt);
|
|
6
|
+
const cleanedTransactionReceipt = Object.assign({}, cleanedTransaction);
|
|
7
|
+
Object.keys(transactionReceipt).forEach((key) => {
|
|
8
|
+
if (!transactionReceipt[key])
|
|
9
|
+
return;
|
|
10
|
+
switch (key) {
|
|
11
|
+
case 'status':
|
|
12
|
+
cleanedTransactionReceipt[key] = Number(hexToDecimal(transactionReceipt[key]));
|
|
13
|
+
break;
|
|
14
|
+
case 'contractAddress':
|
|
15
|
+
if (transactionReceipt[key]) {
|
|
16
|
+
cleanedTransactionReceipt[key] = toChecksumAddress(transactionReceipt[key]);
|
|
17
|
+
}
|
|
18
|
+
break;
|
|
19
|
+
case 'cumulativeGasUsed':
|
|
20
|
+
case 'effectiveGasPrice':
|
|
21
|
+
case 'gasUsed':
|
|
22
|
+
cleanedTransactionReceipt[key] = tinyBig(hexToDecimal(transactionReceipt[key]));
|
|
23
|
+
break;
|
|
24
|
+
case 'logs':
|
|
25
|
+
transactionReceipt[key].forEach((log, index) => {
|
|
26
|
+
Object.keys(log).forEach((logKey) => {
|
|
27
|
+
switch (logKey) {
|
|
28
|
+
case 'address':
|
|
29
|
+
cleanedTransactionReceipt[key][index][logKey] =
|
|
30
|
+
toChecksumAddress(log[logKey]);
|
|
31
|
+
break;
|
|
32
|
+
case 'blockNumber':
|
|
33
|
+
case 'logIndex':
|
|
34
|
+
case 'transactionIndex':
|
|
35
|
+
cleanedTransactionReceipt[key][index][logKey] = Number(hexToDecimal(log[logKey]));
|
|
36
|
+
break;
|
|
37
|
+
case 'removed':
|
|
38
|
+
delete log[logKey];
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
cleanedTransactionReceipt.byzantium =
|
|
46
|
+
cleanedTransactionReceipt.blockNumber >= 4370000;
|
|
47
|
+
return cleanedTransactionReceipt;
|
|
48
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { JSONABIArgument } from '../../types/Contract.types';
|
|
2
|
+
export declare const hexFalse: string;
|
|
2
3
|
export declare function encodeData(jsonABIArgument: JSONABIArgument, args: any[]): string;
|
|
3
4
|
export declare function decodeRPCResponse(jsonABIArgument: JSONABIArgument, nodeResponse: string): string | number | boolean | import("../..").TinyBig | (string | number | boolean | import("../..").TinyBig)[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Keccak } from 'sha3';
|
|
2
2
|
import { tinyBig, toChecksumAddress } from '../..';
|
|
3
3
|
import { hexToDecimal } from './hex-to-decimal';
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
export const hexFalse = '0'.repeat(64);
|
|
5
|
+
const hexTrue = '0'.repeat(63) + '1';
|
|
6
6
|
function expandType(type) {
|
|
7
7
|
if (type === 'uint[]') {
|
|
8
8
|
return 'uint256[]';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare function post(url: string, body: Record<string, unknown>): Promise<any>;
|
|
2
|
-
declare type RPCMethodName = 'eth_getBlockByNumber' | 'eth_call' | 'eth_chainId' | 'eth_gasPrice' | 'eth_getBalance' | 'eth_getTransactionByHash';
|
|
2
|
+
declare type RPCMethodName = 'eth_getBlockByNumber' | 'eth_getBlockByHash' | 'eth_call' | 'eth_chainId' | 'eth_gasPrice' | 'eth_getBalance' | 'eth_getTransactionByHash' | 'eth_getTransactionReceipt' | 'eth_getTransactionCount';
|
|
3
3
|
export declare function buildRPCPostBody(method: RPCMethodName, params: unknown[]): {
|
|
4
4
|
jsonrpc: string;
|
|
5
5
|
id: number;
|
package/lib/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Contract } from './classes/Contract';
|
|
2
|
+
import { FallthroughProvider } from './providers/FallthroughProvider';
|
|
2
3
|
import { JsonRpcProvider, jsonRpcProvider } from './providers/JsonRpcProvider';
|
|
3
4
|
import { tinyBig, TinyBig } from './shared/tiny-big/tiny-big';
|
|
4
5
|
import { BlockResponse } from './types/Block.types';
|
|
@@ -8,8 +9,12 @@ import { TransactionResponse } from './types/Transaction.types';
|
|
|
8
9
|
import { etherToGwei } from './utils/ether-to-gwei';
|
|
9
10
|
import { etherToWei } from './utils/ether-to-wei';
|
|
10
11
|
import { gweiToEther } from './utils/gwei-to-ether';
|
|
11
|
-
import { hexZeroPad } from './utils/hex-zero-pad';
|
|
12
12
|
import { isAddress } from './utils/is-address';
|
|
13
13
|
import { toChecksumAddress } from './utils/to-checksum-address';
|
|
14
|
+
import { toUtf8Bytes } from './utils/to-utf8-bytes';
|
|
14
15
|
import { weiToEther } from './utils/wei-to-ether';
|
|
15
|
-
export
|
|
16
|
+
export * from './utils/bytes';
|
|
17
|
+
export * from './utils/hash-message';
|
|
18
|
+
export * from './utils/keccak256';
|
|
19
|
+
export * from './utils/solidity-keccak256';
|
|
20
|
+
export { etherToWei, etherToGwei, isAddress, jsonRpcProvider, JsonRpcProvider, FallthroughProvider, tinyBig, toChecksumAddress, weiToEther, gweiToEther, toUtf8Bytes, Contract, TinyBig, BlockResponse, ContractTypes, JSONABI, JSONABIArgument, Network, TransactionResponse, };
|
package/lib/esm/index.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { Contract } from './classes/Contract';
|
|
2
|
+
import { FallthroughProvider } from './providers/FallthroughProvider';
|
|
2
3
|
import { JsonRpcProvider, jsonRpcProvider } from './providers/JsonRpcProvider';
|
|
3
4
|
import { tinyBig, TinyBig } from './shared/tiny-big/tiny-big';
|
|
4
5
|
import { etherToGwei } from './utils/ether-to-gwei';
|
|
5
6
|
import { etherToWei } from './utils/ether-to-wei';
|
|
6
7
|
import { gweiToEther } from './utils/gwei-to-ether';
|
|
7
|
-
import { hexZeroPad } from './utils/hex-zero-pad';
|
|
8
8
|
import { isAddress } from './utils/is-address';
|
|
9
9
|
import { toChecksumAddress } from './utils/to-checksum-address';
|
|
10
|
+
import { toUtf8Bytes } from './utils/to-utf8-bytes';
|
|
10
11
|
import { weiToEther } from './utils/wei-to-ether';
|
|
11
|
-
export
|
|
12
|
+
export * from './utils/bytes';
|
|
13
|
+
export * from './utils/hash-message';
|
|
14
|
+
export * from './utils/keccak256';
|
|
15
|
+
export * from './utils/solidity-keccak256';
|
|
16
|
+
export { etherToWei, etherToGwei, isAddress, jsonRpcProvider, JsonRpcProvider, FallthroughProvider, tinyBig, toChecksumAddress, weiToEther, gweiToEther, toUtf8Bytes, Contract, TinyBig, };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare class Logger {
|
|
2
|
+
private packageVersion;
|
|
3
|
+
constructor();
|
|
4
|
+
throwError(message: string, args: {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}): never;
|
|
7
|
+
throwArgumentError(message: string, arg: string, value: any): never;
|
|
8
|
+
checkSafeUint53(value: number, message?: string): void;
|
|
9
|
+
}
|
|
10
|
+
export declare const logger: Logger;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { version } from './package-version';
|
|
2
|
+
class Logger {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.packageVersion = version;
|
|
5
|
+
}
|
|
6
|
+
throwError(message, args) {
|
|
7
|
+
const argsLength = Object.keys(args).length;
|
|
8
|
+
throw new Error(`${message} (${Object.entries(args).map(([key, value], index) => `${key}=${value}${index < argsLength - 1 && ', '}`)}, version=essential-eth@${this.packageVersion})`);
|
|
9
|
+
}
|
|
10
|
+
throwArgumentError(message, arg, value) {
|
|
11
|
+
throw new Error(`${message} (argument="${arg}" value=${value}, version=essential-eth@${this.packageVersion})`);
|
|
12
|
+
}
|
|
13
|
+
checkSafeUint53(value, message = 'value not safe') {
|
|
14
|
+
if (typeof value !== 'number') {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (value < 0 || value >= 0x1fffffffffffff) {
|
|
18
|
+
this.throwError(message, {
|
|
19
|
+
operation: 'checkSafeInteger',
|
|
20
|
+
fault: 'out-of-safe-range',
|
|
21
|
+
value: value,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (value % 1) {
|
|
25
|
+
this.throwError(message, {
|
|
26
|
+
operation: 'checkSafeInteger',
|
|
27
|
+
fault: 'non-integer',
|
|
28
|
+
value: value,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export const logger = new Logger();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const version = "0.5.4";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const version = '0.5.4';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TinyBig } from '../shared/tiny-big/tiny-big';
|
|
2
|
+
import { BlockResponse, BlockTag } from '../types/Block.types';
|
|
3
|
+
import { Network } from '../types/Network.types';
|
|
4
|
+
import { TransactionReceipt, TransactionResponse } from '../types/Transaction.types';
|
|
5
|
+
export declare abstract class BaseProvider {
|
|
6
|
+
abstract selectRpcUrl(): string;
|
|
7
|
+
abstract post(body: Record<string, unknown>): Promise<any>;
|
|
8
|
+
readonly _rpcUrls: string[];
|
|
9
|
+
protected _post: (body: Record<string, unknown>) => Promise<any>;
|
|
10
|
+
constructor(rpcUrls: string[]);
|
|
11
|
+
getNetwork(): Promise<Network>;
|
|
12
|
+
getTransaction(transactionHash: string): Promise<TransactionResponse>;
|
|
13
|
+
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
|
14
|
+
getTransactionCount(address: string, blockTag?: BlockTag): Promise<number>;
|
|
15
|
+
getBlock(timeFrame?: BlockTag, returnTransactionObjects?: boolean): Promise<BlockResponse>;
|
|
16
|
+
getGasPrice(): Promise<TinyBig>;
|
|
17
|
+
getBalance(address: string, blockTag?: BlockTag): Promise<TinyBig>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
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 '../classes/utils/clean-block';
|
|
11
|
+
import { cleanTransaction } from '../classes/utils/clean-transaction';
|
|
12
|
+
import { cleanTransactionReceipt } from '../classes/utils/clean-transaction-receipt';
|
|
13
|
+
import { buildRPCPostBody, post } from '../classes/utils/fetchers';
|
|
14
|
+
import { hexToDecimal } from '../classes/utils/hex-to-decimal';
|
|
15
|
+
import { tinyBig } from '../shared/tiny-big/tiny-big';
|
|
16
|
+
import chainsInfo from './utils/chains-info';
|
|
17
|
+
export class BaseProvider {
|
|
18
|
+
constructor(rpcUrls) {
|
|
19
|
+
this._rpcUrls = [];
|
|
20
|
+
this._post = (body) => post(this.selectRpcUrl(), body);
|
|
21
|
+
this._rpcUrls = rpcUrls;
|
|
22
|
+
}
|
|
23
|
+
getNetwork() {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
const hexChainId = (yield this.post(buildRPCPostBody('eth_chainId', [])));
|
|
26
|
+
const chainId = hexToDecimal(hexChainId);
|
|
27
|
+
const info = chainsInfo[chainId];
|
|
28
|
+
return {
|
|
29
|
+
chainId: Number(chainId),
|
|
30
|
+
name: info[0] || 'unknown',
|
|
31
|
+
ensAddress: info[1] || null,
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
getTransaction(transactionHash) {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
const [rpcTransaction, blockNumber] = yield Promise.all([
|
|
38
|
+
this.post(buildRPCPostBody('eth_getTransactionByHash', [transactionHash])),
|
|
39
|
+
this.getBlock('latest'),
|
|
40
|
+
]);
|
|
41
|
+
const cleanedTransaction = cleanTransaction(rpcTransaction);
|
|
42
|
+
cleanedTransaction.confirmations =
|
|
43
|
+
blockNumber.number - cleanedTransaction.blockNumber + 1;
|
|
44
|
+
return cleanedTransaction;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
getTransactionReceipt(transactionHash) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
const [rpcTransaction, blockNumber] = yield Promise.all([
|
|
50
|
+
this.post(buildRPCPostBody('eth_getTransactionReceipt', [transactionHash])),
|
|
51
|
+
this.getBlock('latest'),
|
|
52
|
+
]);
|
|
53
|
+
const cleanedTransactionReceipt = cleanTransactionReceipt(rpcTransaction);
|
|
54
|
+
cleanedTransactionReceipt.confirmations =
|
|
55
|
+
blockNumber.number - cleanedTransactionReceipt.blockNumber + 1;
|
|
56
|
+
return cleanedTransactionReceipt;
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
getTransactionCount(address, blockTag = 'latest') {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
if (typeof blockTag === 'number') {
|
|
62
|
+
blockTag = `0x${blockTag.toString(16)}`;
|
|
63
|
+
}
|
|
64
|
+
const transactionCount = (yield this.post(buildRPCPostBody('eth_getTransactionCount', [address, blockTag])));
|
|
65
|
+
return Number(hexToDecimal(transactionCount));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
getBlock(timeFrame = 'latest', returnTransactionObjects = false) {
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
let rpcTimeFrame;
|
|
71
|
+
let type = 'Number';
|
|
72
|
+
if (typeof timeFrame === 'number') {
|
|
73
|
+
rpcTimeFrame = `0x${timeFrame.toString(16)}`;
|
|
74
|
+
}
|
|
75
|
+
else if (timeFrame.startsWith('0x')) {
|
|
76
|
+
rpcTimeFrame = timeFrame;
|
|
77
|
+
type = 'Hash';
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
rpcTimeFrame = timeFrame;
|
|
81
|
+
}
|
|
82
|
+
const rpcBlock = (yield this.post(buildRPCPostBody(`eth_getBlockBy${type}`, [
|
|
83
|
+
rpcTimeFrame,
|
|
84
|
+
returnTransactionObjects,
|
|
85
|
+
])));
|
|
86
|
+
return cleanBlock(rpcBlock, returnTransactionObjects);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
getGasPrice() {
|
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
+
const hexGasPrice = (yield this.post(buildRPCPostBody('eth_gasPrice', [])));
|
|
92
|
+
return tinyBig(hexToDecimal(hexGasPrice));
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
getBalance(address, blockTag = 'latest') {
|
|
96
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
97
|
+
const hexBalance = (yield this.post(buildRPCPostBody('eth_getBalance', [address, blockTag])));
|
|
98
|
+
return tinyBig(hexToDecimal(hexBalance));
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BaseProvider } from './BaseProvider';
|
|
2
|
+
interface ConstructorOptions {
|
|
3
|
+
timeoutDuration?: number;
|
|
4
|
+
}
|
|
5
|
+
export declare class FallthroughProvider extends BaseProvider {
|
|
6
|
+
private rpcUrlCounter;
|
|
7
|
+
private readonly timeoutDuration;
|
|
8
|
+
selectRpcUrl(): string;
|
|
9
|
+
constructor(rpcUrls: string[], options?: ConstructorOptions);
|
|
10
|
+
post: (body: Record<string, unknown>) => Promise<any>;
|
|
11
|
+
}
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { logger } from '../logger/logger';
|
|
2
|
+
import { BaseProvider } from './BaseProvider';
|
|
3
|
+
const promiseTimeout = (prom, time) => Promise.race([
|
|
4
|
+
prom,
|
|
5
|
+
new Promise((_r, reject) => setTimeout(() => reject('Promise timed out'), time)),
|
|
6
|
+
]);
|
|
7
|
+
const DEFAULT_TIMEOUT_DURATION = 8000;
|
|
8
|
+
export class FallthroughProvider extends BaseProvider {
|
|
9
|
+
constructor(rpcUrls, options = {}) {
|
|
10
|
+
if (!Array.isArray(rpcUrls)) {
|
|
11
|
+
logger.throwError('Array required', { rpcUrls });
|
|
12
|
+
}
|
|
13
|
+
if (rpcUrls.length <= 1) {
|
|
14
|
+
logger.throwError('More than one rpcUrl is required', { rpcUrls });
|
|
15
|
+
}
|
|
16
|
+
super(rpcUrls);
|
|
17
|
+
this.rpcUrlCounter = 0;
|
|
18
|
+
this.post = (body) => {
|
|
19
|
+
const genesisCount = this.rpcUrlCounter;
|
|
20
|
+
const recursivePostRetry = () => {
|
|
21
|
+
const genesisRpcUrl = this.selectRpcUrl();
|
|
22
|
+
const res = promiseTimeout(this._post(body), this.timeoutDuration).catch((e) => {
|
|
23
|
+
if (genesisRpcUrl === this.selectRpcUrl()) {
|
|
24
|
+
this.rpcUrlCounter =
|
|
25
|
+
(this.rpcUrlCounter + 1) % this._rpcUrls.length;
|
|
26
|
+
}
|
|
27
|
+
if (this.rpcUrlCounter === genesisCount) {
|
|
28
|
+
throw e;
|
|
29
|
+
}
|
|
30
|
+
return recursivePostRetry();
|
|
31
|
+
});
|
|
32
|
+
return res;
|
|
33
|
+
};
|
|
34
|
+
return recursivePostRetry();
|
|
35
|
+
};
|
|
36
|
+
this.timeoutDuration = options.timeoutDuration || DEFAULT_TIMEOUT_DURATION;
|
|
37
|
+
}
|
|
38
|
+
selectRpcUrl() {
|
|
39
|
+
return this._rpcUrls[this.rpcUrlCounter];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -1,15 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export declare class JsonRpcProvider {
|
|
6
|
-
readonly _rpcUrl: string;
|
|
7
|
-
private post;
|
|
1
|
+
import { BaseProvider } from './BaseProvider';
|
|
2
|
+
export declare class JsonRpcProvider extends BaseProvider {
|
|
3
|
+
selectRpcUrl(): string;
|
|
4
|
+
post(body: Record<string, unknown>): Promise<any>;
|
|
8
5
|
constructor(rpcUrl?: string);
|
|
9
|
-
getBlock(timeFrame: BlockTag, returnTransactionObjects?: boolean): Promise<BlockResponse>;
|
|
10
|
-
getNetwork(): Promise<Network>;
|
|
11
|
-
getGasPrice(): Promise<TinyBig>;
|
|
12
|
-
getBalance(address: string, blockTag?: BlockTag): Promise<TinyBig>;
|
|
13
|
-
getTransaction(hash: string): Promise<TransactionResponse>;
|
|
14
6
|
}
|
|
15
7
|
export declare function jsonRpcProvider(rpcUrl?: string): JsonRpcProvider;
|
|
@@ -1,74 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
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 '../classes/utils/clean-block';
|
|
11
|
-
import { cleanTransaction } from '../classes/utils/clean-transaction';
|
|
12
|
-
import { buildRPCPostBody, post } from '../classes/utils/fetchers';
|
|
13
|
-
import { hexToDecimal } from '../classes/utils/hex-to-decimal';
|
|
14
|
-
import { tinyBig } from '../shared/tiny-big/tiny-big';
|
|
15
|
-
import chainsInfo from './utils/chains-info';
|
|
16
|
-
export class JsonRpcProvider {
|
|
17
|
-
constructor(rpcUrl) {
|
|
18
|
-
this.post = (body) => post(this._rpcUrl, body);
|
|
19
|
-
this._rpcUrl = rpcUrl || 'https://free-eth-node.com/api/eth';
|
|
1
|
+
import { BaseProvider } from './BaseProvider';
|
|
2
|
+
export class JsonRpcProvider extends BaseProvider {
|
|
3
|
+
selectRpcUrl() {
|
|
4
|
+
return this._rpcUrls[0];
|
|
20
5
|
}
|
|
21
|
-
|
|
22
|
-
return
|
|
23
|
-
let rpcTimeFrame;
|
|
24
|
-
if (typeof timeFrame === 'number') {
|
|
25
|
-
rpcTimeFrame = `0x${timeFrame.toString(16)}`;
|
|
26
|
-
}
|
|
27
|
-
else {
|
|
28
|
-
rpcTimeFrame = timeFrame;
|
|
29
|
-
}
|
|
30
|
-
const rpcBlock = (yield this.post(buildRPCPostBody('eth_getBlockByNumber', [
|
|
31
|
-
rpcTimeFrame,
|
|
32
|
-
returnTransactionObjects,
|
|
33
|
-
])));
|
|
34
|
-
return cleanBlock(rpcBlock, returnTransactionObjects);
|
|
35
|
-
});
|
|
6
|
+
post(body) {
|
|
7
|
+
return this._post(body);
|
|
36
8
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const hexChainId = (yield this.post(buildRPCPostBody('eth_chainId', [])));
|
|
40
|
-
const chainId = hexToDecimal(hexChainId);
|
|
41
|
-
const info = chainsInfo[chainId];
|
|
42
|
-
return {
|
|
43
|
-
chainId: Number(chainId),
|
|
44
|
-
name: info[0] || 'unknown',
|
|
45
|
-
ensAddress: info[1] || null,
|
|
46
|
-
};
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
getGasPrice() {
|
|
50
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
-
const hexGasPrice = (yield this.post(buildRPCPostBody('eth_gasPrice', [])));
|
|
52
|
-
return tinyBig(hexToDecimal(hexGasPrice));
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
getBalance(address, blockTag = 'latest') {
|
|
56
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
57
|
-
const hexBalance = (yield this.post(buildRPCPostBody('eth_getBalance', [address, blockTag])));
|
|
58
|
-
return tinyBig(hexToDecimal(hexBalance));
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
getTransaction(hash) {
|
|
62
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
-
const [rpcTransaction, blockNumber] = yield Promise.all([
|
|
64
|
-
this.post(buildRPCPostBody('eth_getTransactionByHash', [hash])),
|
|
65
|
-
this.getBlock('latest'),
|
|
66
|
-
]);
|
|
67
|
-
const cleanedTransaction = cleanTransaction(rpcTransaction);
|
|
68
|
-
cleanedTransaction.confirmations =
|
|
69
|
-
blockNumber.number - cleanedTransaction.blockNumber + 1;
|
|
70
|
-
return cleanedTransaction;
|
|
71
|
-
});
|
|
9
|
+
constructor(rpcUrl = 'https://free-eth-node.com/api/eth') {
|
|
10
|
+
super([rpcUrl]);
|
|
72
11
|
}
|
|
73
12
|
}
|
|
74
13
|
export function jsonRpcProvider(rpcUrl) {
|
|
@@ -3,6 +3,7 @@ export const fakeUrls = {
|
|
|
3
3
|
};
|
|
4
4
|
export const rpcUrls = {
|
|
5
5
|
mainnet: `${process.env.RPC_ORIGIN}/api/eth`,
|
|
6
|
+
matic: `${process.env.RPC_ORIGIN}/api/MATIC`,
|
|
6
7
|
gno: `${process.env.RPC_ORIGIN}/api/gno`,
|
|
7
8
|
bnb: `${process.env.RPC_ORIGIN}/api/bnb`,
|
|
8
9
|
arb1: `${process.env.RPC_ORIGIN}/api/arb1`,
|