@mentaproject/client 0.1.35 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,19 +1,1011 @@
1
- /**
2
- * @module @mentaproject/client
3
- * @description This library provides the client-side functionalities for interacting with the Menta blockchain.
4
- * It includes managers for accounts, blocks, contracts, persistence, and transactions,
5
- * as well as core data structures and utility types.
6
- */
7
- /**
8
- * Re-exports all core data structures like MentaClient, Account, Block, and Transaction.
9
- */
10
- export * from './structures';
11
- /**
12
- * Re-exports all manager classes for interacting with different aspects of the Menta blockchain.
13
- */
14
- export * from './managers';
15
- /**
16
- * Re-exports the Cache structure for managing cached data.
17
- */
18
- export * from './structures/Cache';
19
- export * from "./utils/bigint";
1
+ import {
2
+ TransactionReceiptNotFoundError
3
+ } from "./chunk-ZEQAXTUF.js";
4
+ import "./chunk-NV2TBI2O.js";
5
+ import "./chunk-PR4QN5HX.js";
6
+
7
+ // src/structures/Account.ts
8
+ import {
9
+ fetchByBlockRange,
10
+ getBalance,
11
+ getBlockNumber,
12
+ getCode,
13
+ getTransaction,
14
+ getTransactionCount,
15
+ sendTransaction,
16
+ traceFilter
17
+ } from "@mentaproject/core/actions";
18
+
19
+ // src/structures/Transaction.ts
20
+ import { getBlock, getTransactionReceipt, traceTransaction, waitForTransactionReceipt } from "@mentaproject/core/actions";
21
+ import { hexToBigInt } from "@mentaproject/core/utils";
22
+
23
+ // src/utils/toJSON.ts
24
+ function isClassInstance(obj) {
25
+ if (!obj) return false;
26
+ const constructor = obj.constructor;
27
+ const nativeConstructors = [Array, Date, RegExp, Map, Set, Promise, Function, Number, String, Boolean, Error, Object];
28
+ if (nativeConstructors.includes(constructor)) {
29
+ return false;
30
+ }
31
+ return true;
32
+ }
33
+ function convertBigintsToStrings(obj) {
34
+ if (typeof obj === "bigint") {
35
+ return obj.toString() + "n";
36
+ }
37
+ if (typeof obj === "object") {
38
+ for (const key in obj) {
39
+ obj[key] = convertBigintsToStrings(obj[key]);
40
+ }
41
+ }
42
+ if (Array.isArray(obj)) {
43
+ for (let i = 0; i < obj.length; i++) {
44
+ obj[i] = convertBigintsToStrings(obj[i]);
45
+ }
46
+ }
47
+ return obj;
48
+ }
49
+ async function toJSON({ obj, depth = 0 }) {
50
+ const data = {};
51
+ const promises = [];
52
+ for (const key in obj) {
53
+ if (key === "toJSON" || key === "constructor" || key === "client" || key === "persistenceManager") continue;
54
+ const prop = obj[key];
55
+ if (typeof prop === "function") {
56
+ if (depth === 0) continue;
57
+ const promise = async () => {
58
+ const value = await obj[key]();
59
+ if (typeof value === "object" && isClassInstance(value)) return data[key] = await toJSON({ obj: value, depth: depth - 1 });
60
+ data[key] = value;
61
+ };
62
+ promises.push(promise());
63
+ }
64
+ ;
65
+ if (typeof prop === "object" && isClassInstance(prop)) {
66
+ if (depth === 0) {
67
+ const promise2 = async () => {
68
+ data[key] = await toJSON({
69
+ obj: prop,
70
+ depth: depth - 1
71
+ });
72
+ };
73
+ promises.push(promise2());
74
+ continue;
75
+ }
76
+ ;
77
+ const promise = async () => {
78
+ data[key] = await prop.toJSON({ depth: depth - 1 });
79
+ };
80
+ promises.push(promise());
81
+ continue;
82
+ }
83
+ ;
84
+ data[key] = prop;
85
+ }
86
+ ;
87
+ await Promise.all(promises);
88
+ return convertBigintsToStrings(data);
89
+ }
90
+
91
+ // src/structures/Block.ts
92
+ var Block = class {
93
+ /**
94
+ * @description Creates an instance of Block.
95
+ * @param client - The instance of MentaClient used to interact with the blockchain.
96
+ * @param data The raw block data conforming to IBlockData.
97
+ * @param includeTransactions Whether to include full transaction objects. Defaults to false.
98
+ */
99
+ constructor(client, data) {
100
+ this.client = client;
101
+ this.baseFeePerGas = data.baseFeePerGas;
102
+ this.blobGasUsed = data.blobGasUsed;
103
+ this.difficulty = data.difficulty;
104
+ this.excessBlobGas = data.excessBlobGas;
105
+ this.extraData = data.extraData;
106
+ this.gasLimit = data.gasLimit;
107
+ this.gasUsed = data.gasUsed;
108
+ this.hash = data.hash;
109
+ this.logsBloom = data.logsBloom;
110
+ this.mixHash = data.mixHash;
111
+ this.nonce = data.nonce;
112
+ this.number = data.number;
113
+ this.parentBeaconBlockRoot = data.parentBeaconBlockRoot;
114
+ this.parentHash = data.parentHash;
115
+ this.receiptsRoot = data.receiptsRoot;
116
+ this.sealFields = data.sealFields;
117
+ this.sha3Uncles = data.sha3Uncles;
118
+ this.size = data.size;
119
+ this.stateRoot = data.stateRoot;
120
+ this.timestamp = data.timestamp;
121
+ this.totalDifficulty = data.totalDifficulty;
122
+ this.transactionsRoot = data.transactionsRoot;
123
+ this.uncles = data.uncles;
124
+ this.withdrawals = data.withdrawals;
125
+ this.withdrawalsRoot = data.withdrawalsRoot;
126
+ this.miner = new Account(this.client, { address: data.miner });
127
+ if (!data.transactions || data.transactions.length === 0) {
128
+ const parsed = data.transactions.map((data2) => typeof data2 === "string" ? data2 : new Transaction(this.client, data2));
129
+ this.transactions = parsed;
130
+ }
131
+ }
132
+ includeTransactions() {
133
+ if (!this.transactions || this.transactions.length === 0) return false;
134
+ return true;
135
+ }
136
+ /**
137
+ * @description Converts the Block instance to a JSON representation.
138
+ * This method serializes the block's properties into a plain JavaScript object,
139
+ * suitable for JSON serialization.
140
+ * @param depth The depth of the conversion. Defaults to 1.
141
+ * @returns A promise that resolves to the JSON representation of the block.
142
+ */
143
+ async toJSON(depth) {
144
+ return await toJSON({
145
+ obj: {
146
+ ...this
147
+ },
148
+ depth
149
+ });
150
+ }
151
+ };
152
+
153
+ // src/structures/Transaction.ts
154
+ var Transaction = class {
155
+ /**
156
+ * Creates an instance of Transaction.
157
+ * @description Initializes a new Transaction instance with the provided RPC client and transaction data.
158
+ * @param {MentaClient} client - The instance of MentaClient used to interact with the blockchain.
159
+ * @param {ITransactionData} data The raw transaction data.
160
+ */
161
+ constructor(client, data) {
162
+ this.client = client;
163
+ this.accessList = data.accessList;
164
+ this.blobVersionedHashes = data.blobVersionedHashes;
165
+ this.gas = data.gas;
166
+ this.gasPrice = data.gasPrice;
167
+ this.hash = data.hash;
168
+ this.input = data.input;
169
+ this.maxFeePerGas = data.maxFeePerGas;
170
+ this.maxPriorityFeePerGas = data.maxPriorityFeePerGas;
171
+ this.nonce = data.nonce;
172
+ this.r = data.r;
173
+ this.s = data.s;
174
+ this.transactionIndex = data.transactionIndex;
175
+ this.type = data.type;
176
+ this.v = data.v;
177
+ this.value = data.value;
178
+ this.yParity = data.yParity;
179
+ this.blockHash = data.blockHash;
180
+ this.blockNumber = data.blockNumber;
181
+ this.typeHex = data.typeHex;
182
+ this.from = data.from ? this.client.accounts.get(data.from) : void 0;
183
+ this.to = data.to ? this.client.accounts.get(data.to) : void 0;
184
+ }
185
+ /**
186
+ * Retrieves the internal calls made by this transaction.
187
+ * @description Fetches and processes the transaction traces to extract internal call details.
188
+ * @returns {Promise<TransactionCall[] | undefined>} A promise that resolves to an array of call objects, each representing an internal call with sender, recipient, value, input data, gas used, and call type.
189
+ */
190
+ async calls() {
191
+ const traces = await traceTransaction(this.client.rpc, this.hash);
192
+ if (!traces) return void 0;
193
+ const calls = traces.filter((t) => t.type === "call" && t.action !== void 0);
194
+ return calls.map((c) => ({
195
+ from: new Account(this.client, { address: c.action.from }),
196
+ to: new Account(this.client, { address: c.action.to }),
197
+ value: hexToBigInt(c.action.value),
198
+ input: c.action.input,
199
+ gas: hexToBigInt(c.action.gas),
200
+ callType: c.action.callType
201
+ }));
202
+ }
203
+ /**
204
+ * Waits for the transaction receipt to be available.
205
+ * @description Asynchronously waits for the transaction to be confirmed on the blockchain and its receipt to be available.
206
+ * @param {number} [confirmations] The number of confirmations to wait for. Defaults to 1.
207
+ * @returns {Promise<WaitForTransactionReceiptReturnType>} A promise that resolves to the transaction receipt once the specified number of confirmations are met.
208
+ */
209
+ async waitForReceipt(confirmations) {
210
+ return await waitForTransactionReceipt(this.client.rpc, {
211
+ hash: this.hash,
212
+ confirmations: confirmations || 1
213
+ });
214
+ }
215
+ /**
216
+ * Retrieves the transaction receipt.
217
+ * @description Fetches the transaction receipt for the current transaction hash.
218
+ * @returns {Promise<WaitForTransactionReceiptReturnType>} A promise that resolves to the transaction receipt.
219
+ */
220
+ async receipt() {
221
+ try {
222
+ return await getTransactionReceipt(this.client.rpc, { hash: this.hash });
223
+ } catch (error) {
224
+ if (error instanceof TransactionReceiptNotFoundError) {
225
+ return void 0;
226
+ }
227
+ }
228
+ }
229
+ /**
230
+ * Retrieves the block containing this transaction.
231
+ * @description Fetches the block data using the transaction's block hash and returns a Block instance.
232
+ * @returns {Promise<Block>} A promise that resolves to a Block instance representing the block that includes this transaction.
233
+ */
234
+ async block() {
235
+ const data = await getBlock(this.client.rpc, { blockHash: this.blockHash });
236
+ return new Block(this.client, data);
237
+ }
238
+ /**
239
+ * Converts the Transaction instance to a JSON representation.
240
+ * @description Serializes the transaction instance into a JSON object, including nested representations of related entities like block, receipt, and internal calls based on the specified depth.
241
+ * @param {number} [depth=1] The depth of the conversion. Controls how deeply nested objects are serialized.
242
+ * @returns {Promise<object>} A promise that resolves to the JSON representation of the transaction.
243
+ */
244
+ async toJSON(depth) {
245
+ return await toJSON({
246
+ obj: {
247
+ ...this,
248
+ block: this.block,
249
+ receipt: this.receipt,
250
+ calls: async () => {
251
+ const calls = await this.calls();
252
+ if (!calls) return void 0;
253
+ return Promise.all(calls.map(async (c) => await toJSON({ obj: c, depth })));
254
+ }
255
+ },
256
+ depth
257
+ });
258
+ }
259
+ };
260
+
261
+ // src/structures/Account.ts
262
+ import { toHex } from "@mentaproject/core/utils";
263
+ import { getContractType } from "@mentaproject/contracts";
264
+ var Account = class {
265
+ /**
266
+ * Creates an instance of the Account class.
267
+ * @param client.rpc The CoreClient instance used for blockchain interactions.
268
+ * @param address The blockchain address of the account.
269
+ * @param persistenceManager An optional PersistenceManager instance for caching and data synchronization.
270
+ */
271
+ constructor(client, data, persistenceManager) {
272
+ this.client = client;
273
+ this.address = data.address;
274
+ this.persistenceManager = persistenceManager;
275
+ }
276
+ /**
277
+ * Checks if the account's address belongs to a smart contract.
278
+ * @description This method queries the blockchain for the code associated with the account's address.
279
+ * If code is found, it indicates that the account is a contract.
280
+ * @returns {Promise<boolean>} A promise that resolves to `true` if the account is a contract, `false` otherwise.
281
+ */
282
+ async isContract() {
283
+ const code = await getCode(this.client.rpc, { address: this.address });
284
+ if (!code || code === "0x") return false;
285
+ return true;
286
+ }
287
+ /**
288
+ * Retrieves the type of the contract if the account is a smart contract.
289
+ * @description This method first checks if the account is a contract using `isContract()`.
290
+ * If it is a contract, it then attempts to determine and return its type.
291
+ * @returns {Promise<any>} A promise that resolves to the contract type (e.g., 'ERC20', 'ERC721') or `undefined` if the account is not a contract or its type cannot be determined.
292
+ */
293
+ async contractType() {
294
+ const isContract = await this.isContract();
295
+ if (!isContract) return void 0;
296
+ return await getContractType(this.client.rpc, this.address);
297
+ }
298
+ /**
299
+ * Sends a specified amount of native cryptocurrency (ETH) to this account.
300
+ * @description This method constructs and sends a transaction to transfer ETH to the account's address.
301
+ * @param {bigint} amount The amount of ETH to send, specified in wei (the smallest denomination of Ether).
302
+ * @returns {Promise<Transaction>} A promise that resolves to a `Transaction` object representing the sent transaction.
303
+ */
304
+ async sendETH(amount) {
305
+ const hash = await sendTransaction(this.client.rpc, {
306
+ calls: [
307
+ {
308
+ to: this.address,
309
+ value: amount
310
+ }
311
+ ]
312
+ });
313
+ const data = await getTransaction(this.client.rpc, { hash });
314
+ return new Transaction(this.client, data);
315
+ }
316
+ /**
317
+ * Retrieves the current native cryptocurrency (ETH) balance of the account.
318
+ * @description This method queries the blockchain to get the balance associated with the account's address.
319
+ * @returns {Promise<bigint>} A promise that resolves to the ETH balance of the account, in wei.
320
+ */
321
+ async ETHBalance() {
322
+ return await getBalance(this.client.rpc, {
323
+ address: this.address
324
+ });
325
+ }
326
+ /**
327
+ * Retrieves the transaction count (nonce) for the account.
328
+ * @description The transaction count represents the number of transactions sent from this account,
329
+ * which is also used as the nonce for new transactions to prevent replay attacks.
330
+ * @returns {Promise<number>} A promise that resolves to the transaction count of the account.
331
+ */
332
+ async transactionCount() {
333
+ return await getTransactionCount(this.client.rpc, {
334
+ address: this.address
335
+ });
336
+ }
337
+ /**
338
+ * Retrieves all transactions involving this account.
339
+ * @description If a `PersistenceManager` is configured, this method will first attempt to retrieve transactions from the local cache.
340
+ * If not found in cache or if no `PersistenceManager` is configured, it will fetch transactions directly from the remote RPC.
341
+ * @param {GetTransactionsOptions} [options] - Optional parameters for filtering, pagination, and sorting the transactions.
342
+ * @param {number} [options.startBlock] - The starting block number (inclusive) from which to retrieve transactions.
343
+ * @param {number} [options.endBlock] - The ending block number (inclusive) up to which to retrieve transactions.
344
+ * @param {number} [options.page] - The page number for paginated results.
345
+ * @param {number} [options.offset] - The number of items to skip from the beginning of the result set.
346
+ * @param {'asc' | 'desc'} [options.sort] - The sorting order for transactions based on block number ('asc' for ascending, 'desc' for descending).
347
+ * @param {boolean} [forceFetch=false] - Forces the method to fetch transactions from the remote source even if they are already cached. (mostly used internally)
348
+ * @returns {Promise<Transaction[]>} A promise that resolves to an array of transactions.
349
+ */
350
+ async transactions(params, forceFetch = false) {
351
+ if (!this.persistenceManager || forceFetch) {
352
+ const hashes = await this._fetchTransactions(params);
353
+ const transactions = await Promise.all(
354
+ hashes.map((hash) => this.client.transactions.get({ hash }))
355
+ );
356
+ return transactions;
357
+ }
358
+ const jsons = await this.persistenceManager.getTransactions(
359
+ this.address,
360
+ params
361
+ );
362
+ return jsons.map((j) => this.client.transactions.parse(j));
363
+ }
364
+ /**
365
+ * Synchronizes the account's transactions with the remote data source using the configured `PersistenceManager`.
366
+ * @description This method initiates a synchronization process to ensure that the local cache of transactions
367
+ * for this account is up-to-date with the blockchain.
368
+ * @param {number} [limit] The maximum number of transactions to synchronize.
369
+ * @returns {Promise<void>} A promise that resolves when the synchronization process is complete.
370
+ * @throws {Error} If the persistence module is not configured.
371
+ */
372
+ async syncTransactions(limit = 1e3) {
373
+ if (!this.persistenceManager)
374
+ throw new Error("The persistence module is not configured.");
375
+ await this.persistenceManager.syncTransactions(this, limit);
376
+ }
377
+ /**
378
+ * Retrieves transactions involving a specific token. (not implemented yet)
379
+ * @description This method queries the persistence adapter to retrieve transactions involving a specific token.
380
+ * @param {Address} tokenAddress The address of the token.
381
+ * @returns {Promise<any>} A promise that resolves to an array of transactions involving the token.
382
+ * @throws {Error} If the persistence module is not configured.
383
+ */
384
+ async tokenTransactions(tokenAddress) {
385
+ if (!this.persistenceManager)
386
+ throw new Error("The persistence module is not configured.");
387
+ return {};
388
+ }
389
+ /**
390
+ * Converts the Account instance into a JSON-serializable representation.
391
+ * @description This method leverages a utility function to convert the `Account` object,
392
+ * including its asynchronous properties (like `isContract`, `ETHBalance`), into a plain JSON object.
393
+ * @param {number} [depth=1] The depth to which nested objects should be converted. A depth of 1 means only direct properties are included.
394
+ * @returns {Promise<object>} A promise that resolves to the JSON representation of the account.
395
+ */
396
+ async toJSON(depth) {
397
+ return await toJSON({
398
+ obj: {
399
+ address: this.address,
400
+ isContract: this.isContract.bind(this),
401
+ contractType: this.contractType.bind(this),
402
+ ETHBalance: this.ETHBalance.bind(this),
403
+ transactionCount: this.transactionCount.bind(this)
404
+ },
405
+ depth
406
+ });
407
+ }
408
+ /**
409
+ * Fetches transactions from the account using a block range exploration with trace_filter calls.
410
+ *
411
+ * @param params - The parameters for the block range exploration.
412
+ * @returns A Promise that resolves to an array of transaction hashes.
413
+ */
414
+ async _fetchTransactions({
415
+ fromBlock,
416
+ toBlock,
417
+ limit = 50
418
+ }) {
419
+ const lastBlock = await getBlockNumber(this.client.rpc);
420
+ const onBlockRange = async ({ fromBlock: fromBlock2, toBlock: toBlock2 }, stop) => {
421
+ const outgoing = await traceFilter(this.client.rpc, {
422
+ fromBlock: toHex(fromBlock2),
423
+ toBlock: toHex(toBlock2),
424
+ fromAddress: this.address
425
+ });
426
+ const incoming = await traceFilter(this.client.rpc, {
427
+ fromBlock: toHex(fromBlock2),
428
+ toBlock: toHex(toBlock2),
429
+ toAddress: this.address
430
+ });
431
+ const traces = outgoing.concat(incoming).sort((a, b) => a.blockNumber - b.blockNumber);
432
+ return traces.map((t) => t.transactionHash);
433
+ };
434
+ return await fetchByBlockRange({
435
+ toBlock: BigInt(toBlock !== void 0 ? toBlock : 0),
436
+ fromBlock: BigInt(fromBlock !== void 0 ? fromBlock : lastBlock),
437
+ direction: "backward",
438
+ itemLimit: limit,
439
+ onBlockRange
440
+ });
441
+ }
442
+ };
443
+
444
+ // src/structures/MentaClient.ts
445
+ import { createMentaAccount } from "@mentaproject/core/clients";
446
+ import { createClient } from "@mentaproject/core";
447
+
448
+ // src/managers/BlockManager.ts
449
+ import { getBlock as getBlock2 } from "@mentaproject/core/actions";
450
+ var BlockManager = class {
451
+ /**
452
+ * Creates an instance of BlockManager.
453
+ * @param client - The instance of MentaClient used to interact with the blockchain.
454
+ */
455
+ constructor(client) {
456
+ this.client = client;
457
+ }
458
+ /**
459
+ * Retrieves a block from the blockchain based on the provided parameters.
460
+ * This method uses the underlying RPC client to fetch block data and then
461
+ * encapsulates it within a {@link Block} instance.
462
+ * @param params The parameters for retrieving the block, including block hash, block number, or block tag.
463
+ * @returns A promise that resolves to a {@link Block} instance representing the retrieved block.
464
+ * @example
465
+ * import { http } from '@mentaproject/core';
466
+ * import { mainnet } from '@mentaproject/core/chains';
467
+ * import { MentaClient } from '@mentaproject/client';
468
+ *
469
+ * // Initialize the MentaClient
470
+ * const mentaClient = new MentaClient({ chain: mainnet, transport: http("http://rpcurlhere.com") });
471
+ *
472
+ * async function fetchBlock() {
473
+ * // Retrieve the latest block
474
+ * const latestBlock = await mentaClient.blocks.get({ blockTag: 'latest' });
475
+ * console.log('Latest block number:', latestBlock.number);
476
+ *
477
+ * // Retrieve a specific block by its number
478
+ * if (latestBlock.number) {
479
+ * const specificBlock = await mentaClient.blocks.get({ blockNumber: latestBlock.number - 10n });
480
+ * console.log('Specific block hash:', specificBlock.hash);
481
+ * }
482
+ * }
483
+ *
484
+ * fetchBlock();
485
+ */
486
+ async get(params) {
487
+ const data = await getBlock2(this.client.rpc, params);
488
+ return new Block(this.client, data);
489
+ }
490
+ };
491
+
492
+ // src/managers/TransactionManager.ts
493
+ import { getTransaction as getTransaction2, sendTransaction as sendTransaction2 } from "@mentaproject/core/actions";
494
+
495
+ // src/utils/bigint.ts
496
+ var bigIntMax = (...args) => args.reduce((m, e) => e > m ? e : m);
497
+ var bigIntMin = (...args) => args.reduce((m, e) => e < m ? e : m);
498
+ function bigIntReviver(key, value) {
499
+ if (typeof value === "string") {
500
+ if (value.endsWith("n")) {
501
+ try {
502
+ return BigInt(value.slice(0, -1));
503
+ } catch (e) {
504
+ return value;
505
+ }
506
+ }
507
+ ;
508
+ }
509
+ ;
510
+ return value;
511
+ }
512
+ function stringifyBingints(obj) {
513
+ if (typeof obj === "bigint") {
514
+ return obj.toString() + "n";
515
+ }
516
+ if (typeof obj === "object") {
517
+ for (const key in obj) {
518
+ obj[key] = stringifyBingints(obj[key]);
519
+ }
520
+ }
521
+ if (Array.isArray(obj)) {
522
+ for (let i = 0; i < obj.length; i++) {
523
+ obj[i] = stringifyBingints(obj[i]);
524
+ }
525
+ }
526
+ return obj;
527
+ }
528
+ function parseBingints(obj) {
529
+ if (typeof obj !== "object" || obj === null) {
530
+ return obj;
531
+ }
532
+ if (Array.isArray(obj)) {
533
+ return obj.map((item, index) => bigIntReviver(index.toString(), parseBingints(item)));
534
+ }
535
+ const newObj = {};
536
+ for (const key in obj) {
537
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
538
+ const value = obj[key];
539
+ const processedValue = parseBingints(value);
540
+ newObj[key] = bigIntReviver(key, processedValue);
541
+ }
542
+ }
543
+ ;
544
+ return newObj;
545
+ }
546
+
547
+ // src/managers/TransactionManager.ts
548
+ var TransactionManager = class {
549
+ /**
550
+ * Creates an instance of `TransactionManager`.
551
+ * @constructor
552
+ * @param {MentaClient} client - The instance of MentaClient used to interact with the blockchain.
553
+ */
554
+ constructor(client) {
555
+ this.client = client;
556
+ }
557
+ /**
558
+ * Retrieves a transaction by its hash or block number and index.
559
+ * @description This method fetches detailed information about a specific transaction
560
+ * from the blockchain using the provided parameters.
561
+ * @param {GetTransactionParameters} params - The parameters for retrieving the transaction,
562
+ * typically including `hash` or `blockNumber` and `index`.
563
+ * @returns {Promise<Transaction>} A promise that resolves to a {@link Transaction} instance
564
+ * containing the retrieved transaction data.
565
+ * @example
566
+ * const txHash = '0x...'; // Replace with a valid transaction hash
567
+ * const transaction = await client.transactions.get({ hash: txHash });
568
+ * console.log(transaction);
569
+ */
570
+ async get(params) {
571
+ const data = await getTransaction2(this.client.rpc, params);
572
+ return new Transaction(this.client, data);
573
+ }
574
+ /**
575
+ * Parse a transaction object from a JSON converted transaction data object.
576
+ *
577
+ * @param {J} data - The JSON converted transaction data object.
578
+ * @returns {Transaction} A Transaction instance representing the parsed transaction.
579
+ */
580
+ parse(data) {
581
+ const parsed = parseBingints(data);
582
+ const rawData = {
583
+ ...parsed,
584
+ from: parsed.from.address,
585
+ to: parsed.to ? parsed.to.address : null
586
+ };
587
+ return new Transaction(this.client, rawData);
588
+ }
589
+ /**
590
+ * Sends a transaction to the blockchain network.
591
+ * @description This method submits a new transaction to the blockchain. After the transaction
592
+ * is successfully sent, it retrieves and returns the full transaction details.
593
+ * @param {SendTransactionParameters} params - The parameters required to send the transaction,
594
+ * such as `to`, `value`, `data`, `gasLimit`, etc.
595
+ * @returns {Promise<Transaction>} A promise that resolves to a {@link Transaction} instance
596
+ * representing the sent transaction, including its hash and other details.
597
+ * @example
598
+ * import { MentaClient } from '@mentaproject/client';
599
+ * import { http } from '@mentaproject/core';
600
+ *
601
+ * // This example assumes you have an account with funds, which is available to the client.
602
+ * const client = new MentaClient({
603
+ * chain: 'mainnet',
604
+ * transport: http('http://rpcurlhere.com')
605
+ * });
606
+ *
607
+ * const transactionResult = await client.transactions.send({
608
+ * to: '0xRecipientAddress...', // Replace with a valid recipient address
609
+ * value: 1000000000000000000n, // 1 ETH in wei
610
+ * });
611
+ *
612
+ * console.log('Transaction sent with hash:', transactionResult.hash);
613
+ */
614
+ async send(params) {
615
+ const hash = await sendTransaction2(this.client.rpc, params);
616
+ return await this.get({ hash });
617
+ }
618
+ };
619
+
620
+ // src/managers/ContractManager.ts
621
+ import { getContract } from "@mentaproject/contracts";
622
+ var ContractManager = class {
623
+ /**
624
+ * Creates an instance of ContractManager.
625
+ * @description Initializes the ContractManager with a CoreClient instance, which is used for RPC communication.
626
+ * @param client - The instance of MentaClient used to interact with the blockchain.
627
+ */
628
+ constructor(client) {
629
+ this.client = client;
630
+ }
631
+ /**
632
+ * Retrieves a contract instance to interact with it.
633
+ * @description This method fetches a contract instance based on the provided parameters, allowing for interaction with its methods and events.
634
+ * @template P The type of the contract retrieval parameters, extending `GetContractParameters` with `AbiItem` array.
635
+ * @param {P} params The parameters for retrieving the contract, including its Application Binary Interface (ABI) and address.
636
+ * @returns {ReturnType<typeof getContract<ReadonlyArray<AbiItem>, P>>} A contract instance that can be used to call contract methods or listen to events.
637
+ * @example
638
+ * import { MentaClient } from '@mentaproject/client';
639
+ * import { http } from '@mentaproject/core';
640
+ *
641
+ * // Initialize the MentaClient with a transport
642
+ * const client = new MentaClient({
643
+ * transport: http('http://rpcurlhere.com'),
644
+ * });
645
+ *
646
+ * // Define the ABI and address for the smart contract
647
+ * const abi = [
648
+ * {
649
+ * "type": "function",
650
+ * "name": "greet",
651
+ * "stateMutability": "view",
652
+ * "inputs": [],
653
+ * "outputs": [{ "name": "", "type": "string" }]
654
+ * }
655
+ * ] as const;
656
+ * const contractAddress = '0x...'; // Replace with your contract address
657
+ *
658
+ * // Retrieve the contract instance
659
+ * const contract = client.contracts.get({
660
+ * abi,
661
+ * address: contractAddress,
662
+ * });
663
+ *
664
+ * // Example of interacting with the contract
665
+ * const greeting = await contract.greet();
666
+ */
667
+ get(params) {
668
+ return getContract(this.client.rpc, params);
669
+ }
670
+ };
671
+
672
+ // src/managers/AccountManager.ts
673
+ var AccountManager = class {
674
+ /**
675
+ * Creates an instance of AccountManager.
676
+ *
677
+ * @param {MentaClient} client - The instance of MentaClient used to interact with the blockchain.
678
+ * @param {persistenceManager} persistenceManager - The optional persistence manager to store and retrieve account data.
679
+ */
680
+ constructor(client, persistenceManager) {
681
+ this.client = client;
682
+ this.persistenceManager = persistenceManager;
683
+ }
684
+ /**
685
+ * Retrieves an account instance by its blockchain address.
686
+ * @param address - The blockchain address of the account to retrieve.
687
+ * @returns An instance of the `Account` class.
688
+ * @example
689
+ * ```typescript
690
+ * import { MentaClient } from '@mentaproject/client';
691
+ * import { http } from '@mentaproject/core';
692
+ *
693
+ * // Initialize the MentaClient
694
+ * const client = new MentaClient({
695
+ * transport: http('http://rpcurlhere.com'),
696
+ * });
697
+ *
698
+ * // The address of the account to retrieve
699
+ * const accountAddress = '0x1234567890123456789012345678901234567890';
700
+ *
701
+ * // Retrieve the account instance using the account manager from the client
702
+ * const account = client.accounts.get(accountAddress);
703
+ *
704
+ * console.log(account.address); // 0x1234567890123456789012345678901234567890
705
+ * ```
706
+ */
707
+ get(address) {
708
+ return new Account(this.client, { address }, this.persistenceManager);
709
+ }
710
+ };
711
+
712
+ // src/managers/PersistenceManager.ts
713
+ import { getBlockNumber as getBlockNumber2 } from "@mentaproject/core/actions";
714
+ var PersistenceManager = class {
715
+ /**
716
+ * Creates an instance of PersistenceManager.
717
+ * @param client - The instance of MentaClient used to interact with the blockchain.
718
+ * @param persistenceAdapter - The adapter responsible for actual data persistence operations.
719
+ */
720
+ constructor(client, persistenceAdapter) {
721
+ this.client = client;
722
+ this.persistenceAdapter = persistenceAdapter;
723
+ }
724
+ /**
725
+ * Retrieves transactions for a given account, applying a "stale-while-revalidate" strategy.
726
+ * @param params - Parameters for retrieving transactions.
727
+ * @returns A promise that resolves to an array of transactions with associated account information.
728
+ */
729
+ async getTransactions(address, params) {
730
+ return await this.persistenceAdapter.getTransactions(address, params);
731
+ }
732
+ /**
733
+ * Synchronizes an account's transactions from the remote source to the local persistence.
734
+ * It fetches new transactions starting from the last synced block and updates the local storage.
735
+ * @param account - The account whose transactions are to be synchronized.
736
+ * @param limit - The maximum number of transactions to fetch.
737
+ * @returns A promise that resolves when the synchronization is complete.
738
+ */
739
+ async syncTransactions(account, limit = 1e5) {
740
+ const lastSyncedBlock = await this.persistenceAdapter.getLastSyncedBlock(account.address);
741
+ const lastBlock = lastSyncedBlock ?? 0n;
742
+ const fromBlock = lastSyncedBlock ? lastSyncedBlock + 1n : await getBlockNumber2(this.client.rpc);
743
+ const newTransactions = await account.transactions({
744
+ fromBlock,
745
+ toBlock: lastBlock,
746
+ limit
747
+ }, true);
748
+ if (newTransactions.length > 0) {
749
+ await this.persistenceAdapter.upsertTransactions(newTransactions);
750
+ const latestBlock = bigIntMax(...newTransactions.map((t) => t.blockNumber || 0n));
751
+ await this.persistenceAdapter.setLastSyncedBlock(account.address, latestBlock);
752
+ }
753
+ }
754
+ };
755
+
756
+ // src/types/MentaClient.ts
757
+ import { watchBlockNumber, watchBlocks } from "@mentaproject/core/actions";
758
+ var ClientEvents = {
759
+ /**
760
+ * Event for new blocks.
761
+ * Uses the {@link watchBlocks} function from `@mentaproject/core`.
762
+ */
763
+ block: watchBlocks,
764
+ /**
765
+ * Event for new block numbers.
766
+ * Uses the {@link watchBlockNumber} function from `@mentaproject/core`.
767
+ */
768
+ blockNumber: watchBlockNumber
769
+ };
770
+
771
+ // src/utils/withCache.ts
772
+ import { watchBlockNumber as watchBlockNumber2 } from "@mentaproject/core/actions";
773
+ function withCache(client, cache) {
774
+ watchBlockNumber2(client, {
775
+ onBlockNumber: (blockNumber) => {
776
+ cache.setBlockNumber(blockNumber);
777
+ },
778
+ pollingInterval: 1e3
779
+ });
780
+ const originalRequest = client.request;
781
+ client.request = (async (args) => {
782
+ const { method, params } = args;
783
+ const cacheKey = `${client.chain.id}:${method}:${JSON.stringify(params || [], (_, v) => typeof v === "bigint" ? v.toString() : v)}`;
784
+ let result;
785
+ if (method !== "eth_blockNumber") result = cache.get(cacheKey);
786
+ if (!result) {
787
+ result = await originalRequest(args);
788
+ }
789
+ ;
790
+ if (result !== null && result !== void 0 && method !== "eth_blockNumber") {
791
+ const ttl = cache.config.ttlPolicies[method] || cache.config.defaultTtl;
792
+ await cache.set(cacheKey, result, ttl);
793
+ }
794
+ return result;
795
+ });
796
+ return client;
797
+ }
798
+
799
+ // src/structures/MentaClient.ts
800
+ var MentaClient = class {
801
+ /**
802
+ * Creates an instance of MentaClient.
803
+ * @param {MentaClientConfig} params - The configuration parameters for the client.
804
+ * @description The constructor initializes the RPC client and the various managers based on the provided configuration.
805
+ * It also applies caching and persistence if specified in the configuration.
806
+ * @example
807
+ * import { MentaClient } from '@mentaproject/client';
808
+ *
809
+ * // Basic initialization
810
+ * const client = new MentaClient({
811
+ * url: 'http://rpcurlhere.com',
812
+ * });
813
+ *
814
+ * // Initialization with a persistent cache
815
+ * const clientWithCache = new MentaClient({
816
+ * url: 'http://rpcurlhere.com',
817
+ * cache: {
818
+ * ttl: 60000, // 1 minute
819
+ * },
820
+ * });
821
+ */
822
+ constructor(params) {
823
+ this.params = params;
824
+ this.blocks = new BlockManager(this);
825
+ this.transactions = new TransactionManager(this);
826
+ this.contracts = new ContractManager(this);
827
+ if (params.persistenceAdapter) {
828
+ this.persistenceManager = new PersistenceManager(
829
+ this,
830
+ params.persistenceAdapter
831
+ );
832
+ this.accounts = new AccountManager(this, this.persistenceManager);
833
+ } else {
834
+ this.accounts = new AccountManager(this);
835
+ }
836
+ }
837
+ /**
838
+ * The underlying RPC client used for blockchain interactions.
839
+ * @description This client is responsible for low-level communication with the RPC node.
840
+ */
841
+ get rpc() {
842
+ if (!this._rpc) {
843
+ throw new Error("RPC client not initialized");
844
+ }
845
+ return this._rpc;
846
+ }
847
+ /**
848
+ * The account associated with the client.
849
+ * @description This account is used for signing transactions and interacting with the blockchain.
850
+ */
851
+ get account() {
852
+ if (!this._account) {
853
+ throw new Error("Account not initialized");
854
+ }
855
+ return this._account;
856
+ }
857
+ /**
858
+ * Subscribes to a specific client event.
859
+ * @template TEvent The type of the event to listen for.
860
+ * @param {TEvent} event - The event to listen for (e.g., 'block', 'transaction').
861
+ * @param {GetListenerCallback<TEvent>} callback - The callback function to execute when the event is triggered.
862
+ * @returns {() => void} An unsubscribe function to stop listening to the event.
863
+ * @description This method allows the client to listen for real-time events from the blockchain, such as new blocks or transactions.
864
+ * @example
865
+ * import { MentaClient } from '@mentaproject/client';
866
+ *
867
+ * const client = new MentaClient({ url: 'http://rpcurlhere.com' });
868
+ *
869
+ * // Subscribe to new blocks
870
+ * const unsubscribe = client.on('block', (block) => {
871
+ * console.log('New block received:', block);
872
+ * });
873
+ *
874
+ * // To stop listening
875
+ * // unsubscribe();
876
+ */
877
+ on(event, callback) {
878
+ const eventFunction = ClientEvents[event];
879
+ const capitalizedEvent = event.charAt(0).toUpperCase() + event.slice(1);
880
+ const params = {
881
+ [`on${capitalizedEvent}`]: callback,
882
+ pollingInterval: 1e3
883
+ };
884
+ return eventFunction(this.rpc, params);
885
+ }
886
+ async init() {
887
+ let coreClient = createClient(this.params);
888
+ if (this.params.cache) {
889
+ coreClient = withCache(coreClient, this.params.cache);
890
+ }
891
+ this._rpc = await createMentaAccount(coreClient, {
892
+ bundlerTransport: this.params.bundlerTransport,
893
+ publicTransport: this.params.transport,
894
+ signer: this.params.signer,
895
+ validatorAddress: this.params.validatorAddress
896
+ });
897
+ this._account = this.accounts.get(this.rpc.account.address);
898
+ }
899
+ };
900
+
901
+ // src/structures/Cache.ts
902
+ var MemoryCache = class {
903
+ /**
904
+ * @constructor
905
+ * @description Creates an instance of MemoryCache.
906
+ * @param {bigint} blockNumber - The current block number to use for TTL calculations.
907
+ * @param {Partial<ICacheConfig>} [options] - Optional configuration for the cache.
908
+ * @param {number} [options.maxSize=500] - The maximum number of entries the cache can hold.
909
+ * @param {number} [options.defaultTtl=1] - The default time-to-live in blocks for cache entries if not specified.
910
+ * @param {Object.<string, number>} [options.ttlPolicies={}] - A map of specific TTL policies for different keys.
911
+ */
912
+ constructor(blockNumber, options) {
913
+ /**
914
+ * @property {Map<string, ICacheEntry<any>>} cache - The internal Map used to store cache entries.
915
+ * @private
916
+ */
917
+ this.cache = /* @__PURE__ */ new Map();
918
+ this.blockNumber = blockNumber;
919
+ this.config = {
920
+ maxSize: 500,
921
+ defaultTtl: 1,
922
+ ttlPolicies: options?.ttlPolicies || {},
923
+ ...options
924
+ };
925
+ }
926
+ /**
927
+ * @method isExpired
928
+ * @description Checks if a cache entry has expired based on the current block number and the entry's expiry block.
929
+ * @param {bigint} expiry - The expiry block number of the cache entry.
930
+ * @returns {boolean} `true` if the entry has expired, `false` otherwise.
931
+ * @protected
932
+ */
933
+ isExpired(expiry) {
934
+ return this.blockNumber > expiry;
935
+ }
936
+ /**
937
+ * @method setBlockNumber
938
+ * @description Sets the current block number for TTL calculations. This is crucial for managing cache entry expiry.
939
+ * @param {bigint} blockNumber - The new current block number.
940
+ * @returns {void}
941
+ */
942
+ setBlockNumber(blockNumber) {
943
+ this.blockNumber = blockNumber;
944
+ }
945
+ /**
946
+ * @method set
947
+ * @description Sets a value in the cache. If the key already exists, its entry will be updated.
948
+ * If the cache reaches its maximum size, the oldest entry will be evicted before adding the new one.
949
+ * @template T - The type of the value being stored.
950
+ * @param {string} key - The unique key for the cache entry.
951
+ * @param {T} value - The value to store in the cache.
952
+ * @param {number} [ttl=this.config.defaultTtl] - The time-to-live (in blocks) for this specific entry. Defaults to the cache's `defaultTtl`.
953
+ * @returns {void}
954
+ */
955
+ set(key, value, ttl = this.config.defaultTtl) {
956
+ if (this.cache.has(key)) {
957
+ this.cache.delete(key);
958
+ }
959
+ if (this.cache.size >= this.config.maxSize) this.evict();
960
+ const expiry = this.blockNumber + BigInt(ttl);
961
+ this.cache.set(key, { value, expiry });
962
+ }
963
+ /**
964
+ * @method get
965
+ * @description Retrieves a value from the cache. If the entry is found and has not expired,
966
+ * it is moved to the end of the cache (making it the most recently used) to prevent premature eviction.
967
+ * @template T - The expected type of the value.
968
+ * @param {string} key - The key of the cache entry to retrieve.
969
+ * @returns {T | undefined} The cached value if found and not expired, otherwise `undefined`.
970
+ */
971
+ get(key) {
972
+ const entry = this.cache.get(key);
973
+ if (!entry) return void 0;
974
+ if (this.isExpired(entry.expiry)) {
975
+ this.cache.delete(key);
976
+ return void 0;
977
+ }
978
+ this.cache.delete(key);
979
+ this.cache.set(key, entry);
980
+ return entry.value;
981
+ }
982
+ /**
983
+ * @method evict
984
+ * @description Evicts the oldest entry from the cache. This method is called internally when the cache
985
+ * reaches its `maxSize` to make room for new entries.
986
+ * @returns {void}
987
+ * @private
988
+ */
989
+ evict() {
990
+ const oldestKey = this.cache.keys().next().value;
991
+ if (!oldestKey) return;
992
+ this.cache.delete(oldestKey);
993
+ }
994
+ };
995
+ export {
996
+ Account,
997
+ AccountManager,
998
+ Block,
999
+ BlockManager,
1000
+ ContractManager,
1001
+ MemoryCache,
1002
+ MentaClient,
1003
+ Transaction,
1004
+ TransactionManager,
1005
+ bigIntMax,
1006
+ bigIntMin,
1007
+ bigIntReviver,
1008
+ parseBingints,
1009
+ stringifyBingints
1010
+ };
1011
+ //# sourceMappingURL=index.js.map