quantumcoin 7.0.3 → 7.0.5

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 (155) hide show
  1. package/.github/workflows/publish-npmjs.yaml +22 -22
  2. package/.gitignore +15 -15
  3. package/LICENSE +21 -21
  4. package/README-SDK.md +758 -754
  5. package/README.md +165 -150
  6. package/SPEC.md +3845 -3843
  7. package/config.d.ts +50 -50
  8. package/config.js +115 -115
  9. package/examples/AllSolidityTypes.sol +184 -184
  10. package/examples/SimpleIERC20.sol +74 -74
  11. package/examples/events.js +41 -35
  12. package/examples/events.ts +35 -0
  13. package/examples/example-generator-sdk-js.js +100 -95
  14. package/examples/example-generator-sdk-js.ts +77 -0
  15. package/examples/example-generator-sdk-ts.js +100 -95
  16. package/examples/example-generator-sdk-ts.ts +77 -0
  17. package/examples/example.js +72 -61
  18. package/examples/example.ts +61 -0
  19. package/examples/offline-signing.js +79 -73
  20. package/examples/offline-signing.ts +66 -0
  21. package/examples/package-lock.json +596 -57
  22. package/examples/package.json +32 -16
  23. package/examples/read-operations.js +32 -27
  24. package/examples/read-operations.ts +31 -0
  25. package/examples/sdk-generator-erc20.inline.json +251 -251
  26. package/examples/solidity-types.ts +43 -43
  27. package/examples/wallet-offline.js +35 -29
  28. package/examples/wallet-offline.ts +34 -0
  29. package/generate-sdk.js +1824 -1490
  30. package/index.js +12 -12
  31. package/package.json +95 -75
  32. package/scripts/copy-declarations.js +31 -0
  33. package/scripts/run-all-one-by-one.js +151 -0
  34. package/src/abi/fragments.d.ts +42 -42
  35. package/src/abi/fragments.js +63 -63
  36. package/src/abi/index.d.ts +13 -13
  37. package/src/abi/index.js +9 -9
  38. package/src/abi/interface.d.ts +128 -132
  39. package/src/abi/interface.js +590 -590
  40. package/src/abi/js-abi-coder.d.ts +8 -0
  41. package/src/abi/js-abi-coder.js +474 -474
  42. package/src/constants.d.ts +66 -61
  43. package/src/constants.js +101 -94
  44. package/src/contract/contract-factory.d.ts +28 -28
  45. package/src/contract/contract-factory.js +105 -105
  46. package/src/contract/contract.d.ts +113 -114
  47. package/src/contract/contract.js +354 -354
  48. package/src/contract/index.d.ts +9 -9
  49. package/src/contract/index.js +9 -9
  50. package/src/errors/index.d.ts +92 -92
  51. package/src/errors/index.js +188 -188
  52. package/src/generator/index.d.ts +74 -0
  53. package/src/generator/index.js +1404 -1404
  54. package/src/index.d.ts +125 -127
  55. package/src/index.js +41 -41
  56. package/src/internal/hex.d.ts +61 -61
  57. package/src/internal/hex.js +144 -144
  58. package/src/providers/extra-providers.d.ts +139 -128
  59. package/src/providers/extra-providers.js +600 -575
  60. package/src/providers/index.d.ts +17 -16
  61. package/src/providers/index.js +10 -10
  62. package/src/providers/json-rpc-provider.d.ts +12 -12
  63. package/src/providers/json-rpc-provider.js +79 -79
  64. package/src/providers/provider.d.ts +208 -203
  65. package/src/providers/provider.js +393 -371
  66. package/src/types/index.d.ts +214 -462
  67. package/src/types/index.js +9 -9
  68. package/src/utils/address.d.ts +72 -72
  69. package/src/utils/address.js +181 -182
  70. package/src/utils/encoding.d.ts +120 -120
  71. package/src/utils/encoding.js +306 -306
  72. package/src/utils/hashing.d.ts +82 -76
  73. package/src/utils/hashing.js +313 -298
  74. package/src/utils/index.d.ts +65 -55
  75. package/src/utils/index.js +13 -13
  76. package/src/utils/result.d.ts +57 -57
  77. package/src/utils/result.js +128 -128
  78. package/src/utils/rlp.d.ts +12 -12
  79. package/src/utils/rlp.js +200 -200
  80. package/src/utils/units.d.ts +29 -29
  81. package/src/utils/units.js +107 -107
  82. package/src/wallet/index.d.ts +10 -10
  83. package/src/wallet/index.js +8 -8
  84. package/src/wallet/wallet.d.ts +168 -160
  85. package/src/wallet/wallet.js +500 -489
  86. package/test/e2e/all-solidity-types.dynamic.test.js +207 -200
  87. package/test/e2e/all-solidity-types.dynamic.test.ts +191 -0
  88. package/test/e2e/all-solidity-types.fixtures.js +231 -231
  89. package/test/e2e/all-solidity-types.generated-sdks.e2e.test.js +387 -368
  90. package/test/e2e/all-solidity-types.generated-sdks.e2e.test.ts +350 -0
  91. package/test/e2e/helpers.js +59 -47
  92. package/test/e2e/signing-context-and-fee.e2e.test.js +141 -0
  93. package/test/e2e/signing-context-and-fee.e2e.test.ts +128 -0
  94. package/test/e2e/simple-erc20.generated-sdks.e2e.test.js +168 -151
  95. package/test/e2e/simple-erc20.generated-sdks.e2e.test.ts +141 -0
  96. package/test/e2e/transactional.test.js +245 -191
  97. package/test/e2e/transactional.test.ts +208 -0
  98. package/test/e2e/typed-generator.e2e.test.js +407 -404
  99. package/test/e2e/typed-generator.e2e.test.ts +337 -0
  100. package/test/fixtures/ConstructorParam.sol +23 -23
  101. package/test/fixtures/MultiContracts.sol +37 -37
  102. package/test/fixtures/SimpleStorage.sol +18 -18
  103. package/test/fixtures/StakingContract.abi.json +1 -1
  104. package/test/integration/ipc-provider.test.js +49 -44
  105. package/test/integration/ipc-provider.test.ts +44 -0
  106. package/test/integration/provider.test.js +88 -72
  107. package/test/integration/provider.test.ts +85 -0
  108. package/test/integration/ws-provider.test.js +41 -33
  109. package/test/integration/ws-provider.test.ts +38 -0
  110. package/test/security/malformed-input.test.js +37 -31
  111. package/test/security/malformed-input.test.ts +35 -0
  112. package/test/unit/_encrypted-output.txt +6 -0
  113. package/test/unit/_log-encrypted-jsons.js +45 -0
  114. package/test/unit/_write-keystore-fixture.js +16 -0
  115. package/test/unit/abi-interface.test.js +103 -98
  116. package/test/unit/abi-interface.test.ts +102 -0
  117. package/test/unit/address-wallet.test.js +392 -257
  118. package/test/unit/address-wallet.test.ts +379 -0
  119. package/test/unit/browser-provider.test.js +85 -82
  120. package/test/unit/browser-provider.test.ts +79 -0
  121. package/test/unit/contract.test.js +85 -82
  122. package/test/unit/contract.test.ts +83 -0
  123. package/test/unit/encoding-units-rlp.test.js +92 -89
  124. package/test/unit/encoding-units-rlp.test.ts +91 -0
  125. package/test/unit/errors.test.js +77 -74
  126. package/test/unit/errors.test.ts +76 -0
  127. package/test/unit/filter-by-blockhash.test.js +55 -52
  128. package/test/unit/filter-by-blockhash.test.ts +54 -0
  129. package/test/unit/fixtures/encrypted-keystores-48-32-36.js +9 -0
  130. package/test/unit/generate-contract-cli.test.js +42 -39
  131. package/test/unit/generate-contract-cli.test.ts +41 -0
  132. package/test/unit/generate-sdk-artifacts-json.test.js +113 -110
  133. package/test/unit/generate-sdk-artifacts-json.test.ts +110 -0
  134. package/test/unit/generator.test.js +102 -99
  135. package/test/unit/generator.test.ts +101 -0
  136. package/test/unit/hashing.test.js +68 -54
  137. package/test/unit/hashing.test.ts +67 -0
  138. package/test/unit/init.test.js +39 -36
  139. package/test/unit/init.test.ts +38 -0
  140. package/test/unit/interface.test.js +56 -53
  141. package/test/unit/interface.test.ts +54 -0
  142. package/test/unit/internal-hex.test.js +50 -47
  143. package/test/unit/internal-hex.test.ts +49 -0
  144. package/test/unit/populate-transaction.test.js +65 -62
  145. package/test/unit/populate-transaction.test.ts +64 -0
  146. package/test/unit/providers.test.js +200 -144
  147. package/test/unit/providers.test.ts +196 -0
  148. package/test/unit/result.test.js +80 -77
  149. package/test/unit/result.test.ts +79 -0
  150. package/test/unit/solidity-types.test.js +49 -46
  151. package/test/unit/solidity-types.test.ts +39 -0
  152. package/test/unit/utils.test.js +57 -54
  153. package/test/unit/utils.test.ts +56 -0
  154. package/test/verbose-logger.js +74 -0
  155. package/tsconfig.build.json +14 -0
