quantumcoin 7.0.13 → 7.0.15
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 +2 -0
- 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 +144 -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/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 +1689 -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 +100 -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 +115 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-send.js +69 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-token-pack-unpack.js +960 -0
- package/examples/node_modules/quantum-coin-js-sdk/example/example-wallet-version4.js +34 -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 +56 -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 +1047 -0
- package/examples/node_modules/quantum-coin-js-sdk/index.js +3182 -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/get-gas-price.test.js +59 -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 +1389 -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/package-lock.json +6 -6
- package/examples/package.json +1 -1
- package/generate-sdk.js +30 -9
- package/package.json +2 -2
- package/src/abi/interface.js +11 -2
- package/src/abi/js-abi-coder.js +61 -2
- package/src/contract/contract.js +53 -5
- package/src/generator/index.js +152 -13
- package/src/index.d.ts +1 -0
- package/src/providers/index.d.ts +1 -0
- package/src/providers/provider.d.ts +16 -0
- package/src/providers/provider.js +178 -5
- package/src/utils/rlp.js +13 -1
- package/src/wallet/wallet.d.ts +10 -0
- package/src/wallet/wallet.js +136 -15
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package-lock.json +6 -6
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package.json +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.js +3 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.e2e.test.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package-lock.json +6 -6
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package.json +1 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes__factory.ts +3 -1
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.e2e.test.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package-lock.json +6 -6
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package.json +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.js +9 -3
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.js +3 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/test/e2e/SimpleERC20.e2e.test.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.js +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.ts +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package-lock.json +6 -6
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package.json +1 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20.ts +9 -3
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20__factory.ts +3 -1
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js +1 -1
- package/test/e2e/generator-interface.e2e.test.js +6 -4
- package/test/e2e/generator-interface.e2e.test.ts +6 -4
- package/test/security/abi-decoder-bounds.test.js +122 -0
- package/test/security/contract-overrides.test.js +112 -0
- package/test/security/generator-injection.test.js +195 -0
- package/test/security/malformed-input.test.js +26 -27
- package/test/security/rpc-numeric-bounds.test.js +81 -0
- package/test/security/rpc-trust.test.js +202 -0
- package/test/unit/abi-interface.test.js +12 -5
- package/test/unit/abi-interface.test.ts +8 -1
- package/test/unit/address-wallet.test.js +53 -0
- package/test/unit/address-wallet.test.ts +22 -0
- package/test/unit/encoding-units-rlp.test.js +35 -0
- package/test/unit/populate-transaction.test.js +33 -0
- package/test/unit/providers.test.js +53 -0
- package/test/unit/providers.test.ts +53 -0
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const { EventEmitter } = require("events");
|
|
9
|
+
const qcsdk = require("quantum-coin-js-sdk");
|
|
9
10
|
const { makeError, assertArgument } = require("../errors");
|
|
10
11
|
const { normalizeHex, toQuantityHex, isHexString } = require("../internal/hex");
|
|
11
12
|
|
|
@@ -44,7 +45,17 @@ function _hexToBigInt(hex) {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
function _hexToNumber(hex) {
|
|
47
|
-
|
|
48
|
+
// RPC quantities are untrusted. Previously `Number(bigint)` silently
|
|
49
|
+
// truncated values above 2^53, corrupting blockNumber/nonce/status/indices used
|
|
50
|
+
// in confirmation math. We keep returning a `number` (no signature/type change),
|
|
51
|
+
// but fail loudly for out-of-range values instead of returning a corrupted one.
|
|
52
|
+
// Real chain values are far below MAX_SAFE_INTEGER, so honest flows are
|
|
53
|
+
// unaffected. (Returning bigint would break field types and wait() arithmetic.)
|
|
54
|
+
const bi = _hexToBigInt(hex);
|
|
55
|
+
if (bi > BigInt(Number.MAX_SAFE_INTEGER) || bi < BigInt(Number.MIN_SAFE_INTEGER)) {
|
|
56
|
+
throw makeError("RPC quantity exceeds safe integer range", "NUMERIC_FAULT", { value: bi.toString() });
|
|
57
|
+
}
|
|
58
|
+
return Number(bi);
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
/**
|
|
@@ -52,6 +63,47 @@ function _hexToNumber(hex) {
|
|
|
52
63
|
* @param {number|string|undefined} blockTag
|
|
53
64
|
* @returns {string|undefined}
|
|
54
65
|
*/
|
|
66
|
+
/**
|
|
67
|
+
* Build a lowercase Set of allowed log addresses from a filter's `address` field
|
|
68
|
+
* (string or string[]). Returns null when no address constraint is present.
|
|
69
|
+
* @param {string|string[]|undefined|null} address
|
|
70
|
+
* @returns {Set<string>|null}
|
|
71
|
+
*/
|
|
72
|
+
function _normalizeAddressFilter(address) {
|
|
73
|
+
if (address == null) return null;
|
|
74
|
+
const list = Array.isArray(address) ? address : [address];
|
|
75
|
+
const set = new Set();
|
|
76
|
+
for (const a of list) {
|
|
77
|
+
if (typeof a === "string" && a.length > 0) set.add(a.toLowerCase());
|
|
78
|
+
}
|
|
79
|
+
return set.size ? set : null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check a log's topics against a requested topics filter (eth_getLogs
|
|
84
|
+
* semantics). Each filter position may be null (wildcard), a string (exact
|
|
85
|
+
* match), or an array of strings (any match). Used to drop logs a malicious node
|
|
86
|
+
* returns that do not actually match the requested event topic(s).
|
|
87
|
+
* @param {any[]} logTopics
|
|
88
|
+
* @param {(string|string[]|null)[]} filterTopics
|
|
89
|
+
* @returns {boolean}
|
|
90
|
+
*/
|
|
91
|
+
function _topicsMatch(logTopics, filterTopics) {
|
|
92
|
+
if (!Array.isArray(filterTopics)) return true;
|
|
93
|
+
const topics = Array.isArray(logTopics) ? logTopics : [];
|
|
94
|
+
for (let i = 0; i < filterTopics.length; i++) {
|
|
95
|
+
const want = filterTopics[i];
|
|
96
|
+
if (want == null) continue; // wildcard position
|
|
97
|
+
const have = typeof topics[i] === "string" ? topics[i].toLowerCase() : null;
|
|
98
|
+
if (have == null) return false;
|
|
99
|
+
const allowed = (Array.isArray(want) ? want : [want])
|
|
100
|
+
.filter((t) => typeof t === "string")
|
|
101
|
+
.map((t) => t.toLowerCase());
|
|
102
|
+
if (allowed.length && !allowed.includes(have)) return false;
|
|
103
|
+
}
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
|
|
55
107
|
function _blockTagToHex(blockTag) {
|
|
56
108
|
if (blockTag === undefined || blockTag === null) return undefined;
|
|
57
109
|
const s = String(blockTag).toLowerCase();
|
|
@@ -212,6 +264,20 @@ class Block {
|
|
|
212
264
|
}
|
|
213
265
|
}
|
|
214
266
|
|
|
267
|
+
/**
|
|
268
|
+
* Fee data for a transaction. Currently only `gasPrice` (per unit of gas, in wei)
|
|
269
|
+
* is populated. `maxFeePerGas` / `maxPriorityFeePerGas` are not supported yet:
|
|
270
|
+
* QuantumCoin uses a fixed per-scheme fee model with no EIP-1559 base fee / priority tip.
|
|
271
|
+
*/
|
|
272
|
+
class FeeData {
|
|
273
|
+
/**
|
|
274
|
+
* @param {bigint} gasPrice
|
|
275
|
+
*/
|
|
276
|
+
constructor(gasPrice) {
|
|
277
|
+
this.gasPrice = gasPrice;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
215
281
|
/**
|
|
216
282
|
* Base Provider class.
|
|
217
283
|
*/
|
|
@@ -263,7 +329,23 @@ class AbstractProvider extends Provider {
|
|
|
263
329
|
async getTransaction(txHash) {
|
|
264
330
|
const tx = await this._perform("eth_getTransactionByHash", [txHash]);
|
|
265
331
|
if (!tx) return null;
|
|
266
|
-
|
|
332
|
+
const result = new TransactionResponse(tx, this);
|
|
333
|
+
// Do not trust the node to return the transaction we actually asked for.
|
|
334
|
+
// When the response carries a hash, it must match the requested hash;
|
|
335
|
+
// otherwise a malicious node could substitute a different transaction.
|
|
336
|
+
if (
|
|
337
|
+
typeof txHash === "string" &&
|
|
338
|
+
typeof result.hash === "string" &&
|
|
339
|
+
result.hash.length > 0 &&
|
|
340
|
+
result.hash.toLowerCase() !== txHash.toLowerCase()
|
|
341
|
+
) {
|
|
342
|
+
throw makeError("RPC node returned a transaction whose hash does not match the requested hash", "UNKNOWN_ERROR", {
|
|
343
|
+
operation: "getTransaction",
|
|
344
|
+
expected: txHash,
|
|
345
|
+
got: result.hash,
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
return result;
|
|
267
349
|
}
|
|
268
350
|
|
|
269
351
|
/**
|
|
@@ -273,7 +355,23 @@ class AbstractProvider extends Provider {
|
|
|
273
355
|
async getTransactionReceipt(txHash) {
|
|
274
356
|
const receipt = await this._perform("eth_getTransactionReceipt", [txHash]);
|
|
275
357
|
if (!receipt) return null;
|
|
276
|
-
|
|
358
|
+
const result = new TransactionReceipt(receipt, this);
|
|
359
|
+
// The receipt must belong to the transaction we asked about. A node must
|
|
360
|
+
// not be able to confirm an unrelated/fabricated transaction (which would let
|
|
361
|
+
// wait() report success for the wrong tx).
|
|
362
|
+
if (
|
|
363
|
+
typeof txHash === "string" &&
|
|
364
|
+
typeof result.transactionHash === "string" &&
|
|
365
|
+
result.transactionHash.length > 0 &&
|
|
366
|
+
result.transactionHash.toLowerCase() !== txHash.toLowerCase()
|
|
367
|
+
) {
|
|
368
|
+
throw makeError("RPC node returned a receipt whose hash does not match the requested hash", "UNKNOWN_ERROR", {
|
|
369
|
+
operation: "getTransactionReceipt",
|
|
370
|
+
expected: txHash,
|
|
371
|
+
got: result.transactionHash,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
return result;
|
|
277
375
|
}
|
|
278
376
|
|
|
279
377
|
/**
|
|
@@ -299,15 +397,47 @@ class AbstractProvider extends Provider {
|
|
|
299
397
|
/**
|
|
300
398
|
* Broadcasts a signed transaction.
|
|
301
399
|
* @param {TransactionRequest|string} tx
|
|
400
|
+
* @param {{ expectedHash?: string }=} opts Optional. When `expectedHash` is set,
|
|
401
|
+
* the hash returned by the node (and the fetched-back transaction's hash) must
|
|
402
|
+
* match it, otherwise an error is thrown (do not trust the RPC node to
|
|
403
|
+
* broadcast the exact transaction that was signed).
|
|
302
404
|
* @returns {Promise<TransactionResponse>}
|
|
303
405
|
*/
|
|
304
|
-
async sendTransaction(tx) {
|
|
406
|
+
async sendTransaction(tx, opts) {
|
|
305
407
|
// For QuantumCoin.js, tx is expected to be a signed raw transaction hex string.
|
|
306
408
|
const raw = typeof tx === "string" ? tx : tx?.raw;
|
|
307
409
|
if (typeof raw !== "string") throw makeError("sendTransaction requires a signed raw transaction string", "INVALID_ARGUMENT", { tx });
|
|
410
|
+
const expectedHash =
|
|
411
|
+
opts && typeof opts.expectedHash === "string" && opts.expectedHash.length > 0 ? opts.expectedHash.toLowerCase() : null;
|
|
412
|
+
|
|
308
413
|
const hash = await this._perform("eth_sendRawTransaction", [raw]);
|
|
414
|
+
|
|
415
|
+
// The node returns the hash it claims to have accepted. If we know the
|
|
416
|
+
// hash of the transaction we signed, reject any mismatch — a malicious or
|
|
417
|
+
// buggy node must not be able to silently substitute a different transaction.
|
|
418
|
+
if (expectedHash != null && typeof hash === "string" && hash.length > 0) {
|
|
419
|
+
if (hash.toLowerCase() !== expectedHash) {
|
|
420
|
+
throw makeError("RPC node returned a transaction hash that does not match the signed transaction", "UNKNOWN_ERROR", {
|
|
421
|
+
operation: "sendTransaction",
|
|
422
|
+
expected: expectedHash,
|
|
423
|
+
got: hash,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
309
428
|
// Fetch back transaction (best-effort)
|
|
310
429
|
const result = await this.getTransaction(hash);
|
|
430
|
+
|
|
431
|
+
// Verify the fetched-back transaction's hash too, so a node cannot return
|
|
432
|
+
// a fabricated transaction object under the correct hash lookup.
|
|
433
|
+
if (result && expectedHash != null && typeof result.hash === "string" && result.hash.toLowerCase() !== expectedHash) {
|
|
434
|
+
throw makeError("RPC node returned a transaction whose hash does not match the signed transaction", "UNKNOWN_ERROR", {
|
|
435
|
+
operation: "sendTransaction",
|
|
436
|
+
expected: expectedHash,
|
|
437
|
+
got: result.hash,
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
311
441
|
return result || new TransactionResponse({ hash }, this);
|
|
312
442
|
}
|
|
313
443
|
|
|
@@ -344,6 +474,30 @@ class AbstractProvider extends Provider {
|
|
|
344
474
|
return _hexToBigInt(gas);
|
|
345
475
|
}
|
|
346
476
|
|
|
477
|
+
/**
|
|
478
|
+
* Returns fee data (currently the gas price per unit of gas, in wei).
|
|
479
|
+
* Supports only DynamicFeeTx (dynamic-fee transactions); other fee tx types are not supported.
|
|
480
|
+
* @param {import("../wallet/wallet").Wallet|number} walletOrKeyType A Wallet, or a key type number (3 or 5).
|
|
481
|
+
* @param {boolean|null=} fullSign Full signing (keyType 3 only; ignored for keyType 5).
|
|
482
|
+
* @returns {Promise<FeeData>}
|
|
483
|
+
*/
|
|
484
|
+
async getFeeData(walletOrKeyType, fullSign) {
|
|
485
|
+
let keyType;
|
|
486
|
+
if (typeof walletOrKeyType === "number") {
|
|
487
|
+
keyType = walletOrKeyType;
|
|
488
|
+
} else if (walletOrKeyType && typeof walletOrKeyType.getKeyType === "function") {
|
|
489
|
+
keyType = walletOrKeyType.getKeyType();
|
|
490
|
+
} else {
|
|
491
|
+
assertArgument(false, "expected a Wallet or a keyType number", "walletOrKeyType", walletOrKeyType);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const res = qcsdk.getGasPrice(keyType, fullSign ?? false);
|
|
495
|
+
if (!res || res.resultCode !== 0 || res.gasPrice == null) {
|
|
496
|
+
throw makeError("getGasPrice failed", "UNKNOWN_ERROR", { resultCode: res && res.resultCode, keyType });
|
|
497
|
+
}
|
|
498
|
+
return new FeeData(BigInt(res.gasPrice));
|
|
499
|
+
}
|
|
500
|
+
|
|
347
501
|
/**
|
|
348
502
|
* @param {string} address
|
|
349
503
|
* @param {string=} blockTag
|
|
@@ -376,7 +530,25 @@ class AbstractProvider extends Provider {
|
|
|
376
530
|
if (fromBlock !== undefined) normalized.fromBlock = fromBlock;
|
|
377
531
|
if (toBlock !== undefined) normalized.toBlock = toBlock;
|
|
378
532
|
const logs = await this._perform("eth_getLogs", [normalized]);
|
|
379
|
-
|
|
533
|
+
const mapped = (logs || []).map((l) => new Log(l, this));
|
|
534
|
+
|
|
535
|
+
// A malicious node could return logs emitted by contracts other than the
|
|
536
|
+
// one(s) requested. When the filter constrains the address, drop any log whose
|
|
537
|
+
// address is not in that set so foreign-contract events cannot be injected.
|
|
538
|
+
const allowed = _normalizeAddressFilter(filter.address);
|
|
539
|
+
// A malicious node could return logs for a different event (different
|
|
540
|
+
// topic0) or from foreign contracts. Drop anything that does not match the
|
|
541
|
+
// requested address and topic constraints.
|
|
542
|
+
const hasTopicFilter = Array.isArray(filter.topics) && filter.topics.some((t) => t != null);
|
|
543
|
+
if (allowed || hasTopicFilter) {
|
|
544
|
+
return mapped.filter((l) => {
|
|
545
|
+
if (!l) return false;
|
|
546
|
+
if (allowed && !(typeof l.address === "string" && allowed.has(l.address.toLowerCase()))) return false;
|
|
547
|
+
if (hasTopicFilter && !_topicsMatch(l.topics, filter.topics)) return false;
|
|
548
|
+
return true;
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
return mapped;
|
|
380
552
|
}
|
|
381
553
|
}
|
|
382
554
|
|
|
@@ -387,5 +559,6 @@ module.exports = {
|
|
|
387
559
|
TransactionResponse,
|
|
388
560
|
TransactionReceipt,
|
|
389
561
|
Log,
|
|
562
|
+
FeeData,
|
|
390
563
|
};
|
|
391
564
|
|
package/src/utils/rlp.js
CHANGED
|
@@ -103,9 +103,14 @@ function _encode(value) {
|
|
|
103
103
|
function _readLen(bytes, offset, lenOfLen) {
|
|
104
104
|
if (lenOfLen === 0) return 0;
|
|
105
105
|
if (offset + lenOfLen > bytes.length) throw new Error("RLP: insufficient data for length");
|
|
106
|
+
// Canonical encoding forbids a leading zero byte in the length field.
|
|
107
|
+
if (bytes[offset] === 0) throw new Error("RLP: non-canonical length (leading zero byte)");
|
|
108
|
+
// Accumulate with multiplication (not `<< 8`, which is a signed 32-bit op
|
|
109
|
+
// that overflows/wraps for 4+ byte lengths) and reject impossibly large lengths.
|
|
106
110
|
let len = 0;
|
|
107
111
|
for (let i = 0; i < lenOfLen; i++) {
|
|
108
|
-
len =
|
|
112
|
+
len = len * 256 + bytes[offset + i];
|
|
113
|
+
if (len > Number.MAX_SAFE_INTEGER) throw new Error("RLP: length exceeds maximum safe integer");
|
|
109
114
|
}
|
|
110
115
|
return len;
|
|
111
116
|
}
|
|
@@ -128,6 +133,9 @@ function _decode(bytes, start, end, depth) {
|
|
|
128
133
|
const dataStart = start + 1;
|
|
129
134
|
const dataEnd = dataStart + len;
|
|
130
135
|
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
136
|
+
// Canonical encoding requires a single byte < 0x80 to be encoded as
|
|
137
|
+
// itself, never as a 1-byte string.
|
|
138
|
+
if (len === 1 && bytes[dataStart] < 0x80) throw new Error("RLP: non-canonical single byte encoding");
|
|
131
139
|
const out = bytesToHex(bytes.slice(dataStart, dataEnd));
|
|
132
140
|
return { value: out, next: dataEnd };
|
|
133
141
|
}
|
|
@@ -136,6 +144,8 @@ function _decode(bytes, start, end, depth) {
|
|
|
136
144
|
if (prefix <= 0xbf) {
|
|
137
145
|
const lenOfLen = prefix - 0xb7;
|
|
138
146
|
const len = _readLen(bytes, start + 1, lenOfLen);
|
|
147
|
+
// Lengths <= 55 must use the short-string form.
|
|
148
|
+
if (len <= 55) throw new Error("RLP: non-canonical long string (length fits short form)");
|
|
139
149
|
const dataStart = start + 1 + lenOfLen;
|
|
140
150
|
const dataEnd = dataStart + len;
|
|
141
151
|
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
|
@@ -163,6 +173,8 @@ function _decode(bytes, start, end, depth) {
|
|
|
163
173
|
// Long list
|
|
164
174
|
const lenOfLen = prefix - 0xf7;
|
|
165
175
|
const len = _readLen(bytes, start + 1, lenOfLen);
|
|
176
|
+
// Lengths <= 55 must use the short-list form.
|
|
177
|
+
if (len <= 55) throw new Error("RLP: non-canonical long list (length fits short form)");
|
|
166
178
|
const dataStart = start + 1 + lenOfLen;
|
|
167
179
|
const dataEnd = dataStart + len;
|
|
168
180
|
if (dataEnd > end) throw new Error("RLP: out of bounds");
|
package/src/wallet/wallet.d.ts
CHANGED
|
@@ -70,6 +70,16 @@ export class Wallet extends BaseWallet {
|
|
|
70
70
|
* @returns {number}
|
|
71
71
|
*/
|
|
72
72
|
getSigningContext(fullSign?: boolean | null): number;
|
|
73
|
+
/**
|
|
74
|
+
* Returns the key type of this wallet, derived from its public key length:
|
|
75
|
+
* 3 (KEY_TYPE_HYBRIDEDMLDSASLHDSA) or 5 (KEY_TYPE_HYBRIDEDMLDSASLHDSA5).
|
|
76
|
+
*
|
|
77
|
+
* The key type drives gas-price selection via `getFeeData`. Note that the
|
|
78
|
+
* underlying quantum-coin-js-sdk gas-price model supports only DynamicFeeTx
|
|
79
|
+
* (dynamic-fee transactions); legacy/other transaction fee types are not supported.
|
|
80
|
+
* @returns {number} 3 or 5.
|
|
81
|
+
*/
|
|
82
|
+
getKeyType(): number;
|
|
73
83
|
/**
|
|
74
84
|
* Creates a new random wallet.
|
|
75
85
|
* @param {import("../providers/provider").AbstractProvider=} provider
|
package/src/wallet/wallet.js
CHANGED
|
@@ -34,6 +34,32 @@ function _bytesToNumberArray(bytes) {
|
|
|
34
34
|
return Array.from(bytes);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Verify that a private/public key pair is internally consistent (the public
|
|
39
|
+
* key really corresponds to the private key). Constructing a wallet from a
|
|
40
|
+
* mismatched pair must fail loudly here rather than silently producing a wallet
|
|
41
|
+
* that signs with one key but claims another.
|
|
42
|
+
*
|
|
43
|
+
* NOTE: `qcsdk.verifyWallet` requires the raw (non-`0x`-prefixed) address form,
|
|
44
|
+
* so we build the verification wallet from `addressFromPublicKey` directly
|
|
45
|
+
* (mirroring the original `fromKeys` flow) rather than reusing a wallet that may
|
|
46
|
+
* carry a normalized `0x` address.
|
|
47
|
+
*
|
|
48
|
+
* @param {Uint8Array} privateKeyBytes
|
|
49
|
+
* @param {Uint8Array} publicKeyBytes
|
|
50
|
+
*/
|
|
51
|
+
function _assertKeyPairValid(privateKeyBytes, publicKeyBytes) {
|
|
52
|
+
const privArr = _bytesToNumberArray(privateKeyBytes);
|
|
53
|
+
const pubArr = _bytesToNumberArray(publicKeyBytes);
|
|
54
|
+
const addr = qcsdk.addressFromPublicKey(pubArr);
|
|
55
|
+
if (typeof addr !== "string") throw makeError("addressFromPublicKey failed", "UNKNOWN_ERROR", {});
|
|
56
|
+
const checkWallet = new qcsdk.Wallet(addr, privArr, pubArr);
|
|
57
|
+
const verified = qcsdk.verifyWallet(checkWallet);
|
|
58
|
+
if (verified !== true) {
|
|
59
|
+
throw makeError("verifyWallet failed: the provided key pair is invalid", "INVALID_ARGUMENT", { verified });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
37
63
|
const _maxSafeInt = 0x1fffffffffffffn; // 2^53 - 1
|
|
38
64
|
|
|
39
65
|
function _getBigInt(value, name) {
|
|
@@ -57,6 +83,27 @@ function _getNumber(value, name) {
|
|
|
57
83
|
return Number(bi);
|
|
58
84
|
}
|
|
59
85
|
|
|
86
|
+
// Key type / public-key-length constants. The quantum-coin-js-sdk defines these
|
|
87
|
+
// key types internally (KEY_TYPE_HYBRIDEDMLDSASLHDSA = 3,
|
|
88
|
+
// KEY_TYPE_HYBRIDEDMLDSASLHDSA5 = 5) but does not export them, so we mirror them
|
|
89
|
+
// here and derive the key type from the public key length.
|
|
90
|
+
const KEY_TYPE_HYBRIDEDMLDSASLHDSA = 3;
|
|
91
|
+
const KEY_TYPE_HYBRIDEDMLDSASLHDSA5 = 5;
|
|
92
|
+
const PUBLIC_KEY_LENGTH_KEYTYPE3 = 1408;
|
|
93
|
+
const PUBLIC_KEY_LENGTH_KEYTYPE5 = 2688;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Maps a public key length to the wallet key type.
|
|
97
|
+
* @param {number} pubLen
|
|
98
|
+
* @returns {number} KEY_TYPE_HYBRIDEDMLDSASLHDSA (3) or KEY_TYPE_HYBRIDEDMLDSASLHDSA5 (5).
|
|
99
|
+
* @throws if the public key length is unsupported.
|
|
100
|
+
*/
|
|
101
|
+
function _keyTypeFromPublicKeyLength(pubLen) {
|
|
102
|
+
if (pubLen === PUBLIC_KEY_LENGTH_KEYTYPE3) return KEY_TYPE_HYBRIDEDMLDSASLHDSA;
|
|
103
|
+
if (pubLen === PUBLIC_KEY_LENGTH_KEYTYPE5) return KEY_TYPE_HYBRIDEDMLDSASLHDSA5;
|
|
104
|
+
throw makeError("unsupported public key size", "UNSUPPORTED_OPERATION", { publicKeyLength: pubLen });
|
|
105
|
+
}
|
|
106
|
+
|
|
60
107
|
/**
|
|
61
108
|
* SigningKey wrapper (PQC private/public key bytes).
|
|
62
109
|
*/
|
|
@@ -163,6 +210,19 @@ class BaseWallet extends AbstractSigner {
|
|
|
163
210
|
* @returns {Promise<string>}
|
|
164
211
|
*/
|
|
165
212
|
async signTransaction(tx) {
|
|
213
|
+
const { raw } = await this._signDetailed(tx);
|
|
214
|
+
return raw;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Internal: sign a transaction and return both the raw serialized transaction
|
|
219
|
+
* and the signer-computed transaction hash. The hash is later used to
|
|
220
|
+
* verify that an untrusted RPC node broadcast exactly the transaction we
|
|
221
|
+
* signed rather than substituting a different one.
|
|
222
|
+
* @param {import("../providers/provider").TransactionRequest} tx
|
|
223
|
+
* @returns {Promise<{ raw: string, hash: string|null }>}
|
|
224
|
+
*/
|
|
225
|
+
async _signDetailed(tx) {
|
|
166
226
|
_requireInitialized();
|
|
167
227
|
assertArgument(tx && typeof tx === "object", "invalid tx", "tx", tx);
|
|
168
228
|
|
|
@@ -192,9 +252,32 @@ class BaseWallet extends AbstractSigner {
|
|
|
192
252
|
}
|
|
193
253
|
assertArgument(Number.isInteger(nonce) && nonce >= 0, "invalid nonce", "nonce", nonce);
|
|
194
254
|
|
|
255
|
+
// `chainId` remains accepted from the tx (e.g. via contract overrides). We
|
|
256
|
+
// intentionally do NOT assert it against the
|
|
257
|
+
// provider here because `chainId` in quantum-coin-js-sdk (qcsdk) defaults to
|
|
258
|
+
// 123123 internally — an unset chainId resolves to that network default rather
|
|
259
|
+
// than being left unbound. Cross-chain replay risk is therefore bounded by the
|
|
260
|
+
// qcsdk default; explicit per-call chainId overrides are caller responsibility.
|
|
195
261
|
const chainId = tx.chainId != null ? tx.chainId : (this.provider && this.provider.chainId != null ? this.provider.chainId : null);
|
|
196
262
|
const signingContext = tx.signingContext ?? null;
|
|
197
263
|
|
|
264
|
+
// chainId is mandatory for signing. Without it the signed transaction is
|
|
265
|
+
// not bound to a network and can be replayed on a different chain. Online
|
|
266
|
+
// flows resolve chainId from the connected provider; offline signing must
|
|
267
|
+
// pass tx.chainId explicitly.
|
|
268
|
+
let chainIdNum = null;
|
|
269
|
+
try {
|
|
270
|
+
chainIdNum = chainId == null ? null : _getNumber(chainId, "tx.chainId");
|
|
271
|
+
} catch {
|
|
272
|
+
chainIdNum = null;
|
|
273
|
+
}
|
|
274
|
+
assertArgument(
|
|
275
|
+
chainIdNum != null && chainIdNum >= 0,
|
|
276
|
+
"chainId is required for signing; pass tx.chainId or connect to a provider",
|
|
277
|
+
"chainId",
|
|
278
|
+
chainId,
|
|
279
|
+
);
|
|
280
|
+
|
|
198
281
|
/** @type {any} */
|
|
199
282
|
const qcWallet =
|
|
200
283
|
this._qcWallet ||
|
|
@@ -228,7 +311,11 @@ class BaseWallet extends AbstractSigner {
|
|
|
228
311
|
}
|
|
229
312
|
const raw = signResult.txnData;
|
|
230
313
|
if (typeof raw !== "string") throw makeError("signRawTransaction did not return txnData", "UNKNOWN_ERROR", {});
|
|
231
|
-
|
|
314
|
+
let hash = null;
|
|
315
|
+
if (typeof signResult.txnHash === "string" && signResult.txnHash.length > 0) {
|
|
316
|
+
hash = normalizeHex(signResult.txnHash).toLowerCase();
|
|
317
|
+
}
|
|
318
|
+
return { raw: normalizeHex(raw), hash };
|
|
232
319
|
}
|
|
233
320
|
|
|
234
321
|
/**
|
|
@@ -238,8 +325,10 @@ class BaseWallet extends AbstractSigner {
|
|
|
238
325
|
*/
|
|
239
326
|
async sendTransaction(tx) {
|
|
240
327
|
if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "sendTransaction" });
|
|
241
|
-
const raw = await this.
|
|
242
|
-
|
|
328
|
+
const { raw, hash } = await this._signDetailed({ ...tx, from: this.address });
|
|
329
|
+
// Tell the provider which hash we expect so it can reject a node that
|
|
330
|
+
// broadcasts (or echoes back) a different transaction than the one we signed.
|
|
331
|
+
return this.provider.sendTransaction(raw, hash ? { expectedHash: hash } : undefined);
|
|
243
332
|
}
|
|
244
333
|
}
|
|
245
334
|
|
|
@@ -281,6 +370,11 @@ class Wallet extends BaseWallet {
|
|
|
281
370
|
_bytesToNumberArray(signingKey.publicKeyBytes),
|
|
282
371
|
);
|
|
283
372
|
|
|
373
|
+
// Central choke point — every Wallet (createRandom/fromPhrase/fromSeed/
|
|
374
|
+
// fromEncryptedJsonSync/fromKeys/connect all funnel through this constructor)
|
|
375
|
+
// is verified for key-pair consistency before it can be used to sign.
|
|
376
|
+
_assertKeyPairValid(signingKey.privateKeyBytes, signingKey.publicKeyBytes);
|
|
377
|
+
|
|
284
378
|
super(signingKey, provider || null, { address: qcAddress }, qcWallet);
|
|
285
379
|
}
|
|
286
380
|
|
|
@@ -323,6 +417,15 @@ class Wallet extends BaseWallet {
|
|
|
323
417
|
if (this._seed != null) {
|
|
324
418
|
return Wallet.encryptSeedSync(hexToBytes(this._seed), password);
|
|
325
419
|
}
|
|
420
|
+
// A Uint8Array password is decoded as UTF-8 with NFC normalization below.
|
|
421
|
+
// For arbitrary (non-UTF-8) byte passwords this is
|
|
422
|
+
// lossy — invalid sequences become U+FFFD — so a binary password may not
|
|
423
|
+
// round-trip and the keystore could fail to reopen. This is intentionally left
|
|
424
|
+
// as-is because the password->key mapping is part of the shared QuantumCoin
|
|
425
|
+
// keystore format owned by qcsdk (and interoperable with the Desktop/Mobile/Web
|
|
426
|
+
// /CLI wallets); changing it risks breaking existing keystores and cross-app
|
|
427
|
+
// interop. Prefer string passphrases. (Fixing correctly requires a keystore-spec
|
|
428
|
+
// decision, not a local change.)
|
|
326
429
|
const pw = typeof password === "string"
|
|
327
430
|
? password.normalize("NFC")
|
|
328
431
|
: Buffer.from(arrayify(password)).toString("utf8").normalize("NFC");
|
|
@@ -346,6 +449,10 @@ class Wallet extends BaseWallet {
|
|
|
346
449
|
assertArgument(Array.isArray(seedArr), "seed must be an array of numbers or Uint8Array", "seed", seed);
|
|
347
450
|
const allowedLengths = [64, 72, 96];
|
|
348
451
|
assertArgument(allowedLengths.includes(seedArr.length), "seed must be 64, 72, or 96 bytes", "seed", seedArr.length);
|
|
452
|
+
// See encryptSync — a Uint8Array password is decoded as UTF-8/NFC, which is
|
|
453
|
+
// lossy for arbitrary byte passwords. Left as-is
|
|
454
|
+
// because the password->key mapping is part of the shared qcsdk keystore format
|
|
455
|
+
// (cross-app interop); prefer string passphrases.
|
|
349
456
|
const pw = typeof password === "string"
|
|
350
457
|
? password.normalize("NFC")
|
|
351
458
|
: Buffer.from(arrayify(password)).toString("utf8").normalize("NFC");
|
|
@@ -382,14 +489,26 @@ class Wallet extends BaseWallet {
|
|
|
382
489
|
*/
|
|
383
490
|
getSigningContext(fullSign) {
|
|
384
491
|
const fs = fullSign ?? false;
|
|
385
|
-
const
|
|
386
|
-
if (
|
|
492
|
+
const keyType = _keyTypeFromPublicKeyLength(this.signingKey.publicKeyBytes.length);
|
|
493
|
+
if (keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA) {
|
|
387
494
|
return fs ? 2 : 0;
|
|
388
495
|
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
496
|
+
return 1;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Returns the key type of this wallet, derived from its public key length:
|
|
501
|
+
* 3 (KEY_TYPE_HYBRIDEDMLDSASLHDSA) or 5 (KEY_TYPE_HYBRIDEDMLDSASLHDSA5).
|
|
502
|
+
*
|
|
503
|
+
* The key type drives gas-price selection via `getFeeData`. Note that the
|
|
504
|
+
* underlying quantum-coin-js-sdk gas-price model supports only DynamicFeeTx
|
|
505
|
+
* (dynamic-fee transactions); legacy/other transaction fee types are not supported.
|
|
506
|
+
*
|
|
507
|
+
* @returns {number} 3 or 5.
|
|
508
|
+
* @throws if the public key length is unsupported.
|
|
509
|
+
*/
|
|
510
|
+
getKeyType() {
|
|
511
|
+
return _keyTypeFromPublicKeyLength(this.signingKey.publicKeyBytes.length);
|
|
393
512
|
}
|
|
394
513
|
|
|
395
514
|
/**
|
|
@@ -413,7 +532,12 @@ class Wallet extends BaseWallet {
|
|
|
413
532
|
static createRandom(provider, keyType) {
|
|
414
533
|
_requireInitialized();
|
|
415
534
|
if (keyType != null) {
|
|
416
|
-
assertArgument(
|
|
535
|
+
assertArgument(
|
|
536
|
+
keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA || keyType === KEY_TYPE_HYBRIDEDMLDSASLHDSA5,
|
|
537
|
+
"keyType must be null, 3, or 5",
|
|
538
|
+
"keyType",
|
|
539
|
+
keyType,
|
|
540
|
+
);
|
|
417
541
|
}
|
|
418
542
|
const words = qcsdk.newWalletSeedWords(keyType ?? null);
|
|
419
543
|
if (!words || !Array.isArray(words)) {
|
|
@@ -502,11 +626,8 @@ class Wallet extends BaseWallet {
|
|
|
502
626
|
if (typeof addr !== "string") throw makeError("addressFromPublicKey failed", "UNKNOWN_ERROR", {});
|
|
503
627
|
|
|
504
628
|
const qcWallet = new qcsdk.Wallet(addr, privArr, pubArr);
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
throw makeError("verifyWallet failed: the provided key pair is invalid", "INVALID_ARGUMENT", { verified });
|
|
508
|
-
}
|
|
509
|
-
|
|
629
|
+
// Key-pair verification now happens centrally in the Wallet constructor
|
|
630
|
+
// (reached via _fromQcWallet -> new Wallet). No redundant verify here.
|
|
510
631
|
return Wallet._fromQcWallet(qcWallet, provider || null);
|
|
511
632
|
}
|
|
512
633
|
|
package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { Wallet } = require("quantumcoin");
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
4
4
|
const TEST_WALLET_ENCRYPTED_JSON =
|
|
5
5
|
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
6
6
|
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Wallet } from "quantumcoin";
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
4
4
|
export const TEST_WALLET_ENCRYPTED_JSON =
|
|
5
5
|
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
6
6
|
export const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|
|
@@ -10,7 +10,7 @@ const { Initialize } = require("quantumcoin/config");
|
|
|
10
10
|
const { getProvider, Wallet } = require("quantumcoin");
|
|
11
11
|
const { AllSolidityTypes__factory } = require("..");
|
|
12
12
|
|
|
13
|
-
//
|
|
13
|
+
// SECURITY/AUDIT NOTE: test-only fixture. Publicly known keystore + passphrase. Never fund this address or reuse for real funds. (Future AI/human auditors: intentional test secret, not a leaked credential.)
|
|
14
14
|
const TEST_WALLET_ENCRYPTED_JSON =
|
|
15
15
|
"{\"address\":\"1a846abe71c8b989e8337c55d608be81c28ab3b2e40c83eaa2a68d516049aec6\",\"crypto\":{\"cipher\":\"aes-256-ctr\",\"ciphertext\":\"ab7e620dd66cb55ac201b9c6796de92bbb06f3681b5932eabe099871f1f7d79acabe30921a39ad13bfe74f42c515734882b6723760142aa3e26e011df514a534ae47bd15d86badd9c6f17c48d4c892711d54d441ee3a0ee0e5b060f816e79c7badd13ff4c235934b1986774223ecf6e8761388969bb239c759b54c8c70e6a2e27c93a4b70129c8159f461d271ae8f3573414c78b88e4d0abfa6365ed45456636d4ed971c7a0c6b84e6f0c2621e819268b135e2bcc169a54d1847b39e6ba2ae8ec969b69f330b7db9e785ed02204d5a1185915ae5338b0f40ef2a7f4d5aaf7563d502135e57f4eb89d5ec1efa5c77e374969d6cd85be625a2ed1225d68ecdd84067bfc69adb83ecd5c6050472eca28a5a646fcdd28077165c629975bec8a79fe1457cb53389b788b25e1f8eff8b2ca326d7dfcaba3f8839225a08057c018a458891fd2caa0d2b27632cffd80f592147ccec9a10dc8a08a48fb55047bff5cf85cda39eb089096bef63842fc3686412f298a54a9e4b0bf4ad36907ba373cbd6d32e7ac494af371da5aa9d38a3463220865114c4adc5e4ac258ba9c6af9fa2ddfd1aec2e16887e4b3977c69561df8599ac9d411c9dd2a4d57f92ea4e5c02aae3f49fb3bc83e16673e6c2dbe96bb181c8dfd0f9757ade2e4ff27215a836058c5ffeab042f6f97c7c02339f76a6284680e01b4bb733690eb3347fbfcc26614b8bf755f9dfce3fea9d4e4d15b164983201732c2e87593a86bca6da6972e128490338f76ae68135888070f4e59e90db54d23834769bdbda9769213faf5357f9167a224523975a946367b68f0cec98658575609f58bfd329e420a921c06713326e4cb20a0df1d77f37e78a320a637a96c604ca3fa89e24beb42313751b8f09b14f9c14c77e4fd13fc6382505d27c771bca0d821ec7c3765acffa99d83c50140a56b0b28101c762bd682fe55cb6f23cbeb3f421d7b36021010e45ac27160dd7ead99c864a1b550c7edb1246950fe32dcc049799f9085287f0a747a6ef7a023df46a23a22f3e833bbf8d404f84344870492658256ee1dfc40fda33bb8d48fc72d4520ba9fc820c9123104a045206809037709f2a5f6723fa77d6bac5a573823d4ec3a7f1cb786a52ee2697e622e5d75962fa554d1024a6c355e21f33a63b2b72e6c4742a8b1c373aa532b40518c38c90b5373c2eb8c9d7be2a9e16047a3ee09dc9a6849deac5183ace6cfe91a9bef2ffc0a7df6ccebfd4c858c84b0e0355650d7466971e66f1e3883013e5ad1be33199b1d110b79070ac1b745ccb14cf63a08f8cca3a21c9525e626ff5f0c34746e10750fb742ad51f11f2acae3676c2111853d7250d01b77821a6ba9e04400ba2c543ca9f2d701ae6f47bfad14ffe3039ee9e71f7b2401359ade9938750ddb9c5a8b018a7929ed8d0e717ff1861446ce17535e9b17c187711190aae3388bd9490837a636c25ed4d42d7079ad1a51e13292c683d5d012abcf46965c534b83ab53f2c1f0cf5830ef7582e06863a33c19a70511df632885d63245965047ea96b56f1af5b3b94a54999f784fb9574fdfcd7c1230e07a2aaa04acd3097b2b9f8ddba05ae9734491deb5c1a513c76ed276cb78bbf4839dae3156d76af444a5805129d5df791167a9c8576a1d7f760b2d2797c4658669608706fbd0ace1be2346f74862dfc9ef518e55632e43c043186e5d070deb34d12fb9e5aba84e5cb50213dc88efd39cc35bf42455aa82d5e3b707b3140be3b8623b34fdd81d08615c188ae8438a13881fdf6bf32f2cb9ff5fa625561040c6b71d4b8eccc90bc3b99650d28dd1ee63773e49664e3d48c484996b290943635a6f2eb1ce9796d3fa144a3f00ef82faaa32d6a413668f7b521517cb68b2b017fcf56c79326fa5e4060e643631ca3f0a0dc0ed718798b6f46b130d437c33f64039e887324b6f5e604b1669d613923794edbf04b1b3caea54793b52b44b170173a4f25c7ecef3b71e2aad76e556b1cb9f1d637ec52ececfa950dd31dbb6a60828a3ad34c1beffe09eb4785786d63bad10a0b0f66ea88c57380f38ea85f018dbd7f538cf1ee7624095b9a01ec5edd528f281168af020609e651ff316aa1320a710134ddfca600cc72174dcdb846d2aa29916488aa1b537b66da92e61af526debef4eb38c984569eaf549ff2129449269b492d030cd74d885f6f5785881cc4804b4a8a09ba4ff7aefe9074ac7d0c4f05d51fe4cc0ff7388a772092b9d02d70e5433a5cf3e02f46a6bd6b818d59a07ce3b9fbbf8b5faba74563bcc5240930c2d406c9aaee3e3ce0429bf68ac2b0a57adb09414cff50817d2a48fb9fa624ab863cb0c31a8b8dc5eaf6fa68cc1d7c6c685c5a33edd5c8933b9e8ab628ee428d0743699b2ff17f25586c7ce959280bb0b8c5342251f0a30b53dbc7bf1ee426ac9619c3560f811f2268ee37f189794e2e4b3db3a2fb2e34b649e504fb467438abfd1082619cc4a0b30d66beb831077812e418d2e2148db10cf4d4a29101ca52ec445b8d83519dd7de85a98e0beae9ee537096d3f1a55a7a80cdfa93d25f07c9f98e8af18cde19ec1f99c5dd4588b717a5039ddb7f177717caf0d0fd45420a70dbd6d3146890d9e450d5224146db4c33b779e3c3a04b976c052bad042ac57dd38be45407808c0fb0d7e2a8819e6cd53c6739e6612996ddaa6f066552590aa0343bc1e62b298ff2514a0cef8be21956c2e942816f7a3a3a0935eaf9b37251409ce444c986c3817e82835555fe18239f3ae33469d7965c2bde9991fde556bd07af01df52bbde0c35bb4ef48e3b5d0db53f8ca4ed35b83f760f0a1bc4ed9f86e85d6039a17df373c85402ef956f01db00eb39c4b74bd0660d29ee746714d9780d738e05c6cca414ce3d7b40dda8036a9eea9ab1388805f913eb19bdd3f09d9e161eaa50231bd9caba61971f194332dd28c696a60458c1c6c2cc5da8b1192611c7c553e9e12fe48ce46bbb891be8bb118721c86222e671ddd1da8f0ccb2b68e02f2014b4925e904e88369aaf7466bd7033a60c265d45955944916ecbdb84bf1b522b01b0149c632e04c568a7eb627c5bb90ece052ebcf79166c28b30d23fe52da0a5ab5dea83ca479a3e3b7a9cfbbfea04dbe6137c19d067317c2ec427a8c75a6b06bec6dcd5d5c0edc9aa80b9003b8e17c088b2f3db327d3e42630d82d20120240c3ba56232280787da4aabbf5bc95a864029f00710e195f2a76460a0317d10b552fe1bea097e41d49756c680a41d6ac186e62169b6b6cd7776ea84618b5b752328a5bacaa10aa122ff9b2698b43efe73d852a899db644863c8c9bc8068ea86ea843fd6fe36272b91cdc5d5317083ef3fd1e5462a0b0d0604dc57b3bbfceb0fca4cd349625dd7b25166af30efe5ee6a0af953a74d65f4736c59918ee55a3b0d9d9d42e04c7f8a77e479109f740e20c464d5d7e3d16805f47b61f403ff7f408c9e850d9baacd8067e544536a4953480b0f9ee9cd45f41ebd67b51f78788a6470cb1e5ca72ca346ce8a50d0ca0c921d5576a4455a1afb6d0bc688004712ee122cacdb29c51e84893324c27fa4a3f1917edf5352272b4c97579a6152e4b77663d0ab532915f2eeb6a862de8b696452321b660c3f2449673d086e95a7af28845a5259b763e0fcd09f72acf7b6c811066263060e5aa5b24658e880a01fd56bda4dad5ab604e129290f7d5489728f2a40968c6168b21cebbbcd11727cc9e9160c4e92e04387d3b0d62aab06a61f26daedd9fed11816ef2180172a47f47184ac4032b88758c98a2e0fb200f70e93ba695f5ebb7a1029610ad360d3b7fa1b4640b9dc674d3625eef786da93dff19bc7991b5d6193a3896664763fde479b5dfc04812111a80782854f2cf68ca7d82765cc9eb40fba4b44640710ed6e653abf9f07b466333f4fd22784d53cf40e17120f42caa841eaa24056b237827b0f47f7257c103c35027e9f503e5acfd023e7357b600d3084d361d5ee65ba319b45c153212a54e6fed85af7e43e0a926ebcbc2edf8de7e2ec9528f00bec262ad04d5c9dafccaea06a24748d28bf1799bae0e895543084539c50b5aaa4fb50d7431d6f0c8cee2a54aaf7ee7919b55bf40adb688632e5dbe273cea09e97b19c3d8e1f4de000deb66fa1942ad03a62d3252f51992244366c156000b49c297167a6cbdedea7ebae139d295f0ad298e0864249b905b7eb812886ec70ecdb286702274b5b8574149bf3866f9e46b997ff5ed622b169a0eb071347f18d530db1663906a28f4544ee4e004ab87b65476af30ede118052ff052b8dc986ca2c93dd5d4943266a579c7698ea014f688b3e8063a107feb162d392e2177b01bff77fb5abe5feebd0607158049a5a093325b7c9ee6b4dfa7a9f65c7c2fb628920d3603a1c2dad979eaa047cd661a268af1078c9788d720e64e4ce9d12e68de1e417ef2f293323681e1071f9220e1ee43d2e29d111b870ce3439f5100ecd4551ab65ee74aa1667e564957e9bc0ae1ea193980da2a0ec2698073388c85bec25ef447f0d5e93a5203fa44dff268e5cb799ed3b66e63d5e07b487e7534f24934c73a62a243e0151843a0fd3807711a101eaa7fc71f0ba68aebb9534d57cba41b094eebfb4c31cca8eddfa426f676aa347be8a7023a4e91ddb154b35cd4d5f7dbc2e5db491de99f33fc2cff2d57029ac950e1ccd681980af6a4e8969dfe39b3c7bfcbcf8fac92f1e6ec9fe572bfa6a7d65860eab2ed10ac01a71290b52e3148e84b7376a8605cd2bb0e8681ffc54691ce087685e33921bd44d36c78291713dce17569570f62137e6904f0d68cf53aa2ec395c389a75141f08114fb293ea63950e4ffee55ec6fc83cf44876b8e7f25cdd393ff87b9eda6eb746085b61a6900de191f0ce2cb388d61ece52e78bc47368194e8e00277e0d1631e6b9d4626ef76f8522582ccd5a40be3febc699bb510acc6271d55ff0f4cf3bb7669855a72efd9ca3e1056a2fe592a5bc877cce2b1f63b58383971da87873d2d1349cf5881242cdce4e7e2c5c514755746a0e0a7c2a6d9701cde005ae3420beb17c379a3516662253554f51f0423bb1844b0b90c54ed8177ceb0e1036a6609d836e748ca06c40ca64befadc6443ec286a0ce464678e8d11eb455f7bb305acebf6cb1f50e394a9bfeb752df1687831bac9cdd811f4f112ef6658d0f8799a866374ff96c5e2b79f30e7a74f8a2bc9ed1f88f01f30e30cb78ffb2bff10108f35e910ee3be4463e9e6f0ed910e8d598326e71dfa2277ffe5579d7fe9b6018bfe295b25219eae07b3b0270665c3fa00c3e0d180812b5cd62925585de84a7c48a9a86dba96544a251654d1966e082432dc85b6149cf21e91a46020ec32b66d28ba3b6a90c0617bc6fdd55aea819af2bcf84864ad60c28fe3c9f8339d0aee68b39d97f63b6e082835d86119cf9b9fdc8b827c847ce40aa10e1577a710132316845e825345e95bdf94d0c66ec65a6c4319fce4792313663b5f7a651a6710783e6ab71608ac6cbbf3af6911adf596ccf7c172b9bd5bceb6db379967b32b143bdd11d2ee12ddf64ecef6391e0f8570e6cddd3db95204919362b89b739fa94e7c1bfde799fd5e22aa25ca6ca42e30c08e23aae2385d99ebab441072a880dcefdab74a4c9bd39d363f6d1933d59400fca161d432aa00f23b1b1c19a154be8989699d549b66d44e39896f5523443bc6ddf4a65e91f1f3fb7b52318869a05856a4fc92f3694c81ed833c972fb918f7e5\",\"cipherparams\":{\"iv\":\"8c46d6162cd4c765759aedcbce2a5874\"},\"kdf\":\"scrypt\",\"kdfparams\":{\"dklen\":32,\"n\":262144,\"p\":1,\"r\":8,\"salt\":\"82fb6cdc6917609135277badacf15baa31899d08b71a5a0fa33167167c161537\"},\"mac\":\"9187b17f7eca48e6b8c586b0cd790dbe0feb876ac8385f93faa7d5e22a3c8fc7\"},\"id\":\"92caf6ee-2d43-48c0-859e-ffa1e0e23312\",\"version\":3}";
|
|
16
16
|
const TEST_WALLET_PASSPHRASE = "QuantumCoinExample123!";
|