quantumcoin 7.0.12 → 7.0.14
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 +828 -823
- package/README.md +4 -0
- package/config.d.ts +50 -50
- package/examples/example-generated-sdk-js/README.md +65 -0
- package/examples/example-generated-sdk-js/examples/_test-wallet.js +17 -0
- package/examples/example-generated-sdk-js/examples/deploy.js +41 -0
- package/examples/example-generated-sdk-js/examples/events.js +36 -0
- package/examples/example-generated-sdk-js/examples/read-operations.js +46 -0
- package/examples/example-generated-sdk-js/examples/write-operations.js +44 -0
- package/examples/example-generated-sdk-js/index.d.ts +1 -0
- package/examples/example-generated-sdk-js/index.js +15 -0
- package/examples/example-generated-sdk-js/package-lock.json +59 -0
- package/examples/example-generated-sdk-js/package.json +22 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20.d.ts +19 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20.js +353 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20__factory.d.ts +10 -0
- package/examples/example-generated-sdk-js/src/SimpleERC20__factory.js +29 -0
- package/examples/example-generated-sdk-js/src/index.d.ts +4 -0
- package/examples/example-generated-sdk-js/src/index.js +5 -0
- package/examples/example-generated-sdk-js/src/quantumcoin-shims.d.ts +23 -0
- package/examples/example-generated-sdk-js/src/types.d.ts +3 -0
- package/examples/example-generated-sdk-js/src/types.js +3 -0
- package/examples/example-generated-sdk-js/test/e2e/SimpleERC20.e2e.test.js +78 -0
- package/examples/example-generated-sdk-ts/README.md +65 -0
- package/examples/example-generated-sdk-ts/examples/_test-wallet.js +17 -0
- package/examples/example-generated-sdk-ts/examples/deploy.js +41 -0
- package/examples/example-generated-sdk-ts/examples/events.js +36 -0
- package/examples/example-generated-sdk-ts/examples/read-operations.js +46 -0
- package/examples/example-generated-sdk-ts/examples/write-operations.js +44 -0
- package/examples/example-generated-sdk-ts/index.d.ts +1 -0
- package/examples/example-generated-sdk-ts/index.js +15 -0
- package/examples/example-generated-sdk-ts/package-lock.json +59 -0
- package/examples/example-generated-sdk-ts/package.json +23 -0
- package/examples/example-generated-sdk-ts/src/SimpleERC20.ts +334 -0
- package/examples/example-generated-sdk-ts/src/SimpleERC20__factory.ts +28 -0
- package/examples/example-generated-sdk-ts/src/index.ts +4 -0
- package/examples/example-generated-sdk-ts/src/quantumcoin-shims.d.ts +23 -0
- package/examples/example-generated-sdk-ts/src/types.ts +4 -0
- package/examples/example-generated-sdk-ts/test/e2e/SimpleERC20.e2e.test.js +78 -0
- package/examples/example-generated-sdk-ts/tsconfig.json +14 -0
- package/examples/node_modules/.package-lock.json +5 -5
- package/examples/node_modules/quantum-coin-js-sdk/README.md +5 -5
- package/examples/node_modules/quantum-coin-js-sdk/example/package-lock.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/index.d.ts +1031 -1031
- package/examples/node_modules/quantum-coin-js-sdk/index.js +15 -15
- package/examples/node_modules/quantum-coin-js-sdk/package.json +1 -1
- package/examples/node_modules/quantum-coin-js-sdk/wasmBase64.js +2 -2
- package/examples/package-lock.json +6 -6
- package/examples/package.json +1 -1
- package/examples/sdk-generator-erc20.inline.json +251 -251
- package/generate-sdk.js +1845 -1822
- package/package.json +2 -2
- package/src/abi/fragments.d.ts +42 -42
- package/src/abi/index.d.ts +13 -13
- 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/contract/index.d.ts +9 -9
- package/src/errors/index.d.ts +92 -92
- package/src/generator/index.d.ts +11 -4
- package/src/generator/index.js +185 -18
- package/src/internal/hex.d.ts +68 -61
- package/src/internal/hex.js +36 -0
- package/src/providers/json-rpc-provider.d.ts +12 -12
- package/src/providers/provider.js +141 -8
- package/src/utils/address.d.ts +58 -58
- package/src/utils/encoding.d.ts +120 -120
- package/src/utils/hashing.js +298 -298
- package/src/utils/index.d.ts +63 -63
- package/src/utils/index.js +14 -14
- package/src/utils/result.d.ts +57 -57
- package/src/utils/rlp.d.ts +12 -12
- package/src/utils/rlp.js +13 -1
- package/src/utils/units.d.ts +29 -29
- package/src/wallet/index.d.ts +10 -10
- package/src/wallet/wallet.d.ts +192 -192
- package/src/wallet/wallet.js +713 -630
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/README.md +83 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.abi.json +12544 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/artifacts/AllSolidityTypes.bin +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.js +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.d.ts +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/index.js +21 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package-lock.json +597 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/package.json +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.d.ts +1280 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes.js +14021 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.d.ts +11 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/AllSolidityTypes__factory.js +31 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.d.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/index.js +5 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.d.ts +3 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/src/types.js +3 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-js/test/e2e/AllSolidityTypes.extra.test.js +195 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/README.md +83 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.abi.json +12544 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/artifacts/AllSolidityTypes.bin +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.js +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.d.ts +1 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/index.js +21 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package-lock.json +597 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/package.json +26 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes.ts +13940 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/AllSolidityTypes__factory.ts +31 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/index.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/src/types.ts +4 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.e2e.test.js +77 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/test/e2e/AllSolidityTypes.extra.test.js +195 -0
- package/test/e2e/generated-sdks/all-solidity-types/all-solidity-types-ts/tsconfig.json +18 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/README.md +74 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.abi.json +245 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/artifacts/SimpleERC20.bin +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.js +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.d.ts +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/index.js +16 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package-lock.json +597 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/package.json +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.d.ts +24 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20.js +378 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.d.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/SimpleERC20__factory.js +31 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.d.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/index.js +5 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.d.ts +3 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/src/types.js +3 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-js/test/e2e/SimpleERC20.e2e.test.js +90 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/README.md +74 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.abi.json +245 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/artifacts/SimpleERC20.bin +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.js +17 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/_test-wallet.ts +10 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.js +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/deploy.ts +41 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.js +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/events.ts +36 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.js +82 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/offline-signing.ts +80 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.js +46 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/read-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.js +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/examples/write-operations.ts +44 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.d.ts +1 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/index.js +16 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package-lock.json +597 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/package.json +26 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20.ts +361 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/SimpleERC20__factory.ts +30 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/index.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/quantumcoin-shims.d.ts +25 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/src/types.ts +4 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/test/e2e/SimpleERC20.e2e.test.js +90 -0
- package/test/e2e/generated-sdks/simple-erc20/simple-erc20-ts/tsconfig.json +18 -0
- package/test/e2e/generator-interface.e2e.test.js +165 -0
- package/test/e2e/generator-interface.e2e.test.ts +160 -0
- package/test/e2e/signing-context-and-fee.e2e.test.js +141 -141
- package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -128
- package/test/integration/provider.test.js +88 -88
- 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 +923 -892
- package/test/unit/address-wallet.test.ts +877 -877
- package/test/unit/encoding-units-rlp.test.js +35 -0
- package/test/unit/generator.test.js +48 -1
- package/test/unit/generator.test.ts +48 -1
- package/test/unit/hashing.test.js +64 -64
- package/test/unit/hashing.test.ts +63 -63
- package/test/unit/internal-hex.test.js +32 -1
- package/test/unit/internal-hex.test.ts +32 -1
- package/test/unit/populate-transaction.test.js +33 -0
- package/test/unit/providers.test.js +51 -1
- package/test/unit/providers.test.ts +53 -0
package/src/wallet/wallet.js
CHANGED
|
@@ -1,630 +1,713 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Wallet and signer implementations.
|
|
3
|
-
*
|
|
4
|
-
* The QuantumCoin.js wallet model mirrors ethers.js v6:
|
|
5
|
-
* - AbstractSigner -> BaseWallet -> Wallet
|
|
6
|
-
* - NonceManager wrapper
|
|
7
|
-
*
|
|
8
|
-
* Cryptographic operations are delegated to `quantum-coin-js-sdk`.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const qcsdk = require("quantum-coin-js-sdk");
|
|
12
|
-
const seedWords = require("seed-words");
|
|
13
|
-
const { JsonRpcProvider } = require("../providers/json-rpc-provider");
|
|
14
|
-
const { assertArgument, assertSecretArgument, makeError } = require("../errors");
|
|
15
|
-
const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex } = require("../internal/hex");
|
|
16
|
-
const { getAddress } = require("../utils/address");
|
|
17
|
-
const { WeiPerEther } = require("../constants");
|
|
18
|
-
|
|
19
|
-
function _requireInitialized() {
|
|
20
|
-
// eslint-disable-next-line global-require
|
|
21
|
-
const { isInitialized, getInitializationPromise } = require("../../config");
|
|
22
|
-
if (isInitialized()) return;
|
|
23
|
-
if (getInitializationPromise() != null) {
|
|
24
|
-
throw makeError(
|
|
25
|
-
"QuantumCoin SDK is still initializing. Await the Initialize() promise before using SDK methods.",
|
|
26
|
-
"UNKNOWN_ERROR",
|
|
27
|
-
{ operation: "requireInitialized" },
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
throw makeError("QuantumCoin SDK not initialized. Call Initialize() first.", "UNKNOWN_ERROR", { operation: "wallet" });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function _bytesToNumberArray(bytes) {
|
|
34
|
-
return Array.from(bytes);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
Object.defineProperty(this, "
|
|
140
|
-
enumerable: false,
|
|
141
|
-
configurable:
|
|
142
|
-
writable:
|
|
143
|
-
value:
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
if (
|
|
224
|
-
throw makeError("
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
return
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
* @
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
*
|
|
381
|
-
* @
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
*
|
|
515
|
-
* @
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
if (!
|
|
524
|
-
throw makeError("
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Wallet and signer implementations.
|
|
3
|
+
*
|
|
4
|
+
* The QuantumCoin.js wallet model mirrors ethers.js v6:
|
|
5
|
+
* - AbstractSigner -> BaseWallet -> Wallet
|
|
6
|
+
* - NonceManager wrapper
|
|
7
|
+
*
|
|
8
|
+
* Cryptographic operations are delegated to `quantum-coin-js-sdk`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const qcsdk = require("quantum-coin-js-sdk");
|
|
12
|
+
const seedWords = require("seed-words");
|
|
13
|
+
const { JsonRpcProvider } = require("../providers/json-rpc-provider");
|
|
14
|
+
const { assertArgument, assertSecretArgument, makeError } = require("../errors");
|
|
15
|
+
const { arrayify, bytesToHex, hexToBytes, isHexString, normalizeHex } = require("../internal/hex");
|
|
16
|
+
const { getAddress } = require("../utils/address");
|
|
17
|
+
const { WeiPerEther } = require("../constants");
|
|
18
|
+
|
|
19
|
+
function _requireInitialized() {
|
|
20
|
+
// eslint-disable-next-line global-require
|
|
21
|
+
const { isInitialized, getInitializationPromise } = require("../../config");
|
|
22
|
+
if (isInitialized()) return;
|
|
23
|
+
if (getInitializationPromise() != null) {
|
|
24
|
+
throw makeError(
|
|
25
|
+
"QuantumCoin SDK is still initializing. Await the Initialize() promise before using SDK methods.",
|
|
26
|
+
"UNKNOWN_ERROR",
|
|
27
|
+
{ operation: "requireInitialized" },
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
throw makeError("QuantumCoin SDK not initialized. Call Initialize() first.", "UNKNOWN_ERROR", { operation: "wallet" });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function _bytesToNumberArray(bytes) {
|
|
34
|
+
return Array.from(bytes);
|
|
35
|
+
}
|
|
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
|
+
|
|
63
|
+
const _maxSafeInt = 0x1fffffffffffffn; // 2^53 - 1
|
|
64
|
+
|
|
65
|
+
function _getBigInt(value, name) {
|
|
66
|
+
if (typeof value === "bigint") return value;
|
|
67
|
+
if (typeof value === "number") {
|
|
68
|
+
assertArgument(Number.isInteger(value), "underflow", name, value);
|
|
69
|
+
assertArgument(value >= -Number(_maxSafeInt) && value <= Number(_maxSafeInt), "overflow", name, value);
|
|
70
|
+
return BigInt(value);
|
|
71
|
+
}
|
|
72
|
+
if (typeof value === "string") {
|
|
73
|
+
if (value === "0x" || value === "0X") return 0n;
|
|
74
|
+
try { return BigInt(value); }
|
|
75
|
+
catch { assertArgument(false, "invalid BigNumberish string", name, value); }
|
|
76
|
+
}
|
|
77
|
+
assertArgument(false, "invalid BigNumberish", name, value);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function _getNumber(value, name) {
|
|
81
|
+
const bi = _getBigInt(value, name);
|
|
82
|
+
assertArgument(bi >= -_maxSafeInt && bi <= _maxSafeInt, "overflow", name, value);
|
|
83
|
+
return Number(bi);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* SigningKey wrapper (PQC private/public key bytes).
|
|
88
|
+
*/
|
|
89
|
+
class SigningKey {
|
|
90
|
+
/**
|
|
91
|
+
* @param {Uint8Array} privateKeyBytes
|
|
92
|
+
* @param {Uint8Array} publicKeyBytes
|
|
93
|
+
*/
|
|
94
|
+
constructor(privateKeyBytes, publicKeyBytes) {
|
|
95
|
+
Object.defineProperty(this, "privateKeyBytes", {
|
|
96
|
+
enumerable: false,
|
|
97
|
+
configurable: false,
|
|
98
|
+
writable: false,
|
|
99
|
+
value: new Uint8Array(privateKeyBytes),
|
|
100
|
+
});
|
|
101
|
+
this.publicKeyBytes = new Uint8Array(publicKeyBytes);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
toJSON() {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* AbstractSigner base (minimal).
|
|
111
|
+
*/
|
|
112
|
+
class AbstractSigner {
|
|
113
|
+
/**
|
|
114
|
+
* @param {import("../providers/provider").AbstractProvider|null} provider
|
|
115
|
+
*/
|
|
116
|
+
constructor(provider) {
|
|
117
|
+
this.provider = provider || null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async getAddress() {
|
|
121
|
+
throw makeError("getAddress not implemented", "NOT_IMPLEMENTED", {});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* BaseWallet - core signing implementation.
|
|
127
|
+
*/
|
|
128
|
+
class BaseWallet extends AbstractSigner {
|
|
129
|
+
/**
|
|
130
|
+
* @param {SigningKey} signingKey
|
|
131
|
+
* @param {import("../providers/provider").AbstractProvider|null=} provider
|
|
132
|
+
* @param {{ address: string }=} precomputed
|
|
133
|
+
* @param {any=} qcWallet Internal quantum-coin-js-sdk Wallet (optional)
|
|
134
|
+
*/
|
|
135
|
+
constructor(signingKey, provider, precomputed, qcWallet) {
|
|
136
|
+
super(provider || null);
|
|
137
|
+
_requireInitialized();
|
|
138
|
+
|
|
139
|
+
Object.defineProperty(this, "signingKey", {
|
|
140
|
+
enumerable: false,
|
|
141
|
+
configurable: false,
|
|
142
|
+
writable: false,
|
|
143
|
+
value: signingKey,
|
|
144
|
+
});
|
|
145
|
+
Object.defineProperty(this, "_qcWallet", {
|
|
146
|
+
enumerable: false,
|
|
147
|
+
configurable: true,
|
|
148
|
+
writable: true,
|
|
149
|
+
value: qcWallet || null,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/** @type {string} */
|
|
153
|
+
this.address = precomputed?.address || "";
|
|
154
|
+
|
|
155
|
+
Object.defineProperty(this, "privateKey", {
|
|
156
|
+
enumerable: false,
|
|
157
|
+
get: () => bytesToHex(this.signingKey.privateKeyBytes),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
Object.defineProperty(this, "publicKey", {
|
|
161
|
+
enumerable: true,
|
|
162
|
+
get: () => bytesToHex(this.signingKey.publicKeyBytes),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
Object.defineProperty(this, "_seed", {
|
|
166
|
+
enumerable: false,
|
|
167
|
+
configurable: true,
|
|
168
|
+
writable: true,
|
|
169
|
+
value: null,
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
Object.defineProperty(this, "seed", {
|
|
173
|
+
enumerable: false,
|
|
174
|
+
get: () => this._seed,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
toJSON() {
|
|
179
|
+
return { address: this.address };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async getAddress() {
|
|
183
|
+
return this.address;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Sign a transaction using quantum-coin-js-sdk signRawTransaction().
|
|
188
|
+
* @param {import("../providers/provider").TransactionRequest} tx
|
|
189
|
+
* @returns {Promise<string>}
|
|
190
|
+
*/
|
|
191
|
+
async signTransaction(tx) {
|
|
192
|
+
const { raw } = await this._signDetailed(tx);
|
|
193
|
+
return raw;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Internal: sign a transaction and return both the raw serialized transaction
|
|
198
|
+
* and the signer-computed transaction hash. The hash is later used to
|
|
199
|
+
* verify that an untrusted RPC node broadcast exactly the transaction we
|
|
200
|
+
* signed rather than substituting a different one.
|
|
201
|
+
* @param {import("../providers/provider").TransactionRequest} tx
|
|
202
|
+
* @returns {Promise<{ raw: string, hash: string|null }>}
|
|
203
|
+
*/
|
|
204
|
+
async _signDetailed(tx) {
|
|
205
|
+
_requireInitialized();
|
|
206
|
+
assertArgument(tx && typeof tx === "object", "invalid tx", "tx", tx);
|
|
207
|
+
|
|
208
|
+
const toAddress = tx.to == null ? null : getAddress(tx.to);
|
|
209
|
+
const valueInWei = tx.value == null ? 0n : _getBigInt(tx.value, "tx.value");
|
|
210
|
+
const gasLimit = tx.gasLimit == null ? 21000 : _getNumber(tx.gasLimit, "tx.gasLimit");
|
|
211
|
+
|
|
212
|
+
const data = tx.data == null ? null : normalizeHex(tx.data);
|
|
213
|
+
const remarks = tx.remarks == null ? null : normalizeHex(tx.remarks);
|
|
214
|
+
|
|
215
|
+
if (remarks != null) {
|
|
216
|
+
assertArgument(isHexString(remarks), "remarks must be hex string", "remarks", remarks);
|
|
217
|
+
const remarkBytes = hexToBytes(remarks);
|
|
218
|
+
assertArgument(remarkBytes.length <= 32, "remarks too long (max 32 bytes)", "remarks", remarks);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Nonce must be provided or resolved from provider.
|
|
222
|
+
let nonce = tx.nonce;
|
|
223
|
+
if (nonce == null) {
|
|
224
|
+
if (!this.provider) throw makeError("missing provider to resolve nonce", "UNKNOWN_ERROR", { operation: "signTransaction" });
|
|
225
|
+
// Prefer pending to avoid nonce collisions with in-flight transactions.
|
|
226
|
+
try {
|
|
227
|
+
nonce = await this.provider.getTransactionCount(this.address, "pending");
|
|
228
|
+
} catch {
|
|
229
|
+
nonce = await this.provider.getTransactionCount(this.address, "latest");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
assertArgument(Number.isInteger(nonce) && nonce >= 0, "invalid nonce", "nonce", nonce);
|
|
233
|
+
|
|
234
|
+
// `chainId` remains accepted from the tx (e.g. via contract overrides). We
|
|
235
|
+
// intentionally do NOT assert it against the
|
|
236
|
+
// provider here because `chainId` in quantum-coin-js-sdk (qcsdk) defaults to
|
|
237
|
+
// 123123 internally — an unset chainId resolves to that network default rather
|
|
238
|
+
// than being left unbound. Cross-chain replay risk is therefore bounded by the
|
|
239
|
+
// qcsdk default; explicit per-call chainId overrides are caller responsibility.
|
|
240
|
+
const chainId = tx.chainId != null ? tx.chainId : (this.provider && this.provider.chainId != null ? this.provider.chainId : null);
|
|
241
|
+
const signingContext = tx.signingContext ?? null;
|
|
242
|
+
|
|
243
|
+
// chainId is mandatory for signing. Without it the signed transaction is
|
|
244
|
+
// not bound to a network and can be replayed on a different chain. Online
|
|
245
|
+
// flows resolve chainId from the connected provider; offline signing must
|
|
246
|
+
// pass tx.chainId explicitly.
|
|
247
|
+
let chainIdNum = null;
|
|
248
|
+
try {
|
|
249
|
+
chainIdNum = chainId == null ? null : _getNumber(chainId, "tx.chainId");
|
|
250
|
+
} catch {
|
|
251
|
+
chainIdNum = null;
|
|
252
|
+
}
|
|
253
|
+
assertArgument(
|
|
254
|
+
chainIdNum != null && chainIdNum >= 0,
|
|
255
|
+
"chainId is required for signing; pass tx.chainId or connect to a provider",
|
|
256
|
+
"chainId",
|
|
257
|
+
chainId,
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
/** @type {any} */
|
|
261
|
+
const qcWallet =
|
|
262
|
+
this._qcWallet ||
|
|
263
|
+
new qcsdk.Wallet(
|
|
264
|
+
this.address,
|
|
265
|
+
_bytesToNumberArray(this.signingKey.privateKeyBytes),
|
|
266
|
+
_bytesToNumberArray(this.signingKey.publicKeyBytes),
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
const req = new qcsdk.TransactionSigningRequest(
|
|
270
|
+
qcWallet,
|
|
271
|
+
toAddress,
|
|
272
|
+
valueInWei,
|
|
273
|
+
nonce,
|
|
274
|
+
data,
|
|
275
|
+
gasLimit,
|
|
276
|
+
remarks,
|
|
277
|
+
chainId,
|
|
278
|
+
signingContext,
|
|
279
|
+
);
|
|
280
|
+
const signResult = qcsdk.signRawTransaction(req);
|
|
281
|
+
// quantum-coin-js-sdk returns a SignResult object: { resultCode, txnHash, txnData }
|
|
282
|
+
if (!signResult || typeof signResult !== "object") {
|
|
283
|
+
throw makeError("signRawTransaction failed", "UNKNOWN_ERROR", {});
|
|
284
|
+
}
|
|
285
|
+
if (typeof signResult.resultCode === "number" && signResult.resultCode !== 0) {
|
|
286
|
+
throw makeError("signRawTransaction failed", "UNKNOWN_ERROR", {
|
|
287
|
+
resultCode: signResult.resultCode,
|
|
288
|
+
hash: signResult.txnHash || null,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
const raw = signResult.txnData;
|
|
292
|
+
if (typeof raw !== "string") throw makeError("signRawTransaction did not return txnData", "UNKNOWN_ERROR", {});
|
|
293
|
+
let hash = null;
|
|
294
|
+
if (typeof signResult.txnHash === "string" && signResult.txnHash.length > 0) {
|
|
295
|
+
hash = normalizeHex(signResult.txnHash).toLowerCase();
|
|
296
|
+
}
|
|
297
|
+
return { raw: normalizeHex(raw), hash };
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Signs and sends a transaction.
|
|
302
|
+
* @param {import("../providers/provider").TransactionRequest} tx
|
|
303
|
+
* @returns {Promise<import("../providers/provider").TransactionResponse>}
|
|
304
|
+
*/
|
|
305
|
+
async sendTransaction(tx) {
|
|
306
|
+
if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "sendTransaction" });
|
|
307
|
+
const { raw, hash } = await this._signDetailed({ ...tx, from: this.address });
|
|
308
|
+
// Tell the provider which hash we expect so it can reject a node that
|
|
309
|
+
// broadcasts (or echoes back) a different transaction than the one we signed.
|
|
310
|
+
return this.provider.sendTransaction(raw, hash ? { expectedHash: hash } : undefined);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Wallet - convenience methods around BaseWallet.
|
|
316
|
+
*/
|
|
317
|
+
class Wallet extends BaseWallet {
|
|
318
|
+
/**
|
|
319
|
+
* @param {string|Uint8Array|SigningKey} key
|
|
320
|
+
* @param {import("../providers/provider").AbstractProvider=} provider
|
|
321
|
+
*/
|
|
322
|
+
constructor(key, provider) {
|
|
323
|
+
_requireInitialized();
|
|
324
|
+
|
|
325
|
+
let signingKey;
|
|
326
|
+
let qcAddress;
|
|
327
|
+
|
|
328
|
+
if (key instanceof SigningKey) {
|
|
329
|
+
signingKey = key;
|
|
330
|
+
// Compute address from public key
|
|
331
|
+
const addr = qcsdk.addressFromPublicKey(_bytesToNumberArray(signingKey.publicKeyBytes));
|
|
332
|
+
if (typeof addr !== "string") throw makeError("addressFromPublicKey failed", "UNKNOWN_ERROR", {});
|
|
333
|
+
qcAddress = normalizeHex(addr);
|
|
334
|
+
} else {
|
|
335
|
+
const privBytes = typeof key === "string" ? hexToBytes(key) : arrayify(key);
|
|
336
|
+
const pubHex = qcsdk.publicKeyFromPrivateKey(_bytesToNumberArray(privBytes));
|
|
337
|
+
if (typeof pubHex !== "string") throw makeError("publicKeyFromPrivateKey failed", "UNKNOWN_ERROR", {});
|
|
338
|
+
const pubBytes = hexToBytes(pubHex);
|
|
339
|
+
const addr = qcsdk.addressFromPublicKey(_bytesToNumberArray(pubBytes));
|
|
340
|
+
if (typeof addr !== "string") throw makeError("addressFromPublicKey failed", "UNKNOWN_ERROR", {});
|
|
341
|
+
qcAddress = normalizeHex(addr);
|
|
342
|
+
signingKey = new SigningKey(privBytes, pubBytes);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** @type {any} */
|
|
346
|
+
const qcWallet = new qcsdk.Wallet(
|
|
347
|
+
qcAddress,
|
|
348
|
+
_bytesToNumberArray(signingKey.privateKeyBytes),
|
|
349
|
+
_bytesToNumberArray(signingKey.publicKeyBytes),
|
|
350
|
+
);
|
|
351
|
+
|
|
352
|
+
// Central choke point — every Wallet (createRandom/fromPhrase/fromSeed/
|
|
353
|
+
// fromEncryptedJsonSync/fromKeys/connect all funnel through this constructor)
|
|
354
|
+
// is verified for key-pair consistency before it can be used to sign.
|
|
355
|
+
_assertKeyPairValid(signingKey.privateKeyBytes, signingKey.publicKeyBytes);
|
|
356
|
+
|
|
357
|
+
super(signingKey, provider || null, { address: qcAddress }, qcWallet);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Returns wallet address (sync).
|
|
362
|
+
* @returns {string}
|
|
363
|
+
*/
|
|
364
|
+
getAddress() {
|
|
365
|
+
return this.address;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Returns wallet balance.
|
|
370
|
+
* @param {string=} blockTag
|
|
371
|
+
* @returns {Promise<bigint>}
|
|
372
|
+
*/
|
|
373
|
+
async getBalance(blockTag) {
|
|
374
|
+
if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "getBalance" });
|
|
375
|
+
void blockTag;
|
|
376
|
+
return this.provider.getBalance(this.address);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Returns wallet nonce.
|
|
381
|
+
* @param {string=} blockTag
|
|
382
|
+
* @returns {Promise<number>}
|
|
383
|
+
*/
|
|
384
|
+
async getTransactionCount(blockTag) {
|
|
385
|
+
if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "getTransactionCount" });
|
|
386
|
+
return this.provider.getTransactionCount(this.address, blockTag);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Encrypts and serializes this wallet to JSON.
|
|
391
|
+
* @param {string|Uint8Array} password
|
|
392
|
+
* @returns {string}
|
|
393
|
+
*/
|
|
394
|
+
encryptSync(password) {
|
|
395
|
+
_requireInitialized();
|
|
396
|
+
if (this._seed != null) {
|
|
397
|
+
return Wallet.encryptSeedSync(hexToBytes(this._seed), password);
|
|
398
|
+
}
|
|
399
|
+
// A Uint8Array password is decoded as UTF-8 with NFC normalization below.
|
|
400
|
+
// For arbitrary (non-UTF-8) byte passwords this is
|
|
401
|
+
// lossy — invalid sequences become U+FFFD — so a binary password may not
|
|
402
|
+
// round-trip and the keystore could fail to reopen. This is intentionally left
|
|
403
|
+
// as-is because the password->key mapping is part of the shared QuantumCoin
|
|
404
|
+
// keystore format owned by qcsdk (and interoperable with the Desktop/Mobile/Web
|
|
405
|
+
// /CLI wallets); changing it risks breaking existing keystores and cross-app
|
|
406
|
+
// interop. Prefer string passphrases. (Fixing correctly requires a keystore-spec
|
|
407
|
+
// decision, not a local change.)
|
|
408
|
+
const pw = typeof password === "string"
|
|
409
|
+
? password.normalize("NFC")
|
|
410
|
+
: Buffer.from(arrayify(password)).toString("utf8").normalize("NFC");
|
|
411
|
+
assertSecretArgument(pw.length >= 12, "password must be at least 12 characters", "password");
|
|
412
|
+
const json = qcsdk.serializeEncryptedWallet(this._qcWallet, pw);
|
|
413
|
+
if (typeof json !== "string") throw makeError("serializeEncryptedWallet failed", "UNKNOWN_ERROR", {});
|
|
414
|
+
return json;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Encrypts raw seed bytes into a wallet JSON string (version 5 pre-expansion format).
|
|
419
|
+
* The resulting JSON can be opened with `Wallet.fromEncryptedJsonSync()` or
|
|
420
|
+
* Desktop/Mobile/Web/CLI wallet applications.
|
|
421
|
+
* @param {number[]|Uint8Array} seed Raw seed bytes: 64 (keyType 3), 72 (keyType 5), or 96 (legacy)
|
|
422
|
+
* @param {string|Uint8Array} password Passphrase (at least 12 characters)
|
|
423
|
+
* @returns {string}
|
|
424
|
+
*/
|
|
425
|
+
static encryptSeedSync(seed, password) {
|
|
426
|
+
_requireInitialized();
|
|
427
|
+
const seedArr = seed instanceof Uint8Array ? Array.from(seed) : seed;
|
|
428
|
+
assertArgument(Array.isArray(seedArr), "seed must be an array of numbers or Uint8Array", "seed", seed);
|
|
429
|
+
const allowedLengths = [64, 72, 96];
|
|
430
|
+
assertArgument(allowedLengths.includes(seedArr.length), "seed must be 64, 72, or 96 bytes", "seed", seedArr.length);
|
|
431
|
+
// See encryptSync — a Uint8Array password is decoded as UTF-8/NFC, which is
|
|
432
|
+
// lossy for arbitrary byte passwords. Left as-is
|
|
433
|
+
// because the password->key mapping is part of the shared qcsdk keystore format
|
|
434
|
+
// (cross-app interop); prefer string passphrases.
|
|
435
|
+
const pw = typeof password === "string"
|
|
436
|
+
? password.normalize("NFC")
|
|
437
|
+
: Buffer.from(arrayify(password)).toString("utf8").normalize("NFC");
|
|
438
|
+
assertSecretArgument(pw.length >= 12, "password must be at least 12 characters", "password");
|
|
439
|
+
const json = qcsdk.serializeSeedAsEncryptedWallet(seedArr, pw);
|
|
440
|
+
if (typeof json !== "string") throw makeError("serializeSeedAsEncryptedWallet failed", "UNKNOWN_ERROR", {});
|
|
441
|
+
return json;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Returns the seed phrase (list of words) if this wallet has a seed, else null.
|
|
446
|
+
* Derived from the stored pre-expansion seed via seed-words.getWordListFromSeedArray.
|
|
447
|
+
*
|
|
448
|
+
* Non-null for wallets created via createRandom, fromPhrase, fromSeed, and
|
|
449
|
+
* fromEncryptedJsonSync when the JSON is a version-5 keystore produced by
|
|
450
|
+
* encryptSync on a seed-bearing wallet or by encryptSeedSync.
|
|
451
|
+
* Null for fromKeys and for v3/v4 keystores without preExpansionSeed.
|
|
452
|
+
*
|
|
453
|
+
* @returns {string[]|null}
|
|
454
|
+
*/
|
|
455
|
+
getPhrase() {
|
|
456
|
+
_requireInitialized();
|
|
457
|
+
if (this._seed == null) return null;
|
|
458
|
+
const bytes = Array.from(hexToBytes(this._seed));
|
|
459
|
+
const words = seedWords.getWordListFromSeedArray(bytes);
|
|
460
|
+
return Array.isArray(words) ? words : null;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Returns the recommended signing context for this wallet.
|
|
465
|
+
* Setting fullSign to true may incur additional gas cost.
|
|
466
|
+
* @param {boolean|null=} fullSign Defaults to false when null or omitted.
|
|
467
|
+
* @returns {number}
|
|
468
|
+
*/
|
|
469
|
+
getSigningContext(fullSign) {
|
|
470
|
+
const fs = fullSign ?? false;
|
|
471
|
+
const pubLen = this.signingKey.publicKeyBytes.length;
|
|
472
|
+
if (pubLen === 1408) {
|
|
473
|
+
return fs ? 2 : 0;
|
|
474
|
+
}
|
|
475
|
+
if (pubLen === 2688) {
|
|
476
|
+
return 1;
|
|
477
|
+
}
|
|
478
|
+
throw makeError("unsupported public key size", "UNSUPPORTED_OPERATION", { publicKeyLength: pubLen });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Returns a new wallet connected to a provider.
|
|
483
|
+
* @param {import("../providers/provider").AbstractProvider} provider
|
|
484
|
+
* @returns {Wallet}
|
|
485
|
+
*/
|
|
486
|
+
connect(provider) {
|
|
487
|
+
const w = new Wallet(this.signingKey, provider);
|
|
488
|
+
w._qcWallet = this._qcWallet;
|
|
489
|
+
w._seed = this._seed;
|
|
490
|
+
return w;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* Creates a new random wallet.
|
|
495
|
+
* @param {import("../providers/provider").AbstractProvider=} provider
|
|
496
|
+
* @param {number|null=} keyType Optional key type: null (default=3), 3, or 5
|
|
497
|
+
* @returns {Wallet}
|
|
498
|
+
*/
|
|
499
|
+
static createRandom(provider, keyType) {
|
|
500
|
+
_requireInitialized();
|
|
501
|
+
if (keyType != null) {
|
|
502
|
+
assertArgument(keyType === 3 || keyType === 5, "keyType must be null, 3, or 5", "keyType", keyType);
|
|
503
|
+
}
|
|
504
|
+
const words = qcsdk.newWalletSeedWords(keyType ?? null);
|
|
505
|
+
if (!words || !Array.isArray(words)) {
|
|
506
|
+
throw makeError("newWalletSeedWords failed", "UNKNOWN_ERROR", { result: words });
|
|
507
|
+
}
|
|
508
|
+
return Wallet.fromPhrase(words, provider);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Creates a wallet from raw seed bytes.
|
|
513
|
+
* @param {number[]} seed Raw seed bytes: 64 (keyType 3), 72 (keyType 5), or 96 (legacy)
|
|
514
|
+
* @param {import("../providers/provider").AbstractProvider=} provider
|
|
515
|
+
* @returns {Wallet}
|
|
516
|
+
*/
|
|
517
|
+
static fromSeed(seed, provider) {
|
|
518
|
+
_requireInitialized();
|
|
519
|
+
assertArgument(Array.isArray(seed), "seed must be an array of numbers", "seed", seed);
|
|
520
|
+
const allowedLengths = [64, 72, 96];
|
|
521
|
+
assertArgument(allowedLengths.includes(seed.length), "seed must be 64, 72, or 96 bytes", "seed", seed.length);
|
|
522
|
+
const qcWallet = qcsdk.openWalletFromSeed(seed);
|
|
523
|
+
if (!qcWallet || typeof qcWallet === "number") {
|
|
524
|
+
throw makeError("openWalletFromSeed failed", "UNKNOWN_ERROR", { result: qcWallet });
|
|
525
|
+
}
|
|
526
|
+
return Wallet._fromQcWallet(qcWallet, provider || null);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Creates a wallet from an encrypted JSON string.
|
|
531
|
+
* @param {string} json
|
|
532
|
+
* @param {string} password
|
|
533
|
+
* @param {import("../providers/provider").AbstractProvider=} provider
|
|
534
|
+
* @returns {Wallet}
|
|
535
|
+
*/
|
|
536
|
+
static fromEncryptedJsonSync(json, password, provider) {
|
|
537
|
+
_requireInitialized();
|
|
538
|
+
const qcWallet = qcsdk.deserializeEncryptedWallet(json, password);
|
|
539
|
+
if (!qcWallet) throw makeError("deserializeEncryptedWallet failed", "UNKNOWN_ERROR", {});
|
|
540
|
+
return Wallet._fromQcWallet(qcWallet, provider || null);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Creates a wallet from a seed phrase (32, 36, or 48 words).
|
|
545
|
+
* @param {string|string[]} phrase
|
|
546
|
+
* @param {import("../providers/provider").AbstractProvider=} provider
|
|
547
|
+
* @returns {Wallet}
|
|
548
|
+
*/
|
|
549
|
+
static fromPhrase(phrase, provider) {
|
|
550
|
+
_requireInitialized();
|
|
551
|
+
let words = phrase;
|
|
552
|
+
if (typeof phrase === "string") {
|
|
553
|
+
words = phrase
|
|
554
|
+
.split(/[,\s]+/g)
|
|
555
|
+
.map((w) => w.trim())
|
|
556
|
+
.filter(Boolean);
|
|
557
|
+
}
|
|
558
|
+
assertArgument(Array.isArray(words), "phrase must be a string or string[]", "phrase", phrase);
|
|
559
|
+
const allowedLengths = [32, 36, 48];
|
|
560
|
+
assertArgument(
|
|
561
|
+
allowedLengths.includes(words.length),
|
|
562
|
+
"seed phrase must contain 32, 36, or 48 words",
|
|
563
|
+
"phrase",
|
|
564
|
+
words.length,
|
|
565
|
+
);
|
|
566
|
+
const qcWallet = qcsdk.openWalletFromSeedWords(words);
|
|
567
|
+
if (!qcWallet) throw makeError("openWalletFromSeedWords failed", "UNKNOWN_ERROR", {});
|
|
568
|
+
return Wallet._fromQcWallet(qcWallet, provider || null);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Creates a wallet from raw private and public key bytes.
|
|
573
|
+
* @param {Uint8Array|string} privateKey Private key bytes or hex string
|
|
574
|
+
* @param {Uint8Array|string} publicKey Public key bytes or hex string
|
|
575
|
+
* @param {import("../providers/provider").AbstractProvider=} provider
|
|
576
|
+
* @returns {Wallet}
|
|
577
|
+
*/
|
|
578
|
+
static fromKeys(privateKey, publicKey, provider) {
|
|
579
|
+
_requireInitialized();
|
|
580
|
+
const privBytes = typeof privateKey === "string" ? hexToBytes(privateKey) : arrayify(privateKey);
|
|
581
|
+
const pubBytes = typeof publicKey === "string" ? hexToBytes(publicKey) : arrayify(publicKey);
|
|
582
|
+
assertSecretArgument(privBytes.length > 0, "privateKey must not be empty", "privateKey");
|
|
583
|
+
assertSecretArgument(pubBytes.length > 0, "publicKey must not be empty", "publicKey");
|
|
584
|
+
|
|
585
|
+
const privArr = _bytesToNumberArray(privBytes);
|
|
586
|
+
const pubArr = _bytesToNumberArray(pubBytes);
|
|
587
|
+
const addr = qcsdk.addressFromPublicKey(pubArr);
|
|
588
|
+
if (typeof addr !== "string") throw makeError("addressFromPublicKey failed", "UNKNOWN_ERROR", {});
|
|
589
|
+
|
|
590
|
+
const qcWallet = new qcsdk.Wallet(addr, privArr, pubArr);
|
|
591
|
+
// Key-pair verification now happens centrally in the Wallet constructor
|
|
592
|
+
// (reached via _fromQcWallet -> new Wallet). No redundant verify here.
|
|
593
|
+
return Wallet._fromQcWallet(qcWallet, provider || null);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Internal helper: build a Wallet from a quantum-coin-js-sdk Wallet object.
|
|
598
|
+
* @param {any} qcWallet
|
|
599
|
+
* @param {import("../providers/provider").AbstractProvider|null} provider
|
|
600
|
+
* @returns {Wallet}
|
|
601
|
+
*/
|
|
602
|
+
static _fromQcWallet(qcWallet, provider) {
|
|
603
|
+
const privSrc = qcWallet.privateKey;
|
|
604
|
+
const pubSrc = qcWallet.publicKey;
|
|
605
|
+
|
|
606
|
+
if (!privSrc || (privSrc instanceof Uint8Array && privSrc.length === 0) || (Array.isArray(privSrc) && privSrc.length === 0)) {
|
|
607
|
+
throw makeError("qcWallet.privateKey is empty or missing", "UNKNOWN_ERROR", {});
|
|
608
|
+
}
|
|
609
|
+
if (!pubSrc || (pubSrc instanceof Uint8Array && pubSrc.length === 0) || (Array.isArray(pubSrc) && pubSrc.length === 0)) {
|
|
610
|
+
throw makeError("qcWallet.publicKey is empty or missing", "UNKNOWN_ERROR", {});
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const privBytes =
|
|
614
|
+
privSrc instanceof Uint8Array ? new Uint8Array(privSrc) : Uint8Array.from(Array.from(privSrc).map((n) => (Number(n) & 0xff)));
|
|
615
|
+
const pubBytes =
|
|
616
|
+
pubSrc instanceof Uint8Array ? new Uint8Array(pubSrc) : Uint8Array.from(Array.from(pubSrc).map((n) => (Number(n) & 0xff)));
|
|
617
|
+
const key = new SigningKey(privBytes, pubBytes);
|
|
618
|
+
|
|
619
|
+
const w = new Wallet(key, provider || null);
|
|
620
|
+
// Ensure we keep the exact underlying qcWallet for operations like encrypt/signRawTransaction.
|
|
621
|
+
w._qcWallet = qcWallet;
|
|
622
|
+
if (typeof qcWallet.address === "string") {
|
|
623
|
+
w.address = normalizeHex(qcWallet.address);
|
|
624
|
+
}
|
|
625
|
+
if (qcWallet.preExpansionSeed != null) {
|
|
626
|
+
const seedSrc = qcWallet.preExpansionSeed;
|
|
627
|
+
const seedBytes =
|
|
628
|
+
seedSrc instanceof Uint8Array ? seedSrc : Uint8Array.from(Array.from(seedSrc).map((n) => (Number(n) & 0xff)));
|
|
629
|
+
w._seed = bytesToHex(seedBytes);
|
|
630
|
+
}
|
|
631
|
+
return w;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* NonceManager wrapper.
|
|
637
|
+
*/
|
|
638
|
+
class NonceManager extends AbstractSigner {
|
|
639
|
+
/**
|
|
640
|
+
* @param {AbstractSigner} signer
|
|
641
|
+
*/
|
|
642
|
+
constructor(signer) {
|
|
643
|
+
super(signer.provider || null);
|
|
644
|
+
this.signer = signer;
|
|
645
|
+
this._nonce = null;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
async getAddress() {
|
|
649
|
+
return this.signer.getAddress();
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
async getTransactionCount(blockTag) {
|
|
653
|
+
if (this._nonce != null) return this._nonce;
|
|
654
|
+
if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "getTransactionCount" });
|
|
655
|
+
const address = await this.getAddress();
|
|
656
|
+
this._nonce = await this.provider.getTransactionCount(address, blockTag);
|
|
657
|
+
return this._nonce;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
async sendTransaction(tx) {
|
|
661
|
+
const nonce = await this.getTransactionCount("latest");
|
|
662
|
+
const result = await this.signer.sendTransaction({ ...tx, nonce });
|
|
663
|
+
this._nonce = nonce + 1;
|
|
664
|
+
return result;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
reset() {
|
|
668
|
+
this._nonce = null;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
increment() {
|
|
672
|
+
if (this._nonce == null) this._nonce = 0;
|
|
673
|
+
this._nonce++;
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/**
|
|
678
|
+
* JsonRpcSigner placeholder (ethers-like).
|
|
679
|
+
* This SDK encourages using Wallet directly for signing.
|
|
680
|
+
*/
|
|
681
|
+
class JsonRpcSigner extends AbstractSigner {
|
|
682
|
+
constructor(provider, address) {
|
|
683
|
+
super(provider);
|
|
684
|
+
this._address = address;
|
|
685
|
+
}
|
|
686
|
+
async getAddress() {
|
|
687
|
+
return this._address;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* VoidSigner (cannot sign, only provides address).
|
|
693
|
+
*/
|
|
694
|
+
class VoidSigner extends AbstractSigner {
|
|
695
|
+
constructor(address, provider) {
|
|
696
|
+
super(provider || null);
|
|
697
|
+
this._address = getAddress(address);
|
|
698
|
+
}
|
|
699
|
+
async getAddress() {
|
|
700
|
+
return this._address;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
module.exports = {
|
|
705
|
+
SigningKey,
|
|
706
|
+
AbstractSigner,
|
|
707
|
+
BaseWallet,
|
|
708
|
+
Wallet,
|
|
709
|
+
NonceManager,
|
|
710
|
+
JsonRpcSigner,
|
|
711
|
+
VoidSigner,
|
|
712
|
+
};
|
|
713
|
+
|