quantumcoin 7.0.10 → 7.0.11
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/README-SDK.md +0 -5
- package/README.md +1 -3
- package/SPEC.md +2 -63
- package/config.js +10 -2
- package/examples/example.js +0 -5
- package/examples/example.ts +0 -5
- package/examples/node_modules/.bin/esbuild +16 -0
- package/examples/node_modules/.bin/esbuild.cmd +17 -0
- package/examples/node_modules/.bin/esbuild.ps1 +28 -0
- package/examples/node_modules/.bin/sdkgen +16 -0
- package/examples/node_modules/.bin/sdkgen.cmd +17 -0
- package/examples/node_modules/.bin/sdkgen.ps1 +28 -0
- package/examples/node_modules/.bin/tsx +16 -0
- package/examples/node_modules/.bin/tsx.cmd +17 -0
- package/examples/node_modules/.bin/tsx.ps1 +28 -0
- package/examples/node_modules/.package-lock.json +235 -0
- package/examples/node_modules/@esbuild/win32-x64/README.md +3 -0
- package/examples/node_modules/@esbuild/win32-x64/esbuild.exe +0 -0
- package/examples/node_modules/@esbuild/win32-x64/package.json +20 -0
- package/examples/node_modules/esbuild/LICENSE.md +21 -0
- package/examples/node_modules/esbuild/README.md +3 -0
- package/examples/node_modules/esbuild/bin/esbuild +223 -0
- package/examples/node_modules/esbuild/install.js +289 -0
- package/examples/node_modules/esbuild/lib/main.d.ts +716 -0
- package/examples/node_modules/esbuild/lib/main.js +2532 -0
- package/examples/node_modules/esbuild/package.json +49 -0
- package/examples/node_modules/get-tsconfig/LICENSE +21 -0
- package/examples/node_modules/get-tsconfig/README.md +235 -0
- package/examples/node_modules/get-tsconfig/dist/index.cjs +7 -0
- package/examples/node_modules/get-tsconfig/dist/index.d.cts +2088 -0
- package/examples/node_modules/get-tsconfig/dist/index.d.mts +2088 -0
- package/examples/node_modules/get-tsconfig/dist/index.mjs +7 -0
- package/examples/node_modules/get-tsconfig/package.json +46 -0
- package/examples/node_modules/quantum-coin-js-sdk/.github/workflows/publish-npmjs.yaml +22 -0
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE +21 -0
- package/examples/node_modules/quantum-coin-js-sdk/LICENSE-wasm_exec.js.txt +30 -0
- package/examples/node_modules/quantum-coin-js-sdk/README.md +1665 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/README.md +14 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/conversion-example.js +19 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-create-contract.js +396 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-encode-decode-rlp.js +225 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-event-pack-unpack.js +391 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-misc.js +101 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send-signRawTransaction.js +318 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-rpc-send.js +116 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +70 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +961 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +35 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet.js +43 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example.js +405 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +134 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/package.json +15 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +1024 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.js +3062 -0
- package/examples/node_modules/quantum-coin-js-sdk/package.json +34 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-32.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-36.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/encrypted-48.json +1 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/generate-verify-vectors.js +91 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.preinit.test.js +41 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/non-transactional.test.js +686 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-keytype5-context-null.test.js +107 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-raw-transaction.test.js +196 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/sign-verify.test.js +311 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.relay.test.js +131 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/transactional.rpc.test.js +103 -0
- package/examples/node_modules/quantum-coin-js-sdk/tests/verify-vectors.json +95035 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.d.ts +9 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +16 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.d.ts +0 -0
- package/examples/node_modules/quantum-coin-js-sdk/wasm_exec.js +587 -0
- package/examples/node_modules/resolve-pkg-maps/LICENSE +21 -0
- package/examples/node_modules/resolve-pkg-maps/README.md +216 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.cjs +1 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.cts +11 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.d.mts +11 -0
- package/examples/node_modules/resolve-pkg-maps/dist/index.mjs +1 -0
- package/examples/node_modules/resolve-pkg-maps/package.json +42 -0
- package/examples/node_modules/seed-words/.github/workflows/publish-npmjs.yaml +22 -0
- package/examples/node_modules/seed-words/BUILD.md +7 -0
- package/examples/node_modules/seed-words/LICENSE +121 -0
- package/examples/node_modules/seed-words/README.md +67 -0
- package/examples/node_modules/seed-words/dist/seedwords.d.ts +39 -0
- package/examples/node_modules/seed-words/package.json +27 -0
- package/examples/node_modules/seed-words/seedwords.js +315 -0
- package/examples/node_modules/seed-words/seedwords.txt +65536 -0
- package/examples/node_modules/seed-words/tsconfig.json +21 -0
- package/examples/node_modules/tsx/LICENSE +21 -0
- package/examples/node_modules/tsx/README.md +32 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.d.cts +35 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.d.mts +35 -0
- package/examples/node_modules/tsx/dist/cjs/api/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/cjs/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/cli.cjs +54 -0
- package/examples/node_modules/tsx/dist/cli.mjs +55 -0
- package/examples/node_modules/tsx/dist/client-BQVF1NaW.mjs +1 -0
- package/examples/node_modules/tsx/dist/client-D6NvIMSC.cjs +1 -0
- package/examples/node_modules/tsx/dist/esm/api/index.cjs +1 -0
- package/examples/node_modules/tsx/dist/esm/api/index.d.cts +35 -0
- package/examples/node_modules/tsx/dist/esm/api/index.d.mts +35 -0
- package/examples/node_modules/tsx/dist/esm/api/index.mjs +1 -0
- package/examples/node_modules/tsx/dist/esm/index.cjs +2 -0
- package/examples/node_modules/tsx/dist/esm/index.mjs +2 -0
- package/examples/node_modules/tsx/dist/get-pipe-path-BHW2eJdv.mjs +1 -0
- package/examples/node_modules/tsx/dist/get-pipe-path-BoR10qr8.cjs +1 -0
- package/examples/node_modules/tsx/dist/index-7AaEi15b.mjs +14 -0
- package/examples/node_modules/tsx/dist/index-BWFBUo6r.cjs +1 -0
- package/examples/node_modules/tsx/dist/index-gbaejti9.mjs +1 -0
- package/examples/node_modules/tsx/dist/index-gckBtVBf.cjs +14 -0
- package/examples/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +3 -0
- package/examples/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +3 -0
- package/examples/node_modules/tsx/dist/loader.cjs +1 -0
- package/examples/node_modules/tsx/dist/loader.mjs +1 -0
- package/examples/node_modules/tsx/dist/node-features-_8ZFwP_x.mjs +1 -0
- package/examples/node_modules/tsx/dist/node-features-roYmp9jK.cjs +1 -0
- package/examples/node_modules/tsx/dist/package-CeBgXWuR.mjs +1 -0
- package/examples/node_modules/tsx/dist/package-Dxt5kIHw.cjs +1 -0
- package/examples/node_modules/tsx/dist/patch-repl.cjs +1 -0
- package/examples/node_modules/tsx/dist/patch-repl.mjs +1 -0
- package/examples/node_modules/tsx/dist/preflight.cjs +1 -0
- package/examples/node_modules/tsx/dist/preflight.mjs +1 -0
- package/examples/node_modules/tsx/dist/register-2sWVXuRQ.cjs +1 -0
- package/examples/node_modules/tsx/dist/register-B7jrtLTO.mjs +1 -0
- package/examples/node_modules/tsx/dist/register-CFH5oNdT.mjs +4 -0
- package/examples/node_modules/tsx/dist/register-D46fvsV_.cjs +4 -0
- package/examples/node_modules/tsx/dist/repl.cjs +3 -0
- package/examples/node_modules/tsx/dist/repl.mjs +3 -0
- package/examples/node_modules/tsx/dist/require-D4F1Lv60.cjs +1 -0
- package/examples/node_modules/tsx/dist/require-DQxpCAr4.mjs +1 -0
- package/examples/node_modules/tsx/dist/suppress-warnings.cjs +1 -0
- package/examples/node_modules/tsx/dist/suppress-warnings.mjs +1 -0
- package/examples/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +1 -0
- package/examples/node_modules/tsx/dist/temporary-directory-CwHp0_NW.mjs +1 -0
- package/examples/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +5 -0
- package/examples/node_modules/tsx/package.json +68 -0
- package/examples/offline-signing.js +0 -2
- package/examples/offline-signing.ts +0 -1
- package/examples/package-lock.json +422 -73
- package/examples/package.json +1 -1
- package/examples/wallet-offline.js +1 -9
- package/examples/wallet-offline.ts +1 -9
- package/generate-sdk.js +4 -6
- package/package.json +2 -2
- package/src/abi/interface.js +13 -7
- package/src/abi/js-abi-coder.js +23 -18
- package/src/constants.d.ts +0 -5
- package/src/constants.js +0 -7
- package/src/contract/contract-factory.js +9 -3
- package/src/contract/contract.js +9 -3
- package/src/errors/index.js +12 -0
- package/src/index.d.ts +0 -3
- package/src/providers/extra-providers.js +20 -6
- package/src/providers/json-rpc-provider.js +15 -5
- package/src/providers/provider.d.ts +0 -2
- package/src/providers/provider.js +1 -3
- package/src/utils/address.d.ts +0 -14
- package/src/utils/address.js +12 -49
- package/src/utils/hashing.d.ts +0 -6
- package/src/utils/hashing.js +8 -23
- package/src/utils/index.d.ts +0 -3
- package/src/utils/rlp.js +7 -4
- package/src/wallet/wallet.d.ts +2 -13
- package/src/wallet/wallet.js +116 -97
- package/test/security/malformed-input.test.js +295 -1
- package/test/unit/address-wallet.test.js +188 -129
- package/test/unit/address-wallet.test.ts +187 -128
- package/test/unit/hashing.test.js +0 -11
- package/test/unit/hashing.test.ts +0 -11
- package/test/unit/providers.test.js +3 -1
- package/test/unit/providers.test.ts +3 -1
package/src/utils/address.js
CHANGED
|
@@ -8,18 +8,22 @@
|
|
|
8
8
|
const qcsdk = require("quantum-coin-js-sdk");
|
|
9
9
|
const { assertArgument, makeError } = require("../errors");
|
|
10
10
|
const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex } = require("../internal/hex");
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
|
|
13
13
|
function _requireInitialized() {
|
|
14
|
-
// The spec requires Initialize() to be called before using the SDK.
|
|
15
|
-
// config.js tracks initialization state for this package.
|
|
16
14
|
// eslint-disable-next-line global-require
|
|
17
|
-
const { isInitialized } = require("../../config");
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
const { isInitialized, getInitializationPromise } = require("../../config");
|
|
16
|
+
if (isInitialized()) return;
|
|
17
|
+
if (getInitializationPromise() != null) {
|
|
18
|
+
throw makeError(
|
|
19
|
+
"QuantumCoin SDK is still initializing. Await the Initialize() promise before using SDK methods.",
|
|
20
|
+
"UNKNOWN_ERROR",
|
|
21
|
+
{ operation: "requireInitialized" },
|
|
22
|
+
);
|
|
22
23
|
}
|
|
24
|
+
throw makeError("QuantumCoin SDK not initialized. Call Initialize() first.", "UNKNOWN_ERROR", {
|
|
25
|
+
operation: "address-utils",
|
|
26
|
+
});
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
/**
|
|
@@ -127,45 +131,6 @@ function computeAddress(key) {
|
|
|
127
131
|
return normalizeHex(out);
|
|
128
132
|
}
|
|
129
133
|
|
|
130
|
-
function _digestMessage(message) {
|
|
131
|
-
const digestHex = hashMessage(message);
|
|
132
|
-
const digest = Array.from(hexToBytes(digestHex));
|
|
133
|
-
assertArgument(digest.length === 32, "invalid digest length", "digest", digest.length);
|
|
134
|
-
return digest;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
function _signatureToBytes(signature) {
|
|
138
|
-
assertArgument(typeof signature === "string", "signature must be a hex string", "signature", signature);
|
|
139
|
-
assertArgument(isHexString(signature), "invalid signature hex", "signature", signature);
|
|
140
|
-
return Array.from(hexToBytes(signature));
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Verifies a message signature and recovers the address.
|
|
145
|
-
* @param {string|Uint8Array} message
|
|
146
|
-
* @param {string} signature Hex string signature
|
|
147
|
-
* @returns {string}
|
|
148
|
-
*/
|
|
149
|
-
function verifyMessage(message, signature) {
|
|
150
|
-
return recoverAddress(message, signature);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Recovers the address from a message signature.
|
|
155
|
-
* @param {string|Uint8Array} message
|
|
156
|
-
* @param {string} signature Hex string signature
|
|
157
|
-
* @returns {string}
|
|
158
|
-
*/
|
|
159
|
-
function recoverAddress(message, signature) {
|
|
160
|
-
_requireInitialized();
|
|
161
|
-
const digest = _digestMessage(message);
|
|
162
|
-
const sigBytes = _signatureToBytes(signature);
|
|
163
|
-
const pubHex = qcsdk.publicKeyFromSignature(digest, sigBytes);
|
|
164
|
-
if (typeof pubHex !== "string") throw makeError("publicKeyFromSignature failed", "UNKNOWN_ERROR", {});
|
|
165
|
-
const addr = computeAddress(pubHex);
|
|
166
|
-
return addr;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
134
|
module.exports = {
|
|
170
135
|
isAddress,
|
|
171
136
|
getAddress,
|
|
@@ -175,7 +140,5 @@ module.exports = {
|
|
|
175
140
|
getCreateAddress,
|
|
176
141
|
getCreate2Address,
|
|
177
142
|
computeAddress,
|
|
178
|
-
verifyMessage,
|
|
179
|
-
recoverAddress,
|
|
180
143
|
};
|
|
181
144
|
|
package/src/utils/hashing.d.ts
CHANGED
|
@@ -4,12 +4,6 @@
|
|
|
4
4
|
* @returns {string}
|
|
5
5
|
*/
|
|
6
6
|
export function keccak256(data: string | Uint8Array): string;
|
|
7
|
-
/**
|
|
8
|
-
* EIP-191 personal-sign message digest (ethers.js hashMessage pattern).
|
|
9
|
-
* @param {string|Uint8Array} message
|
|
10
|
-
* @returns {string}
|
|
11
|
-
*/
|
|
12
|
-
export function hashMessage(message: string | Uint8Array): string;
|
|
13
7
|
/**
|
|
14
8
|
* sha256 hash of BytesLike.
|
|
15
9
|
* @param {string|Uint8Array} data
|
package/src/utils/hashing.js
CHANGED
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const crypto = require("crypto");
|
|
10
|
-
const { MessagePrefix } = require("../constants");
|
|
11
10
|
const { arrayify, bytesToHex, utf8ToBytes } = require("../internal/hex");
|
|
12
|
-
const { concat } = require("./encoding");
|
|
13
11
|
|
|
14
12
|
const _MASK64 = (1n << 64n) - 1n;
|
|
15
13
|
|
|
@@ -192,18 +190,6 @@ function ripemd160(data) {
|
|
|
192
190
|
return _hash("ripemd160", data);
|
|
193
191
|
}
|
|
194
192
|
|
|
195
|
-
/**
|
|
196
|
-
* EIP-191 personal-sign message digest (ethers.js hashMessage pattern).
|
|
197
|
-
* Prefixes message with MessagePrefix and decimal length, then keccak256.
|
|
198
|
-
* If message is a string, it is converted to UTF-8 bytes first.
|
|
199
|
-
* @param {string|Uint8Array} message
|
|
200
|
-
* @returns {string} Hex digest
|
|
201
|
-
*/
|
|
202
|
-
function hashMessage(message) {
|
|
203
|
-
const msgBytes = typeof message === "string" ? utf8ToBytes(message) : arrayify(message);
|
|
204
|
-
return keccak256(concat([utf8ToBytes(MessagePrefix), utf8ToBytes(String(msgBytes.length)), msgBytes]));
|
|
205
|
-
}
|
|
206
|
-
|
|
207
193
|
/**
|
|
208
194
|
* ethers-style id(text) => keccak256(utf8Bytes(text))
|
|
209
195
|
* @param {string} text
|
|
@@ -230,8 +216,8 @@ function randomBytes(length) {
|
|
|
230
216
|
* @returns {string}
|
|
231
217
|
*/
|
|
232
218
|
function computeHmac(algorithm, key, data) {
|
|
233
|
-
const k = arrayify(key);
|
|
234
|
-
const d = arrayify(data);
|
|
219
|
+
const k = typeof key === "string" ? utf8ToBytes(key) : arrayify(key);
|
|
220
|
+
const d = typeof data === "string" ? utf8ToBytes(data) : arrayify(data);
|
|
235
221
|
const h = crypto.createHmac(algorithm, Buffer.from(k)).update(Buffer.from(d)).digest();
|
|
236
222
|
return bytesToHex(new Uint8Array(h));
|
|
237
223
|
}
|
|
@@ -246,8 +232,8 @@ function computeHmac(algorithm, key, data) {
|
|
|
246
232
|
* @returns {string}
|
|
247
233
|
*/
|
|
248
234
|
function pbkdf2(password, salt, iterations, keylen, algorithm) {
|
|
249
|
-
const p = arrayify(password);
|
|
250
|
-
const s = arrayify(salt);
|
|
235
|
+
const p = typeof password === "string" ? utf8ToBytes(password) : arrayify(password);
|
|
236
|
+
const s = typeof salt === "string" ? utf8ToBytes(salt) : arrayify(salt);
|
|
251
237
|
const a = algorithm || "sha256";
|
|
252
238
|
const out = crypto.pbkdf2Sync(Buffer.from(p), Buffer.from(s), iterations, keylen, a);
|
|
253
239
|
return bytesToHex(new Uint8Array(out));
|
|
@@ -264,8 +250,8 @@ function pbkdf2(password, salt, iterations, keylen, algorithm) {
|
|
|
264
250
|
* @returns {Promise<string>}
|
|
265
251
|
*/
|
|
266
252
|
function scrypt(password, salt, N, r, p, dkLen) {
|
|
267
|
-
const pw = arrayify(password);
|
|
268
|
-
const sa = arrayify(salt);
|
|
253
|
+
const pw = typeof password === "string" ? utf8ToBytes(password) : arrayify(password);
|
|
254
|
+
const sa = typeof salt === "string" ? utf8ToBytes(salt) : arrayify(salt);
|
|
269
255
|
return new Promise((resolve, reject) => {
|
|
270
256
|
crypto.scrypt(
|
|
271
257
|
Buffer.from(pw),
|
|
@@ -291,15 +277,14 @@ function scrypt(password, salt, N, r, p, dkLen) {
|
|
|
291
277
|
* @returns {string}
|
|
292
278
|
*/
|
|
293
279
|
function scryptSync(password, salt, N, r, p, dkLen) {
|
|
294
|
-
const pw = arrayify(password);
|
|
295
|
-
const sa = arrayify(salt);
|
|
280
|
+
const pw = typeof password === "string" ? utf8ToBytes(password) : arrayify(password);
|
|
281
|
+
const sa = typeof salt === "string" ? utf8ToBytes(salt) : arrayify(salt);
|
|
296
282
|
const out = crypto.scryptSync(Buffer.from(pw), Buffer.from(sa), dkLen, { N, r, p, maxmem: 257 * 1024 * 1024 }); //257 instead of 256 for buffer for compat for N=262144, r=8, p=1
|
|
297
283
|
return bytesToHex(new Uint8Array(out));
|
|
298
284
|
}
|
|
299
285
|
|
|
300
286
|
module.exports = {
|
|
301
287
|
keccak256,
|
|
302
|
-
hashMessage,
|
|
303
288
|
sha256,
|
|
304
289
|
sha512,
|
|
305
290
|
ripemd160,
|
package/src/utils/index.d.ts
CHANGED
|
@@ -12,7 +12,6 @@ declare const _exports: {
|
|
|
12
12
|
encodeRlp(value: any): string;
|
|
13
13
|
decodeRlp(data: string): any;
|
|
14
14
|
keccak256(data: string | Uint8Array): string;
|
|
15
|
-
hashMessage(message: string | Uint8Array): string;
|
|
16
15
|
sha256(data: string | Uint8Array): string;
|
|
17
16
|
sha512(data: string | Uint8Array): string;
|
|
18
17
|
ripemd160(data: string | Uint8Array): string;
|
|
@@ -59,8 +58,6 @@ declare const _exports: {
|
|
|
59
58
|
}): string;
|
|
60
59
|
getCreate2Address(from: string, salt: string, initCodeHash: string): string;
|
|
61
60
|
computeAddress(key: string | Uint8Array): string;
|
|
62
|
-
verifyMessage(message: string | Uint8Array, signature: string): string;
|
|
63
|
-
recoverAddress(message: string | Uint8Array, signature: string): string;
|
|
64
61
|
FixedNumber: typeof import("./fixednumber").FixedNumber;
|
|
65
62
|
};
|
|
66
63
|
export = _exports;
|
package/src/utils/rlp.js
CHANGED
|
@@ -110,7 +110,10 @@ function _readLen(bytes, offset, lenOfLen) {
|
|
|
110
110
|
return len;
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
const MAX_RLP_DEPTH = 64;
|
|
114
|
+
|
|
115
|
+
function _decode(bytes, start, end, depth) {
|
|
116
|
+
if (depth > MAX_RLP_DEPTH) throw new Error("RLP: maximum nesting depth exceeded");
|
|
114
117
|
if (start >= end) throw new Error("RLP: empty input");
|
|
115
118
|
const prefix = bytes[start];
|
|
116
119
|
|
|
@@ -149,7 +152,7 @@ function _decode(bytes, start, end) {
|
|
|
149
152
|
const out = [];
|
|
150
153
|
let pos = dataStart;
|
|
151
154
|
while (pos < dataEnd) {
|
|
152
|
-
const decoded = _decode(bytes, pos, dataEnd);
|
|
155
|
+
const decoded = _decode(bytes, pos, dataEnd, depth + 1);
|
|
153
156
|
out.push(decoded.value);
|
|
154
157
|
pos = decoded.next;
|
|
155
158
|
}
|
|
@@ -166,7 +169,7 @@ function _decode(bytes, start, end) {
|
|
|
166
169
|
const out = [];
|
|
167
170
|
let pos = dataStart;
|
|
168
171
|
while (pos < dataEnd) {
|
|
169
|
-
const decoded = _decode(bytes, pos, dataEnd);
|
|
172
|
+
const decoded = _decode(bytes, pos, dataEnd, depth + 1);
|
|
170
173
|
out.push(decoded.value);
|
|
171
174
|
pos = decoded.next;
|
|
172
175
|
}
|
|
@@ -191,7 +194,7 @@ function encodeRlp(value) {
|
|
|
191
194
|
function decodeRlp(data) {
|
|
192
195
|
if (typeof data !== "string") throw new TypeError("RLP data must be a hex string");
|
|
193
196
|
const bytes = arrayify(data);
|
|
194
|
-
const decoded = _decode(bytes, 0, bytes.length);
|
|
197
|
+
const decoded = _decode(bytes, 0, bytes.length, 0);
|
|
195
198
|
if (decoded.next !== bytes.length) throw new Error("RLP: trailing data");
|
|
196
199
|
return decoded.value;
|
|
197
200
|
}
|
package/src/wallet/wallet.d.ts
CHANGED
|
@@ -38,14 +38,9 @@ export class BaseWallet extends AbstractSigner {
|
|
|
38
38
|
_qcWallet: any;
|
|
39
39
|
/** @type {string} */
|
|
40
40
|
address: string;
|
|
41
|
+
readonly publicKey: string;
|
|
42
|
+
readonly seed: string | null;
|
|
41
43
|
getAddress(): Promise<string>;
|
|
42
|
-
/**
|
|
43
|
-
* Sign a message synchronously.
|
|
44
|
-
* Signature format: combined publicKey+signature as a hex string.
|
|
45
|
-
* @param {string|Uint8Array} message
|
|
46
|
-
* @returns {string}
|
|
47
|
-
*/
|
|
48
|
-
signMessageSync(message: string | Uint8Array): string;
|
|
49
44
|
/**
|
|
50
45
|
* Sign a transaction using quantum-coin-js-sdk signRawTransaction().
|
|
51
46
|
* @param {import("../providers/provider").TransactionRequest} tx
|
|
@@ -77,12 +72,6 @@ export class Wallet extends BaseWallet {
|
|
|
77
72
|
* @returns {Wallet}
|
|
78
73
|
*/
|
|
79
74
|
static createRandom(provider?: import("../providers/provider").AbstractProvider | undefined, keyType?: number | null): Wallet;
|
|
80
|
-
/**
|
|
81
|
-
* Creates a new random seed word list (32 words for keyType 3, 36 for keyType 5).
|
|
82
|
-
* @param {number|null=} keyType Optional key type: null (default=3), 3, or 5
|
|
83
|
-
* @returns {string[]}
|
|
84
|
-
*/
|
|
85
|
-
static createRandomSeed(keyType?: number | null): string[];
|
|
86
75
|
/**
|
|
87
76
|
* Creates a wallet from raw seed bytes.
|
|
88
77
|
* @param {number[]} seed Raw seed bytes: 64 (keyType 3), 72 (keyType 5), or 96 (legacy)
|
package/src/wallet/wallet.js
CHANGED
|
@@ -10,24 +10,52 @@
|
|
|
10
10
|
|
|
11
11
|
const qcsdk = require("quantum-coin-js-sdk");
|
|
12
12
|
const { JsonRpcProvider } = require("../providers/json-rpc-provider");
|
|
13
|
-
const { assertArgument, makeError } = require("../errors");
|
|
13
|
+
const { assertArgument, assertSecretArgument, makeError } = require("../errors");
|
|
14
14
|
const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex } = require("../internal/hex");
|
|
15
|
-
const { hashMessage } = require("../utils/hashing");
|
|
16
15
|
const { getAddress } = require("../utils/address");
|
|
17
16
|
const { WeiPerEther } = require("../constants");
|
|
18
17
|
|
|
19
18
|
function _requireInitialized() {
|
|
20
19
|
// eslint-disable-next-line global-require
|
|
21
|
-
const { isInitialized } = require("../../config");
|
|
22
|
-
if (
|
|
23
|
-
|
|
20
|
+
const { isInitialized, getInitializationPromise } = require("../../config");
|
|
21
|
+
if (isInitialized()) return;
|
|
22
|
+
if (getInitializationPromise() != null) {
|
|
23
|
+
throw makeError(
|
|
24
|
+
"QuantumCoin SDK is still initializing. Await the Initialize() promise before using SDK methods.",
|
|
25
|
+
"UNKNOWN_ERROR",
|
|
26
|
+
{ operation: "requireInitialized" },
|
|
27
|
+
);
|
|
24
28
|
}
|
|
29
|
+
throw makeError("QuantumCoin SDK not initialized. Call Initialize() first.", "UNKNOWN_ERROR", { operation: "wallet" });
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
function _bytesToNumberArray(bytes) {
|
|
28
33
|
return Array.from(bytes);
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
const _maxSafeInt = 0x1fffffffffffffn; // 2^53 - 1
|
|
37
|
+
|
|
38
|
+
function _getBigInt(value, name) {
|
|
39
|
+
if (typeof value === "bigint") return value;
|
|
40
|
+
if (typeof value === "number") {
|
|
41
|
+
assertArgument(Number.isInteger(value), "underflow", name, value);
|
|
42
|
+
assertArgument(value >= -Number(_maxSafeInt) && value <= Number(_maxSafeInt), "overflow", name, value);
|
|
43
|
+
return BigInt(value);
|
|
44
|
+
}
|
|
45
|
+
if (typeof value === "string") {
|
|
46
|
+
if (value === "0x" || value === "0X") return 0n;
|
|
47
|
+
try { return BigInt(value); }
|
|
48
|
+
catch { assertArgument(false, "invalid BigNumberish string", name, value); }
|
|
49
|
+
}
|
|
50
|
+
assertArgument(false, "invalid BigNumberish", name, value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _getNumber(value, name) {
|
|
54
|
+
const bi = _getBigInt(value, name);
|
|
55
|
+
assertArgument(bi >= -_maxSafeInt && bi <= _maxSafeInt, "overflow", name, value);
|
|
56
|
+
return Number(bi);
|
|
57
|
+
}
|
|
58
|
+
|
|
31
59
|
/**
|
|
32
60
|
* SigningKey wrapper (PQC private/public key bytes).
|
|
33
61
|
*/
|
|
@@ -37,9 +65,18 @@ class SigningKey {
|
|
|
37
65
|
* @param {Uint8Array} publicKeyBytes
|
|
38
66
|
*/
|
|
39
67
|
constructor(privateKeyBytes, publicKeyBytes) {
|
|
40
|
-
this
|
|
68
|
+
Object.defineProperty(this, "privateKeyBytes", {
|
|
69
|
+
enumerable: false,
|
|
70
|
+
configurable: false,
|
|
71
|
+
writable: false,
|
|
72
|
+
value: new Uint8Array(privateKeyBytes),
|
|
73
|
+
});
|
|
41
74
|
this.publicKeyBytes = new Uint8Array(publicKeyBytes);
|
|
42
75
|
}
|
|
76
|
+
|
|
77
|
+
toJSON() {
|
|
78
|
+
return {};
|
|
79
|
+
}
|
|
43
80
|
}
|
|
44
81
|
|
|
45
82
|
/**
|
|
@@ -71,56 +108,52 @@ class BaseWallet extends AbstractSigner {
|
|
|
71
108
|
constructor(signingKey, provider, precomputed, qcWallet) {
|
|
72
109
|
super(provider || null);
|
|
73
110
|
_requireInitialized();
|
|
74
|
-
|
|
75
|
-
this
|
|
111
|
+
|
|
112
|
+
Object.defineProperty(this, "signingKey", {
|
|
113
|
+
enumerable: false,
|
|
114
|
+
configurable: false,
|
|
115
|
+
writable: false,
|
|
116
|
+
value: signingKey,
|
|
117
|
+
});
|
|
118
|
+
Object.defineProperty(this, "_qcWallet", {
|
|
119
|
+
enumerable: false,
|
|
120
|
+
configurable: true,
|
|
121
|
+
writable: true,
|
|
122
|
+
value: qcWallet || null,
|
|
123
|
+
});
|
|
76
124
|
|
|
77
125
|
/** @type {string} */
|
|
78
126
|
this.address = precomputed?.address || "";
|
|
79
127
|
|
|
80
128
|
Object.defineProperty(this, "privateKey", {
|
|
81
|
-
enumerable:
|
|
129
|
+
enumerable: false,
|
|
82
130
|
get: () => bytesToHex(this.signingKey.privateKeyBytes),
|
|
83
131
|
});
|
|
132
|
+
|
|
133
|
+
Object.defineProperty(this, "publicKey", {
|
|
134
|
+
enumerable: true,
|
|
135
|
+
get: () => bytesToHex(this.signingKey.publicKeyBytes),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
Object.defineProperty(this, "_seed", {
|
|
139
|
+
enumerable: false,
|
|
140
|
+
configurable: true,
|
|
141
|
+
writable: true,
|
|
142
|
+
value: null,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
Object.defineProperty(this, "seed", {
|
|
146
|
+
enumerable: false,
|
|
147
|
+
get: () => this._seed,
|
|
148
|
+
});
|
|
84
149
|
}
|
|
85
150
|
|
|
86
|
-
|
|
87
|
-
return this.address;
|
|
151
|
+
toJSON() {
|
|
152
|
+
return { address: this.address };
|
|
88
153
|
}
|
|
89
154
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
* Signature format: combined publicKey+signature as a hex string.
|
|
93
|
-
* @param {string|Uint8Array} message
|
|
94
|
-
* @returns {string}
|
|
95
|
-
*/
|
|
96
|
-
signMessageSync(message) {
|
|
97
|
-
_requireInitialized();
|
|
98
|
-
const digestHex = hashMessage(message);
|
|
99
|
-
const digest = hexToBytes(digestHex);
|
|
100
|
-
const signResult = qcsdk.sign(this.signingKey.privateKeyBytes, digest, null);
|
|
101
|
-
if (signResult.resultCode !== 0) {
|
|
102
|
-
throw makeError("sign failed", "UNKNOWN_ERROR", { resultCode: signResult.resultCode });
|
|
103
|
-
}
|
|
104
|
-
const sigBytes = signResult.signature;
|
|
105
|
-
if (!sigBytes) throw makeError("sign returned no signature", "UNKNOWN_ERROR", {});
|
|
106
|
-
const sigArr = Array.from(sigBytes instanceof Uint8Array ? sigBytes : sigBytes);
|
|
107
|
-
let combined = qcsdk.combinePublicKeySignature(
|
|
108
|
-
_bytesToNumberArray(this.signingKey.publicKeyBytes),
|
|
109
|
-
sigArr,
|
|
110
|
-
);
|
|
111
|
-
if (combined != null && typeof combined === "object") {
|
|
112
|
-
if (typeof combined.String === "function") combined = combined.String();
|
|
113
|
-
else if (combined instanceof Uint8Array) combined = bytesToHex(combined);
|
|
114
|
-
else if (Array.isArray(combined)) combined = bytesToHex(new Uint8Array(combined));
|
|
115
|
-
else if (typeof combined.length === "number" && combined.length >= 0) combined = bytesToHex(new Uint8Array(Array.from(combined)));
|
|
116
|
-
}
|
|
117
|
-
if (combined == null || typeof combined !== "string") {
|
|
118
|
-
throw makeError("combinePublicKeySignature failed (SDK may not support this key type for message signing)", "UNKNOWN_ERROR", {
|
|
119
|
-
combinedType: typeof combined,
|
|
120
|
-
sigLength: sigArr.length,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
return normalizeHex(combined);
|
|
155
|
+
async getAddress() {
|
|
156
|
+
return this.address;
|
|
124
157
|
}
|
|
125
158
|
|
|
126
159
|
/**
|
|
@@ -133,27 +166,8 @@ class BaseWallet extends AbstractSigner {
|
|
|
133
166
|
assertArgument(tx && typeof tx === "object", "invalid tx", "tx", tx);
|
|
134
167
|
|
|
135
168
|
const toAddress = tx.to == null ? null : getAddress(tx.to);
|
|
136
|
-
const valueInWei =
|
|
137
|
-
|
|
138
|
-
? 0n
|
|
139
|
-
: typeof tx.value === "bigint"
|
|
140
|
-
? tx.value
|
|
141
|
-
: typeof tx.value === "number"
|
|
142
|
-
? BigInt(tx.value)
|
|
143
|
-
: typeof tx.value === "string"
|
|
144
|
-
? BigInt(tx.value.startsWith("0x") ? tx.value : tx.value)
|
|
145
|
-
: 0n;
|
|
146
|
-
|
|
147
|
-
const gasLimit =
|
|
148
|
-
tx.gasLimit == null
|
|
149
|
-
? 21000
|
|
150
|
-
: typeof tx.gasLimit === "bigint"
|
|
151
|
-
? Number(tx.gasLimit)
|
|
152
|
-
: typeof tx.gasLimit === "number"
|
|
153
|
-
? tx.gasLimit
|
|
154
|
-
: typeof tx.gasLimit === "string"
|
|
155
|
-
? Number(BigInt(tx.gasLimit))
|
|
156
|
-
: 21000;
|
|
169
|
+
const valueInWei = tx.value == null ? 0n : _getBigInt(tx.value, "tx.value");
|
|
170
|
+
const gasLimit = tx.gasLimit == null ? 21000 : _getNumber(tx.gasLimit, "tx.gasLimit");
|
|
157
171
|
|
|
158
172
|
const data = tx.data == null ? null : normalizeHex(tx.data);
|
|
159
173
|
const remarks = tx.remarks == null ? null : normalizeHex(tx.remarks);
|
|
@@ -299,13 +313,19 @@ class Wallet extends BaseWallet {
|
|
|
299
313
|
}
|
|
300
314
|
|
|
301
315
|
/**
|
|
302
|
-
* Encrypts and serializes this wallet to JSON.
|
|
316
|
+
* Encrypts and serializes this wallet to JSON.
|
|
303
317
|
* @param {string|Uint8Array} password
|
|
304
318
|
* @returns {string}
|
|
305
319
|
*/
|
|
306
320
|
encryptSync(password) {
|
|
307
321
|
_requireInitialized();
|
|
308
|
-
|
|
322
|
+
if (this._seed != null) {
|
|
323
|
+
return Wallet.encryptSeedSync(hexToBytes(this._seed), password);
|
|
324
|
+
}
|
|
325
|
+
const pw = typeof password === "string"
|
|
326
|
+
? password.normalize("NFC")
|
|
327
|
+
: Buffer.from(arrayify(password)).toString("utf8").normalize("NFC");
|
|
328
|
+
assertSecretArgument(pw.length >= 12, "password must be at least 12 characters", "password");
|
|
309
329
|
const json = qcsdk.serializeEncryptedWallet(this._qcWallet, pw);
|
|
310
330
|
if (typeof json !== "string") throw makeError("serializeEncryptedWallet failed", "UNKNOWN_ERROR", {});
|
|
311
331
|
return json;
|
|
@@ -325,7 +345,10 @@ class Wallet extends BaseWallet {
|
|
|
325
345
|
assertArgument(Array.isArray(seedArr), "seed must be an array of numbers or Uint8Array", "seed", seed);
|
|
326
346
|
const allowedLengths = [64, 72, 96];
|
|
327
347
|
assertArgument(allowedLengths.includes(seedArr.length), "seed must be 64, 72, or 96 bytes", "seed", seedArr.length);
|
|
328
|
-
const pw = typeof password === "string"
|
|
348
|
+
const pw = typeof password === "string"
|
|
349
|
+
? password.normalize("NFC")
|
|
350
|
+
: Buffer.from(arrayify(password)).toString("utf8").normalize("NFC");
|
|
351
|
+
assertSecretArgument(pw.length >= 12, "password must be at least 12 characters", "password");
|
|
329
352
|
const json = qcsdk.serializeSeedAsEncryptedWallet(seedArr, pw);
|
|
330
353
|
if (typeof json !== "string") throw makeError("serializeSeedAsEncryptedWallet failed", "UNKNOWN_ERROR", {});
|
|
331
354
|
return json;
|
|
@@ -355,7 +378,10 @@ class Wallet extends BaseWallet {
|
|
|
355
378
|
* @returns {Wallet}
|
|
356
379
|
*/
|
|
357
380
|
connect(provider) {
|
|
358
|
-
|
|
381
|
+
const w = new Wallet(this.signingKey, provider);
|
|
382
|
+
w._qcWallet = this._qcWallet;
|
|
383
|
+
w._seed = this._seed;
|
|
384
|
+
return w;
|
|
359
385
|
}
|
|
360
386
|
|
|
361
387
|
/**
|
|
@@ -369,29 +395,11 @@ class Wallet extends BaseWallet {
|
|
|
369
395
|
if (keyType != null) {
|
|
370
396
|
assertArgument(keyType === 3 || keyType === 5, "keyType must be null, 3, or 5", "keyType", keyType);
|
|
371
397
|
}
|
|
372
|
-
const
|
|
373
|
-
if (!qcWallet || typeof qcWallet === "number") {
|
|
374
|
-
throw makeError("newWallet failed", "UNKNOWN_ERROR", { result: qcWallet });
|
|
375
|
-
}
|
|
376
|
-
return Wallet._fromQcWallet(qcWallet, provider || null);
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Creates a new random seed word list (32 words for keyType 3, 36 for keyType 5).
|
|
381
|
-
* Use the returned words with `Wallet.fromPhrase()` to create a wallet.
|
|
382
|
-
* @param {number|null=} keyType Optional key type: null (default=3), 3, or 5
|
|
383
|
-
* @returns {string[]}
|
|
384
|
-
*/
|
|
385
|
-
static createRandomSeed(keyType) {
|
|
386
|
-
_requireInitialized();
|
|
387
|
-
if (keyType != null) {
|
|
388
|
-
assertArgument(keyType === 3 || keyType === 5, "keyType must be null, 3, or 5", "keyType", keyType);
|
|
389
|
-
}
|
|
390
|
-
const words = qcsdk.newWalletSeed(keyType ?? null);
|
|
398
|
+
const words = qcsdk.newWalletSeedWords(keyType ?? null);
|
|
391
399
|
if (!words || !Array.isArray(words)) {
|
|
392
|
-
throw makeError("
|
|
400
|
+
throw makeError("newWalletSeedWords failed", "UNKNOWN_ERROR", { result: words });
|
|
393
401
|
}
|
|
394
|
-
return words;
|
|
402
|
+
return Wallet.fromPhrase(words, provider);
|
|
395
403
|
}
|
|
396
404
|
|
|
397
405
|
/**
|
|
@@ -465,8 +473,8 @@ class Wallet extends BaseWallet {
|
|
|
465
473
|
_requireInitialized();
|
|
466
474
|
const privBytes = typeof privateKey === "string" ? hexToBytes(privateKey) : arrayify(privateKey);
|
|
467
475
|
const pubBytes = typeof publicKey === "string" ? hexToBytes(publicKey) : arrayify(publicKey);
|
|
468
|
-
|
|
469
|
-
|
|
476
|
+
assertSecretArgument(privBytes.length > 0, "privateKey must not be empty", "privateKey");
|
|
477
|
+
assertSecretArgument(pubBytes.length > 0, "publicKey must not be empty", "publicKey");
|
|
470
478
|
|
|
471
479
|
const privArr = _bytesToNumberArray(privBytes);
|
|
472
480
|
const pubArr = _bytesToNumberArray(pubBytes);
|
|
@@ -489,15 +497,20 @@ class Wallet extends BaseWallet {
|
|
|
489
497
|
* @returns {Wallet}
|
|
490
498
|
*/
|
|
491
499
|
static _fromQcWallet(qcWallet, provider) {
|
|
492
|
-
// Preserve key material from quantum-coin-js-sdk Wallet.
|
|
493
|
-
// newWallet() returns Uint8Array keys; other constructors may return number[].
|
|
494
500
|
const privSrc = qcWallet.privateKey;
|
|
495
501
|
const pubSrc = qcWallet.publicKey;
|
|
496
502
|
|
|
503
|
+
if (!privSrc || (privSrc instanceof Uint8Array && privSrc.length === 0) || (Array.isArray(privSrc) && privSrc.length === 0)) {
|
|
504
|
+
throw makeError("qcWallet.privateKey is empty or missing", "UNKNOWN_ERROR", {});
|
|
505
|
+
}
|
|
506
|
+
if (!pubSrc || (pubSrc instanceof Uint8Array && pubSrc.length === 0) || (Array.isArray(pubSrc) && pubSrc.length === 0)) {
|
|
507
|
+
throw makeError("qcWallet.publicKey is empty or missing", "UNKNOWN_ERROR", {});
|
|
508
|
+
}
|
|
509
|
+
|
|
497
510
|
const privBytes =
|
|
498
|
-
privSrc instanceof Uint8Array ? new Uint8Array(privSrc) : Uint8Array.from(Array.from(privSrc
|
|
511
|
+
privSrc instanceof Uint8Array ? new Uint8Array(privSrc) : Uint8Array.from(Array.from(privSrc).map((n) => (Number(n) & 0xff)));
|
|
499
512
|
const pubBytes =
|
|
500
|
-
pubSrc instanceof Uint8Array ? new Uint8Array(pubSrc) : Uint8Array.from(Array.from(pubSrc
|
|
513
|
+
pubSrc instanceof Uint8Array ? new Uint8Array(pubSrc) : Uint8Array.from(Array.from(pubSrc).map((n) => (Number(n) & 0xff)));
|
|
501
514
|
const key = new SigningKey(privBytes, pubBytes);
|
|
502
515
|
|
|
503
516
|
const w = new Wallet(key, provider || null);
|
|
@@ -506,6 +519,12 @@ class Wallet extends BaseWallet {
|
|
|
506
519
|
if (typeof qcWallet.address === "string") {
|
|
507
520
|
w.address = normalizeHex(qcWallet.address);
|
|
508
521
|
}
|
|
522
|
+
if (qcWallet.preExpansionSeed != null) {
|
|
523
|
+
const seedSrc = qcWallet.preExpansionSeed;
|
|
524
|
+
const seedBytes =
|
|
525
|
+
seedSrc instanceof Uint8Array ? seedSrc : Uint8Array.from(Array.from(seedSrc).map((n) => (Number(n) & 0xff)));
|
|
526
|
+
w._seed = bytesToHex(seedBytes);
|
|
527
|
+
}
|
|
509
528
|
return w;
|
|
510
529
|
}
|
|
511
530
|
}
|