@@ -1,371 +1,393 @@
1
- /**
2
- * @fileoverview Provider base classes and common types.
3
- *
4
- * This module models ethers.js v6 Provider patterns, adapted for QuantumCoin.
5
- * The concrete JSON-RPC implementation lives in `json-rpc-provider.js`.
6
- */
7
-
8
- const { EventEmitter } = require("events");
9
- const { makeError, assertArgument } = require("../errors");
10
- const { normalizeHex, isHexString } = require("../internal/hex");
11
-
12
- /**
13
- * @typedef {import("../utils/encoding").BytesLike} BytesLike
14
- */
15
-
16
- /**
17
- * @typedef {Object} TransactionRequest
18
- * @property {string=} to
19
- * @property {string=} from
20
- * @property {bigint|string|number=} value
21
- * @property {string=} data
22
- * @property {bigint|string|number=} gasLimit
23
- * @property {bigint|string|number=} gasPrice
24
- * @property {number=} nonce
25
- * @property {number=} chainId
26
- * @property {string=} remarks Optional remark field (hex, max 32 bytes)
27
- */
28
-
29
- /**
30
- * @typedef {Object} Filter
31
- * @property {string|string[]=} address
32
- * @property {(string|string[]|null)[]=} topics
33
- * @property {number|string=} fromBlock
34
- * @property {number|string=} toBlock
35
- * @property {string=} blockHash
36
- */
37
-
38
- function _hexToBigInt(hex) {
39
- if (typeof hex === "bigint") return hex;
40
- if (typeof hex === "number") return BigInt(hex);
41
- // JSON-RPC "quantity" values may be odd-length (e.g. "0x0", "0x1").
42
- assertArgument(typeof hex === "string" && /^0x[0-9a-fA-F]+$/.test(hex), "invalid hex quantity", "hex", hex);
43
- return BigInt(hex);
44
- }
45
-
46
- function _hexToNumber(hex) {
47
- return Number(_hexToBigInt(hex));
48
- }
49
-
50
- /**
51
- * Minimal Log wrapper (ethers-like).
52
- */
53
- class Log {
54
- /**
55
- * @param {any} log
56
- * @param {AbstractProvider=} provider
57
- */
58
- constructor(log, provider) {
59
- this.provider = provider || null;
60
- this.address = log.address;
61
- this.topics = log.topics || [];
62
- this.data = log.data || "0x";
63
- this.blockHash = log.blockHash || null;
64
- this.blockNumber = log.blockNumber != null ? _hexToNumber(log.blockNumber) : null;
65
- this.transactionHash = log.transactionHash || null;
66
- this.transactionIndex = log.transactionIndex != null ? _hexToNumber(log.transactionIndex) : null;
67
- this.logIndex = log.logIndex != null ? _hexToNumber(log.logIndex) : null;
68
- this.removed = Boolean(log.removed);
69
- }
70
-
71
- async getBlock() {
72
- if (!this.provider || this.blockNumber == null) return null;
73
- return this.provider.getBlock(this.blockNumber);
74
- }
75
-
76
- async getTransaction() {
77
- if (!this.provider || !this.transactionHash) return null;
78
- return this.provider.getTransaction(this.transactionHash);
79
- }
80
-
81
- async getTransactionReceipt() {
82
- if (!this.provider || !this.transactionHash) return null;
83
- return this.provider.getTransactionReceipt(this.transactionHash);
84
- }
85
- }
86
-
87
- /**
88
- * Minimal TransactionReceipt wrapper (ethers-like).
89
- */
90
- class TransactionReceipt {
91
- /**
92
- * @param {any} receipt
93
- * @param {AbstractProvider=} provider
94
- */
95
- constructor(receipt, provider) {
96
- this.provider = provider || null;
97
- this.to = receipt.to || null;
98
- this.from = receipt.from || null;
99
- this.contractAddress = receipt.contractAddress || null;
100
- this.transactionHash = receipt.transactionHash;
101
- this.blockHash = receipt.blockHash;
102
- this.blockNumber = receipt.blockNumber != null ? _hexToNumber(receipt.blockNumber) : null;
103
- this.transactionIndex = receipt.transactionIndex != null ? _hexToNumber(receipt.transactionIndex) : null;
104
- this.gasUsed = receipt.gasUsed != null ? _hexToBigInt(receipt.gasUsed) : null;
105
- this.status = receipt.status != null ? _hexToNumber(receipt.status) : null;
106
- this.logs = Array.isArray(receipt.logs) ? receipt.logs.map((l) => new Log(l, provider)) : [];
107
- }
108
- }
109
-
110
- /**
111
- * Minimal TransactionResponse wrapper (ethers-like).
112
- */
113
- class TransactionResponse {
114
- /**
115
- * @param {any} tx
116
- * @param {AbstractProvider=} provider
117
- */
118
- constructor(tx, provider) {
119
- this.provider = provider || null;
120
- this.hash = tx.hash;
121
- this.to = tx.to || null;
122
- this.from = tx.from || null;
123
- this.nonce = tx.nonce != null ? _hexToNumber(tx.nonce) : null;
124
- this.data = tx.input || tx.data || "0x";
125
- this.value = tx.value != null ? _hexToBigInt(tx.value) : 0n;
126
- this.gasLimit = tx.gas != null ? _hexToBigInt(tx.gas) : null;
127
- this.gasPrice = tx.gasPrice != null ? _hexToBigInt(tx.gasPrice) : null;
128
- this.chainId = tx.chainId != null ? _hexToNumber(tx.chainId) : null;
129
- this.blockNumber = tx.blockNumber != null ? _hexToNumber(tx.blockNumber) : null;
130
- }
131
-
132
- /**
133
- * Wait for confirmations.
134
- * @param {number=} confirmations
135
- * @param {number=} timeoutMs
136
- * @returns {Promise<TransactionReceipt>}
137
- */
138
- async wait(confirmations, timeoutMs) {
139
- if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "wait" });
140
- const conf = confirmations == null ? 1 : confirmations;
141
- const start = Date.now();
142
- const timeout = timeoutMs == null ? 120_000 : timeoutMs;
143
-
144
- while (true) {
145
- const receipt = await this.provider.getTransactionReceipt(this.hash);
146
- if (receipt && receipt.blockNumber != null) {
147
- if (conf <= 1) return receipt;
148
- const current = await this.provider.getBlockNumber();
149
- if (current - receipt.blockNumber + 1 >= conf) return receipt;
150
- }
151
- if (Date.now() - start > timeout) {
152
- throw makeError("timeout waiting for transaction", "UNKNOWN_ERROR", { hash: this.hash });
153
- }
154
- await new Promise((r) => setTimeout(r, 2_000));
155
- }
156
- }
157
- }
158
-
159
- /**
160
- * Minimal Block wrapper (ethers-like).
161
- */
162
- class Block {
163
- /**
164
- * @param {any} block
165
- * @param {AbstractProvider=} provider
166
- */
167
- constructor(block, provider) {
168
- this.provider = provider || null;
169
- this.hash = block.hash || null;
170
- this.parentHash = block.parentHash || null;
171
- this.number = block.number != null ? _hexToNumber(block.number) : null;
172
- this.timestamp = block.timestamp != null ? _hexToNumber(block.timestamp) : null;
173
- this.transactions = block.transactions || [];
174
- }
175
-
176
- async getTransaction(indexOrHash) {
177
- if (!this.provider) return null;
178
- if (typeof indexOrHash === "number") {
179
- const hash = this.transactions[indexOrHash];
180
- if (!hash) return null;
181
- return this.provider.getTransaction(hash);
182
- }
183
- if (typeof indexOrHash === "string") return this.provider.getTransaction(indexOrHash);
184
- return null;
185
- }
186
-
187
- async getTransactionReceipt(indexOrHash) {
188
- if (!this.provider) return null;
189
- const tx = await this.getTransaction(indexOrHash);
190
- if (!tx) return null;
191
- return this.provider.getTransactionReceipt(tx.hash);
192
- }
193
-
194
- getPrefetchedTransactions() {
195
- // This implementation returns only hashes unless `eth_getBlockByNumber(..., true)` is used.
196
- return [];
197
- }
198
- }
199
-
200
- /**
201
- * Base Provider class.
202
- */
203
- class Provider extends EventEmitter {
204
- constructor() {
205
- super();
206
- }
207
- }
208
-
209
- /**
210
- * AbstractProvider base class (ethers-like).
211
- */
212
- class AbstractProvider extends Provider {
213
- constructor() {
214
- super();
215
- }
216
-
217
- /**
218
- * Implemented by subclasses to perform JSON-RPC.
219
- * @param {string} method
220
- * @param {any[]=} params
221
- * @returns {Promise<any>}
222
- */
223
- async _perform(method, params) {
224
- void method;
225
- void params;
226
- throw makeError("_perform not implemented", "NOT_IMPLEMENTED", {});
227
- }
228
-
229
- async getBlockNumber() {
230
- const hex = await this._perform("eth_blockNumber", []);
231
- return _hexToNumber(hex);
232
- }
233
-
234
- /**
235
- * @param {number|"latest"} blockNumber
236
- * @returns {Promise<Block>}
237
- */
238
- async getBlock(blockNumber) {
239
- const tag = blockNumber === "latest" ? "latest" : normalizeHex("0x" + Number(blockNumber).toString(16));
240
- const block = await this._perform("eth_getBlockByNumber", [tag, false]);
241
- return new Block(block, this);
242
- }
243
-
244
- /**
245
- * @param {string} txHash
246
- * @returns {Promise<TransactionResponse>}
247
- */
248
- async getTransaction(txHash) {
249
- const tx = await this._perform("eth_getTransactionByHash", [txHash]);
250
- if (!tx) return null;
251
- return new TransactionResponse(tx, this);
252
- }
253
-
254
- /**
255
- * @param {string} txHash
256
- * @returns {Promise<TransactionReceipt>}
257
- */
258
- async getTransactionReceipt(txHash) {
259
- const receipt = await this._perform("eth_getTransactionReceipt", [txHash]);
260
- if (!receipt) return null;
261
- return new TransactionReceipt(receipt, this);
262
- }
263
-
264
- /**
265
- * @param {string} address
266
- * @returns {Promise<bigint>}
267
- */
268
- async getBalance(address) {
269
- const bal = await this._perform("eth_getBalance", [address, "latest"]);
270
- return _hexToBigInt(bal);
271
- }
272
-
273
- /**
274
- * @param {string} address
275
- * @param {string=} blockTag
276
- * @returns {Promise<number>}
277
- */
278
- async getTransactionCount(address, blockTag) {
279
- const tag = blockTag || "latest";
280
- const nonce = await this._perform("eth_getTransactionCount", [address, tag]);
281
- return _hexToNumber(nonce);
282
- }
283
-
284
- /**
285
- * Broadcasts a signed transaction.
286
- * @param {TransactionRequest|string} tx
287
- * @returns {Promise<TransactionResponse>}
288
- */
289
- async sendTransaction(tx) {
290
- // For QuantumCoin.js, tx is expected to be a signed raw transaction hex string.
291
- const raw = typeof tx === "string" ? tx : tx?.raw;
292
- if (typeof raw !== "string") throw makeError("sendTransaction requires a signed raw transaction string", "INVALID_ARGUMENT", { tx });
293
- const hash = await this._perform("eth_sendRawTransaction", [raw]);
294
- // Fetch back transaction (best-effort)
295
- const result = await this.getTransaction(hash);
296
- return result || new TransactionResponse({ hash }, this);
297
- }
298
-
299
- /**
300
- * Broadcast a signed raw transaction.
301
- * Alias of sendTransaction(rawTx) for clarity when doing offline signing flows.
302
- *
303
- * @param {string} rawTx
304
- * @returns {Promise<TransactionResponse>}
305
- */
306
- async sendRawTransaction(rawTx) {
307
- assertArgument(typeof rawTx === "string", "invalid rawTx", "rawTx", rawTx);
308
- return this.sendTransaction(rawTx);
309
- }
310
-
311
- /**
312
- * Perform a call (read-only) and return hex data.
313
- * @param {TransactionRequest} tx
314
- * @param {string=} blockTag
315
- * @returns {Promise<string>}
316
- */
317
- async call(tx, blockTag) {
318
- const tag = blockTag || "latest";
319
- return this._perform("eth_call", [tx, tag]);
320
- }
321
-
322
- /**
323
- * Estimate gas for a call/transaction.
324
- * @param {TransactionRequest} tx
325
- * @returns {Promise<bigint>}
326
- */
327
- async estimateGas(tx) {
328
- const gas = await this._perform("eth_estimateGas", [tx]);
329
- return _hexToBigInt(gas);
330
- }
331
-
332
- /**
333
- * @param {string} address
334
- * @param {string=} blockTag
335
- * @returns {Promise<string>}
336
- */
337
- async getCode(address, blockTag) {
338
- const tag = blockTag || "latest";
339
- return this._perform("eth_getCode", [address, tag]);
340
- }
341
-
342
- /**
343
- * @param {string} address
344
- * @param {bigint} position
345
- * @param {string=} blockTag
346
- * @returns {Promise<string>}
347
- */
348
- async getStorageAt(address, position, blockTag) {
349
- const tag = blockTag || "latest";
350
- return this._perform("eth_getStorageAt", [address, "0x" + position.toString(16), tag]);
351
- }
352
-
353
- /**
354
- * @param {Filter} filter
355
- * @returns {Promise<Log[]>}
356
- */
357
- async getLogs(filter) {
358
- const logs = await this._perform("eth_getLogs", [filter]);
359
- return (logs || []).map((l) => new Log(l, this));
360
- }
361
- }
362
-
363
- module.exports = {
364
- Provider,
365
- AbstractProvider,
366
- Block,
367
- TransactionResponse,
368
- TransactionReceipt,
369
- Log,
370
- };
371
-
1
+ /**
2
+ * @fileoverview Provider base classes and common types.
3
+ *
4
+ * This module models ethers.js v6 Provider patterns, adapted for QuantumCoin.
5
+ * The concrete JSON-RPC implementation lives in `json-rpc-provider.js`.
6
+ */
7
+
8
+ const { EventEmitter } = require("events");
9
+ const { makeError, assertArgument } = require("../errors");
10
+ const { normalizeHex, isHexString } = require("../internal/hex");
11
+
12
+ /**
13
+ * @typedef {import("../utils/encoding").BytesLike} BytesLike
14
+ */
15
+
16
+ /**
17
+ * @typedef {Object} TransactionRequest
18
+ * @property {string=} to
19
+ * @property {string=} from
20
+ * @property {bigint|string|number=} value
21
+ * @property {string=} data
22
+ * @property {bigint|string|number=} gasLimit
23
+ * @property {bigint|string|number=} gasPrice
24
+ * @property {number=} nonce
25
+ * @property {number=} chainId
26
+ * @property {string=} remarks Optional remark field (hex, max 32 bytes)
27
+ * @property {number|null=} signingContext Optional signing context (0, 1, 2, or null). Passed to SDK TransactionSigningRequest; default null.
28
+ */
29
+
30
+ /**
31
+ * @typedef {Object} Filter
32
+ * @property {string|string[]=} address
33
+ * @property {(string|string[]|null)[]=} topics
34
+ * @property {number|string=} fromBlock
35
+ * @property {number|string=} toBlock
36
+ * @property {string=} blockHash
37
+ */
38
+
39
+ function _hexToBigInt(hex) {
40
+ if (typeof hex === "bigint") return hex;
41
+ if (typeof hex === "number") return BigInt(hex);
42
+ // JSON-RPC "quantity" values may be odd-length (e.g. "0x0", "0x1").
43
+ assertArgument(typeof hex === "string" && /^0x[0-9a-fA-F]+$/.test(hex), "invalid hex quantity", "hex", hex);
44
+ return BigInt(hex);
45
+ }
46
+
47
+ function _hexToNumber(hex) {
48
+ return Number(_hexToBigInt(hex));
49
+ }
50
+
51
+ /**
52
+ * Convert block tag (number or string) to the format eth_getLogs expects (hex with 0x or "latest"/"pending"/"earliest").
53
+ * @param {number|string|undefined} blockTag
54
+ * @returns {string|undefined}
55
+ */
56
+ function _blockTagToHex(blockTag) {
57
+ if (blockTag === undefined || blockTag === null) return undefined;
58
+ const s = String(blockTag).toLowerCase();
59
+ if (s === "latest" || s === "pending" || s === "earliest") return s;
60
+ const n = typeof blockTag === "number" ? blockTag : Number(blockTag);
61
+ if (!Number.isInteger(n) || n < 0) return undefined;
62
+ return normalizeHex("0x" + n.toString(16));
63
+ }
64
+
65
+ /**
66
+ * Minimal Log wrapper (ethers-like).
67
+ */
68
+ class Log {
69
+ /**
70
+ * @param {any} log
71
+ * @param {AbstractProvider=} provider
72
+ */
73
+ constructor(log, provider) {
74
+ this.provider = provider || null;
75
+ this.address = log.address;
76
+ this.topics = log.topics || [];
77
+ this.data = log.data || "0x";
78
+ this.blockHash = log.blockHash || null;
79
+ this.blockNumber = log.blockNumber != null ? _hexToNumber(log.blockNumber) : null;
80
+ this.transactionHash = log.transactionHash || null;
81
+ this.transactionIndex = log.transactionIndex != null ? _hexToNumber(log.transactionIndex) : null;
82
+ this.logIndex = log.logIndex != null ? _hexToNumber(log.logIndex) : null;
83
+ this.removed = Boolean(log.removed);
84
+ }
85
+
86
+ async getBlock() {
87
+ if (!this.provider || this.blockNumber == null) return null;
88
+ return this.provider.getBlock(this.blockNumber);
89
+ }
90
+
91
+ async getTransaction() {
92
+ if (!this.provider || !this.transactionHash) return null;
93
+ return this.provider.getTransaction(this.transactionHash);
94
+ }
95
+
96
+ async getTransactionReceipt() {
97
+ if (!this.provider || !this.transactionHash) return null;
98
+ return this.provider.getTransactionReceipt(this.transactionHash);
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Minimal TransactionReceipt wrapper (ethers-like).
104
+ */
105
+ class TransactionReceipt {
106
+ /**
107
+ * @param {any} receipt
108
+ * @param {AbstractProvider=} provider
109
+ */
110
+ constructor(receipt, provider) {
111
+ this.provider = provider || null;
112
+ this.to = receipt.to || null;
113
+ this.from = receipt.from || null;
114
+ this.contractAddress = receipt.contractAddress || null;
115
+ this.transactionHash = receipt.transactionHash;
116
+ this.blockHash = receipt.blockHash;
117
+ this.blockNumber = receipt.blockNumber != null ? _hexToNumber(receipt.blockNumber) : null;
118
+ this.transactionIndex = receipt.transactionIndex != null ? _hexToNumber(receipt.transactionIndex) : null;
119
+ this.gasUsed = receipt.gasUsed != null ? _hexToBigInt(receipt.gasUsed) : null;
120
+ this.status = receipt.status != null ? _hexToNumber(receipt.status) : null;
121
+ this.logs = Array.isArray(receipt.logs) ? receipt.logs.map((l) => new Log(l, provider)) : [];
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Minimal TransactionResponse wrapper (ethers-like).
127
+ */
128
+ class TransactionResponse {
129
+ /**
130
+ * @param {any} tx
131
+ * @param {AbstractProvider=} provider
132
+ */
133
+ constructor(tx, provider) {
134
+ this.provider = provider || null;
135
+ this.hash = tx.hash;
136
+ this.to = tx.to || null;
137
+ this.from = tx.from || null;
138
+ this.nonce = tx.nonce != null ? _hexToNumber(tx.nonce) : null;
139
+ this.data = tx.input || tx.data || "0x";
140
+ this.value = tx.value != null ? _hexToBigInt(tx.value) : 0n;
141
+ this.gasLimit = tx.gas != null ? _hexToBigInt(tx.gas) : null;
142
+ this.gasPrice = tx.gasPrice != null ? _hexToBigInt(tx.gasPrice) : null;
143
+ this.chainId = tx.chainId != null ? _hexToNumber(tx.chainId) : null;
144
+ this.blockNumber = tx.blockNumber != null ? _hexToNumber(tx.blockNumber) : null;
145
+ this.txType = tx.type != null ? _hexToNumber(tx.type) : null;
146
+ this.remarks = tx.remarks != null ? normalizeHex(tx.remarks) : null;
147
+ }
148
+
149
+ /**
150
+ * Wait for confirmations.
151
+ * @param {number=} confirmations
152
+ * @param {number=} timeoutMs
153
+ * @returns {Promise<TransactionReceipt>}
154
+ */
155
+ async wait(confirmations, timeoutMs) {
156
+ if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "wait" });
157
+ const conf = confirmations == null ? 1 : confirmations;
158
+ const start = Date.now();
159
+ const timeout = timeoutMs == null ? 120_000 : timeoutMs;
160
+
161
+ while (true) {
162
+ const receipt = await this.provider.getTransactionReceipt(this.hash);
163
+ if (receipt && receipt.blockNumber != null) {
164
+ if (conf <= 1) return receipt;
165
+ const current = await this.provider.getBlockNumber();
166
+ if (current - receipt.blockNumber + 1 >= conf) return receipt;
167
+ }
168
+ if (Date.now() - start > timeout) {
169
+ throw makeError("timeout waiting for transaction", "UNKNOWN_ERROR", { hash: this.hash });
170
+ }
171
+ await new Promise((r) => setTimeout(r, 2_000));
172
+ }
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Minimal Block wrapper (ethers-like).
178
+ */
179
+ class Block {
180
+ /**
181
+ * @param {any} block
182
+ * @param {AbstractProvider=} provider
183
+ */
184
+ constructor(block, provider) {
185
+ this.provider = provider || null;
186
+ this.hash = block.hash || null;
187
+ this.parentHash = block.parentHash || null;
188
+ this.number = block.number != null ? _hexToNumber(block.number) : null;
189
+ this.timestamp = block.timestamp != null ? _hexToNumber(block.timestamp) : null;
190
+ this.transactions = block.transactions || [];
191
+ }
192
+
193
+ async getTransaction(indexOrHash) {
194
+ if (!this.provider) return null;
195
+ if (typeof indexOrHash === "number") {
196
+ const hash = this.transactions[indexOrHash];
197
+ if (!hash) return null;
198
+ return this.provider.getTransaction(hash);
199
+ }
200
+ if (typeof indexOrHash === "string") return this.provider.getTransaction(indexOrHash);
201
+ return null;
202
+ }
203
+
204
+ async getTransactionReceipt(indexOrHash) {
205
+ if (!this.provider) return null;
206
+ const tx = await this.getTransaction(indexOrHash);
207
+ if (!tx) return null;
208
+ return this.provider.getTransactionReceipt(tx.hash);
209
+ }
210
+
211
+ getPrefetchedTransactions() {
212
+ // This implementation returns only hashes unless `eth_getBlockByNumber(..., true)` is used.
213
+ return [];
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Base Provider class.
219
+ */
220
+ class Provider extends EventEmitter {
221
+ constructor() {
222
+ super();
223
+ }
224
+ }
225
+
226
+ /**
227
+ * AbstractProvider base class (ethers-like).
228
+ */
229
+ class AbstractProvider extends Provider {
230
+ constructor() {
231
+ super();
232
+ }
233
+
234
+ /**
235
+ * Implemented by subclasses to perform JSON-RPC.
236
+ * @param {string} method
237
+ * @param {any[]=} params
238
+ * @returns {Promise<any>}
239
+ */
240
+ async _perform(method, params) {
241
+ void method;
242
+ void params;
243
+ throw makeError("_perform not implemented", "NOT_IMPLEMENTED", {});
244
+ }
245
+
246
+ async getBlockNumber() {
247
+ const hex = await this._perform("eth_blockNumber", []);
248
+ return _hexToNumber(hex);
249
+ }
250
+
251
+ /**
252
+ * @param {number|"latest"} blockNumber
253
+ * @returns {Promise<Block>}
254
+ */
255
+ async getBlock(blockNumber) {
256
+ const tag = blockNumber === "latest" ? "latest" : normalizeHex("0x" + Number(blockNumber).toString(16));
257
+ const block = await this._perform("eth_getBlockByNumber", [tag, false]);
258
+ return new Block(block, this);
259
+ }
260
+
261
+ /**
262
+ * @param {string} txHash
263
+ * @returns {Promise<TransactionResponse>}
264
+ */
265
+ async getTransaction(txHash) {
266
+ const tx = await this._perform("eth_getTransactionByHash", [txHash]);
267
+ if (!tx) return null;
268
+ return new TransactionResponse(tx, this);
269
+ }
270
+
271
+ /**
272
+ * @param {string} txHash
273
+ * @returns {Promise<TransactionReceipt>}
274
+ */
275
+ async getTransactionReceipt(txHash) {
276
+ const receipt = await this._perform("eth_getTransactionReceipt", [txHash]);
277
+ if (!receipt) return null;
278
+ return new TransactionReceipt(receipt, this);
279
+ }
280
+
281
+ /**
282
+ * @param {string} address
283
+ * @returns {Promise<bigint>}
284
+ */
285
+ async getBalance(address) {
286
+ const bal = await this._perform("eth_getBalance", [address, "latest"]);
287
+ return _hexToBigInt(bal);
288
+ }
289
+
290
+ /**
291
+ * @param {string} address
292
+ * @param {string=} blockTag
293
+ * @returns {Promise<number>}
294
+ */
295
+ async getTransactionCount(address, blockTag) {
296
+ const tag = blockTag || "latest";
297
+ const nonce = await this._perform("eth_getTransactionCount", [address, tag]);
298
+ return _hexToNumber(nonce);
299
+ }
300
+
301
+ /**
302
+ * Broadcasts a signed transaction.
303
+ * @param {TransactionRequest|string} tx
304
+ * @returns {Promise<TransactionResponse>}
305
+ */
306
+ async sendTransaction(tx) {
307
+ // For QuantumCoin.js, tx is expected to be a signed raw transaction hex string.
308
+ const raw = typeof tx === "string" ? tx : tx?.raw;
309
+ if (typeof raw !== "string") throw makeError("sendTransaction requires a signed raw transaction string", "INVALID_ARGUMENT", { tx });
310
+ const hash = await this._perform("eth_sendRawTransaction", [raw]);
311
+ // Fetch back transaction (best-effort)
312
+ const result = await this.getTransaction(hash);
313
+ return result || new TransactionResponse({ hash }, this);
314
+ }
315
+
316
+ /**
317
+ * Broadcast a signed raw transaction.
318
+ * Alias of sendTransaction(rawTx) for clarity when doing offline signing flows.
319
+ *
320
+ * @param {string} rawTx
321
+ * @returns {Promise<TransactionResponse>}
322
+ */
323
+ async sendRawTransaction(rawTx) {
324
+ assertArgument(typeof rawTx === "string", "invalid rawTx", "rawTx", rawTx);
325
+ return this.sendTransaction(rawTx);
326
+ }
327
+
328
+ /**
329
+ * Perform a call (read-only) and return hex data.
330
+ * @param {TransactionRequest} tx
331
+ * @param {string=} blockTag
332
+ * @returns {Promise<string>}
333
+ */
334
+ async call(tx, blockTag) {
335
+ const tag = blockTag || "latest";
336
+ return this._perform("eth_call", [tx, tag]);
337
+ }
338
+
339
+ /**
340
+ * Estimate gas for a call/transaction.
341
+ * @param {TransactionRequest} tx
342
+ * @returns {Promise<bigint>}
343
+ */
344
+ async estimateGas(tx) {
345
+ const gas = await this._perform("eth_estimateGas", [tx]);
346
+ return _hexToBigInt(gas);
347
+ }
348
+
349
+ /**
350
+ * @param {string} address
351
+ * @param {string=} blockTag
352
+ * @returns {Promise<string>}
353
+ */
354
+ async getCode(address, blockTag) {
355
+ const tag = blockTag || "latest";
356
+ return this._perform("eth_getCode", [address, tag]);
357
+ }
358
+
359
+ /**
360
+ * @param {string} address
361
+ * @param {bigint} position
362
+ * @param {string=} blockTag
363
+ * @returns {Promise<string>}
364
+ */
365
+ async getStorageAt(address, position, blockTag) {
366
+ const tag = blockTag || "latest";
367
+ return this._perform("eth_getStorageAt", [address, "0x" + position.toString(16), tag]);
368
+ }
369
+
370
+ /**
371
+ * @param {Filter} filter
372
+ * @returns {Promise<Log[]>}
373
+ */
374
+ async getLogs(filter) {
375
+ const fromBlock = _blockTagToHex(filter.fromBlock);
376
+ const toBlock = _blockTagToHex(filter.toBlock);
377
+ const normalized = { ...filter };
378
+ if (fromBlock !== undefined) normalized.fromBlock = fromBlock;
379
+ if (toBlock !== undefined) normalized.toBlock = toBlock;
380
+ const logs = await this._perform("eth_getLogs", [normalized]);
381
+ return (logs || []).map((l) => new Log(l, this));
382
+ }
383
+ }
384
+
385
+ module.exports = {
386
+ Provider,
387
+ AbstractProvider,
388
+ Block,
389
+ TransactionResponse,
390
+ TransactionReceipt,
391
+ Log,
392
+ };
393
+