quantumcoin 7.0.3 → 7.0.4

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 +756 -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 +48 -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 +207 -203
  65. package/src/providers/provider.js +392 -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 +160 -160
  85. package/src/wallet/wallet.js +483 -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 +137 -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 +355 -257
  118. package/test/unit/address-wallet.test.ts +342 -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,354 +1,354 @@
1
- /**
2
- * @fileoverview Contract implementation (ethers.js v6 compatible shape).
3
- */
4
-
5
- const qcsdk = require("quantum-coin-js-sdk");
6
- const { Interface } = require("../abi/interface");
7
- const { makeError, assertArgument } = require("../errors");
8
- const { getAddress } = require("../utils/address");
9
- const { normalizeHex } = require("../internal/hex");
10
-
11
- function _requireInitialized() {
12
- // eslint-disable-next-line global-require
13
- const { isInitialized } = require("../../config");
14
- if (!isInitialized()) {
15
- throw makeError("QuantumCoin SDK not initialized. Call Initialize() first.", "UNKNOWN_ERROR", { operation: "contract" });
16
- }
17
- }
18
-
19
- function _isProvider(obj) {
20
- return Boolean(obj && typeof obj === "object" && typeof obj.call === "function" && typeof obj.getBlockNumber === "function");
21
- }
22
-
23
- function _isSigner(obj) {
24
- return Boolean(obj && typeof obj === "object" && typeof obj.signTransaction === "function");
25
- }
26
-
27
- function _isOverridesLike(value) {
28
- if (!value || typeof value !== "object") return false;
29
- if (Array.isArray(value)) return false;
30
- if (value instanceof Uint8Array) return false;
31
- return true;
32
- }
33
-
34
- /**
35
- * BaseContract placeholder (ethers-like).
36
- */
37
- class BaseContract {
38
- constructor() {}
39
- }
40
-
41
- /**
42
- * ContractTransactionResponse (aliasing provider TransactionResponse).
43
- */
44
- class ContractTransactionResponse {
45
- /**
46
- * @param {any} tx
47
- */
48
- constructor(tx) {
49
- this._tx = tx;
50
- // Copy common enumerable fields (hash, from, to, etc.)
51
- Object.assign(this, tx);
52
- }
53
-
54
- /**
55
- * Wait for confirmations (delegated to underlying TransactionResponse).
56
- * @param {number=} confirmations
57
- * @param {number=} timeoutMs
58
- * @returns {Promise<any>}
59
- */
60
- wait(confirmations, timeoutMs) {
61
- if (!this._tx || typeof this._tx.wait !== "function") {
62
- throw makeError("underlying transaction does not support wait()", "UNKNOWN_ERROR", {});
63
- }
64
- return this._tx.wait(confirmations, timeoutMs);
65
- }
66
-
67
- /**
68
- * Return the underlying transaction response object.
69
- * @returns {any}
70
- */
71
- getTransaction() {
72
- return this._tx;
73
- }
74
- }
75
-
76
- /**
77
- * ContractTransactionReceipt (aliasing provider TransactionReceipt).
78
- */
79
- class ContractTransactionReceipt {
80
- /**
81
- * @param {any} receipt
82
- */
83
- constructor(receipt) {
84
- Object.assign(this, receipt);
85
- }
86
-
87
- getEvent(eventName) {
88
- const list = this.getEvents(eventName);
89
- return list.length ? list[0] : null;
90
- }
91
-
92
- getEvents(eventName) {
93
- if (!this.logs) return [];
94
- return this.logs.filter((l) => l && l.eventName === eventName);
95
- }
96
- }
97
-
98
- /**
99
- * EventLog placeholder.
100
- */
101
- class EventLog {
102
- constructor(log) {
103
- Object.assign(this, log);
104
- }
105
- }
106
-
107
- class Contract extends BaseContract {
108
- /**
109
- * @param {string} address
110
- * @param {any[]|Interface} abi
111
- * @param {any=} providerOrSigner
112
- * @param {string=} bytecode
113
- */
114
- constructor(address, abi, providerOrSigner, bytecode) {
115
- super();
116
- _requireInitialized();
117
- this.address = getAddress(address);
118
- this.target = this.address;
119
- this.bytecode = bytecode || null;
120
- this.interface = abi instanceof Interface ? abi : new Interface(abi);
121
-
122
- this.provider = null;
123
- this.signer = null;
124
- this.runner = null;
125
- if (providerOrSigner) {
126
- if (_isProvider(providerOrSigner)) this.provider = providerOrSigner;
127
- if (_isSigner(providerOrSigner)) this.signer = providerOrSigner;
128
- // Ethers' ContractRunner can be a provider or signer
129
- this.runner = providerOrSigner;
130
- if (!this.provider && this.signer && this.signer.provider) this.provider = this.signer.provider;
131
- }
132
-
133
- this._listeners = new Map();
134
-
135
- // ethers-style populateTransaction namespace:
136
- // await contract.populateTransaction.someMethod(arg1, ..., overrides?)
137
- //
138
- // NOTE: This will shadow any ABI function literally named "populateTransaction".
139
- // Such a function can still be invoked via `contract.call("populateTransaction", ...)`
140
- // or `contract.send("populateTransaction", ...)`.
141
- const self = this;
142
- this.populateTransaction = new Proxy(
143
- {},
144
- {
145
- get(_t, prop) {
146
- if (typeof prop !== "string") return undefined;
147
- const fn = self.interface.abi.find((f) => f && f.type === "function" && f.name === prop);
148
- if (!fn) return undefined;
149
- return (...args) => self._populate(prop, args);
150
- },
151
- },
152
- );
153
-
154
- // Proxy to support dynamic method names: contract.someMethod(...)
155
- return new Proxy(this, {
156
- get: (target, prop, receiver) => {
157
- if (typeof prop === "string" && !(prop in target)) {
158
- // Treat unknown properties as function invocations if present in ABI
159
- const fn = target.interface.abi.find((f) => f && f.type === "function" && f.name === prop);
160
- if (fn) {
161
- return (...args) => target._invoke(prop, args);
162
- }
163
- }
164
- return Reflect.get(target, prop, receiver);
165
- },
166
- });
167
- }
168
-
169
- getAddress() {
170
- return this.address;
171
- }
172
-
173
- /**
174
- * Invoke a contract function, dispatching to call() or send().
175
- * @param {string} methodName
176
- * @param {any[]} args
177
- * @returns {Promise<any>}
178
- */
179
- async _invoke(methodName, args) {
180
- const fn = this.interface.abi.find((f) => f && f.type === "function" && f.name === methodName);
181
- if (!fn) throw makeError("function not found", "INVALID_ARGUMENT", { methodName });
182
-
183
- const mut = fn.stateMutability || "";
184
- const isView = mut === "view" || mut === "pure";
185
-
186
- // ethers-style overrides:
187
- // - for nonpayable/payable: last arg may be overrides object
188
- // - for view/pure: last arg may be overrides (call overrides)
189
- const inputCount = Array.isArray(fn.inputs) ? fn.inputs.length : 0;
190
- let overrides = undefined;
191
- let callArgs = Array.isArray(args) ? args : [];
192
-
193
- if (callArgs.length === inputCount + 1 && _isOverridesLike(callArgs[callArgs.length - 1])) {
194
- overrides = callArgs[callArgs.length - 1];
195
- callArgs = callArgs.slice(0, inputCount);
196
- }
197
-
198
- if (isView) {
199
- return this.call(methodName, callArgs, overrides);
200
- }
201
-
202
- return this.send(methodName, callArgs, overrides);
203
- }
204
-
205
- /**
206
- * Build an unsigned transaction request for a contract method call.
207
- * @param {string} methodName
208
- * @param {any[]} args
209
- * @returns {Promise<import("../providers/provider").TransactionRequest>}
210
- */
211
- async _populate(methodName, args) {
212
- const fn = this.interface.abi.find((f) => f && f.type === "function" && f.name === methodName);
213
- if (!fn) throw makeError("function not found", "INVALID_ARGUMENT", { methodName });
214
-
215
- const inputCount = Array.isArray(fn.inputs) ? fn.inputs.length : 0;
216
- let overrides = undefined;
217
- let callArgs = Array.isArray(args) ? args : [];
218
-
219
- if (callArgs.length === inputCount + 1 && _isOverridesLike(callArgs[callArgs.length - 1])) {
220
- overrides = callArgs[callArgs.length - 1];
221
- callArgs = callArgs.slice(0, inputCount);
222
- }
223
-
224
- const data = this.interface.encodeFunctionData(methodName, callArgs);
225
- return { to: this.address, data, ...(overrides || {}) };
226
- }
227
-
228
- /**
229
- * Perform a read-only call.
230
- * @param {string} methodName
231
- * @param {any[]} args
232
- * @param {import("../providers/provider").TransactionRequest=} overrides
233
- * @returns {Promise<any>}
234
- */
235
- async call(methodName, args, overrides) {
236
- if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "call" });
237
- const data = this.interface.encodeFunctionData(methodName, args);
238
- const tx = { to: this.address, data, ...(overrides || {}) };
239
- const raw = await this.provider.call(tx, "latest");
240
- const decoded = this.interface.decodeFunctionResult(methodName, raw);
241
- return decoded;
242
- }
243
-
244
- /**
245
- * Send a state-changing transaction.
246
- * @param {string} methodName
247
- * @param {any[]} args
248
- * @param {import("../providers/provider").TransactionRequest=} overrides
249
- * @returns {Promise<ContractTransactionResponse>}
250
- */
251
- async send(methodName, args, overrides) {
252
- if (!this.signer) throw makeError("missing signer", "UNKNOWN_ERROR", { operation: "send" });
253
- const data = this.interface.encodeFunctionData(methodName, args);
254
- const tx = { to: this.address, data, ...(overrides || {}) };
255
- const resp = await this.signer.sendTransaction(tx);
256
- return new ContractTransactionResponse(resp);
257
- }
258
-
259
- /**
260
- * Query logs for an event.
261
- * @param {any} event
262
- * @param {number|string=} fromBlock
263
- * @param {number|string=} toBlock
264
- * @returns {Promise<EventLog[]>}
265
- */
266
- async queryFilter(event, fromBlock, toBlock) {
267
- if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "queryFilter" });
268
- const name = typeof event === "string" ? event : event?.name;
269
- assertArgument(typeof name === "string", "invalid event", "event", event);
270
- const filter = { address: this.address, fromBlock, toBlock };
271
- const logs = await this.provider.getLogs(filter);
272
- return logs.map((l) => new EventLog(l));
273
- }
274
-
275
- on(event, callback) {
276
- const name = typeof event === "string" ? event : event?.name;
277
- if (!name) throw makeError("invalid event", "INVALID_ARGUMENT", { event });
278
- const list = this._listeners.get(name) || [];
279
- list.push(callback);
280
- this._listeners.set(name, list);
281
- return this;
282
- }
283
-
284
- once(event, callback) {
285
- const wrap = (...args) => {
286
- this.removeListener(event, wrap);
287
- callback(...args);
288
- };
289
- return this.on(event, wrap);
290
- }
291
-
292
- removeListener(event, callback) {
293
- const name = typeof event === "string" ? event : event?.name;
294
- const list = this._listeners.get(name) || [];
295
- this._listeners.set(
296
- name,
297
- list.filter((cb) => cb !== callback),
298
- );
299
- return this;
300
- }
301
-
302
- removeAllListeners(event) {
303
- if (!event) {
304
- this._listeners.clear();
305
- return this;
306
- }
307
- const name = typeof event === "string" ? event : event?.name;
308
- this._listeners.delete(name);
309
- return this;
310
- }
311
-
312
- connect(signerOrProvider) {
313
- return new Contract(this.address, this.interface, signerOrProvider, this.bytecode);
314
- }
315
-
316
- attach(address) {
317
- return new Contract(address, this.interface, this.runner, this.bytecode);
318
- }
319
-
320
- deployTransaction() {
321
- return this._deployTx || null;
322
- }
323
-
324
- async getTransactionReceipt(hash) {
325
- if (!this.provider) return null;
326
- const receipt = await this.provider.getTransactionReceipt(hash);
327
- return receipt ? new ContractTransactionReceipt(receipt) : null;
328
- }
329
-
330
- async waitForDeployment() {
331
- if (!this._deployTx) return this;
332
- await this._deployTx.wait();
333
- return this;
334
- }
335
-
336
- async getDeployedCode() {
337
- if (!this.provider) return null;
338
- return this.provider.getCode(this.address, "latest");
339
- }
340
-
341
- static from(target, abi, runner) {
342
- const address = typeof target === "string" ? target : target?.address || target?.target;
343
- return new Contract(address, abi, runner);
344
- }
345
- }
346
-
347
- module.exports = {
348
- BaseContract,
349
- Contract,
350
- ContractTransactionResponse,
351
- ContractTransactionReceipt,
352
- EventLog,
353
- };
354
-
1
+ /**
2
+ * @fileoverview Contract implementation (ethers.js v6 compatible shape).
3
+ */
4
+
5
+ const qcsdk = require("quantum-coin-js-sdk");
6
+ const { Interface } = require("../abi/interface");
7
+ const { makeError, assertArgument } = require("../errors");
8
+ const { getAddress } = require("../utils/address");
9
+ const { normalizeHex } = require("../internal/hex");
10
+
11
+ function _requireInitialized() {
12
+ // eslint-disable-next-line global-require
13
+ const { isInitialized } = require("../../config");
14
+ if (!isInitialized()) {
15
+ throw makeError("QuantumCoin SDK not initialized. Call Initialize() first.", "UNKNOWN_ERROR", { operation: "contract" });
16
+ }
17
+ }
18
+
19
+ function _isProvider(obj) {
20
+ return Boolean(obj && typeof obj === "object" && typeof obj.call === "function" && typeof obj.getBlockNumber === "function");
21
+ }
22
+
23
+ function _isSigner(obj) {
24
+ return Boolean(obj && typeof obj === "object" && typeof obj.signTransaction === "function");
25
+ }
26
+
27
+ function _isOverridesLike(value) {
28
+ if (!value || typeof value !== "object") return false;
29
+ if (Array.isArray(value)) return false;
30
+ if (value instanceof Uint8Array) return false;
31
+ return true;
32
+ }
33
+
34
+ /**
35
+ * BaseContract placeholder (ethers-like).
36
+ */
37
+ class BaseContract {
38
+ constructor() {}
39
+ }
40
+
41
+ /**
42
+ * ContractTransactionResponse (aliasing provider TransactionResponse).
43
+ */
44
+ class ContractTransactionResponse {
45
+ /**
46
+ * @param {any} tx
47
+ */
48
+ constructor(tx) {
49
+ this._tx = tx;
50
+ // Copy common enumerable fields (hash, from, to, etc.)
51
+ Object.assign(this, tx);
52
+ }
53
+
54
+ /**
55
+ * Wait for confirmations (delegated to underlying TransactionResponse).
56
+ * @param {number=} confirmations
57
+ * @param {number=} timeoutMs
58
+ * @returns {Promise<any>}
59
+ */
60
+ wait(confirmations, timeoutMs) {
61
+ if (!this._tx || typeof this._tx.wait !== "function") {
62
+ throw makeError("underlying transaction does not support wait()", "UNKNOWN_ERROR", {});
63
+ }
64
+ return this._tx.wait(confirmations, timeoutMs);
65
+ }
66
+
67
+ /**
68
+ * Return the underlying transaction response object.
69
+ * @returns {any}
70
+ */
71
+ getTransaction() {
72
+ return this._tx;
73
+ }
74
+ }
75
+
76
+ /**
77
+ * ContractTransactionReceipt (aliasing provider TransactionReceipt).
78
+ */
79
+ class ContractTransactionReceipt {
80
+ /**
81
+ * @param {any} receipt
82
+ */
83
+ constructor(receipt) {
84
+ Object.assign(this, receipt);
85
+ }
86
+
87
+ getEvent(eventName) {
88
+ const list = this.getEvents(eventName);
89
+ return list.length ? list[0] : null;
90
+ }
91
+
92
+ getEvents(eventName) {
93
+ if (!this.logs) return [];
94
+ return this.logs.filter((l) => l && l.eventName === eventName);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * EventLog placeholder.
100
+ */
101
+ class EventLog {
102
+ constructor(log) {
103
+ Object.assign(this, log);
104
+ }
105
+ }
106
+
107
+ class Contract extends BaseContract {
108
+ /**
109
+ * @param {string} address
110
+ * @param {any[]|Interface} abi
111
+ * @param {any=} providerOrSigner
112
+ * @param {string=} bytecode
113
+ */
114
+ constructor(address, abi, providerOrSigner, bytecode) {
115
+ super();
116
+ _requireInitialized();
117
+ this.address = getAddress(address);
118
+ this.target = this.address;
119
+ this.bytecode = bytecode || null;
120
+ this.interface = abi instanceof Interface ? abi : new Interface(abi);
121
+
122
+ this.provider = null;
123
+ this.signer = null;
124
+ this.runner = null;
125
+ if (providerOrSigner) {
126
+ if (_isProvider(providerOrSigner)) this.provider = providerOrSigner;
127
+ if (_isSigner(providerOrSigner)) this.signer = providerOrSigner;
128
+ // Ethers' ContractRunner can be a provider or signer
129
+ this.runner = providerOrSigner;
130
+ if (!this.provider && this.signer && this.signer.provider) this.provider = this.signer.provider;
131
+ }
132
+
133
+ this._listeners = new Map();
134
+
135
+ // ethers-style populateTransaction namespace:
136
+ // await contract.populateTransaction.someMethod(arg1, ..., overrides?)
137
+ //
138
+ // NOTE: This will shadow any ABI function literally named "populateTransaction".
139
+ // Such a function can still be invoked via `contract.call("populateTransaction", ...)`
140
+ // or `contract.send("populateTransaction", ...)`.
141
+ const self = this;
142
+ this.populateTransaction = new Proxy(
143
+ {},
144
+ {
145
+ get(_t, prop) {
146
+ if (typeof prop !== "string") return undefined;
147
+ const fn = self.interface.abi.find((f) => f && f.type === "function" && f.name === prop);
148
+ if (!fn) return undefined;
149
+ return (...args) => self._populate(prop, args);
150
+ },
151
+ },
152
+ );
153
+
154
+ // Proxy to support dynamic method names: contract.someMethod(...)
155
+ return new Proxy(this, {
156
+ get: (target, prop, receiver) => {
157
+ if (typeof prop === "string" && !(prop in target)) {
158
+ // Treat unknown properties as function invocations if present in ABI
159
+ const fn = target.interface.abi.find((f) => f && f.type === "function" && f.name === prop);
160
+ if (fn) {
161
+ return (...args) => target._invoke(prop, args);
162
+ }
163
+ }
164
+ return Reflect.get(target, prop, receiver);
165
+ },
166
+ });
167
+ }
168
+
169
+ getAddress() {
170
+ return this.address;
171
+ }
172
+
173
+ /**
174
+ * Invoke a contract function, dispatching to call() or send().
175
+ * @param {string} methodName
176
+ * @param {any[]} args
177
+ * @returns {Promise<any>}
178
+ */
179
+ async _invoke(methodName, args) {
180
+ const fn = this.interface.abi.find((f) => f && f.type === "function" && f.name === methodName);
181
+ if (!fn) throw makeError("function not found", "INVALID_ARGUMENT", { methodName });
182
+
183
+ const mut = fn.stateMutability || "";
184
+ const isView = mut === "view" || mut === "pure";
185
+
186
+ // ethers-style overrides:
187
+ // - for nonpayable/payable: last arg may be overrides object
188
+ // - for view/pure: last arg may be overrides (call overrides)
189
+ const inputCount = Array.isArray(fn.inputs) ? fn.inputs.length : 0;
190
+ let overrides = undefined;
191
+ let callArgs = Array.isArray(args) ? args : [];
192
+
193
+ if (callArgs.length === inputCount + 1 && _isOverridesLike(callArgs[callArgs.length - 1])) {
194
+ overrides = callArgs[callArgs.length - 1];
195
+ callArgs = callArgs.slice(0, inputCount);
196
+ }
197
+
198
+ if (isView) {
199
+ return this.call(methodName, callArgs, overrides);
200
+ }
201
+
202
+ return this.send(methodName, callArgs, overrides);
203
+ }
204
+
205
+ /**
206
+ * Build an unsigned transaction request for a contract method call.
207
+ * @param {string} methodName
208
+ * @param {any[]} args
209
+ * @returns {Promise<import("../providers/provider").TransactionRequest>}
210
+ */
211
+ async _populate(methodName, args) {
212
+ const fn = this.interface.abi.find((f) => f && f.type === "function" && f.name === methodName);
213
+ if (!fn) throw makeError("function not found", "INVALID_ARGUMENT", { methodName });
214
+
215
+ const inputCount = Array.isArray(fn.inputs) ? fn.inputs.length : 0;
216
+ let overrides = undefined;
217
+ let callArgs = Array.isArray(args) ? args : [];
218
+
219
+ if (callArgs.length === inputCount + 1 && _isOverridesLike(callArgs[callArgs.length - 1])) {
220
+ overrides = callArgs[callArgs.length - 1];
221
+ callArgs = callArgs.slice(0, inputCount);
222
+ }
223
+
224
+ const data = this.interface.encodeFunctionData(methodName, callArgs);
225
+ return { to: this.address, data, ...(overrides || {}) };
226
+ }
227
+
228
+ /**
229
+ * Perform a read-only call.
230
+ * @param {string} methodName
231
+ * @param {any[]} args
232
+ * @param {import("../providers/provider").TransactionRequest=} overrides
233
+ * @returns {Promise<any>}
234
+ */
235
+ async call(methodName, args, overrides) {
236
+ if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "call" });
237
+ const data = this.interface.encodeFunctionData(methodName, args);
238
+ const tx = { to: this.address, data, ...(overrides || {}) };
239
+ const raw = await this.provider.call(tx, "latest");
240
+ const decoded = this.interface.decodeFunctionResult(methodName, raw);
241
+ return decoded;
242
+ }
243
+
244
+ /**
245
+ * Send a state-changing transaction.
246
+ * @param {string} methodName
247
+ * @param {any[]} args
248
+ * @param {import("../providers/provider").TransactionRequest=} overrides
249
+ * @returns {Promise<ContractTransactionResponse>}
250
+ */
251
+ async send(methodName, args, overrides) {
252
+ if (!this.signer) throw makeError("missing signer", "UNKNOWN_ERROR", { operation: "send" });
253
+ const data = this.interface.encodeFunctionData(methodName, args);
254
+ const tx = { to: this.address, data, ...(overrides || {}) };
255
+ const resp = await this.signer.sendTransaction(tx);
256
+ return new ContractTransactionResponse(resp);
257
+ }
258
+
259
+ /**
260
+ * Query logs for an event.
261
+ * @param {any} event
262
+ * @param {number|string=} fromBlock
263
+ * @param {number|string=} toBlock
264
+ * @returns {Promise<EventLog[]>}
265
+ */
266
+ async queryFilter(event, fromBlock, toBlock) {
267
+ if (!this.provider) throw makeError("missing provider", "UNKNOWN_ERROR", { operation: "queryFilter" });
268
+ const name = typeof event === "string" ? event : event?.name;
269
+ assertArgument(typeof name === "string", "invalid event", "event", event);
270
+ const filter = { address: this.address, fromBlock, toBlock };
271
+ const logs = await this.provider.getLogs(filter);
272
+ return logs.map((l) => new EventLog(l));
273
+ }
274
+
275
+ on(event, callback) {
276
+ const name = typeof event === "string" ? event : event?.name;
277
+ if (!name) throw makeError("invalid event", "INVALID_ARGUMENT", { event });
278
+ const list = this._listeners.get(name) || [];
279
+ list.push(callback);
280
+ this._listeners.set(name, list);
281
+ return this;
282
+ }
283
+
284
+ once(event, callback) {
285
+ const wrap = (...args) => {
286
+ this.removeListener(event, wrap);
287
+ callback(...args);
288
+ };
289
+ return this.on(event, wrap);
290
+ }
291
+
292
+ removeListener(event, callback) {
293
+ const name = typeof event === "string" ? event : event?.name;
294
+ const list = this._listeners.get(name) || [];
295
+ this._listeners.set(
296
+ name,
297
+ list.filter((cb) => cb !== callback),
298
+ );
299
+ return this;
300
+ }
301
+
302
+ removeAllListeners(event) {
303
+ if (!event) {
304
+ this._listeners.clear();
305
+ return this;
306
+ }
307
+ const name = typeof event === "string" ? event : event?.name;
308
+ this._listeners.delete(name);
309
+ return this;
310
+ }
311
+
312
+ connect(signerOrProvider) {
313
+ return new Contract(this.address, this.interface, signerOrProvider, this.bytecode);
314
+ }
315
+
316
+ attach(address) {
317
+ return new Contract(address, this.interface, this.runner, this.bytecode);
318
+ }
319
+
320
+ deployTransaction() {
321
+ return this._deployTx || null;
322
+ }
323
+
324
+ async getTransactionReceipt(hash) {
325
+ if (!this.provider) return null;
326
+ const receipt = await this.provider.getTransactionReceipt(hash);
327
+ return receipt ? new ContractTransactionReceipt(receipt) : null;
328
+ }
329
+
330
+ async waitForDeployment() {
331
+ if (!this._deployTx) return this;
332
+ await this._deployTx.wait();
333
+ return this;
334
+ }
335
+
336
+ async getDeployedCode() {
337
+ if (!this.provider) return null;
338
+ return this.provider.getCode(this.address, "latest");
339
+ }
340
+
341
+ static from(target, abi, runner) {
342
+ const address = typeof target === "string" ? target : target?.address || target?.target;
343
+ return new Contract(address, abi, runner);
344
+ }
345
+ }
346
+
347
+ module.exports = {
348
+ BaseContract,
349
+ Contract,
350
+ ContractTransactionResponse,
351
+ ContractTransactionReceipt,
352
+ EventLog,
353
+ };
354
+