quantumcoin 7.0.9 → 7.0.11

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