quantumcoin 7.0.3 → 7.0.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/.github/workflows/publish-npmjs.yaml +22 -22
- package/.gitignore +15 -15
- package/LICENSE +21 -21
- package/README-SDK.md +756 -754
- package/README.md +165 -150
- package/SPEC.md +3845 -3843
- package/config.d.ts +50 -50
- package/config.js +115 -115
- package/examples/AllSolidityTypes.sol +184 -184
- package/examples/SimpleIERC20.sol +74 -74
- package/examples/events.js +41 -35
- package/examples/events.ts +35 -0
- package/examples/example-generator-sdk-js.js +100 -95
- package/examples/example-generator-sdk-js.ts +77 -0
- package/examples/example-generator-sdk-ts.js +100 -95
- package/examples/example-generator-sdk-ts.ts +77 -0
- package/examples/example.js +72 -61
- package/examples/example.ts +61 -0
- package/examples/offline-signing.js +79 -73
- package/examples/offline-signing.ts +66 -0
- package/examples/package-lock.json +48 -57
- package/examples/package.json +32 -16
- package/examples/read-operations.js +32 -27
- package/examples/read-operations.ts +31 -0
- package/examples/sdk-generator-erc20.inline.json +251 -251
- package/examples/solidity-types.ts +43 -43
- package/examples/wallet-offline.js +35 -29
- package/examples/wallet-offline.ts +34 -0
- package/generate-sdk.js +1824 -1490
- package/index.js +12 -12
- package/package.json +95 -75
- package/scripts/copy-declarations.js +31 -0
- package/scripts/run-all-one-by-one.js +151 -0
- package/src/abi/fragments.d.ts +42 -42
- package/src/abi/fragments.js +63 -63
- package/src/abi/index.d.ts +13 -13
- package/src/abi/index.js +9 -9
- package/src/abi/interface.d.ts +128 -132
- package/src/abi/interface.js +590 -590
- package/src/abi/js-abi-coder.d.ts +8 -0
- package/src/abi/js-abi-coder.js +474 -474
- package/src/constants.d.ts +66 -61
- package/src/constants.js +101 -94
- package/src/contract/contract-factory.d.ts +28 -28
- package/src/contract/contract-factory.js +105 -105
- package/src/contract/contract.d.ts +113 -114
- package/src/contract/contract.js +354 -354
- package/src/contract/index.d.ts +9 -9
- package/src/contract/index.js +9 -9
- package/src/errors/index.d.ts +92 -92
- package/src/errors/index.js +188 -188
- package/src/generator/index.d.ts +74 -0
- package/src/generator/index.js +1404 -1404
- package/src/index.d.ts +125 -127
- package/src/index.js +41 -41
- package/src/internal/hex.d.ts +61 -61
- package/src/internal/hex.js +144 -144
- package/src/providers/extra-providers.d.ts +139 -128
- package/src/providers/extra-providers.js +600 -575
- package/src/providers/index.d.ts +17 -16
- package/src/providers/index.js +10 -10
- package/src/providers/json-rpc-provider.d.ts +12 -12
- package/src/providers/json-rpc-provider.js +79 -79
- package/src/providers/provider.d.ts +207 -203
- package/src/providers/provider.js +392 -371
- package/src/types/index.d.ts +214 -462
- package/src/types/index.js +9 -9
- package/src/utils/address.d.ts +72 -72
- package/src/utils/address.js +181 -182
- package/src/utils/encoding.d.ts +120 -120
- package/src/utils/encoding.js +306 -306
- package/src/utils/hashing.d.ts +82 -76
- package/src/utils/hashing.js +313 -298
- package/src/utils/index.d.ts +65 -55
- package/src/utils/index.js +13 -13
- package/src/utils/result.d.ts +57 -57
- package/src/utils/result.js +128 -128
- package/src/utils/rlp.d.ts +12 -12
- package/src/utils/rlp.js +200 -200
- package/src/utils/units.d.ts +29 -29
- package/src/utils/units.js +107 -107
- package/src/wallet/index.d.ts +10 -10
- package/src/wallet/index.js +8 -8
- package/src/wallet/wallet.d.ts +160 -160
- package/src/wallet/wallet.js +483 -489
- package/test/e2e/all-solidity-types.dynamic.test.js +207 -200
- package/test/e2e/all-solidity-types.dynamic.test.ts +191 -0
- package/test/e2e/all-solidity-types.fixtures.js +231 -231
- package/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +387 -368
- package/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +350 -0
- package/test/e2e/helpers.js +59 -47
- package/test/e2e/signing-context-and-fee.e2e.test.js +137 -0
- package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -0
- package/test/e2e/simple-erc20.generated-sdks.e2e.test.js +168 -151
- package/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +141 -0
- package/test/e2e/transactional.test.js +245 -191
- package/test/e2e/transactional.test.ts +208 -0
- package/test/e2e/typed-generator.e2e.test.js +407 -404
- package/test/e2e/typed-generator.e2e.test.ts +337 -0
- package/test/fixtures/ConstructorParam.sol +23 -23
- package/test/fixtures/MultiContracts.sol +37 -37
- package/test/fixtures/SimpleStorage.sol +18 -18
- package/test/fixtures/StakingContract.abi.json +1 -1
- package/test/integration/ipc-provider.test.js +49 -44
- package/test/integration/ipc-provider.test.ts +44 -0
- package/test/integration/provider.test.js +88 -72
- package/test/integration/provider.test.ts +85 -0
- package/test/integration/ws-provider.test.js +41 -33
- package/test/integration/ws-provider.test.ts +38 -0
- package/test/security/malformed-input.test.js +37 -31
- package/test/security/malformed-input.test.ts +35 -0
- package/test/unit/_encrypted-output.txt +6 -0
- package/test/unit/_log-encrypted-jsons.js +45 -0
- package/test/unit/_write-keystore-fixture.js +16 -0
- package/test/unit/abi-interface.test.js +103 -98
- package/test/unit/abi-interface.test.ts +102 -0
- package/test/unit/address-wallet.test.js +355 -257
- package/test/unit/address-wallet.test.ts +342 -0
- package/test/unit/browser-provider.test.js +85 -82
- package/test/unit/browser-provider.test.ts +79 -0
- package/test/unit/contract.test.js +85 -82
- package/test/unit/contract.test.ts +83 -0
- package/test/unit/encoding-units-rlp.test.js +92 -89
- package/test/unit/encoding-units-rlp.test.ts +91 -0
- package/test/unit/errors.test.js +77 -74
- package/test/unit/errors.test.ts +76 -0
- package/test/unit/filter-by-blockhash.test.js +55 -52
- package/test/unit/filter-by-blockhash.test.ts +54 -0
- package/test/unit/fixtures/encrypted-keystores-48-32-36.js +9 -0
- package/test/unit/generate-contract-cli.test.js +42 -39
- package/test/unit/generate-contract-cli.test.ts +41 -0
- package/test/unit/generate-sdk-artifacts-json.test.js +113 -110
- package/test/unit/generate-sdk-artifacts-json.test.ts +110 -0
- package/test/unit/generator.test.js +102 -99
- package/test/unit/generator.test.ts +101 -0
- package/test/unit/hashing.test.js +68 -54
- package/test/unit/hashing.test.ts +67 -0
- package/test/unit/init.test.js +39 -36
- package/test/unit/init.test.ts +38 -0
- package/test/unit/interface.test.js +56 -53
- package/test/unit/interface.test.ts +54 -0
- package/test/unit/internal-hex.test.js +50 -47
- package/test/unit/internal-hex.test.ts +49 -0
- package/test/unit/populate-transaction.test.js +65 -62
- package/test/unit/populate-transaction.test.ts +64 -0
- package/test/unit/providers.test.js +200 -144
- package/test/unit/providers.test.ts +196 -0
- package/test/unit/result.test.js +80 -77
- package/test/unit/result.test.ts +79 -0
- package/test/unit/solidity-types.test.js +49 -46
- package/test/unit/solidity-types.test.ts +39 -0
- package/test/unit/utils.test.js +57 -54
- package/test/unit/utils.test.ts +56 -0
- package/test/verbose-logger.js +74 -0
- package/tsconfig.build.json +14 -0
package/src/utils/rlp.js
CHANGED
|
@@ -1,200 +1,200 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview RLP encoding utilities.
|
|
3
|
-
*
|
|
4
|
-
* SPEC.md section 5.9 mirrors ethers.js v6 RLP helpers.
|
|
5
|
-
*
|
|
6
|
-
* This implementation is self-contained (no vendored ethers.js dependency).
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex, utf8ToBytes } = require("../internal/hex");
|
|
10
|
-
|
|
11
|
-
function _toBytes(value) {
|
|
12
|
-
if (value == null) return new Uint8Array([]);
|
|
13
|
-
|
|
14
|
-
if (value instanceof Uint8Array) return new Uint8Array(value);
|
|
15
|
-
if (Buffer.isBuffer(value)) return new Uint8Array(value);
|
|
16
|
-
|
|
17
|
-
if (Array.isArray(value)) {
|
|
18
|
-
// List gets handled elsewhere; here we accept array-of-bytes as a BytesLike.
|
|
19
|
-
if (value.every((v) => Number.isInteger(v) && v >= 0 && v <= 255)) {
|
|
20
|
-
return new Uint8Array(value);
|
|
21
|
-
}
|
|
22
|
-
throw new TypeError("invalid RLP bytes array");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (typeof value === "string") {
|
|
26
|
-
// Prefer hex strings (ethers-style); otherwise treat as utf8.
|
|
27
|
-
if (value === "0x" || value === "") return new Uint8Array([]);
|
|
28
|
-
if (isHexString(value)) return hexToBytes(normalizeHex(value));
|
|
29
|
-
return utf8ToBytes(value);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (typeof value === "number") {
|
|
33
|
-
if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("invalid RLP number");
|
|
34
|
-
if (value === 0) return new Uint8Array([]);
|
|
35
|
-
let n = BigInt(value);
|
|
36
|
-
const out = [];
|
|
37
|
-
while (n > 0n) {
|
|
38
|
-
out.push(Number(n & 0xffn));
|
|
39
|
-
n >>= 8n;
|
|
40
|
-
}
|
|
41
|
-
out.reverse();
|
|
42
|
-
return new Uint8Array(out);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (typeof value === "bigint") {
|
|
46
|
-
if (value < 0n) throw new TypeError("invalid RLP bigint");
|
|
47
|
-
if (value === 0n) return new Uint8Array([]);
|
|
48
|
-
let n = value;
|
|
49
|
-
const out = [];
|
|
50
|
-
while (n > 0n) {
|
|
51
|
-
out.push(Number(n & 0xffn));
|
|
52
|
-
n >>= 8n;
|
|
53
|
-
}
|
|
54
|
-
out.reverse();
|
|
55
|
-
return new Uint8Array(out);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
throw new TypeError("unsupported RLP value type");
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function _encodeLen(len, offsetShort, offsetLong) {
|
|
62
|
-
if (len <= 55) {
|
|
63
|
-
return new Uint8Array([offsetShort + len]);
|
|
64
|
-
}
|
|
65
|
-
// length-of-length (big-endian)
|
|
66
|
-
let l = len;
|
|
67
|
-
const bytes = [];
|
|
68
|
-
while (l > 0) {
|
|
69
|
-
bytes.push(l & 0xff);
|
|
70
|
-
l >>= 8;
|
|
71
|
-
}
|
|
72
|
-
bytes.reverse();
|
|
73
|
-
return new Uint8Array([offsetLong + bytes.length, ...bytes]);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function _concat(a, b) {
|
|
77
|
-
const out = new Uint8Array(a.length + b.length);
|
|
78
|
-
out.set(a, 0);
|
|
79
|
-
out.set(b, a.length);
|
|
80
|
-
return out;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function _encode(value) {
|
|
84
|
-
if (Array.isArray(value) && !value.every((v) => Number.isInteger(v) && v >= 0 && v <= 255)) {
|
|
85
|
-
// List
|
|
86
|
-
let payload = new Uint8Array([]);
|
|
87
|
-
for (const item of value) {
|
|
88
|
-
payload = _concat(payload, _encode(item));
|
|
89
|
-
}
|
|
90
|
-
const prefix = _encodeLen(payload.length, 0xc0, 0xf7);
|
|
91
|
-
return _concat(prefix, payload);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// String/bytes/integer
|
|
95
|
-
const bytes = _toBytes(value);
|
|
96
|
-
if (bytes.length === 1 && bytes[0] < 0x80) {
|
|
97
|
-
return bytes;
|
|
98
|
-
}
|
|
99
|
-
const prefix = _encodeLen(bytes.length, 0x80, 0xb7);
|
|
100
|
-
return _concat(prefix, bytes);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function _readLen(bytes, offset, lenOfLen) {
|
|
104
|
-
if (lenOfLen === 0) return 0;
|
|
105
|
-
if (offset + lenOfLen > bytes.length) throw new Error("RLP: insufficient data for length");
|
|
106
|
-
let len = 0;
|
|
107
|
-
for (let i = 0; i < lenOfLen; i++) {
|
|
108
|
-
len = (len << 8) | bytes[offset + i];
|
|
109
|
-
}
|
|
110
|
-
return len;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function _decode(bytes, start, end) {
|
|
114
|
-
if (start >= end) throw new Error("RLP: empty input");
|
|
115
|
-
const prefix = bytes[start];
|
|
116
|
-
|
|
117
|
-
// Single byte
|
|
118
|
-
if (prefix <= 0x7f) {
|
|
119
|
-
return { value: bytesToHex(new Uint8Array([prefix])), next: start + 1 };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// Short string
|
|
123
|
-
if (prefix <= 0xb7) {
|
|
124
|
-
const len = prefix - 0x80;
|
|
125
|
-
const dataStart = start + 1;
|
|
126
|
-
const dataEnd = dataStart + len;
|
|
127
|
-
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
128
|
-
const out = bytesToHex(bytes.slice(dataStart, dataEnd));
|
|
129
|
-
return { value: out, next: dataEnd };
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Long string
|
|
133
|
-
if (prefix <= 0xbf) {
|
|
134
|
-
const lenOfLen = prefix - 0xb7;
|
|
135
|
-
const len = _readLen(bytes, start + 1, lenOfLen);
|
|
136
|
-
const dataStart = start + 1 + lenOfLen;
|
|
137
|
-
const dataEnd = dataStart + len;
|
|
138
|
-
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
139
|
-
const out = bytesToHex(bytes.slice(dataStart, dataEnd));
|
|
140
|
-
return { value: out, next: dataEnd };
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Short list
|
|
144
|
-
if (prefix <= 0xf7) {
|
|
145
|
-
const len = prefix - 0xc0;
|
|
146
|
-
const dataStart = start + 1;
|
|
147
|
-
const dataEnd = dataStart + len;
|
|
148
|
-
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
149
|
-
const out = [];
|
|
150
|
-
let pos = dataStart;
|
|
151
|
-
while (pos < dataEnd) {
|
|
152
|
-
const decoded = _decode(bytes, pos, dataEnd);
|
|
153
|
-
out.push(decoded.value);
|
|
154
|
-
pos = decoded.next;
|
|
155
|
-
}
|
|
156
|
-
if (pos !== dataEnd) throw new Error("RLP: list length mismatch");
|
|
157
|
-
return { value: out, next: dataEnd };
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
// Long list
|
|
161
|
-
const lenOfLen = prefix - 0xf7;
|
|
162
|
-
const len = _readLen(bytes, start + 1, lenOfLen);
|
|
163
|
-
const dataStart = start + 1 + lenOfLen;
|
|
164
|
-
const dataEnd = dataStart + len;
|
|
165
|
-
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
166
|
-
const out = [];
|
|
167
|
-
let pos = dataStart;
|
|
168
|
-
while (pos < dataEnd) {
|
|
169
|
-
const decoded = _decode(bytes, pos, dataEnd);
|
|
170
|
-
out.push(decoded.value);
|
|
171
|
-
pos = decoded.next;
|
|
172
|
-
}
|
|
173
|
-
if (pos !== dataEnd) throw new Error("RLP: list length mismatch");
|
|
174
|
-
return { value: out, next: dataEnd };
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* RLP-encode a value.
|
|
179
|
-
* @param {any} value
|
|
180
|
-
* @returns {string}
|
|
181
|
-
*/
|
|
182
|
-
function encodeRlp(value) {
|
|
183
|
-
return bytesToHex(_encode(value));
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* RLP-decode a hex string.
|
|
188
|
-
* @param {string} data
|
|
189
|
-
* @returns {any}
|
|
190
|
-
*/
|
|
191
|
-
function decodeRlp(data) {
|
|
192
|
-
if (typeof data !== "string") throw new TypeError("RLP data must be a hex string");
|
|
193
|
-
const bytes = arrayify(data);
|
|
194
|
-
const decoded = _decode(bytes, 0, bytes.length);
|
|
195
|
-
if (decoded.next !== bytes.length) throw new Error("RLP: trailing data");
|
|
196
|
-
return decoded.value;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
module.exports = { encodeRlp, decodeRlp };
|
|
200
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview RLP encoding utilities.
|
|
3
|
+
*
|
|
4
|
+
* SPEC.md section 5.9 mirrors ethers.js v6 RLP helpers.
|
|
5
|
+
*
|
|
6
|
+
* This implementation is self-contained (no vendored ethers.js dependency).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex, utf8ToBytes } = require("../internal/hex");
|
|
10
|
+
|
|
11
|
+
function _toBytes(value) {
|
|
12
|
+
if (value == null) return new Uint8Array([]);
|
|
13
|
+
|
|
14
|
+
if (value instanceof Uint8Array) return new Uint8Array(value);
|
|
15
|
+
if (Buffer.isBuffer(value)) return new Uint8Array(value);
|
|
16
|
+
|
|
17
|
+
if (Array.isArray(value)) {
|
|
18
|
+
// List gets handled elsewhere; here we accept array-of-bytes as a BytesLike.
|
|
19
|
+
if (value.every((v) => Number.isInteger(v) && v >= 0 && v <= 255)) {
|
|
20
|
+
return new Uint8Array(value);
|
|
21
|
+
}
|
|
22
|
+
throw new TypeError("invalid RLP bytes array");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (typeof value === "string") {
|
|
26
|
+
// Prefer hex strings (ethers-style); otherwise treat as utf8.
|
|
27
|
+
if (value === "0x" || value === "") return new Uint8Array([]);
|
|
28
|
+
if (isHexString(value)) return hexToBytes(normalizeHex(value));
|
|
29
|
+
return utf8ToBytes(value);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (typeof value === "number") {
|
|
33
|
+
if (!Number.isSafeInteger(value) || value < 0) throw new TypeError("invalid RLP number");
|
|
34
|
+
if (value === 0) return new Uint8Array([]);
|
|
35
|
+
let n = BigInt(value);
|
|
36
|
+
const out = [];
|
|
37
|
+
while (n > 0n) {
|
|
38
|
+
out.push(Number(n & 0xffn));
|
|
39
|
+
n >>= 8n;
|
|
40
|
+
}
|
|
41
|
+
out.reverse();
|
|
42
|
+
return new Uint8Array(out);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (typeof value === "bigint") {
|
|
46
|
+
if (value < 0n) throw new TypeError("invalid RLP bigint");
|
|
47
|
+
if (value === 0n) return new Uint8Array([]);
|
|
48
|
+
let n = value;
|
|
49
|
+
const out = [];
|
|
50
|
+
while (n > 0n) {
|
|
51
|
+
out.push(Number(n & 0xffn));
|
|
52
|
+
n >>= 8n;
|
|
53
|
+
}
|
|
54
|
+
out.reverse();
|
|
55
|
+
return new Uint8Array(out);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new TypeError("unsupported RLP value type");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function _encodeLen(len, offsetShort, offsetLong) {
|
|
62
|
+
if (len <= 55) {
|
|
63
|
+
return new Uint8Array([offsetShort + len]);
|
|
64
|
+
}
|
|
65
|
+
// length-of-length (big-endian)
|
|
66
|
+
let l = len;
|
|
67
|
+
const bytes = [];
|
|
68
|
+
while (l > 0) {
|
|
69
|
+
bytes.push(l & 0xff);
|
|
70
|
+
l >>= 8;
|
|
71
|
+
}
|
|
72
|
+
bytes.reverse();
|
|
73
|
+
return new Uint8Array([offsetLong + bytes.length, ...bytes]);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function _concat(a, b) {
|
|
77
|
+
const out = new Uint8Array(a.length + b.length);
|
|
78
|
+
out.set(a, 0);
|
|
79
|
+
out.set(b, a.length);
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function _encode(value) {
|
|
84
|
+
if (Array.isArray(value) && !value.every((v) => Number.isInteger(v) && v >= 0 && v <= 255)) {
|
|
85
|
+
// List
|
|
86
|
+
let payload = new Uint8Array([]);
|
|
87
|
+
for (const item of value) {
|
|
88
|
+
payload = _concat(payload, _encode(item));
|
|
89
|
+
}
|
|
90
|
+
const prefix = _encodeLen(payload.length, 0xc0, 0xf7);
|
|
91
|
+
return _concat(prefix, payload);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// String/bytes/integer
|
|
95
|
+
const bytes = _toBytes(value);
|
|
96
|
+
if (bytes.length === 1 && bytes[0] < 0x80) {
|
|
97
|
+
return bytes;
|
|
98
|
+
}
|
|
99
|
+
const prefix = _encodeLen(bytes.length, 0x80, 0xb7);
|
|
100
|
+
return _concat(prefix, bytes);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function _readLen(bytes, offset, lenOfLen) {
|
|
104
|
+
if (lenOfLen === 0) return 0;
|
|
105
|
+
if (offset + lenOfLen > bytes.length) throw new Error("RLP: insufficient data for length");
|
|
106
|
+
let len = 0;
|
|
107
|
+
for (let i = 0; i < lenOfLen; i++) {
|
|
108
|
+
len = (len << 8) | bytes[offset + i];
|
|
109
|
+
}
|
|
110
|
+
return len;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function _decode(bytes, start, end) {
|
|
114
|
+
if (start >= end) throw new Error("RLP: empty input");
|
|
115
|
+
const prefix = bytes[start];
|
|
116
|
+
|
|
117
|
+
// Single byte
|
|
118
|
+
if (prefix <= 0x7f) {
|
|
119
|
+
return { value: bytesToHex(new Uint8Array([prefix])), next: start + 1 };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Short string
|
|
123
|
+
if (prefix <= 0xb7) {
|
|
124
|
+
const len = prefix - 0x80;
|
|
125
|
+
const dataStart = start + 1;
|
|
126
|
+
const dataEnd = dataStart + len;
|
|
127
|
+
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
128
|
+
const out = bytesToHex(bytes.slice(dataStart, dataEnd));
|
|
129
|
+
return { value: out, next: dataEnd };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Long string
|
|
133
|
+
if (prefix <= 0xbf) {
|
|
134
|
+
const lenOfLen = prefix - 0xb7;
|
|
135
|
+
const len = _readLen(bytes, start + 1, lenOfLen);
|
|
136
|
+
const dataStart = start + 1 + lenOfLen;
|
|
137
|
+
const dataEnd = dataStart + len;
|
|
138
|
+
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
139
|
+
const out = bytesToHex(bytes.slice(dataStart, dataEnd));
|
|
140
|
+
return { value: out, next: dataEnd };
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Short list
|
|
144
|
+
if (prefix <= 0xf7) {
|
|
145
|
+
const len = prefix - 0xc0;
|
|
146
|
+
const dataStart = start + 1;
|
|
147
|
+
const dataEnd = dataStart + len;
|
|
148
|
+
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
149
|
+
const out = [];
|
|
150
|
+
let pos = dataStart;
|
|
151
|
+
while (pos < dataEnd) {
|
|
152
|
+
const decoded = _decode(bytes, pos, dataEnd);
|
|
153
|
+
out.push(decoded.value);
|
|
154
|
+
pos = decoded.next;
|
|
155
|
+
}
|
|
156
|
+
if (pos !== dataEnd) throw new Error("RLP: list length mismatch");
|
|
157
|
+
return { value: out, next: dataEnd };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Long list
|
|
161
|
+
const lenOfLen = prefix - 0xf7;
|
|
162
|
+
const len = _readLen(bytes, start + 1, lenOfLen);
|
|
163
|
+
const dataStart = start + 1 + lenOfLen;
|
|
164
|
+
const dataEnd = dataStart + len;
|
|
165
|
+
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
166
|
+
const out = [];
|
|
167
|
+
let pos = dataStart;
|
|
168
|
+
while (pos < dataEnd) {
|
|
169
|
+
const decoded = _decode(bytes, pos, dataEnd);
|
|
170
|
+
out.push(decoded.value);
|
|
171
|
+
pos = decoded.next;
|
|
172
|
+
}
|
|
173
|
+
if (pos !== dataEnd) throw new Error("RLP: list length mismatch");
|
|
174
|
+
return { value: out, next: dataEnd };
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* RLP-encode a value.
|
|
179
|
+
* @param {any} value
|
|
180
|
+
* @returns {string}
|
|
181
|
+
*/
|
|
182
|
+
function encodeRlp(value) {
|
|
183
|
+
return bytesToHex(_encode(value));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* RLP-decode a hex string.
|
|
188
|
+
* @param {string} data
|
|
189
|
+
* @returns {any}
|
|
190
|
+
*/
|
|
191
|
+
function decodeRlp(data) {
|
|
192
|
+
if (typeof data !== "string") throw new TypeError("RLP data must be a hex string");
|
|
193
|
+
const bytes = arrayify(data);
|
|
194
|
+
const decoded = _decode(bytes, 0, bytes.length);
|
|
195
|
+
if (decoded.next !== bytes.length) throw new Error("RLP: trailing data");
|
|
196
|
+
return decoded.value;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = { encodeRlp, decodeRlp };
|
|
200
|
+
|
package/src/utils/units.d.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
export type BigNumberish = string | number | bigint;
|
|
2
|
-
/**
|
|
3
|
-
* Format a BigNumberish into a decimal string with `decimals` places.
|
|
4
|
-
* @param {BigNumberish} value
|
|
5
|
-
* @param {number=} decimals
|
|
6
|
-
* @returns {string}
|
|
7
|
-
*/
|
|
8
|
-
export function formatUnits(value: BigNumberish, decimals?: number | undefined): string;
|
|
9
|
-
/**
|
|
10
|
-
* Parse a decimal string into bigint with `decimals` places.
|
|
11
|
-
* @param {string} value
|
|
12
|
-
* @param {number=} decimals
|
|
13
|
-
* @returns {bigint}
|
|
14
|
-
*/
|
|
15
|
-
export function parseUnits(value: string, decimals?: number | undefined): bigint;
|
|
16
|
-
/**
|
|
17
|
-
* Format wei as coin string.
|
|
18
|
-
* @param {BigNumberish} value
|
|
19
|
-
* @returns {string}
|
|
20
|
-
*/
|
|
21
|
-
export function formatEther(value: BigNumberish): string;
|
|
22
|
-
/**
|
|
23
|
-
* Parse coin string to wei.
|
|
24
|
-
* @param {string} value
|
|
25
|
-
* @returns {bigint}
|
|
26
|
-
*/
|
|
27
|
-
export function parseEther(value: string): bigint;
|
|
28
|
-
import { WeiPerEther } from "../constants";
|
|
29
|
-
export { WeiPerEther };
|
|
1
|
+
export type BigNumberish = string | number | bigint;
|
|
2
|
+
/**
|
|
3
|
+
* Format a BigNumberish into a decimal string with `decimals` places.
|
|
4
|
+
* @param {BigNumberish} value
|
|
5
|
+
* @param {number=} decimals
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
export function formatUnits(value: BigNumberish, decimals?: number | undefined): string;
|
|
9
|
+
/**
|
|
10
|
+
* Parse a decimal string into bigint with `decimals` places.
|
|
11
|
+
* @param {string} value
|
|
12
|
+
* @param {number=} decimals
|
|
13
|
+
* @returns {bigint}
|
|
14
|
+
*/
|
|
15
|
+
export function parseUnits(value: string, decimals?: number | undefined): bigint;
|
|
16
|
+
/**
|
|
17
|
+
* Format wei as coin string.
|
|
18
|
+
* @param {BigNumberish} value
|
|
19
|
+
* @returns {string}
|
|
20
|
+
*/
|
|
21
|
+
export function formatEther(value: BigNumberish): string;
|
|
22
|
+
/**
|
|
23
|
+
* Parse coin string to wei.
|
|
24
|
+
* @param {string} value
|
|
25
|
+
* @returns {bigint}
|
|
26
|
+
*/
|
|
27
|
+
export function parseEther(value: string): bigint;
|
|
28
|
+
import { WeiPerEther } from "../constants";
|
|
29
|
+
export { WeiPerEther };
|
package/src/utils/units.js
CHANGED
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Unit conversion helpers (ethers.js v6 compatible names).
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const { WeiPerEther } = require("../constants");
|
|
6
|
-
const { assertArgument, makeError } = require("../errors");
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @typedef {string | number | bigint} BigNumberish
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
function _toBigInt(value) {
|
|
13
|
-
if (typeof value === "bigint") return value;
|
|
14
|
-
if (typeof value === "number") {
|
|
15
|
-
assertArgument(Number.isFinite(value) && Math.floor(value) === value, "invalid number", "value", value);
|
|
16
|
-
return BigInt(value);
|
|
17
|
-
}
|
|
18
|
-
if (typeof value === "string") {
|
|
19
|
-
if (value.trim() === "") throw makeError("invalid BigNumberish string", "INVALID_ARGUMENT", { value });
|
|
20
|
-
if (value.startsWith("0x") || value.startsWith("0X")) return BigInt(value);
|
|
21
|
-
return BigInt(value);
|
|
22
|
-
}
|
|
23
|
-
throw makeError("invalid BigNumberish", "INVALID_ARGUMENT", { value });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Format a BigNumberish into a decimal string with `decimals` places.
|
|
28
|
-
* @param {BigNumberish} value
|
|
29
|
-
* @param {number=} decimals
|
|
30
|
-
* @returns {string}
|
|
31
|
-
*/
|
|
32
|
-
function formatUnits(value, decimals) {
|
|
33
|
-
const dec = decimals == null ? 18 : decimals;
|
|
34
|
-
assertArgument(Number.isInteger(dec) && dec >= 0 && dec <= 256, "invalid decimals", "decimals", decimals);
|
|
35
|
-
const v = _toBigInt(value);
|
|
36
|
-
const neg = v < 0n;
|
|
37
|
-
const abs = neg ? -v : v;
|
|
38
|
-
|
|
39
|
-
const base = 10n ** BigInt(dec);
|
|
40
|
-
const whole = abs / base;
|
|
41
|
-
const frac = abs % base;
|
|
42
|
-
|
|
43
|
-
let fracStr = frac.toString().padStart(dec, "0");
|
|
44
|
-
// trim trailing zeros
|
|
45
|
-
fracStr = fracStr.replace(/0+$/, "");
|
|
46
|
-
const out = fracStr.length ? `${whole.toString()}.${fracStr}` : whole.toString();
|
|
47
|
-
return neg ? "-" + out : out;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Parse a decimal string into bigint with `decimals` places.
|
|
52
|
-
* @param {string} value
|
|
53
|
-
* @param {number=} decimals
|
|
54
|
-
* @returns {bigint}
|
|
55
|
-
*/
|
|
56
|
-
function parseUnits(value, decimals) {
|
|
57
|
-
const dec = decimals == null ? 18 : decimals;
|
|
58
|
-
assertArgument(Number.isInteger(dec) && dec >= 0 && dec <= 256, "invalid decimals", "decimals", decimals);
|
|
59
|
-
assertArgument(typeof value === "string", "value must be a string", "value", value);
|
|
60
|
-
|
|
61
|
-
const v = value.trim();
|
|
62
|
-
assertArgument(v.length > 0, "invalid value", "value", value);
|
|
63
|
-
|
|
64
|
-
const neg = v.startsWith("-");
|
|
65
|
-
const s = neg ? v.slice(1) : v;
|
|
66
|
-
const parts = s.split(".");
|
|
67
|
-
assertArgument(parts.length <= 2, "invalid decimal string", "value", value);
|
|
68
|
-
|
|
69
|
-
const whole = parts[0] || "0";
|
|
70
|
-
const frac = parts[1] || "";
|
|
71
|
-
assertArgument(/^\d+$/.test(whole), "invalid whole component", "value", value);
|
|
72
|
-
assertArgument(/^\d*$/.test(frac), "invalid fractional component", "value", value);
|
|
73
|
-
assertArgument(frac.length <= dec, "fractional component exceeds decimals", "value", value);
|
|
74
|
-
|
|
75
|
-
const base = 10n ** BigInt(dec);
|
|
76
|
-
const wholeBI = BigInt(whole) * base;
|
|
77
|
-
const fracBI = frac.length ? BigInt(frac.padEnd(dec, "0")) : 0n;
|
|
78
|
-
const out = wholeBI + fracBI;
|
|
79
|
-
return neg ? -out : out;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Format wei as coin string.
|
|
84
|
-
* @param {BigNumberish} value
|
|
85
|
-
* @returns {string}
|
|
86
|
-
*/
|
|
87
|
-
function formatEther(value) {
|
|
88
|
-
return formatUnits(value, 18);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Parse coin string to wei.
|
|
93
|
-
* @param {string} value
|
|
94
|
-
* @returns {bigint}
|
|
95
|
-
*/
|
|
96
|
-
function parseEther(value) {
|
|
97
|
-
return parseUnits(value, 18);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
module.exports = {
|
|
101
|
-
formatUnits,
|
|
102
|
-
parseUnits,
|
|
103
|
-
formatEther,
|
|
104
|
-
parseEther,
|
|
105
|
-
WeiPerEther,
|
|
106
|
-
};
|
|
107
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Unit conversion helpers (ethers.js v6 compatible names).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { WeiPerEther } = require("../constants");
|
|
6
|
+
const { assertArgument, makeError } = require("../errors");
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {string | number | bigint} BigNumberish
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
function _toBigInt(value) {
|
|
13
|
+
if (typeof value === "bigint") return value;
|
|
14
|
+
if (typeof value === "number") {
|
|
15
|
+
assertArgument(Number.isFinite(value) && Math.floor(value) === value, "invalid number", "value", value);
|
|
16
|
+
return BigInt(value);
|
|
17
|
+
}
|
|
18
|
+
if (typeof value === "string") {
|
|
19
|
+
if (value.trim() === "") throw makeError("invalid BigNumberish string", "INVALID_ARGUMENT", { value });
|
|
20
|
+
if (value.startsWith("0x") || value.startsWith("0X")) return BigInt(value);
|
|
21
|
+
return BigInt(value);
|
|
22
|
+
}
|
|
23
|
+
throw makeError("invalid BigNumberish", "INVALID_ARGUMENT", { value });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Format a BigNumberish into a decimal string with `decimals` places.
|
|
28
|
+
* @param {BigNumberish} value
|
|
29
|
+
* @param {number=} decimals
|
|
30
|
+
* @returns {string}
|
|
31
|
+
*/
|
|
32
|
+
function formatUnits(value, decimals) {
|
|
33
|
+
const dec = decimals == null ? 18 : decimals;
|
|
34
|
+
assertArgument(Number.isInteger(dec) && dec >= 0 && dec <= 256, "invalid decimals", "decimals", decimals);
|
|
35
|
+
const v = _toBigInt(value);
|
|
36
|
+
const neg = v < 0n;
|
|
37
|
+
const abs = neg ? -v : v;
|
|
38
|
+
|
|
39
|
+
const base = 10n ** BigInt(dec);
|
|
40
|
+
const whole = abs / base;
|
|
41
|
+
const frac = abs % base;
|
|
42
|
+
|
|
43
|
+
let fracStr = frac.toString().padStart(dec, "0");
|
|
44
|
+
// trim trailing zeros
|
|
45
|
+
fracStr = fracStr.replace(/0+$/, "");
|
|
46
|
+
const out = fracStr.length ? `${whole.toString()}.${fracStr}` : whole.toString();
|
|
47
|
+
return neg ? "-" + out : out;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parse a decimal string into bigint with `decimals` places.
|
|
52
|
+
* @param {string} value
|
|
53
|
+
* @param {number=} decimals
|
|
54
|
+
* @returns {bigint}
|
|
55
|
+
*/
|
|
56
|
+
function parseUnits(value, decimals) {
|
|
57
|
+
const dec = decimals == null ? 18 : decimals;
|
|
58
|
+
assertArgument(Number.isInteger(dec) && dec >= 0 && dec <= 256, "invalid decimals", "decimals", decimals);
|
|
59
|
+
assertArgument(typeof value === "string", "value must be a string", "value", value);
|
|
60
|
+
|
|
61
|
+
const v = value.trim();
|
|
62
|
+
assertArgument(v.length > 0, "invalid value", "value", value);
|
|
63
|
+
|
|
64
|
+
const neg = v.startsWith("-");
|
|
65
|
+
const s = neg ? v.slice(1) : v;
|
|
66
|
+
const parts = s.split(".");
|
|
67
|
+
assertArgument(parts.length <= 2, "invalid decimal string", "value", value);
|
|
68
|
+
|
|
69
|
+
const whole = parts[0] || "0";
|
|
70
|
+
const frac = parts[1] || "";
|
|
71
|
+
assertArgument(/^\d+$/.test(whole), "invalid whole component", "value", value);
|
|
72
|
+
assertArgument(/^\d*$/.test(frac), "invalid fractional component", "value", value);
|
|
73
|
+
assertArgument(frac.length <= dec, "fractional component exceeds decimals", "value", value);
|
|
74
|
+
|
|
75
|
+
const base = 10n ** BigInt(dec);
|
|
76
|
+
const wholeBI = BigInt(whole) * base;
|
|
77
|
+
const fracBI = frac.length ? BigInt(frac.padEnd(dec, "0")) : 0n;
|
|
78
|
+
const out = wholeBI + fracBI;
|
|
79
|
+
return neg ? -out : out;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Format wei as coin string.
|
|
84
|
+
* @param {BigNumberish} value
|
|
85
|
+
* @returns {string}
|
|
86
|
+
*/
|
|
87
|
+
function formatEther(value) {
|
|
88
|
+
return formatUnits(value, 18);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Parse coin string to wei.
|
|
93
|
+
* @param {string} value
|
|
94
|
+
* @returns {bigint}
|
|
95
|
+
*/
|
|
96
|
+
function parseEther(value) {
|
|
97
|
+
return parseUnits(value, 18);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
formatUnits,
|
|
102
|
+
parseUnits,
|
|
103
|
+
formatEther,
|
|
104
|
+
parseEther,
|
|
105
|
+
WeiPerEther,
|
|
106
|
+
};
|
|
107
|
+
|