essential-eth 0.11.2 → 1.0.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/dist/chunk-CLIQ4S3P.js +780 -0
- package/dist/chunk-GFWRB7PT.js +96 -0
- package/dist/conversions.d.ts +9 -0
- package/dist/conversions.js +1 -0
- package/dist/index-utils-e8a8adc8.d.ts +63 -0
- package/dist/index.cjs +419 -286
- package/dist/index.d.ts +60 -101
- package/dist/index.js +239 -1046
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +2 -0
- package/package.json +14 -7
- package/readme.md +750 -449
- package/dist/index.d.cts +0 -330
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
import { validateType } from './chunk-GFWRB7PT.js';
|
|
2
|
+
import { keccak_256 } from '@noble/hashes/sha3.js';
|
|
3
|
+
import { bytesToHex } from '@noble/hashes/utils.js';
|
|
4
|
+
import { Point } from '@noble/secp256k1';
|
|
5
|
+
|
|
6
|
+
function toChecksumAddress(address) {
|
|
7
|
+
validateType(address, ["string"]);
|
|
8
|
+
if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) {
|
|
9
|
+
throw new Error(`Invalid Ethereum address "${address}"`);
|
|
10
|
+
}
|
|
11
|
+
const _address = address.toLowerCase().replace(/^0x/i, "");
|
|
12
|
+
const addressBytes = new TextEncoder().encode(_address);
|
|
13
|
+
const addressHash = bytesToHex(keccak_256(addressBytes));
|
|
14
|
+
let checksumAddress = "0x";
|
|
15
|
+
for (let i = 0; i < _address.length; i++) {
|
|
16
|
+
if (parseInt(addressHash[i], 16) > 7) {
|
|
17
|
+
checksumAddress += _address[i].toUpperCase();
|
|
18
|
+
} else {
|
|
19
|
+
checksumAddress += _address[i];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (address.match(/([A-F].*[a-f])|([a-f].*[A-F])/) && checksumAddress !== address) {
|
|
23
|
+
throw new Error(`Invalid Checksum address for "${address}"`);
|
|
24
|
+
}
|
|
25
|
+
return checksumAddress;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/logger/package-version.ts
|
|
29
|
+
var version = "1.0.0";
|
|
30
|
+
|
|
31
|
+
// src/logger/logger.ts
|
|
32
|
+
var Logger = class {
|
|
33
|
+
packageVersion;
|
|
34
|
+
constructor() {
|
|
35
|
+
this.packageVersion = version;
|
|
36
|
+
}
|
|
37
|
+
throwError(message, args) {
|
|
38
|
+
const argsLength = Object.keys(args).length;
|
|
39
|
+
throw new Error(
|
|
40
|
+
`${message} (${Object.entries(args).map(
|
|
41
|
+
([key, value], index) => `${key}=${value}${index < argsLength - 1 && ", "}`
|
|
42
|
+
)}, version=essential-eth@${this.packageVersion})`
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
throwArgumentError(message, arg, value) {
|
|
46
|
+
throw new Error(
|
|
47
|
+
`${message} (argument="${arg}" value=${value}, version=essential-eth@${this.packageVersion})`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
checkSafeUint53(value, message = "value not safe") {
|
|
51
|
+
if (typeof value !== "number") {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (value < 0 || value >= 9007199254740991) {
|
|
55
|
+
this.throwError(message, {
|
|
56
|
+
operation: "checkSafeInteger",
|
|
57
|
+
fault: "out-of-safe-range",
|
|
58
|
+
value
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (value % 1) {
|
|
62
|
+
this.throwError(message, {
|
|
63
|
+
operation: "checkSafeInteger",
|
|
64
|
+
fault: "non-integer",
|
|
65
|
+
value
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var logger = new Logger();
|
|
71
|
+
|
|
72
|
+
// src/utils/bytes.ts
|
|
73
|
+
function isHexable(value) {
|
|
74
|
+
return !!value.toHexString;
|
|
75
|
+
}
|
|
76
|
+
function isBytesLike(value) {
|
|
77
|
+
return isHexString(value) && !(value.length % 2) || isBytes(value);
|
|
78
|
+
}
|
|
79
|
+
function isInteger(value) {
|
|
80
|
+
return typeof value === "number" && value == value && value % 1 === 0;
|
|
81
|
+
}
|
|
82
|
+
function isBytes(value) {
|
|
83
|
+
if (value == null) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (value.constructor === Uint8Array) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
if (typeof value === "string") {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (!isInteger(value.length) || value.length < 0) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
for (let i = 0; i < value.length; i++) {
|
|
96
|
+
const v = value[i];
|
|
97
|
+
if (!isInteger(v) || v < 0 || v >= 256) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
function arrayify(value, options) {
|
|
104
|
+
if (!options) {
|
|
105
|
+
options = {};
|
|
106
|
+
}
|
|
107
|
+
if (typeof value === "number") {
|
|
108
|
+
logger.checkSafeUint53(value, "invalid arrayify value");
|
|
109
|
+
const result = [];
|
|
110
|
+
while (value) {
|
|
111
|
+
result.unshift(value & 255);
|
|
112
|
+
value = parseInt(String(value / 256));
|
|
113
|
+
}
|
|
114
|
+
if (result.length === 0) {
|
|
115
|
+
result.push(0);
|
|
116
|
+
}
|
|
117
|
+
return new Uint8Array(result);
|
|
118
|
+
}
|
|
119
|
+
if (typeof value === "bigint") {
|
|
120
|
+
const hex = value.toString(16).padStart(2, "0");
|
|
121
|
+
const padded = hex.length % 2 ? "0" + hex : hex;
|
|
122
|
+
const result = new Uint8Array(padded.length / 2);
|
|
123
|
+
for (let i = 0; i < result.length; i++) {
|
|
124
|
+
result[i] = parseInt(padded.substring(i * 2, i * 2 + 2), 16);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
if (options.allowMissingPrefix && typeof value === "string" && value.substring(0, 2) !== "0x") {
|
|
129
|
+
value = "0x" + value;
|
|
130
|
+
}
|
|
131
|
+
if (isHexable(value)) {
|
|
132
|
+
value = value.toHexString();
|
|
133
|
+
}
|
|
134
|
+
if (isHexString(value)) {
|
|
135
|
+
let hex = value.substring(2);
|
|
136
|
+
if (hex.length % 2) {
|
|
137
|
+
if (options.hexPad === "left") {
|
|
138
|
+
hex = "0" + hex;
|
|
139
|
+
} else if (options.hexPad === "right") {
|
|
140
|
+
hex += "0";
|
|
141
|
+
} else {
|
|
142
|
+
logger.throwArgumentError("hex data is odd-length", "value", value);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const result = [];
|
|
146
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
147
|
+
result.push(parseInt(hex.substring(i, i + 2), 16));
|
|
148
|
+
}
|
|
149
|
+
return new Uint8Array(result);
|
|
150
|
+
}
|
|
151
|
+
if (isBytes(value)) {
|
|
152
|
+
return new Uint8Array(value);
|
|
153
|
+
}
|
|
154
|
+
return logger.throwArgumentError("invalid arrayify value", "value", value);
|
|
155
|
+
}
|
|
156
|
+
function concat(arrayOfBytesLike) {
|
|
157
|
+
const objects = arrayOfBytesLike.map((item) => arrayify(item));
|
|
158
|
+
const length = objects.reduce((accum, item) => accum + item.length, 0);
|
|
159
|
+
const result = new Uint8Array(length);
|
|
160
|
+
objects.reduce((offset, object) => {
|
|
161
|
+
result.set(object, offset);
|
|
162
|
+
return offset + object.length;
|
|
163
|
+
}, 0);
|
|
164
|
+
return result;
|
|
165
|
+
}
|
|
166
|
+
function stripZeros(value) {
|
|
167
|
+
let result = arrayify(value);
|
|
168
|
+
if (result.length === 0) {
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
let start = 0;
|
|
172
|
+
while (start < result.length && result[start] === 0) {
|
|
173
|
+
start++;
|
|
174
|
+
}
|
|
175
|
+
if (start) {
|
|
176
|
+
result = result.slice(start);
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
function zeroPad(value, length) {
|
|
181
|
+
value = arrayify(value);
|
|
182
|
+
if (value.length > length) {
|
|
183
|
+
logger.throwArgumentError("value out of range", "value", value);
|
|
184
|
+
}
|
|
185
|
+
const result = new Uint8Array(length);
|
|
186
|
+
result.set(value, length - value.length);
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
function isHexString(value, length) {
|
|
190
|
+
if (typeof value !== "string" || !value.match(/^0x[0-9A-Fa-f]*$/)) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
if (length && value.length !== 2 + 2 * length) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
var HexCharacters = "0123456789abcdef";
|
|
199
|
+
function hexlify(value, options) {
|
|
200
|
+
if (!options) {
|
|
201
|
+
options = {};
|
|
202
|
+
}
|
|
203
|
+
if (typeof value === "number") {
|
|
204
|
+
logger.checkSafeUint53(value, "invalid hexlify value");
|
|
205
|
+
let hex = "";
|
|
206
|
+
while (value) {
|
|
207
|
+
hex = HexCharacters[value & 15] + hex;
|
|
208
|
+
value = Math.floor(value / 16);
|
|
209
|
+
}
|
|
210
|
+
if (hex.length) {
|
|
211
|
+
if (hex.length % 2) {
|
|
212
|
+
hex = "0" + hex;
|
|
213
|
+
}
|
|
214
|
+
return "0x" + hex;
|
|
215
|
+
}
|
|
216
|
+
return "0x00";
|
|
217
|
+
}
|
|
218
|
+
if (typeof value === "bigint") {
|
|
219
|
+
value = value.toString(16);
|
|
220
|
+
if (value.length % 2) {
|
|
221
|
+
return "0x0" + value;
|
|
222
|
+
}
|
|
223
|
+
return "0x" + value;
|
|
224
|
+
}
|
|
225
|
+
if (options.allowMissingPrefix && typeof value === "string" && value.substring(0, 2) !== "0x") {
|
|
226
|
+
value = "0x" + value;
|
|
227
|
+
}
|
|
228
|
+
if (isHexable(value)) {
|
|
229
|
+
return value.toHexString();
|
|
230
|
+
}
|
|
231
|
+
if (isHexString(value)) {
|
|
232
|
+
if (value.length % 2) {
|
|
233
|
+
if (options.hexPad === "left") {
|
|
234
|
+
value = "0x0" + value.substring(2);
|
|
235
|
+
} else if (options.hexPad === "right") {
|
|
236
|
+
value += "0";
|
|
237
|
+
} else {
|
|
238
|
+
logger.throwArgumentError("hex data is odd-length", "value", value);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return value.toLowerCase();
|
|
242
|
+
}
|
|
243
|
+
if (isBytes(value)) {
|
|
244
|
+
let result = "0x";
|
|
245
|
+
for (let i = 0; i < value.length; i++) {
|
|
246
|
+
const v = value[i];
|
|
247
|
+
result += HexCharacters[(v & 240) >> 4] + HexCharacters[v & 15];
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
}
|
|
251
|
+
return logger.throwArgumentError("invalid hexlify value", "value", value);
|
|
252
|
+
}
|
|
253
|
+
function hexDataLength(data) {
|
|
254
|
+
if (typeof data !== "string") {
|
|
255
|
+
data = hexlify(data);
|
|
256
|
+
} else if (!isHexString(data) || data.length % 2) {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
return (data.length - 2) / 2;
|
|
260
|
+
}
|
|
261
|
+
function hexDataSlice(data, offset, endOffset) {
|
|
262
|
+
if (typeof data !== "string") {
|
|
263
|
+
data = hexlify(data);
|
|
264
|
+
} else if (!isHexString(data) || data.length % 2) {
|
|
265
|
+
logger.throwArgumentError("invalid hexData", "value", data);
|
|
266
|
+
}
|
|
267
|
+
offset = 2 + 2 * offset;
|
|
268
|
+
if (endOffset != null) {
|
|
269
|
+
return "0x" + data.substring(offset, 2 + 2 * endOffset);
|
|
270
|
+
}
|
|
271
|
+
return "0x" + data.substring(offset);
|
|
272
|
+
}
|
|
273
|
+
function hexConcat(items) {
|
|
274
|
+
let result = "0x";
|
|
275
|
+
items.forEach((item) => {
|
|
276
|
+
result += hexlify(item).substring(2);
|
|
277
|
+
});
|
|
278
|
+
return result;
|
|
279
|
+
}
|
|
280
|
+
function hexValue(value) {
|
|
281
|
+
const trimmed = hexStripZeros(hexlify(value, { hexPad: "left" }));
|
|
282
|
+
if (trimmed === "0x") {
|
|
283
|
+
return "0x0";
|
|
284
|
+
}
|
|
285
|
+
return trimmed;
|
|
286
|
+
}
|
|
287
|
+
function hexStripZeros(value) {
|
|
288
|
+
if (typeof value !== "string") {
|
|
289
|
+
value = hexlify(value);
|
|
290
|
+
}
|
|
291
|
+
if (!isHexString(value)) {
|
|
292
|
+
logger.throwArgumentError("invalid hex string", "value", value);
|
|
293
|
+
}
|
|
294
|
+
value = value.substring(2);
|
|
295
|
+
let offset = 0;
|
|
296
|
+
while (offset < value.length && value[offset] === "0") {
|
|
297
|
+
offset++;
|
|
298
|
+
}
|
|
299
|
+
return "0x" + value.substring(offset);
|
|
300
|
+
}
|
|
301
|
+
function hexZeroPad(value, length) {
|
|
302
|
+
if (typeof value !== "string") {
|
|
303
|
+
value = hexlify(value);
|
|
304
|
+
} else if (!isHexString(value)) {
|
|
305
|
+
logger.throwArgumentError("invalid hex string", "value", value);
|
|
306
|
+
}
|
|
307
|
+
if (value.length > 2 * length + 2) {
|
|
308
|
+
logger.throwError("value out of range", { value, length });
|
|
309
|
+
}
|
|
310
|
+
while (value.length < 2 * length + 2) {
|
|
311
|
+
value = "0x0" + value.substring(2);
|
|
312
|
+
}
|
|
313
|
+
return value;
|
|
314
|
+
}
|
|
315
|
+
function keccak256(data) {
|
|
316
|
+
let bytes;
|
|
317
|
+
if (typeof data === "string") {
|
|
318
|
+
const hex = data.replace(/^0x/, "");
|
|
319
|
+
bytes = new Uint8Array(hex.length / 2);
|
|
320
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
321
|
+
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
bytes = new Uint8Array(data);
|
|
325
|
+
}
|
|
326
|
+
return "0x" + bytesToHex(keccak_256(bytes));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/utils/to-utf8-bytes.ts
|
|
330
|
+
function toUtf8Bytes(data) {
|
|
331
|
+
return new TextEncoder().encode(data);
|
|
332
|
+
}
|
|
333
|
+
function computePublicKey(privKey) {
|
|
334
|
+
privKey = hexlify(privKey).slice(2);
|
|
335
|
+
return "0x" + Point.fromPrivateKey(privKey).toHex();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/utils/compute-address.ts
|
|
339
|
+
function computeAddress(key) {
|
|
340
|
+
if (!key.startsWith("0x04") && !key.startsWith("0x03") && !key.startsWith("0x02")) {
|
|
341
|
+
key = computePublicKey(key);
|
|
342
|
+
}
|
|
343
|
+
return toChecksumAddress(hexDataSlice(keccak256(hexDataSlice(key, 1)), 12));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// src/utils/hash-message.ts
|
|
347
|
+
var messagePrefix = "Ethereum Signed Message:\n";
|
|
348
|
+
function hashMessage(message) {
|
|
349
|
+
if (typeof message === "string") {
|
|
350
|
+
message = toUtf8Bytes(message);
|
|
351
|
+
}
|
|
352
|
+
return keccak256(
|
|
353
|
+
concat([
|
|
354
|
+
toUtf8Bytes(messagePrefix),
|
|
355
|
+
toUtf8Bytes(String(message.length)),
|
|
356
|
+
message
|
|
357
|
+
])
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/utils/is-address.ts
|
|
362
|
+
function isAddress(address) {
|
|
363
|
+
validateType(address, ["string"]);
|
|
364
|
+
try {
|
|
365
|
+
toChecksumAddress(address);
|
|
366
|
+
return true;
|
|
367
|
+
} catch (error) {
|
|
368
|
+
return false;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/classes/utils/hex-to-decimal.ts
|
|
373
|
+
function hexToDecimal(hex) {
|
|
374
|
+
return BigInt(hex).toString();
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/classes/utils/encode-decode-transaction.ts
|
|
378
|
+
var hexFalse = "0".repeat(64);
|
|
379
|
+
var hexTrue = "0".repeat(63) + "1";
|
|
380
|
+
function hexToUtf8(hex) {
|
|
381
|
+
let str = "";
|
|
382
|
+
let i = 0;
|
|
383
|
+
const l = hex.length;
|
|
384
|
+
if (hex.substring(0, 2) === "0x") {
|
|
385
|
+
i = 2;
|
|
386
|
+
}
|
|
387
|
+
for (; i < l; i += 2) {
|
|
388
|
+
const code = parseInt(hex.substr(i, 2), 16);
|
|
389
|
+
if (code === 0)
|
|
390
|
+
continue;
|
|
391
|
+
str += String.fromCharCode(code);
|
|
392
|
+
}
|
|
393
|
+
try {
|
|
394
|
+
return decodeURIComponent(escape(str));
|
|
395
|
+
} catch (e) {
|
|
396
|
+
return str;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
function expandType(type) {
|
|
400
|
+
if (type === "uint[]") {
|
|
401
|
+
return "uint256[]";
|
|
402
|
+
}
|
|
403
|
+
if (type === "int[]") {
|
|
404
|
+
return "int256[]";
|
|
405
|
+
}
|
|
406
|
+
return type;
|
|
407
|
+
}
|
|
408
|
+
function encodeData(jsonABIArgument, args) {
|
|
409
|
+
const functionString = `${jsonABIArgument.name}(${jsonABIArgument.inputs.map(
|
|
410
|
+
(input) => expandType(input.type)
|
|
411
|
+
)})`;
|
|
412
|
+
const functionHash = bytesToHex(
|
|
413
|
+
keccak_256(new TextEncoder().encode(functionString))
|
|
414
|
+
);
|
|
415
|
+
const jsonABIInputsLength = jsonABIArgument.inputs.length;
|
|
416
|
+
let shouldValidateInputLength = true;
|
|
417
|
+
if (jsonABIArgument.inputs.find((input) => input.type.includes("["))) {
|
|
418
|
+
shouldValidateInputLength = false;
|
|
419
|
+
}
|
|
420
|
+
if (shouldValidateInputLength && args.length !== jsonABIInputsLength) {
|
|
421
|
+
throw new Error(
|
|
422
|
+
`args inputs of "${args.length}" does not match expected length of "${jsonABIArgument.inputs.length}"`
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
const argsWithTypes = (jsonABIArgument.inputs || []).reduce(
|
|
426
|
+
(acc, input, i) => {
|
|
427
|
+
if (input.type.includes("[")) {
|
|
428
|
+
const basicType = /([^[]*)\[.*$/g.exec(input.type)?.[1];
|
|
429
|
+
args.forEach((arg) => {
|
|
430
|
+
acc = acc.concat([[arg, basicType]]);
|
|
431
|
+
});
|
|
432
|
+
return acc;
|
|
433
|
+
} else {
|
|
434
|
+
return acc.concat([[args[i], input.type]]);
|
|
435
|
+
}
|
|
436
|
+
},
|
|
437
|
+
[]
|
|
438
|
+
);
|
|
439
|
+
const encodedArgs = argsWithTypes.map(([arg, inputType]) => {
|
|
440
|
+
let rawArg = arg;
|
|
441
|
+
switch (inputType) {
|
|
442
|
+
case "bool":
|
|
443
|
+
return arg ? hexTrue : hexFalse;
|
|
444
|
+
case "address":
|
|
445
|
+
rawArg = arg.replace(/^0x/g, "").toLowerCase();
|
|
446
|
+
break;
|
|
447
|
+
default:
|
|
448
|
+
if (inputType.startsWith("bytes")) {
|
|
449
|
+
if (Array.isArray(arg)) {
|
|
450
|
+
throw new Error(
|
|
451
|
+
`essential-eth does not yet support "${inputType}[]" inputs. Make a PR today!"`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
const argEncoded2 = BigInt(arg).toString(16);
|
|
455
|
+
const paddedEncodedArg2 = argEncoded2.padStart(64, "0");
|
|
456
|
+
return paddedEncodedArg2;
|
|
457
|
+
} else if (inputType === "uint256") {
|
|
458
|
+
const argEncoded2 = BigInt(arg).toString(16);
|
|
459
|
+
const paddedEncodedArg2 = argEncoded2.padStart(64, "0");
|
|
460
|
+
return paddedEncodedArg2;
|
|
461
|
+
} else if (inputType.startsWith("uint")) {
|
|
462
|
+
break;
|
|
463
|
+
} else {
|
|
464
|
+
throw new Error(
|
|
465
|
+
`essential-eth does not yet support "${inputType}" inputs. Make a PR today!"`
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
const argEncoded = rawArg.toString(16);
|
|
470
|
+
const paddedEncodedArg = argEncoded.padStart(64, "0");
|
|
471
|
+
return paddedEncodedArg;
|
|
472
|
+
});
|
|
473
|
+
const functionEncoded = functionHash.slice(0, 8);
|
|
474
|
+
const data = `0x${functionEncoded}${encodedArgs.join("")}`;
|
|
475
|
+
return data;
|
|
476
|
+
}
|
|
477
|
+
function decodeRPCResponse(jsonABIArgument, nodeResponse) {
|
|
478
|
+
const rawOutputs = jsonABIArgument.outputs || [];
|
|
479
|
+
const slicedResponse = nodeResponse.slice(2);
|
|
480
|
+
if (rawOutputs.length === 1 && rawOutputs[0].type === "string") {
|
|
481
|
+
const [hexOffset, responseData] = [
|
|
482
|
+
slicedResponse.slice(0, 64),
|
|
483
|
+
slicedResponse.slice(64)
|
|
484
|
+
];
|
|
485
|
+
const decimalOffset = Number(hexToDecimal(`0x${hexOffset}`));
|
|
486
|
+
const hexLength = responseData.slice(0, decimalOffset * 2);
|
|
487
|
+
const decimalLength = Number(hexToDecimal(`0x${hexLength}`));
|
|
488
|
+
const hexToDecode = responseData.slice(
|
|
489
|
+
decimalOffset * 2,
|
|
490
|
+
decimalOffset * 2 + decimalLength * 2
|
|
491
|
+
);
|
|
492
|
+
return hexToUtf8(hexToDecode);
|
|
493
|
+
}
|
|
494
|
+
const encodedOutputs = slicedResponse.match(/.{1,64}/g) || [];
|
|
495
|
+
if (rawOutputs.length === 1 && rawOutputs[0].type === "address[]") {
|
|
496
|
+
const unformattedAddresses = encodedOutputs.slice(2);
|
|
497
|
+
return unformattedAddresses.map((unformattedAddress) => {
|
|
498
|
+
return toChecksumAddress(`0x${unformattedAddress.slice(24)}`);
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
if (rawOutputs?.length === 1 && rawOutputs[0].type === "uint256[]") {
|
|
502
|
+
const outputs2 = encodedOutputs.slice(2);
|
|
503
|
+
return outputs2.map((output) => {
|
|
504
|
+
return BigInt(hexToDecimal(`0x${output}`));
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
const outputs = encodedOutputs.map((output, i) => {
|
|
508
|
+
const outputType = rawOutputs[i].type;
|
|
509
|
+
switch (outputType) {
|
|
510
|
+
case "bool":
|
|
511
|
+
return output === hexTrue;
|
|
512
|
+
case "address":
|
|
513
|
+
return toChecksumAddress(`0x${output.slice(24)}`);
|
|
514
|
+
case "bytes32":
|
|
515
|
+
return `0x${output}`;
|
|
516
|
+
case "uint8":
|
|
517
|
+
return Number(hexToDecimal(`0x${output}`));
|
|
518
|
+
default:
|
|
519
|
+
if (outputType.startsWith("uint")) {
|
|
520
|
+
return BigInt(hexToDecimal(`0x${output}`));
|
|
521
|
+
}
|
|
522
|
+
if (outputType.startsWith("int")) {
|
|
523
|
+
return BigInt(hexToDecimal(`0x${output}`));
|
|
524
|
+
}
|
|
525
|
+
throw new Error(
|
|
526
|
+
`essential-eth does not yet support "${outputType}" outputs. Make a PR today!"`
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
return outputs.length === 1 ? outputs[0] : outputs;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// src/utils/solidity-keccak256.ts
|
|
534
|
+
var regexBytes = new RegExp("^bytes([0-9]+)$");
|
|
535
|
+
var regexNumber = new RegExp("^(u?int)([0-9]*)$");
|
|
536
|
+
var regexArray = new RegExp("^(.*)\\[([0-9]*)\\]$");
|
|
537
|
+
function _pack(type, value, isArray) {
|
|
538
|
+
switch (type) {
|
|
539
|
+
case "address":
|
|
540
|
+
if (isArray) {
|
|
541
|
+
return zeroPad(value, 32);
|
|
542
|
+
}
|
|
543
|
+
return arrayify(value);
|
|
544
|
+
case "string":
|
|
545
|
+
return new TextEncoder().encode(value);
|
|
546
|
+
case "bytes":
|
|
547
|
+
return arrayify(value);
|
|
548
|
+
case "bool":
|
|
549
|
+
value = value ? "0x01" : "0x00";
|
|
550
|
+
if (isArray) {
|
|
551
|
+
return zeroPad(value, 32);
|
|
552
|
+
}
|
|
553
|
+
return arrayify(value);
|
|
554
|
+
}
|
|
555
|
+
let match = type.match(regexNumber);
|
|
556
|
+
if (match) {
|
|
557
|
+
let size = parseInt(match[2] || "256");
|
|
558
|
+
if (match[2] && String(size) !== match[2] || size % 8 !== 0 || size === 0 || size > 256) {
|
|
559
|
+
logger.throwArgumentError("invalid number type", "type", type);
|
|
560
|
+
}
|
|
561
|
+
if (isArray) {
|
|
562
|
+
size = 256;
|
|
563
|
+
}
|
|
564
|
+
let bigVal = BigInt(value);
|
|
565
|
+
if (bigVal < 0n) {
|
|
566
|
+
bigVal = bigVal + (1n << BigInt(size));
|
|
567
|
+
}
|
|
568
|
+
value = Number(bigVal);
|
|
569
|
+
const hexValue2 = hexlify(value);
|
|
570
|
+
return zeroPad(hexValue2, size / 8);
|
|
571
|
+
}
|
|
572
|
+
match = type.match(regexBytes);
|
|
573
|
+
if (match) {
|
|
574
|
+
const size = parseInt(match[1]);
|
|
575
|
+
if (String(size) !== match[1] || size === 0 || size > 32) {
|
|
576
|
+
logger.throwArgumentError("invalid bytes type", "type", type);
|
|
577
|
+
}
|
|
578
|
+
if (arrayify(value).byteLength !== size) {
|
|
579
|
+
logger.throwArgumentError(`invalid value for ${type}`, "value", value);
|
|
580
|
+
}
|
|
581
|
+
if (isArray) {
|
|
582
|
+
return arrayify((value + hexFalse).substring(0, 66));
|
|
583
|
+
}
|
|
584
|
+
return value;
|
|
585
|
+
}
|
|
586
|
+
match = type.match(regexArray);
|
|
587
|
+
if (match && Array.isArray(value)) {
|
|
588
|
+
const baseType = match[1];
|
|
589
|
+
const count = parseInt(match[2] || String(value.length));
|
|
590
|
+
if (count != value.length) {
|
|
591
|
+
logger.throwArgumentError(
|
|
592
|
+
`invalid array length for ${type}`,
|
|
593
|
+
"value",
|
|
594
|
+
value
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
const result = [];
|
|
598
|
+
value.forEach(function(value2) {
|
|
599
|
+
result.push(_pack(baseType, value2, true));
|
|
600
|
+
});
|
|
601
|
+
return concat(result);
|
|
602
|
+
}
|
|
603
|
+
return logger.throwArgumentError("invalid type", "type", type);
|
|
604
|
+
}
|
|
605
|
+
function pack(types, values) {
|
|
606
|
+
if (types.length != values.length) {
|
|
607
|
+
logger.throwArgumentError(
|
|
608
|
+
"wrong number of values; expected ${ types.length }",
|
|
609
|
+
"values",
|
|
610
|
+
values
|
|
611
|
+
);
|
|
612
|
+
}
|
|
613
|
+
const tight = [];
|
|
614
|
+
types.forEach(function(type, index) {
|
|
615
|
+
tight.push(_pack(type, values[index]));
|
|
616
|
+
});
|
|
617
|
+
return hexlify(concat(tight));
|
|
618
|
+
}
|
|
619
|
+
function solidityKeccak256(types, values) {
|
|
620
|
+
return keccak256(pack(types, values));
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// src/utils/split-signature.ts
|
|
624
|
+
function splitSignature(signature) {
|
|
625
|
+
const result = {
|
|
626
|
+
r: "0x",
|
|
627
|
+
s: "0x",
|
|
628
|
+
_vs: "0x",
|
|
629
|
+
recoveryParam: 0,
|
|
630
|
+
v: 0,
|
|
631
|
+
yParityAndS: "0x",
|
|
632
|
+
compact: "0x"
|
|
633
|
+
};
|
|
634
|
+
if (isBytesLike(signature)) {
|
|
635
|
+
const bytes = arrayify(signature);
|
|
636
|
+
if (bytes.length === 64) {
|
|
637
|
+
result.v = 27 + (bytes[32] >> 7);
|
|
638
|
+
bytes[32] &= 127;
|
|
639
|
+
result.r = hexlify(bytes.slice(0, 32));
|
|
640
|
+
result.s = hexlify(bytes.slice(32, 64));
|
|
641
|
+
} else if (bytes.length === 65) {
|
|
642
|
+
result.r = hexlify(bytes.slice(0, 32));
|
|
643
|
+
result.s = hexlify(bytes.slice(32, 64));
|
|
644
|
+
result.v = bytes[64];
|
|
645
|
+
} else {
|
|
646
|
+
logger.throwArgumentError(
|
|
647
|
+
"invalid signature string",
|
|
648
|
+
"signature",
|
|
649
|
+
signature
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
if (result.v < 27) {
|
|
653
|
+
if (result.v === 0 || result.v === 1) {
|
|
654
|
+
result.v += 27;
|
|
655
|
+
} else {
|
|
656
|
+
logger.throwArgumentError(
|
|
657
|
+
"signature invalid v byte",
|
|
658
|
+
"signature",
|
|
659
|
+
signature
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
result.recoveryParam = 1 - result.v % 2;
|
|
664
|
+
if (result.recoveryParam) {
|
|
665
|
+
bytes[32] |= 128;
|
|
666
|
+
}
|
|
667
|
+
result._vs = hexlify(bytes.slice(32, 64));
|
|
668
|
+
} else {
|
|
669
|
+
result.r = signature.r;
|
|
670
|
+
result.s = signature.s;
|
|
671
|
+
result.v = signature.v;
|
|
672
|
+
result.recoveryParam = signature.recoveryParam;
|
|
673
|
+
result._vs = signature._vs;
|
|
674
|
+
if (result._vs != null) {
|
|
675
|
+
const vs_1 = zeroPad(arrayify(result._vs), 32);
|
|
676
|
+
result._vs = hexlify(vs_1);
|
|
677
|
+
const recoveryParam = vs_1[0] >= 128 ? 1 : 0;
|
|
678
|
+
if (result.recoveryParam == null) {
|
|
679
|
+
result.recoveryParam = recoveryParam;
|
|
680
|
+
} else if (result.recoveryParam !== recoveryParam) {
|
|
681
|
+
logger.throwArgumentError(
|
|
682
|
+
"signature recoveryParam mismatch _vs",
|
|
683
|
+
"signature",
|
|
684
|
+
signature
|
|
685
|
+
);
|
|
686
|
+
}
|
|
687
|
+
vs_1[0] &= 127;
|
|
688
|
+
const s = hexlify(vs_1);
|
|
689
|
+
if (result.s == null) {
|
|
690
|
+
result.s = s;
|
|
691
|
+
} else if (result.s !== s) {
|
|
692
|
+
logger.throwArgumentError(
|
|
693
|
+
"signature v mismatch _vs",
|
|
694
|
+
"signature",
|
|
695
|
+
signature
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (result.recoveryParam == null) {
|
|
700
|
+
if (result.v == null) {
|
|
701
|
+
logger.throwArgumentError(
|
|
702
|
+
"signature missing v and recoveryParam",
|
|
703
|
+
"signature",
|
|
704
|
+
signature
|
|
705
|
+
);
|
|
706
|
+
} else if (result.v === 0 || result.v === 1) {
|
|
707
|
+
result.recoveryParam = result.v;
|
|
708
|
+
} else {
|
|
709
|
+
result.recoveryParam = 1 - result.v % 2;
|
|
710
|
+
}
|
|
711
|
+
} else {
|
|
712
|
+
if (result.v == null) {
|
|
713
|
+
result.v = 27 + result.recoveryParam;
|
|
714
|
+
} else {
|
|
715
|
+
const recId = result.v === 0 || result.v === 1 ? result.v : 1 - result.v % 2;
|
|
716
|
+
if (result.recoveryParam !== recId) {
|
|
717
|
+
logger.throwArgumentError(
|
|
718
|
+
"signature recoveryParam mismatch v",
|
|
719
|
+
"signature",
|
|
720
|
+
signature
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
if (result.r == null || !isHexString(result.r)) {
|
|
726
|
+
logger.throwArgumentError(
|
|
727
|
+
"signature missing or invalid r",
|
|
728
|
+
"signature",
|
|
729
|
+
signature
|
|
730
|
+
);
|
|
731
|
+
} else {
|
|
732
|
+
result.r = hexZeroPad(result.r, 32);
|
|
733
|
+
}
|
|
734
|
+
if (result.s == null || !isHexString(result.s)) {
|
|
735
|
+
logger.throwArgumentError(
|
|
736
|
+
"signature missing or invalid s",
|
|
737
|
+
"signature",
|
|
738
|
+
signature
|
|
739
|
+
);
|
|
740
|
+
} else {
|
|
741
|
+
result.s = hexZeroPad(result.s, 32);
|
|
742
|
+
}
|
|
743
|
+
const vs = arrayify(result.s);
|
|
744
|
+
if (vs[0] >= 128) {
|
|
745
|
+
logger.throwArgumentError(
|
|
746
|
+
"signature s out of range",
|
|
747
|
+
"signature",
|
|
748
|
+
signature
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
if (result.recoveryParam) {
|
|
752
|
+
vs[0] |= 128;
|
|
753
|
+
}
|
|
754
|
+
const _vs = hexlify(vs);
|
|
755
|
+
if (result._vs) {
|
|
756
|
+
if (!isHexString(result._vs)) {
|
|
757
|
+
logger.throwArgumentError(
|
|
758
|
+
"signature invalid _vs",
|
|
759
|
+
"signature",
|
|
760
|
+
signature
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
result._vs = hexZeroPad(result._vs, 32);
|
|
764
|
+
}
|
|
765
|
+
if (result._vs == null) {
|
|
766
|
+
result._vs = _vs;
|
|
767
|
+
} else if (result._vs !== _vs) {
|
|
768
|
+
logger.throwArgumentError(
|
|
769
|
+
"signature _vs mismatch v and s",
|
|
770
|
+
"signature",
|
|
771
|
+
signature
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
result.yParityAndS = result._vs;
|
|
776
|
+
result.compact = result.r + result.yParityAndS.substring(2);
|
|
777
|
+
return result;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
export { arrayify, computeAddress, computePublicKey, concat, decodeRPCResponse, encodeData, hashMessage, hexConcat, hexDataLength, hexDataSlice, hexStripZeros, hexToDecimal, hexValue, hexZeroPad, hexlify, isAddress, isBytes, isBytesLike, isHexString, keccak256, logger, pack, solidityKeccak256, splitSignature, stripZeros, toChecksumAddress, toUtf8Bytes, zeroPad };
|