essential-eth 0.5.0 → 0.5.1
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 +3 -2
- package/lib/cjs/index.js +17 -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/JsonRpcProvider.d.ts +1 -1
- package/lib/cjs/providers/JsonRpcProvider.js +1 -1
- package/lib/cjs/providers/utils/chains-info.d.ts +4 -0
- package/lib/cjs/providers/utils/chains-info.js +12 -0
- package/lib/cjs/shared/tiny-big/tiny-big.d.ts +7 -0
- package/lib/cjs/shared/tiny-big/tiny-big.js +25 -7
- package/lib/cjs/utils/bytes.d.ts +90 -0
- package/lib/cjs/utils/bytes.js +484 -0
- package/lib/cjs/utils/solidity-keccak256.d.ts +30 -0
- package/lib/cjs/utils/solidity-keccak256.js +125 -0
- package/lib/esm/index.d.ts +3 -2
- package/lib/esm/index.js +3 -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/JsonRpcProvider.d.ts +1 -1
- package/lib/esm/providers/JsonRpcProvider.js +1 -1
- package/lib/esm/providers/utils/chains-info.d.ts +4 -0
- package/lib/esm/providers/utils/chains-info.js +12 -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/utils/bytes.d.ts +39 -0
- package/lib/esm/utils/bytes.js +245 -0
- package/lib/esm/utils/solidity-keccak256.d.ts +3 -0
- package/lib/esm/utils/solidity-keccak256.js +91 -0
- package/package.json +12 -14
- 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,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.1";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const version = '0.5.1';
|
|
@@ -6,7 +6,7 @@ export declare class JsonRpcProvider {
|
|
|
6
6
|
readonly _rpcUrl: string;
|
|
7
7
|
private post;
|
|
8
8
|
constructor(rpcUrl?: string);
|
|
9
|
-
getBlock(timeFrame
|
|
9
|
+
getBlock(timeFrame?: BlockTag, returnTransactionObjects?: boolean): Promise<BlockResponse>;
|
|
10
10
|
getNetwork(): Promise<Network>;
|
|
11
11
|
getGasPrice(): Promise<TinyBig>;
|
|
12
12
|
getBalance(address: string, blockTag?: BlockTag): Promise<TinyBig>;
|
|
@@ -18,7 +18,7 @@ export class JsonRpcProvider {
|
|
|
18
18
|
this.post = (body) => post(this._rpcUrl, body);
|
|
19
19
|
this._rpcUrl = rpcUrl || 'https://free-eth-node.com/api/eth';
|
|
20
20
|
}
|
|
21
|
-
getBlock(timeFrame, returnTransactionObjects = false) {
|
|
21
|
+
getBlock(timeFrame = 'latest', returnTransactionObjects = false) {
|
|
22
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
23
23
|
let rpcTimeFrame;
|
|
24
24
|
if (typeof timeFrame === 'number') {
|
|
@@ -215,6 +215,7 @@ declare const _default: {
|
|
|
215
215
|
"2153": string[];
|
|
216
216
|
"2213": string[];
|
|
217
217
|
"2221": string[];
|
|
218
|
+
"2223": string[];
|
|
218
219
|
"2559": string[];
|
|
219
220
|
"3000": string[];
|
|
220
221
|
"3001": string[];
|
|
@@ -233,6 +234,8 @@ declare const _default: {
|
|
|
233
234
|
"4918": string[];
|
|
234
235
|
"5197": string[];
|
|
235
236
|
"5315": string[];
|
|
237
|
+
"5551": string[];
|
|
238
|
+
"5553": string[];
|
|
236
239
|
"5700": string[];
|
|
237
240
|
"5777": string[];
|
|
238
241
|
"5851": string[];
|
|
@@ -351,6 +354,7 @@ declare const _default: {
|
|
|
351
354
|
"11155111": string[];
|
|
352
355
|
"13371337": string[];
|
|
353
356
|
"18289463": string[];
|
|
357
|
+
"20180430": string[];
|
|
354
358
|
"20181205": string[];
|
|
355
359
|
"28945486": string[];
|
|
356
360
|
"35855456": string[];
|
|
@@ -651,6 +651,9 @@ export default {
|
|
|
651
651
|
"2221": [
|
|
652
652
|
"kava"
|
|
653
653
|
],
|
|
654
|
+
"2223": [
|
|
655
|
+
"VChain"
|
|
656
|
+
],
|
|
654
657
|
"2559": [
|
|
655
658
|
"ktoc"
|
|
656
659
|
],
|
|
@@ -705,6 +708,12 @@ export default {
|
|
|
705
708
|
"5315": [
|
|
706
709
|
"UZMI"
|
|
707
710
|
],
|
|
711
|
+
"5551": [
|
|
712
|
+
"Nahmii"
|
|
713
|
+
],
|
|
714
|
+
"5553": [
|
|
715
|
+
"Nahmii testnet"
|
|
716
|
+
],
|
|
708
717
|
"5700": [
|
|
709
718
|
"tsys"
|
|
710
719
|
],
|
|
@@ -1059,6 +1068,9 @@ export default {
|
|
|
1059
1068
|
"18289463": [
|
|
1060
1069
|
"ilt"
|
|
1061
1070
|
],
|
|
1071
|
+
"20180430": [
|
|
1072
|
+
"spectrum"
|
|
1073
|
+
],
|
|
1062
1074
|
"20181205": [
|
|
1063
1075
|
"qki"
|
|
1064
1076
|
],
|
|
@@ -2,13 +2,10 @@ import Big from 'big.js';
|
|
|
2
2
|
import { scientificStrToDecimalStr } from './helpers';
|
|
3
3
|
export class TinyBig extends Big {
|
|
4
4
|
constructor(value) {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
console.error(`TinyBig cannot parse value (value=${value})`);
|
|
10
|
-
throw e;
|
|
11
|
-
}
|
|
5
|
+
super(value);
|
|
6
|
+
this.padAndChop = (str, padChar, length) => {
|
|
7
|
+
return (Array(length).fill(padChar).join('') + str).slice(length * -1);
|
|
8
|
+
};
|
|
12
9
|
}
|
|
13
10
|
toHexString() {
|
|
14
11
|
return `0x${BigInt(this.toString()).toString(16)}`;
|
|
@@ -22,6 +19,22 @@ export class TinyBig extends Big {
|
|
|
22
19
|
}
|
|
23
20
|
return scientificStrToDecimalStr(super.toString());
|
|
24
21
|
}
|
|
22
|
+
toTwos(bitCount) {
|
|
23
|
+
let binaryStr;
|
|
24
|
+
if (this.gte(0)) {
|
|
25
|
+
const twosComp = this.toNumber().toString(2);
|
|
26
|
+
binaryStr = this.padAndChop(twosComp, '0', bitCount || twosComp.length);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
binaryStr = this.plus(Math.pow(2, bitCount)).toNumber().toString(2);
|
|
30
|
+
if (Number(binaryStr) < 0) {
|
|
31
|
+
throw new Error('Cannot calculate twos complement');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const binary = `0b${binaryStr}`;
|
|
35
|
+
const decimal = Number(binary);
|
|
36
|
+
return tinyBig(decimal);
|
|
37
|
+
}
|
|
25
38
|
}
|
|
26
39
|
export function tinyBig(value) {
|
|
27
40
|
return new TinyBig(value);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export declare type Bytes = ArrayLike<number>;
|
|
2
|
+
export declare type BytesLike = Bytes | string | number;
|
|
3
|
+
export interface DataOptions {
|
|
4
|
+
allowMissingPrefix?: boolean;
|
|
5
|
+
hexPad?: 'left' | 'right' | null;
|
|
6
|
+
}
|
|
7
|
+
export interface Hexable {
|
|
8
|
+
toHexString(): string;
|
|
9
|
+
}
|
|
10
|
+
export declare type SignatureLike = {
|
|
11
|
+
r: string;
|
|
12
|
+
s?: string;
|
|
13
|
+
_vs?: string;
|
|
14
|
+
recoveryParam?: number;
|
|
15
|
+
v?: number;
|
|
16
|
+
} | BytesLike;
|
|
17
|
+
export interface Signature {
|
|
18
|
+
r: string;
|
|
19
|
+
s: string;
|
|
20
|
+
_vs: string;
|
|
21
|
+
recoveryParam: number;
|
|
22
|
+
v: number;
|
|
23
|
+
yParityAndS: string;
|
|
24
|
+
compact: string;
|
|
25
|
+
}
|
|
26
|
+
export declare function isBytesLike(value: any): value is BytesLike;
|
|
27
|
+
export declare function isBytes(value: any): value is Bytes;
|
|
28
|
+
export declare function arrayify(value: BytesLike | Hexable | number, options?: DataOptions): Uint8Array;
|
|
29
|
+
export declare function concat(items: ReadonlyArray<BytesLike>): Uint8Array;
|
|
30
|
+
export declare function stripZeros(value: BytesLike): Uint8Array;
|
|
31
|
+
export declare function zeroPad(value: BytesLike, length: number): Uint8Array;
|
|
32
|
+
export declare function isHexString(value: any, length?: number): boolean;
|
|
33
|
+
export declare function hexlify(value: BytesLike | Hexable | number | bigint, options?: DataOptions): string;
|
|
34
|
+
export declare function hexDataLength(data: BytesLike): number | null;
|
|
35
|
+
export declare function hexDataSlice(data: BytesLike, offset: number, endOffset?: number): string;
|
|
36
|
+
export declare function hexConcat(items: ReadonlyArray<BytesLike>): string;
|
|
37
|
+
export declare function hexValue(value: BytesLike | Hexable | number | bigint): string;
|
|
38
|
+
export declare function hexStripZeros(value: BytesLike): string;
|
|
39
|
+
export declare function hexZeroPad(value: BytesLike, length: number): string;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { logger } from '../logger/logger';
|
|
2
|
+
function isHexable(value) {
|
|
3
|
+
return !!value.toHexString;
|
|
4
|
+
}
|
|
5
|
+
export function isBytesLike(value) {
|
|
6
|
+
return (isHexString(value) && !(value.length % 2)) || isBytes(value);
|
|
7
|
+
}
|
|
8
|
+
function isInteger(value) {
|
|
9
|
+
return typeof value === 'number' && value == value && value % 1 === 0;
|
|
10
|
+
}
|
|
11
|
+
export function isBytes(value) {
|
|
12
|
+
if (value == null) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
if (value.constructor === Uint8Array) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === 'string') {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (!isInteger(value.length) || value.length < 0) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
for (let i = 0; i < value.length; i++) {
|
|
25
|
+
const v = value[i];
|
|
26
|
+
if (!isInteger(v) || v < 0 || v >= 256) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
export function arrayify(value, options) {
|
|
33
|
+
if (!options) {
|
|
34
|
+
options = {};
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === 'number') {
|
|
37
|
+
logger.checkSafeUint53(value, 'invalid arrayify value');
|
|
38
|
+
const result = [];
|
|
39
|
+
while (value) {
|
|
40
|
+
result.unshift(value & 0xff);
|
|
41
|
+
value = parseInt(String(value / 256));
|
|
42
|
+
}
|
|
43
|
+
if (result.length === 0) {
|
|
44
|
+
result.push(0);
|
|
45
|
+
}
|
|
46
|
+
return new Uint8Array(result);
|
|
47
|
+
}
|
|
48
|
+
if (options.allowMissingPrefix &&
|
|
49
|
+
typeof value === 'string' &&
|
|
50
|
+
value.substring(0, 2) !== '0x') {
|
|
51
|
+
value = '0x' + value;
|
|
52
|
+
}
|
|
53
|
+
if (isHexable(value)) {
|
|
54
|
+
value = value.toHexString();
|
|
55
|
+
}
|
|
56
|
+
if (isHexString(value)) {
|
|
57
|
+
let hex = value.substring(2);
|
|
58
|
+
if (hex.length % 2) {
|
|
59
|
+
if (options.hexPad === 'left') {
|
|
60
|
+
hex = '0' + hex;
|
|
61
|
+
}
|
|
62
|
+
else if (options.hexPad === 'right') {
|
|
63
|
+
hex += '0';
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
logger.throwArgumentError('hex data is odd-length', 'value', value);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const result = [];
|
|
70
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
71
|
+
result.push(parseInt(hex.substring(i, i + 2), 16));
|
|
72
|
+
}
|
|
73
|
+
return new Uint8Array(result);
|
|
74
|
+
}
|
|
75
|
+
if (isBytes(value)) {
|
|
76
|
+
return new Uint8Array(value);
|
|
77
|
+
}
|
|
78
|
+
return logger.throwArgumentError('invalid arrayify value', 'value', value);
|
|
79
|
+
}
|
|
80
|
+
export function concat(items) {
|
|
81
|
+
const objects = items.map((item) => arrayify(item));
|
|
82
|
+
const length = objects.reduce((accum, item) => accum + item.length, 0);
|
|
83
|
+
const result = new Uint8Array(length);
|
|
84
|
+
objects.reduce((offset, object) => {
|
|
85
|
+
result.set(object, offset);
|
|
86
|
+
return offset + object.length;
|
|
87
|
+
}, 0);
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
export function stripZeros(value) {
|
|
91
|
+
let result = arrayify(value);
|
|
92
|
+
if (result.length === 0) {
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
let start = 0;
|
|
96
|
+
while (start < result.length && result[start] === 0) {
|
|
97
|
+
start++;
|
|
98
|
+
}
|
|
99
|
+
if (start) {
|
|
100
|
+
result = result.slice(start);
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
export function zeroPad(value, length) {
|
|
105
|
+
value = arrayify(value);
|
|
106
|
+
if (value.length > length) {
|
|
107
|
+
logger.throwArgumentError('value out of range', 'value', value);
|
|
108
|
+
}
|
|
109
|
+
const result = new Uint8Array(length);
|
|
110
|
+
result.set(value, length - value.length);
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
export function isHexString(value, length) {
|
|
114
|
+
if (typeof value !== 'string' || !value.match(/^0x[0-9A-Fa-f]*$/)) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
if (length && value.length !== 2 + 2 * length) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
const HexCharacters = '0123456789abcdef';
|
|
123
|
+
export function hexlify(value, options) {
|
|
124
|
+
if (!options) {
|
|
125
|
+
options = {};
|
|
126
|
+
}
|
|
127
|
+
if (typeof value === 'number') {
|
|
128
|
+
logger.checkSafeUint53(value, 'invalid hexlify value');
|
|
129
|
+
let hex = '';
|
|
130
|
+
while (value) {
|
|
131
|
+
hex = HexCharacters[value & 0xf] + hex;
|
|
132
|
+
value = Math.floor(value / 16);
|
|
133
|
+
}
|
|
134
|
+
if (hex.length) {
|
|
135
|
+
if (hex.length % 2) {
|
|
136
|
+
hex = '0' + hex;
|
|
137
|
+
}
|
|
138
|
+
return '0x' + hex;
|
|
139
|
+
}
|
|
140
|
+
return '0x00';
|
|
141
|
+
}
|
|
142
|
+
if (typeof value === 'bigint') {
|
|
143
|
+
value = value.toString(16);
|
|
144
|
+
if (value.length % 2) {
|
|
145
|
+
return '0x0' + value;
|
|
146
|
+
}
|
|
147
|
+
return '0x' + value;
|
|
148
|
+
}
|
|
149
|
+
if (options.allowMissingPrefix &&
|
|
150
|
+
typeof value === 'string' &&
|
|
151
|
+
value.substring(0, 2) !== '0x') {
|
|
152
|
+
value = '0x' + value;
|
|
153
|
+
}
|
|
154
|
+
if (isHexable(value)) {
|
|
155
|
+
return value.toHexString();
|
|
156
|
+
}
|
|
157
|
+
if (isHexString(value)) {
|
|
158
|
+
if (value.length % 2) {
|
|
159
|
+
if (options.hexPad === 'left') {
|
|
160
|
+
value = '0x0' + value.substring(2);
|
|
161
|
+
}
|
|
162
|
+
else if (options.hexPad === 'right') {
|
|
163
|
+
value += '0';
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
logger.throwArgumentError('hex data is odd-length', 'value', value);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return value.toLowerCase();
|
|
170
|
+
}
|
|
171
|
+
if (isBytes(value)) {
|
|
172
|
+
let result = '0x';
|
|
173
|
+
for (let i = 0; i < value.length; i++) {
|
|
174
|
+
const v = value[i];
|
|
175
|
+
result += HexCharacters[(v & 0xf0) >> 4] + HexCharacters[v & 0x0f];
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
return logger.throwArgumentError('invalid hexlify value', 'value', value);
|
|
180
|
+
}
|
|
181
|
+
export function hexDataLength(data) {
|
|
182
|
+
if (typeof data !== 'string') {
|
|
183
|
+
data = hexlify(data);
|
|
184
|
+
}
|
|
185
|
+
else if (!isHexString(data) || data.length % 2) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
return (data.length - 2) / 2;
|
|
189
|
+
}
|
|
190
|
+
export function hexDataSlice(data, offset, endOffset) {
|
|
191
|
+
if (typeof data !== 'string') {
|
|
192
|
+
data = hexlify(data);
|
|
193
|
+
}
|
|
194
|
+
else if (!isHexString(data) || data.length % 2) {
|
|
195
|
+
logger.throwArgumentError('invalid hexData', 'value', data);
|
|
196
|
+
}
|
|
197
|
+
offset = 2 + 2 * offset;
|
|
198
|
+
if (endOffset != null) {
|
|
199
|
+
return '0x' + data.substring(offset, 2 + 2 * endOffset);
|
|
200
|
+
}
|
|
201
|
+
return '0x' + data.substring(offset);
|
|
202
|
+
}
|
|
203
|
+
export function hexConcat(items) {
|
|
204
|
+
let result = '0x';
|
|
205
|
+
items.forEach((item) => {
|
|
206
|
+
result += hexlify(item).substring(2);
|
|
207
|
+
});
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
export function hexValue(value) {
|
|
211
|
+
const trimmed = hexStripZeros(hexlify(value, { hexPad: 'left' }));
|
|
212
|
+
if (trimmed === '0x') {
|
|
213
|
+
return '0x0';
|
|
214
|
+
}
|
|
215
|
+
return trimmed;
|
|
216
|
+
}
|
|
217
|
+
export function hexStripZeros(value) {
|
|
218
|
+
if (typeof value !== 'string') {
|
|
219
|
+
value = hexlify(value);
|
|
220
|
+
}
|
|
221
|
+
if (!isHexString(value)) {
|
|
222
|
+
logger.throwArgumentError('invalid hex string', 'value', value);
|
|
223
|
+
}
|
|
224
|
+
value = value.substring(2);
|
|
225
|
+
let offset = 0;
|
|
226
|
+
while (offset < value.length && value[offset] === '0') {
|
|
227
|
+
offset++;
|
|
228
|
+
}
|
|
229
|
+
return '0x' + value.substring(offset);
|
|
230
|
+
}
|
|
231
|
+
export function hexZeroPad(value, length) {
|
|
232
|
+
if (typeof value !== 'string') {
|
|
233
|
+
value = hexlify(value);
|
|
234
|
+
}
|
|
235
|
+
else if (!isHexString(value)) {
|
|
236
|
+
logger.throwArgumentError('invalid hex string', 'value', value);
|
|
237
|
+
}
|
|
238
|
+
if (value.length > 2 * length + 2) {
|
|
239
|
+
logger.throwError('value out of range', { value, length });
|
|
240
|
+
}
|
|
241
|
+
while (value.length < 2 * length + 2) {
|
|
242
|
+
value = '0x0' + value.substring(2);
|
|
243
|
+
}
|
|
244
|
+
return value;
|
|
245
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { Keccak } from 'sha3';
|
|
3
|
+
import { logger } from '../logger/logger';
|
|
4
|
+
import { tinyBig } from '../shared/tiny-big/tiny-big';
|
|
5
|
+
import { arrayify, concat, hexlify, zeroPad } from './bytes';
|
|
6
|
+
const regexBytes = new RegExp('^bytes([0-9]+)$');
|
|
7
|
+
const regexNumber = new RegExp('^(u?int)([0-9]*)$');
|
|
8
|
+
const regexArray = new RegExp('^(.*)\\[([0-9]*)\\]$');
|
|
9
|
+
const Zeros = '0000000000000000000000000000000000000000000000000000000000000000';
|
|
10
|
+
function _pack(type, value, isArray) {
|
|
11
|
+
switch (type) {
|
|
12
|
+
case 'address':
|
|
13
|
+
if (isArray) {
|
|
14
|
+
return zeroPad(value, 32);
|
|
15
|
+
}
|
|
16
|
+
return arrayify(value);
|
|
17
|
+
case 'string':
|
|
18
|
+
return Buffer.from(value);
|
|
19
|
+
case 'bytes':
|
|
20
|
+
return arrayify(value);
|
|
21
|
+
case 'bool':
|
|
22
|
+
value = value ? '0x01' : '0x00';
|
|
23
|
+
if (isArray) {
|
|
24
|
+
return zeroPad(value, 32);
|
|
25
|
+
}
|
|
26
|
+
return arrayify(value);
|
|
27
|
+
}
|
|
28
|
+
let match = type.match(regexNumber);
|
|
29
|
+
if (match) {
|
|
30
|
+
let size = parseInt(match[2] || '256');
|
|
31
|
+
if ((match[2] && String(size) !== match[2]) ||
|
|
32
|
+
size % 8 !== 0 ||
|
|
33
|
+
size === 0 ||
|
|
34
|
+
size > 256) {
|
|
35
|
+
logger.throwArgumentError('invalid number type', 'type', type);
|
|
36
|
+
}
|
|
37
|
+
if (isArray) {
|
|
38
|
+
size = 256;
|
|
39
|
+
}
|
|
40
|
+
value = tinyBig(value).toTwos(size).toNumber();
|
|
41
|
+
const hexValue = hexlify(value);
|
|
42
|
+
return zeroPad(hexValue, size / 8);
|
|
43
|
+
}
|
|
44
|
+
match = type.match(regexBytes);
|
|
45
|
+
if (match) {
|
|
46
|
+
const size = parseInt(match[1]);
|
|
47
|
+
if (String(size) !== match[1] || size === 0 || size > 32) {
|
|
48
|
+
logger.throwArgumentError('invalid bytes type', 'type', type);
|
|
49
|
+
}
|
|
50
|
+
if (arrayify(value).byteLength !== size) {
|
|
51
|
+
logger.throwArgumentError(`invalid value for ${type}`, 'value', value);
|
|
52
|
+
}
|
|
53
|
+
if (isArray) {
|
|
54
|
+
return arrayify((value + Zeros).substring(0, 66));
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
match = type.match(regexArray);
|
|
59
|
+
if (match && Array.isArray(value)) {
|
|
60
|
+
const baseType = match[1];
|
|
61
|
+
const count = parseInt(match[2] || String(value.length));
|
|
62
|
+
if (count != value.length) {
|
|
63
|
+
logger.throwArgumentError(`invalid array length for ${type}`, 'value', value);
|
|
64
|
+
}
|
|
65
|
+
const result = [];
|
|
66
|
+
value.forEach(function (value) {
|
|
67
|
+
result.push(_pack(baseType, value, true));
|
|
68
|
+
});
|
|
69
|
+
return concat(result);
|
|
70
|
+
}
|
|
71
|
+
return logger.throwArgumentError('invalid type', 'type', type);
|
|
72
|
+
}
|
|
73
|
+
export function pack(types, values) {
|
|
74
|
+
if (types.length != values.length) {
|
|
75
|
+
logger.throwArgumentError('wrong number of values; expected ${ types.length }', 'values', values);
|
|
76
|
+
}
|
|
77
|
+
const tight = [];
|
|
78
|
+
types.forEach(function (type, index) {
|
|
79
|
+
tight.push(_pack(type, values[index]));
|
|
80
|
+
});
|
|
81
|
+
return hexlify(concat(tight));
|
|
82
|
+
}
|
|
83
|
+
export const hashKeccak256 = (data) => {
|
|
84
|
+
const keccak = new Keccak(256);
|
|
85
|
+
const bufferableData = Buffer.from(data.replace(/^0x/, ''), 'hex');
|
|
86
|
+
const addressHash = '0x' + keccak.update(bufferableData).digest('hex');
|
|
87
|
+
return addressHash;
|
|
88
|
+
};
|
|
89
|
+
export function solidityKeccak256(types, values) {
|
|
90
|
+
return hashKeccak256(pack(types, values));
|
|
91
|
+
}
|
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.5.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./lib/cjs/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"scripts": {
|
|
18
18
|
"test": "npm-run-all --parallel jest compile lint",
|
|
19
19
|
"test:all-node-versions": "npx trevor",
|
|
20
|
-
"lint": "eslint .",
|
|
20
|
+
"lint": "eslint --cache --fix .",
|
|
21
21
|
"compile": "npm-run-all --parallel tsc:esm tsc:cjs",
|
|
22
22
|
"tsc:esm": "tsc -p tsconfig.json",
|
|
23
23
|
"tsc:cjs": "tsc -p tsconfig-cjs.json",
|
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
"prepublishOnly": "npm run build",
|
|
26
26
|
"jest": "jest",
|
|
27
27
|
"build:chains-info": "npx ts-node scripts/fetch-chains-info.ts # used in getNetwork()",
|
|
28
|
-
"
|
|
28
|
+
"update-deps": "sh ./scripts/pre-commit.sh",
|
|
29
|
+
"pre-commit": "run-p build:chains-info update-deps",
|
|
30
|
+
"prepare": "husky install"
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|
|
31
33
|
"@ethersproject/keccak256": "^5.4.0",
|
|
@@ -36,19 +38,19 @@
|
|
|
36
38
|
"@types/jest-dev-server": "^5.0.0",
|
|
37
39
|
"@types/node": "^16.10.1",
|
|
38
40
|
"@types/prettier": "^2.4.4",
|
|
39
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
40
|
-
"@typescript-eslint/parser": "^5.
|
|
41
|
+
"@typescript-eslint/eslint-plugin": "^5.20.0",
|
|
42
|
+
"@typescript-eslint/parser": "^5.20.0",
|
|
41
43
|
"body-parser": "^1.19.0",
|
|
42
44
|
"dotenv": "^16.0.0",
|
|
43
45
|
"eslint": "^8.13.0",
|
|
44
46
|
"eslint-plugin-jest": "^26.1.4",
|
|
45
|
-
"ethers": "^5.6.
|
|
47
|
+
"ethers": "^5.6.4",
|
|
46
48
|
"express": "^4.17.1",
|
|
47
|
-
"husky": "^
|
|
49
|
+
"husky": "^7.0.4",
|
|
48
50
|
"jest": "^27.5.1",
|
|
49
51
|
"jest-dev-server": "^6.0.3",
|
|
50
52
|
"just-omit": "^2.0.1",
|
|
51
|
-
"lint-staged": "^12.
|
|
53
|
+
"lint-staged": "^12.4.0",
|
|
52
54
|
"npm-run-all": "^4.1.5",
|
|
53
55
|
"prettier": "^2.6.2",
|
|
54
56
|
"prettier-plugin-organize-imports": "^2.3.4",
|
|
@@ -64,15 +66,11 @@
|
|
|
64
66
|
"isomorphic-unfetch": "^3.1.0",
|
|
65
67
|
"sha3": "^2.1.4"
|
|
66
68
|
},
|
|
67
|
-
"husky": {
|
|
68
|
-
"hooks": {
|
|
69
|
-
"pre-commit": "lint-staged && run-p pre-commit test build:chains-info"
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
69
|
"lint-staged": {
|
|
73
70
|
"*.{js,jsx,ts,tsx,css,scss,md,json,html,yml,yaml}": [
|
|
74
71
|
"prettier --write"
|
|
75
|
-
]
|
|
72
|
+
],
|
|
73
|
+
"*.{ts,tsx}": "eslint --cache --fix"
|
|
76
74
|
},
|
|
77
75
|
"prettier": {
|
|
78
76
|
"trailingComma": "all",
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Returns a hex string padded to a specified length of bytes.
|
|
3
|
-
*
|
|
4
|
-
* Similar to ["hexZeroPad" in ethers.js](https://docs.ethers.io/v5/api/utils/bytes/#utils-hexZeroPad)
|
|
5
|
-
*
|
|
6
|
-
* Differs from ["padLeft" in web3.js](https://web3js.readthedocs.io/en/v1.7.1/web3-utils.html#padleft) because web3 counts by characters, not bytes.
|
|
7
|
-
*
|
|
8
|
-
* @param hexValue - A hex-string, hex-number, or decimal number (auto-converts to base-16) to be padded
|
|
9
|
-
* @param length - The final length in bytes
|
|
10
|
-
*
|
|
11
|
-
* @throws - If the value is not a hex string or number
|
|
12
|
-
* @throws - If the value is longer than the length
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```javascript
|
|
16
|
-
* hexZeroPad('0x60', 2);
|
|
17
|
-
* // '0x0060'
|
|
18
|
-
* ```
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* ```javascript
|
|
22
|
-
* hexZeroPad(0x60, 3);
|
|
23
|
-
* // '0x000060'
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```javascript
|
|
28
|
-
* hexZeroPad('12345', 1);
|
|
29
|
-
* // Throws
|
|
30
|
-
* ```
|
|
31
|
-
*/
|
|
32
|
-
export declare function hexZeroPad(hexValue: string | number, length: number): string;
|